1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28 package org.apache.http.impl.io;
29
30 import java.io.IOException;
31 import java.util.ArrayList;
32 import java.util.List;
33
34 import org.apache.http.Header;
35 import org.apache.http.HttpException;
36 import org.apache.http.HttpMessage;
37 import org.apache.http.MessageConstraintException;
38 import org.apache.http.ParseException;
39 import org.apache.http.ProtocolException;
40 import org.apache.http.config.MessageConstraints;
41 import org.apache.http.io.HttpMessageParser;
42 import org.apache.http.io.SessionInputBuffer;
43 import org.apache.http.message.BasicLineParser;
44 import org.apache.http.message.LineParser;
45 import org.apache.http.params.HttpParamConfig;
46 import org.apache.http.params.HttpParams;
47 import org.apache.http.util.Args;
48 import org.apache.http.util.CharArrayBuffer;
49
50
51
52
53
54
55
56 @SuppressWarnings("deprecation")
57 public abstract class AbstractMessageParser<T extends HttpMessage> implements HttpMessageParser<T> {
58
59 private static final int HEAD_LINE = 0;
60 private static final int HEADERS = 1;
61
62 private final SessionInputBuffer sessionBuffer;
63 private final MessageConstraints messageConstraints;
64 private final List<CharArrayBuffer> headerLines;
65 protected final LineParser lineParser;
66
67 private int state;
68 private T message;
69
70
71
72
73
74
75
76
77
78
79
80 @Deprecated
81 public AbstractMessageParser(
82 final SessionInputBuffer buffer,
83 final LineParser parser,
84 final HttpParams params) {
85 super();
86 Args.notNull(buffer, "Session input buffer");
87 Args.notNull(params, "HTTP parameters");
88 this.sessionBuffer = buffer;
89 this.messageConstraints = HttpParamConfig.getMessageConstraints(params);
90 this.lineParser = (parser != null) ? parser : BasicLineParser.INSTANCE;
91 this.headerLines = new ArrayList<CharArrayBuffer>();
92 this.state = HEAD_LINE;
93 }
94
95
96
97
98
99
100
101
102
103
104
105
106 public AbstractMessageParser(
107 final SessionInputBuffer buffer,
108 final LineParser lineParser,
109 final MessageConstraints constraints) {
110 super();
111 this.sessionBuffer = Args.notNull(buffer, "Session input buffer");
112 this.lineParser = lineParser != null ? lineParser : BasicLineParser.INSTANCE;
113 this.messageConstraints = constraints != null ? constraints : MessageConstraints.DEFAULT;
114 this.headerLines = new ArrayList<CharArrayBuffer>();
115 this.state = HEAD_LINE;
116 }
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137 public static Header[] parseHeaders(
138 final SessionInputBuffer inBuffer,
139 final int maxHeaderCount,
140 final int maxLineLen,
141 final LineParser parser) throws HttpException, IOException {
142 final List<CharArrayBuffer> headerLines = new ArrayList<CharArrayBuffer>();
143 return parseHeaders(inBuffer, maxHeaderCount, maxLineLen,
144 parser != null ? parser : BasicLineParser.INSTANCE,
145 headerLines);
146 }
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172 public static Header[] parseHeaders(
173 final SessionInputBuffer inBuffer,
174 final int maxHeaderCount,
175 final int maxLineLen,
176 final LineParser parser,
177 final List<CharArrayBuffer> headerLines) throws HttpException, IOException {
178 Args.notNull(inBuffer, "Session input buffer");
179 Args.notNull(parser, "Line parser");
180 Args.notNull(headerLines, "Header line list");
181
182 CharArrayBuffer current = null;
183 CharArrayBuffer previous = null;
184 for (;;) {
185 if (current == null) {
186 current = new CharArrayBuffer(64);
187 } else {
188 current.clear();
189 }
190 final int readLen = inBuffer.readLine(current);
191 if (readLen == -1 || current.length() < 1) {
192 break;
193 }
194
195
196
197
198 if ((current.charAt(0) == ' ' || current.charAt(0) == '\t') && previous != null) {
199
200
201 int i = 0;
202 while (i < current.length()) {
203 final char ch = current.charAt(i);
204 if (ch != ' ' && ch != '\t') {
205 break;
206 }
207 i++;
208 }
209 if (maxLineLen > 0
210 && previous.length() + 1 + current.length() - i > maxLineLen) {
211 throw new MessageConstraintException("Maximum line length limit exceeded");
212 }
213 previous.append(' ');
214 previous.append(current, i, current.length() - i);
215 } else {
216 headerLines.add(current);
217 previous = current;
218 current = null;
219 }
220 if (maxHeaderCount > 0 && headerLines.size() >= maxHeaderCount) {
221 throw new MessageConstraintException("Maximum header count exceeded");
222 }
223 }
224 final HeaderHeader">Header[] headers = new Header[headerLines.size()];
225 for (int i = 0; i < headerLines.size(); i++) {
226 final CharArrayBuffer buffer = headerLines.get(i);
227 try {
228 headers[i] = parser.parseHeader(buffer);
229 } catch (final ParseException ex) {
230 throw new ProtocolException(ex.getMessage());
231 }
232 }
233 return headers;
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250 protected abstract T parseHead(SessionInputBuffer sessionBuffer)
251 throws IOException, HttpException, ParseException;
252
253 @Override
254 public T parse() throws IOException, HttpException {
255 final int st = this.state;
256 switch (st) {
257 case HEAD_LINE:
258 try {
259 this.message = parseHead(this.sessionBuffer);
260 } catch (final ParseException px) {
261 throw new ProtocolException(px.getMessage(), px);
262 }
263 this.state = HEADERS;
264
265 case HEADERS:
266 final Header[] headers = AbstractMessageParser.parseHeaders(
267 this.sessionBuffer,
268 this.messageConstraints.getMaxHeaderCount(),
269 this.messageConstraints.getMaxLineLength(),
270 this.lineParser,
271 this.headerLines);
272 this.message.setHeaders(headers);
273 final T result = this.message;
274 this.message = null;
275 this.headerLines.clear();
276 this.state = HEAD_LINE;
277 return result;
278 default:
279 throw new IllegalStateException("Inconsistent parser state");
280 }
281 }
282
283 }