• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/impl/io/AbstractMessageParser.java $
3  * $Revision: 576077 $
4  * $Date: 2007-09-16 04:50:22 -0700 (Sun, 16 Sep 2007) $
5  *
6  * ====================================================================
7  * Licensed to the Apache Software Foundation (ASF) under one
8  * or more contributor license agreements.  See the NOTICE file
9  * distributed with this work for additional information
10  * regarding copyright ownership.  The ASF licenses this file
11  * to you under the Apache License, Version 2.0 (the
12  * "License"); you may not use this file except in compliance
13  * with the License.  You may obtain a copy of the License at
14  *
15  *   http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing,
18  * software distributed under the License is distributed on an
19  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20  * KIND, either express or implied.  See the License for the
21  * specific language governing permissions and limitations
22  * under the License.
23  * ====================================================================
24  *
25  * This software consists of voluntary contributions made by many
26  * individuals on behalf of the Apache Software Foundation.  For more
27  * information on the Apache Software Foundation, please see
28  * <http://www.apache.org/>.
29  *
30  */
31 
32 package org.apache.http.impl.io;
33 
34 import java.io.IOException;
35 import java.util.ArrayList;
36 
37 import org.apache.http.Header;
38 import org.apache.http.HttpException;
39 import org.apache.http.HttpMessage;
40 import org.apache.http.ParseException;
41 import org.apache.http.ProtocolException;
42 import org.apache.http.io.HttpMessageParser;
43 import org.apache.http.io.SessionInputBuffer;
44 import org.apache.http.message.LineParser;
45 import org.apache.http.message.BasicLineParser;
46 import org.apache.http.params.CoreConnectionPNames;
47 import org.apache.http.params.HttpParams;
48 import org.apache.http.util.CharArrayBuffer;
49 
50 /**
51  * Message parser base class.
52  *
53  * @author Michael Becke
54  * @author <a href="mailto:oleg at ural.ru">Oleg Kalnichevski</a>
55  */
56 public abstract class AbstractMessageParser implements HttpMessageParser {
57 
58     private final SessionInputBuffer sessionBuffer;
59     private final int maxHeaderCount;
60     private final int maxLineLen;
61     protected final LineParser lineParser;
62 
63 
AbstractMessageParser( final SessionInputBuffer buffer, final LineParser parser, final HttpParams params)64     public AbstractMessageParser(
65             final SessionInputBuffer buffer,
66             final LineParser parser,
67             final HttpParams params) {
68         super();
69         if (buffer == null) {
70             throw new IllegalArgumentException("Session input buffer may not be null");
71         }
72         if (params == null) {
73             throw new IllegalArgumentException("HTTP parameters may not be null");
74         }
75         this.sessionBuffer = buffer;
76         this.maxHeaderCount = params.getIntParameter(
77                 CoreConnectionPNames.MAX_HEADER_COUNT, -1);
78         this.maxLineLen = params.getIntParameter(
79                 CoreConnectionPNames.MAX_LINE_LENGTH, -1);
80         this.lineParser = (parser != null) ? parser : BasicLineParser.DEFAULT;
81     }
82 
83     /**
84      * Parses HTTP headers from the data receiver stream according to the generic
85      * format as given in Section 3.1 of RFC 822, RFC-2616 Section 4 and 19.3.
86      *
87      * @param inbuffer Session input buffer
88      * @param maxHeaderCount maximum number of headers allowed. If the number
89      *  of headers received from the data stream exceeds maxCount value, an
90      *  IOException will be thrown. Setting this parameter to a negative value
91      *  or zero  will disable the check.
92      * @param maxLineLen maximum number of characters for a header line,
93      *                   including the continuation lines
94      * @return array of HTTP headers
95      *
96      * @throws HttpException
97      * @throws IOException
98      */
parseHeaders( final SessionInputBuffer inbuffer, int maxHeaderCount, int maxLineLen, LineParser parser)99     public static Header[] parseHeaders(
100             final SessionInputBuffer inbuffer,
101             int maxHeaderCount,
102             int maxLineLen,
103             LineParser parser)
104         throws HttpException, IOException {
105 
106         if (inbuffer == null) {
107             throw new IllegalArgumentException("Session input buffer may not be null");
108         }
109         if (parser == null)
110             parser = BasicLineParser.DEFAULT;
111 
112         ArrayList headerLines = new ArrayList();
113 
114         CharArrayBuffer current = null;
115         CharArrayBuffer previous = null;
116         for (;;) {
117             if (current == null) {
118                 current = new CharArrayBuffer(64);
119             } else {
120                 current.clear();
121             }
122             int l = inbuffer.readLine(current);
123             if (l == -1 || current.length() < 1) {
124                 break;
125             }
126             // Parse the header name and value
127             // Check for folded headers first
128             // Detect LWS-char see HTTP/1.0 or HTTP/1.1 Section 2.2
129             // discussion on folded headers
130             if ((current.charAt(0) == ' ' || current.charAt(0) == '\t') && previous != null) {
131                 // we have continuation folded header
132                 // so append value
133                 int i = 0;
134                 while (i < current.length()) {
135                     char ch = current.charAt(i);
136                     if (ch != ' ' && ch != '\t') {
137                         break;
138                     }
139                     i++;
140                 }
141                 if (maxLineLen > 0
142                         && previous.length() + 1 + current.length() - i > maxLineLen) {
143                     throw new IOException("Maximum line length limit exceeded");
144                 }
145                 previous.append(' ');
146                 previous.append(current, i, current.length() - i);
147             } else {
148                 headerLines.add(current);
149                 previous = current;
150                 current = null;
151             }
152             if (maxHeaderCount > 0 && headerLines.size() >= maxHeaderCount) {
153                 throw new IOException("Maximum header count exceeded");
154             }
155         }
156         Header[] headers = new Header[headerLines.size()];
157         for (int i = 0; i < headerLines.size(); i++) {
158             CharArrayBuffer buffer = (CharArrayBuffer) headerLines.get(i);
159             try {
160                 headers[i] = parser.parseHeader(buffer);
161             } catch (ParseException ex) {
162                 throw new ProtocolException(ex.getMessage());
163             }
164         }
165         return headers;
166     }
167 
parseHead(SessionInputBuffer sessionBuffer)168     protected abstract HttpMessage parseHead(SessionInputBuffer sessionBuffer)
169         throws IOException, HttpException, ParseException;
170 
parse()171     public HttpMessage parse() throws IOException, HttpException {
172         HttpMessage message = null;
173         try {
174             message = parseHead(this.sessionBuffer);
175         } catch (ParseException px) {
176             throw new ProtocolException(px.getMessage(), px);
177         }
178         Header[] headers = AbstractMessageParser.parseHeaders(
179                 this.sessionBuffer,
180                 this.maxHeaderCount,
181                 this.maxLineLen,
182                 this.lineParser);
183         message.setHeaders(headers);
184         return message;
185     }
186 
187 }
188