1 /*
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements.  See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License.  You may obtain a copy of the License at
8  *
9  *      http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17 package org.apache.catalina.connector;
18
19 import java.io.BufferedReader;
20 import java.io.IOException;
21
22
23 /**
24  * Coyote implementation of the buffered reader.
25  *
26  * @author Remy Maucherat
27  */

28 public class CoyoteReader
29     extends BufferedReader {
30
31
32     // -------------------------------------------------------------- Constants
33
34
35     private static final char[] LINE_SEP = { '\r', '\n' };
36     private static final int MAX_LINE_LENGTH = 4096;
37
38
39     // ----------------------------------------------------- Instance Variables
40
41
42     protected InputBuffer ib;
43
44
45     protected char[] lineBuffer = null;
46
47
48     // ----------------------------------------------------------- Constructors
49
50
51     public CoyoteReader(InputBuffer ib) {
52         super(ib, 1);
53         this.ib = ib;
54     }
55
56
57     // --------------------------------------------------------- Public Methods
58
59
60     /**
61      * Prevent cloning the facade.
62      */

63     @Override
64     protected Object clone()
65         throws CloneNotSupportedException {
66         throw new CloneNotSupportedException();
67     }
68
69
70     // -------------------------------------------------------- Package Methods
71
72
73     /**
74      * Clear facade.
75      */

76     void clear() {
77         ib = null;
78     }
79
80
81     // --------------------------------------------------------- Reader Methods
82
83
84     @Override
85     public void close()
86         throws IOException {
87         ib.close();
88     }
89
90
91     @Override
92     public int read()
93         throws IOException {
94         return ib.read();
95     }
96
97
98     @Override
99     public int read(char[] cbuf)
100         throws IOException {
101         return ib.read(cbuf, 0, cbuf.length);
102     }
103
104
105     @Override
106     public int read(char[] cbuf, int off, int len)
107         throws IOException {
108         return ib.read(cbuf, off, len);
109     }
110
111
112     @Override
113     public long skip(long n)
114         throws IOException {
115         return ib.skip(n);
116     }
117
118
119     @Override
120     public boolean ready()
121         throws IOException {
122         return ib.ready();
123     }
124
125
126     @Override
127     public boolean markSupported() {
128         return true;
129     }
130
131
132     @Override
133     public void mark(int readAheadLimit)
134         throws IOException {
135         ib.mark(readAheadLimit);
136     }
137
138
139     @Override
140     public void reset()
141         throws IOException {
142         ib.reset();
143     }
144
145
146     @Override
147     public String readLine()
148         throws IOException {
149
150         if (lineBuffer == null) {
151             lineBuffer = new char[MAX_LINE_LENGTH];
152        }
153
154         String result = null;
155
156         int pos = 0;
157         int end = -1;
158         int skip = -1;
159         StringBuilder aggregator = null;
160         while (end < 0) {
161             mark(MAX_LINE_LENGTH);
162             while ((pos < MAX_LINE_LENGTH) && (end < 0)) {
163                 int nRead = read(lineBuffer, pos, MAX_LINE_LENGTH - pos);
164                 if (nRead < 0) {
165                     if (pos == 0 && aggregator == null) {
166                         return null;
167                     }
168                     end = pos;
169                     skip = pos;
170                 }
171                 for (int i = pos; (i < (pos + nRead)) && (end < 0); i++) {
172                     if (lineBuffer[i] == LINE_SEP[0]) {
173                         end = i;
174                         skip = i + 1;
175                         char nextchar;
176                         if (i == (pos + nRead - 1)) {
177                             nextchar = (char) read();
178                         } else {
179                             nextchar = lineBuffer[i+1];
180                         }
181                         if (nextchar == LINE_SEP[1]) {
182                             skip++;
183                         }
184                     } else if (lineBuffer[i] == LINE_SEP[1]) {
185                         end = i;
186                         skip = i + 1;
187                     }
188                 }
189                 if (nRead > 0) {
190                     pos += nRead;
191                 }
192             }
193             if (end < 0) {
194                 if (aggregator == null) {
195                     aggregator = new StringBuilder();
196                 }
197                 aggregator.append(lineBuffer);
198                 pos = 0;
199             } else {
200                 reset();
201                 skip(skip);
202             }
203         }
204
205         if (aggregator == null) {
206             result = new String(lineBuffer, 0, end);
207         } else {
208             aggregator.append(lineBuffer, 0, end);
209             result = aggregator.toString();
210         }
211
212         return result;
213
214     }
215
216
217 }
218