Index: module-main/src/test/java/org/apache/http/impl/io/TestMessageParser.java
===================================================================
--- module-main/src/test/java/org/apache/http/impl/io/TestMessageParser.java (revision 568813)
+++ module-main/src/test/java/org/apache/http/impl/io/TestMessageParser.java (working copy)
@@ -67,7 +67,7 @@
public void testInvalidInput() throws Exception {
try {
- AbstractMessageParser.parseHeaders(null);
+ AbstractMessageParser.parseHeaders(null, -1, -1);
fail("IllegalArgumentException should have been thrown");
} catch (IllegalArgumentException ex) {
// expected
@@ -90,7 +90,7 @@
" \r\n" +
"\r\n";
SessionInputBuffer receiver = new SessionInputBufferMockup(s, "US-ASCII");
- Header[] headers = AbstractMessageParser.parseHeaders(receiver);
+ Header[] headers = AbstractMessageParser.parseHeaders(receiver,-1,-1);
assertNotNull(headers);
assertEquals(3, headers.length);
assertEquals("header1", headers[0].getName());
@@ -113,7 +113,7 @@
"header1 : stuff; param1 = value1; param2 = \"value 2\" \r\n" +
"\r\n";
SessionInputBuffer receiver = new SessionInputBufferMockup(s, "US-ASCII");
- Header[] headers = AbstractMessageParser.parseHeaders(receiver);
+ Header[] headers = AbstractMessageParser.parseHeaders(receiver,-1,-1);
assertNotNull(headers);
assertEquals(1, headers.length);
assertEquals("header1 : stuff; param1 = value1; param2 = \"value 2\" ", headers[0].toString());
@@ -137,7 +137,7 @@
"\r\n";
SessionInputBuffer receiver = new SessionInputBufferMockup(s, "US-ASCII");
try {
- AbstractMessageParser.parseHeaders(receiver);
+ AbstractMessageParser.parseHeaders(receiver, -1, -1);
fail("ProtocolException should have been thrown");
} catch (ProtocolException ex) {
// expected
@@ -147,7 +147,7 @@
"\r\n";
receiver = new SessionInputBufferMockup(s, "US-ASCII");
try {
- AbstractMessageParser.parseHeaders(receiver);
+ AbstractMessageParser.parseHeaders(receiver, -1, -1);
fail("ProtocolException should have been thrown");
} catch (ProtocolException ex) {
// expected
@@ -159,7 +159,7 @@
" header1: stuff\r\n" +
"header2 : stuff \r\n";
SessionInputBuffer receiver = new SessionInputBufferMockup(s, "US-ASCII");
- Header[] headers = AbstractMessageParser.parseHeaders(receiver);
+ Header[] headers = AbstractMessageParser.parseHeaders(receiver,-1,-1);
assertNotNull(headers);
assertEquals(2, headers.length);
assertEquals("header1", headers[0].getName());
@@ -171,7 +171,7 @@
public void testEmptyDataStream() throws Exception {
String s = "";
SessionInputBuffer receiver = new SessionInputBufferMockup(s, "US-ASCII");
- Header[] headers = AbstractMessageParser.parseHeaders(receiver);
+ Header[] headers = AbstractMessageParser.parseHeaders(receiver,-1,-1);
assertNotNull(headers);
assertEquals(0, headers.length);
}
@@ -185,8 +185,8 @@
SessionInputBuffer receiver = new SessionInputBufferMockup(s, "US-ASCII");
try {
AbstractMessageParser.parseHeaders(receiver, 2, -1);
- fail("IOException should have been thrown");
- } catch (IOException ex) {
+ fail("exception should have been thrown");
+ } catch (ProtocolException ex) {
// expected
}
}
@@ -200,8 +200,8 @@
SessionInputBuffer receiver = new SessionInputBufferMockup(s, "US-ASCII");
try {
AbstractMessageParser.parseHeaders(receiver, 2, 15);
- fail("IOException should have been thrown");
- } catch (IOException ex) {
+ fail("exception should have been thrown");
+ } catch (ProtocolException ex) {
// expected
}
}
Index: module-main/src/main/java/org/apache/http/message/LineParser.java
===================================================================
--- module-main/src/main/java/org/apache/http/message/LineParser.java (revision 568813)
+++ module-main/src/main/java/org/apache/http/message/LineParser.java (working copy)
@@ -127,4 +127,15 @@
;
+ /**
+ * Creates a stateful header section parser.
+ * The returned parser will call back to {@link #parseHeader}
+ * in this parser for parsing the header lines.
+ * It still has to be initialized before use.
+ *
+ * @return a new parser for header sections
+ */
+ HeaderSectionParser createHeaderSectionParser()
+ ;
+
}
Index: module-main/src/main/java/org/apache/http/message/BasicLineParser.java
===================================================================
--- module-main/src/main/java/org/apache/http/message/BasicLineParser.java (revision 568813)
+++ module-main/src/main/java/org/apache/http/message/BasicLineParser.java (working copy)
@@ -421,4 +421,11 @@
}
+
+ // non-javadoc, see interface LineParser
+ public HeaderSectionParser createHeaderSectionParser() {
+ return new BasicHeaderSectionParser(this);
+ }
+
+
} // class BasicLineParser
Index: module-main/src/main/java/org/apache/http/message/HeaderSectionParser.java
===================================================================
--- module-main/src/main/java/org/apache/http/message/HeaderSectionParser.java (revision 0)
+++ module-main/src/main/java/org/apache/http/message/HeaderSectionParser.java (revision 0)
@@ -0,0 +1,173 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ *
+ * In order to process header continuation lines, a header section parser
+ * needs either one line of look-ahead or has to be stateful.
+ * This interface is for a stateful parser. Instances are expected
+ * to be re-usable, but not thread-safe.
+ * Instances of this interface are expected to be stateless and thread-safe.
+ *
+ * @author Roland Weber
+ *
+ *
+ *
+ * @version $Revision$ $Date$
+ *
+ * @since 4.0
+ */
+public interface HeaderSectionParser {
+
+ /**
+ * Initializes this parser.
+ * A parser is re-usable, each call to this method will re-set
+ * it to a defined state. Implementations must not assume that
+ * the previous parse run is complete when the parser is re-set.
+ * Parse runs can be cancelled at any time.
+ *
+ * @param maxHeaderCount the maximum number of headers to parse,
+ * or negative to disable this limit
+ * @param maxLineLength the maximum length of a header line
+ * after concatenation of continuation lines,
+ * or negative to disable this limit
+ * @param params additional implementation-specific parameters,
+ * or null
+ */
+ void init(int maxHeaderCount, int maxLineLength, HttpParams params)
+ ;
+
+
+ /**
+ * Checks whether a parse run is complete.
+ * A parse run starts with a call to {@link #init} and is complete
+ * when the parser has detected the end of the header section.
+ * The latter happens in a call to {@link #parseLine parseLine}.
+ * Once the parse run is complete, the result can be obtained from
+ * {@link #getHeaders getHeaders}.
+ * A parse run can also be completed prematurely by calling
+ * {@link #complete}.
+ *
+ * @return true if the current parse run is complete,
+ * false otherwise
+ */
+ boolean isComplete()
+ ;
+
+
+ /**
+ * Parses an input line of a header section.
+ * The parser may need to keep the argument buffer for further
+ * processing. In that case, this method returns null
+ * and the caller MUST NOT re-use or modify the buffer afterwards.
+ * If the parser does not need the buffer anymore, a reference to
+ * the buffer is returned. This can be used as follows:
+ *
+ * buffer = headerSectionParser.parseLine(buffer); + * if (buffer == null) + * ...; // need to create a new buffer + *+ * + * @param buffer the buffer holding the line to parse + * + * @return
null if the parser takes control of the argument
+ * buffer, keeping it for further use. In that case, the caller
+ * MUST NOT alter the buffer afterwards, ever.
+ * buffer indicates that the parser will not need
+ * the buffer content anymore.
+ *
+ * @throws ProtocolException in case of a parse error
+ */
+ CharArrayBuffer parseLine(CharArrayBuffer buffer)
+ throws ProtocolException
+ ;
+
+
+ /**
+ * Completes a parse run explicitly.
+ * If the parse run was already complete, this method does nothing.
+ * Otherwise, the parser behaves as if the end of the header section
+ * had been detected.
+ *
+ * @throws ProtocolException in case of a parse error
+ */
+ void complete()
+ throws ProtocolException
+ ;
+
+
+ /**
+ * Obtains the headers collected during the parse run.
+ * Once a parse run is {@link #isComplete complete}, this method will
+ * return all headers found in the parsed section.
+ * At any other time, the behavior is undefined.
+ *
+ * @return the headers collected during the parse run,
+ * never null
+ *
+ * @throws ProtocolException in case of a parse error
+ */
+ Header[] getHeaders()
+ throws ProtocolException
+ ;
+
+
+ /**
+ * Adds the headers collected during the parse run to a message.
+ * This avoids creating the array returned by {@link #getHeaders}.
+ * This method must only be called when a parse run is
+ * {@link #isComplete complete}.
+ *
+ * @param message the message to which to append the headers
+ *
+ * @throws ProtocolException in case of a parse error
+ */
+ void addHeadersTo(HttpMessage message)
+ throws ProtocolException
+ ;
+}
Property changes on: module-main/src/main/java/org/apache/http/message/HeaderSectionParser.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Author Id Revision HeadURL
Name: svn:eol-style
+ native
Index: module-main/src/main/java/org/apache/http/message/BasicHeaderSectionParser.java
===================================================================
--- module-main/src/main/java/org/apache/http/message/BasicHeaderSectionParser.java (revision 0)
+++ module-main/src/main/java/org/apache/http/message/BasicHeaderSectionParser.java (revision 0)
@@ -0,0 +1,347 @@
+/*
+ * $HeadURL$
+ * $Revision$
+ * $Date$
+ *
+ * ====================================================================
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements. See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership. The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License. You may obtain a copy of the License at
+ *
+ * http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied. See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ * ====================================================================
+ *
+ * This software consists of voluntary contributions made by many
+ * individuals on behalf of the Apache Software Foundation. For more
+ * information on the Apache Software Foundation, please see
+ * null. */
+ protected LineParser lineParser;
+
+ /** The current state of this parser. */
+ protected int parseState;
+
+
+ /** The maximum number of headers. */
+ protected int maxHeaderCount;
+
+ /** The maximum length of a header line, including continuations. */
+ protected int maxLineLength;
+
+
+ /**
+ * The list of headers in the current parse run.
+ * Filled by {@link #storeCurrentHeader},
+ * accessed by {@link #getHeaders} and {@link #addHeadersTo}.
+ * Holds {@link Header} objects.
+ */
+ protected List collectedHeaders;
+
+ /** The header currently being parsed. */
+ protected CharArrayBuffer currentHeader;
+
+ /** A line counter, for improved error reporting. */
+ protected int lineCounter;
+
+
+
+ /**
+ * Instantiates a new header section parser.
+ *
+ * @param linep the line parser to use for the headers, or
+ * null for the default
+ */
+ public BasicHeaderSectionParser(LineParser linep) {
+
+ lineParser = (linep != null) ? linep : BasicLineParser.DEFAULT;
+ parseState = STATE_INVALID; // until initialized
+ lineCounter = -1;
+ }
+
+
+
+
+ // non-javadoc, see interface HeaderSectionParser
+ public void init(int maxCount, int maxLength, HttpParams params) {
+
+ // params are allowed to be null here
+
+ maxLineLength = maxLength;
+ maxHeaderCount = maxCount;
+
+ if (collectedHeaders == null)
+ collectedHeaders = new ArrayList(); // default size from params?
+ else
+ collectedHeaders.clear(); // reduce capacity if too large?
+
+ currentHeader = null;
+ lineCounter = 0;
+
+ // init/reset complete
+ parseState = STATE_PARSING;
+ }
+
+
+ // non-javadoc, see interface HeaderSectionParser
+ public boolean isComplete() {
+ return (parseState == STATE_COMPLETE);
+ }
+
+
+ // non-javadoc, see interface HeaderSectionParser
+ public CharArrayBuffer parseLine(CharArrayBuffer buffer)
+ throws ProtocolException {
+
+ if (buffer == null) {
+ throw new IllegalArgumentException
+ ("Buffer to parse must not be null.");
+ }
+ if (parseState != STATE_PARSING) {
+ throw new IllegalStateException
+ ("Not parsing at line " +
+ lineCounter + ", state " + parseState);
+ }
+
+ // We count the lines before they are parsed. Line numbers in
+ // exception messages are therefore 1-based, starting at the header
+ // section. For message heads, that corresponds to a 0-based count
+ // from the request or status line. For footers... who cares? ;-)
+ // Counting the line now makes sure that the count is updated
+ // in case of a parse error. Note that the caller may continue
+ // to parse a header section even if some lines cause errors.
+ lineCounter++;
+
+ boolean keepbuffer = false;
+ if (isContinuationLine(buffer)) {
+ keepbuffer = handleContinuationLine(buffer);
+
+ } else { // we have a new header, or an empty line
+
+ storeCurrentHeader();
+
+ if (buffer.length() > 0) {
+ // new header, check the count
+ if ((maxHeaderCount >= 0) &&
+ (collectedHeaders.size() >= maxHeaderCount)) {
+ throw new ProtocolException
+ ("Maximum header count exceeded at line " +
+ lineCounter + ".");
+ }
+ // wait for possible continuation lines
+ currentHeader = buffer;
+ keepbuffer = true;
+ } else {
+ // empty line marks end of headers
+ parseState = STATE_COMPLETE;
+ }
+ }
+
+ return keepbuffer ? null : buffer;
+
+ } // parseLine
+
+
+ // non-javadoc, see interface HeaderSectionParser
+ public void complete()
+ throws ProtocolException {
+
+ switch (parseState) {
+
+ case STATE_PARSING:
+ storeCurrentHeader();
+ parseState = STATE_COMPLETE;
+ break;
+
+ case STATE_COMPLETE:
+ break;
+ // do nothing
+
+ default:
+ throw new IllegalStateException
+ ("Parsing not in progress at line " +
+ lineCounter + ", state " + parseState + ".");
+ }
+ }
+
+
+ /**
+ * Checks whether the given buffer holds a header continuation line.
+ *
+ * @param buffer the buffer to check
+ *
+ * @return true if the buffer holds a continuation line,
+ * false otherwise
+ */
+ protected boolean isContinuationLine(CharArrayBuffer buffer) {
+
+ // should we allow for a malformed first header anyway?
+ // there is a test case, so the code needs be remain here for now
+ return (currentHeader != null) &&
+ isContinuationLineLead(buffer.charAt(0));
+ }
+
+
+ /**
+ * Checks whether the given character is a continuation line indicator.
+ * The default implementation accepts space and tab characters.
+ *
+ * @param c the character to check
+ *
+ * @return true if the argument is a header continuation line
+ * indicator, false otherwise
+ */
+ protected boolean isContinuationLineLead(char c) {
+ return (c == ' ' || c == '\t');
+ }
+
+
+ /**
+ * Called to append a continuation line to the current header.
+ * The default implementation skips leading whitespace, then
+ * joins the rest of the line to {@link #currentHeader}.
+ *
+ * @param buffer the buffer holding the continuation line
+ *
+ * @return true if the argument buffer needs to be kept
+ * unmodified, false if it is no longer needed
+ */
+ protected boolean handleContinuationLine(CharArrayBuffer buffer)
+ throws ProtocolException {
+
+ if (currentHeader == null) {
+ throw new ProtocolException
+ ("No header to continue at line " + lineCounter + ".");
+ }
+
+ int i;
+ for (i=0;
+ (inull. In that case, it does nothing.
+ */
+ protected void storeCurrentHeader()
+ throws ProtocolException {
+
+ if (currentHeader == null)
+ return;
+
+ Header h;
+ try {
+ h = lineParser.parseHeader(currentHeader);
+ } catch (ParseException ex) {
+ throw new ProtocolException(ex.getMessage()); // line number?
+ }
+
+ collectedHeaders.add(h);
+ }
+
+
+ // non-javadoc, see interface HeaderSectionParser
+ public Header[] getHeaders() throws ProtocolException {
+
+ if (parseState != STATE_COMPLETE) {
+ throw new IllegalStateException
+ ("Parsing not complete at line " +
+ lineCounter + ", state " + parseState + ".");
+ }
+
+ return (Header[])
+ collectedHeaders.toArray(new Header[collectedHeaders.size()]);
+ }
+
+
+ // non-javadoc, see interface HeaderSectionParser
+ public void addHeadersTo(HttpMessage message)
+ throws ProtocolException {
+
+ if (parseState != STATE_COMPLETE) {
+ throw new IllegalStateException
+ ("Parsing not complete at line " +
+ lineCounter + ", state " + parseState + ".");
+ }
+
+ for (int i = 0; i < collectedHeaders.size(); i++) { // iterator?
+ message.addHeader((Header)collectedHeaders.get(i));
+ }
+ }
+
+
+} // class BasicHeaderSectionParser
Property changes on: module-main/src/main/java/org/apache/http/message/BasicHeaderSectionParser.java
___________________________________________________________________
Name: svn:mime-type
+ text/plain
Name: svn:keywords
+ Date Author Id Revision HeadURL
Name: svn:eol-style
+ native
Index: module-main/src/main/java/org/apache/http/impl/io/ChunkedInputStream.java
===================================================================
--- module-main/src/main/java/org/apache/http/impl/io/ChunkedInputStream.java (revision 568813)
+++ module-main/src/main/java/org/apache/http/impl/io/ChunkedInputStream.java (working copy)
@@ -239,7 +239,7 @@
*/
private void parseTrailerHeaders() throws IOException {
try {
- this.footers = AbstractMessageParser.parseHeaders(in);
+ this.footers = AbstractMessageParser.parseHeaders(in, -1, -1);
} catch (HttpException e) {
IOException ioe = new MalformedChunkCodingException("Invalid footer: "
+ e.getMessage());
Index: module-main/src/main/java/org/apache/http/impl/io/AbstractMessageParser.java
===================================================================
--- module-main/src/main/java/org/apache/http/impl/io/AbstractMessageParser.java (revision 568813)
+++ module-main/src/main/java/org/apache/http/impl/io/AbstractMessageParser.java (working copy)
@@ -41,6 +41,7 @@
import org.apache.http.io.HttpMessageParser;
import org.apache.http.io.SessionInputBuffer;
import org.apache.http.message.LineParser;
+import org.apache.http.message.HeaderSectionParser;
import org.apache.http.message.BasicLineParser;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
@@ -77,116 +78,72 @@
this.maxLineLen = params.getIntParameter(
HttpConnectionParams.MAX_LINE_LENGTH, -1);
this.lineParser = (parser != null) ? parser : BasicLineParser.DEFAULT;
+ //@@@ remember params to initialize header section parser?
}
- /**
- * Parses HTTP headers from the data receiver stream according to the generic
- * format as given in Section 3.1 of RFC 822, RFC-2616 Section 4 and 19.3.
- *
- * @param inbuffer Session input buffer
- * @param maxHeaderCount maximum number of headers allowed. If the number
- * of headers received from the data stream exceeds maxCount value, an
- * IOException will be thrown. Setting this parameter to a negative value
- * or zero will disable the check.
- * @param maxLineLen maximum number of characters for a header line,
- * including the continuation lines
- * @return array of HTTP headers
- *
- * @throws HttpException
- * @throws IOException
- */
+
+ //@@@ currently needed for parsing footers in ChunkedInputStream
public static Header[] parseHeaders(
final SessionInputBuffer inbuffer,
int maxHeaderCount,
- int maxLineLen,
- LineParser parser)
+ int maxLineLen)
throws HttpException, IOException {
if (inbuffer == null) {
- throw new IllegalArgumentException("Session input buffer may not be null");
+ throw new IllegalArgumentException
+ ("Session input buffer may not be null");
}
- if (parser == null)
- parser = BasicLineParser.DEFAULT;
- ArrayList headerLines = new ArrayList();
+ HeaderSectionParser hsp =
+ BasicLineParser.DEFAULT.createHeaderSectionParser();
+ hsp.init(maxHeaderCount, maxLineLen, null);
- CharArrayBuffer current = null;
- CharArrayBuffer previous = null;
- for (;;) {
- if (current == null) {
- current = new CharArrayBuffer(64);
+ CharArrayBuffer buffer = null;
+ boolean done = false;
+ while (!done) {
+ if (buffer == null) {
+ buffer = new CharArrayBuffer(64);
} else {
- current.clear();
+ buffer.clear();
}
- int l = inbuffer.readLine(current);
- if (l == -1 || current.length() < 1) {
- break;
- }
- // Parse the header name and value
- // Check for folded headers first
- // Detect LWS-char see HTTP/1.0 or HTTP/1.1 Section 2.2
- // discussion on folded headers
- if ((current.charAt(0) == ' ' || current.charAt(0) == '\t') && previous != null) {
- // we have continuation folded header
- // so append value
- int i = 0;
- while (i < current.length()) {
- char ch = current.charAt(i);
- if (ch != ' ' && ch != '\t') {
- break;
- }
- i++;
- }
- if (maxLineLen > 0
- && previous.length() + 1 + current.length() - i > maxLineLen) {
- throw new IOException("Maximum line length limit exceeded");
- }
- previous.append(' ');
- previous.append(current, i, current.length() - i);
+ int l = inbuffer.readLine(buffer);
+ if (l < 0) {
+ hsp.complete(); // premature end of header section
} else {
- headerLines.add(current);
- previous = current;
- current = null;
+ buffer = hsp.parseLine(buffer);
}
- if (maxHeaderCount > 0 && headerLines.size() >= maxHeaderCount) {
- throw new IOException("Maximum header count exceeded");
- }
+ done = hsp.isComplete();
}
- Header[] headers = new Header[headerLines.size()];
- for (int i = 0; i < headerLines.size(); i++) {
- CharArrayBuffer buffer = (CharArrayBuffer) headerLines.get(i);
- try {
- headers[i] = parser.parseHeader(buffer);
- } catch (IllegalArgumentException ex) {
- throw new ProtocolException(ex.getMessage());
- }
- }
- return headers;
+ return hsp.getHeaders();
}
- public static Header[] parseHeaders(
- final SessionInputBuffer inbuffer,
- int maxHeaderCount,
- int maxLineLen) throws HttpException, IOException {
- return parseHeaders(inbuffer, maxHeaderCount, maxLineLen, null);
- }
-
- public static Header[] parseHeaders(final SessionInputBuffer inbuffer)
- throws HttpException, IOException {
- return parseHeaders(inbuffer, -1, -1, null);
- }
-
protected abstract HttpMessage parseHead(SessionInputBuffer sessionBuffer)
throws IOException, HttpException;
public HttpMessage parse() throws IOException, HttpException {
HttpMessage message = parseHead(this.sessionBuffer);
- Header[] headers = AbstractMessageParser.parseHeaders(
- this.sessionBuffer,
- this.maxHeaderCount,
- this.maxLineLen,
- this.lineParser);
- message.setHeaders(headers);
+
+ HeaderSectionParser hsp = lineParser.createHeaderSectionParser();
+ hsp.init(maxHeaderCount, maxLineLen, null);
+
+ CharArrayBuffer buffer = null;
+ boolean done = false;
+ while (!done) {
+ if (buffer == null) {
+ buffer = new CharArrayBuffer(64);
+ } else {
+ buffer.clear();
+ }
+ int l = this.sessionBuffer.readLine(buffer);
+ if (l < 0) {
+ hsp.complete(); // premature end of header section
+ } else {
+ buffer = hsp.parseLine(buffer);
+ }
+ done = hsp.isComplete();
+ }
+ hsp.addHeadersTo(message);
+
return message;
}