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