Index: module-main/src/main/java/org/apache/http/message/HeaderValueParser.java =================================================================== --- module-main/src/main/java/org/apache/http/message/HeaderValueParser.java (revision 0) +++ module-main/src/main/java/org/apache/http/message/HeaderValueParser.java (revision 0) @@ -0,0 +1,182 @@ +/* + * $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 + * . + * + */ + +package org.apache.http.message; + + +import org.apache.http.HeaderElement; +import org.apache.http.NameValuePair; +import org.apache.http.util.CharArrayBuffer; + + + +/** + * Interface for parsing header values into elements. + * Instances of this interface are expected to be stateless and thread-safe. + * + * + * + * @version $Revision$ $Date$ + * + * @since 4.0 + */ +public interface HeaderValueParser { + + /** + * Parses a header value into elements. + *

+ * Some HTTP headers (such as the set-cookie header) have values that + * can be decomposed into multiple elements. In order to be processed + * by this parser, such headers must be in the following form: + *

+ *
+     * header  = [ element ] *( "," [ element ] )
+     * element = name [ "=" [ value ] ] *( ";" [ param ] )
+     * param   = name [ "=" [ value ] ]
+     *
+     * name    = token
+     * value   = ( token | quoted-string )
+     *
+     * token         = 1*<any char except "=", ",", ";", <"> and
+     *                       white space>
+     * quoted-string = <"> *( text | quoted-char ) <">
+     * text          = any char except <">
+     * quoted-char   = "\" char
+     * 
+ *

+ * Any amount of white space is allowed between any part of the + * header, element or param and is ignored. A missing value in any + * element or param will be stored as the empty {@link String}; + * if the "=" is also missing null will be stored instead. + *

+ * + * @param buffer buffer holding the header value to parse + * + * @return an array holding all elements of the header value + * + * @throws RuntimeException + * in case of invalid arguments or a parse error + */ + public HeaderElement[] parseElements(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) + throws RuntimeException + ; + + + /** + * Parses a list of name-value pairs. + * These lists are used to specify parameters to a header element. + *

+ * This method comforms to the generic grammar and formatting rules + * outlined in the + * Section 2.2 + * and + * Section 3.6 + * of + * RFC 2616. + *

+ * 2.2 Basic Rules + *

+ * The following rules are used throughout this specification to + * describe basic parsing constructs. + * The US-ASCII coded character set is defined by ANSI X3.4-1986. + *

+ *
+     *     OCTET          = 
+     *     CHAR           = 
+     *     UPALPHA        = 
+     *     LOALPHA        = 
+     *     ALPHA          = UPALPHA | LOALPHA
+     *     DIGIT          = 
+     *     CTL            = 
+     *     CR             = 
+     *     LF             = 
+     *     SP             = 
+     *     HT             = 
+     *     <">            = 
+     * 
+ *

+ * Many HTTP/1.1 header field values consist of words separated + * by LWS or special characters. These special characters MUST be + * in a quoted string to be used within + * a parameter value (as defined in section 3.6). + *

+ *

+     * token          = 1*
+     * separators     = "(" | ")" | "<" | ">" | "@"
+     *                | "," | ";" | ":" | "\" | <">
+     *                | "/" | "[" | "]" | "?" | "="
+     *                | "{" | "}" | SP | HT
+     * 
+ *

+ * A string of text is parsed as a single word if it is quoted using + * double-quote marks. + *

+ *
+     * quoted-string  = ( <"> *(qdtext | quoted-pair ) <"> )
+     * qdtext         = >
+     * 
+ *

+ * The backslash character ("\") MAY be used as a single-character + * quoting mechanism only within quoted-string and comment constructs. + *

+ *
+     * quoted-pair    = "\" CHAR
+     * 
+ * 3.6 Transfer Codings + *

+ * Parameters are in the form of attribute/value pairs. + *

+ *
+     * parameter               = attribute "=" value
+     * attribute               = token
+     * value                   = token | quoted-string
+     * 
+ * + * @param buffer buffer holding the name-value list to parse + * + * @return an array holding all items of the name-value list + * + * @throws RuntimeException + * in case of invalid arguments or a parse error + */ + public NameValuePair[] parseParameters(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) + throws RuntimeException + ; + +} + Property changes on: module-main/src/main/java/org/apache/http/message/HeaderValueParser.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/LineParser.java =================================================================== --- module-main/src/main/java/org/apache/http/message/LineParser.java (revision 0) +++ module-main/src/main/java/org/apache/http/message/LineParser.java (revision 0) @@ -0,0 +1,130 @@ +/* + * $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 + * . + * + */ + +package org.apache.http.message; + + +import org.apache.http.HttpVersion; +import org.apache.http.ProtocolException; +import org.apache.http.RequestLine; +import org.apache.http.StatusLine; +import org.apache.http.Header; +import org.apache.http.util.CharArrayBuffer; + + +/** + * Interface for parsing lines in the HEAD section of an HTTP message. + * There are individual methods for parsing a request line, a + * status line, or a header line. + * The lines to parse are passed in memory, the parser does not depend + * on any specific IO mechanism. + * Instances of this interface are expected to be stateless and thread-safe. + * + * + * + * @version $Revision$ $Date$ + * + * @since 4.0 + */ +public interface LineParser { + + + /** + * Parses the textual representation of a protocol version. + * This is needed for parsing request lines (last element) + * as well as status lines (first element). + * + * @param buffer a buffer holding the protocol version to parse + * + * @return the parsed protocol version + * + * @throws ProtocolException in case of a parse error + */ + public HttpVersion parseProtocolVersion(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) + throws ProtocolException + ; + + + /** + * Parses a request line. + * + * @param buffer a buffer holding the line to parse + * + * @return the parsed request line + * + * @throws ProtocolException in case of a parse error + */ + public RequestLine parseRequestLine(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) + throws ProtocolException + ; + + + /** + * Parses a status line. + * + * @param buffer a buffer holding the line to parse + * + * @return the parsed status line + * + * @throws ProtocolException in case of a parse error + */ + public StatusLine parseStatusLine(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) + throws ProtocolException + ; + + + /** + * Creates a header from a line. + * The full header line is expected here. Header continuation lines + * must be joined by the caller before invoking this method. + * + * @param buffer a buffer holding the full header line. + * This buffer MUST NOT be re-used afterwards, since + * the returned object may reference the contents later. + * + * @return the header in the argument buffer. + * The returned object MAY be a wrapper for the argument buffer. + * The argument buffer MUST NOT be re-used or changed afterwards. + * + * @throws ProtocolException in case of a parse error + */ + public Header parseHeader(CharArrayBuffer buffer) + throws ProtocolException + ; + + +} Property changes on: module-main/src/main/java/org/apache/http/message/LineParser.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/BasicHeaderValueParser.java =================================================================== --- module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.java (revision 0) +++ module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.java (revision 0) @@ -0,0 +1,287 @@ +/* + * $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 + * . + * + */ + +package org.apache.http.message; + + +import java.util.List; +import java.util.ArrayList; + +import org.apache.http.HeaderElement; +import org.apache.http.NameValuePair; +import org.apache.http.protocol.HTTP; +import org.apache.http.util.CharArrayBuffer; + + + +/** + * Basic implementation for parsing header values into elements. + * Instances of this class are stateless and thread-safe. + * Derived classes are expected to maintain these properties. + * + * @author B.C. Holmes + * @author Park, Sung-Gu + * @author Mike Bowler + * @author Oleg Kalnichevski + * @author and others + * + * + * + * @version $Revision$ $Date$ + * + * @since 4.0 + */ +public class BasicHeaderValueParser implements HeaderValueParser { + + /** + * A default instance of this class, for use as default or fallback. + * Note that {@link BasicLineParser} is not a singleton, there can + * be many instances of the class itself and of derived classes. + * The instance here provides non-customized, default behavior. + */ + public final static + BasicHeaderValueParser DEFAULT = new BasicHeaderValueParser(); + + + // public default constructor + + + // non-javadoc, see interface HeaderValueParser + public HeaderElement[] parseElements(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) { + + if (buffer == null) { + throw new IllegalArgumentException + ("Char array buffer may not be null"); + } + if (indexFrom < 0) { + throw new IndexOutOfBoundsException(); + } + if (indexTo > buffer.length()) { + throw new IndexOutOfBoundsException(); + } + if (indexFrom > indexTo) { + throw new IndexOutOfBoundsException(); + } + List elements = new ArrayList(); + int cur = indexFrom; + int from = indexFrom; + boolean qouted = false; + boolean escaped = false; + while (cur < indexTo) { + char ch = buffer.charAt(cur); + if (ch == '"' && !escaped) { + qouted = !qouted; + } + HeaderElement element = null; + if ((!qouted) && (ch == ',')) { + element = parseHeaderElement(buffer, from, cur); + from = cur + 1; + } else if (cur == indexTo - 1) { + element = parseHeaderElement(buffer, from, indexTo); + } + if (element != null && !(element.getName().length() == 0 && + element.getValue() == null) + ) { + elements.add(element); + } + if (escaped) { + escaped = false; + } else { + escaped = qouted && ch == '\\'; + } + cur++; + } + return (HeaderElement[]) + elements.toArray(new HeaderElement[elements.size()]); + } + + + /** + * Parses a single header element. + * A header element consist of a semicolon-separate list + * of name=value definitions. + */ + protected HeaderElement parseHeaderElement(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) { + if (buffer == null) { + throw new IllegalArgumentException + ("Char array buffer may not be null"); + } + if (indexFrom < 0) { + throw new IndexOutOfBoundsException(); + } + if (indexTo > buffer.length()) { + throw new IndexOutOfBoundsException(); + } + if (indexFrom > indexTo) { + throw new IndexOutOfBoundsException(); + } + NameValuePair[] nvps = parseParameters(buffer, indexFrom, indexTo); + return createHeaderElement(nvps); + } + + + /** + * Craetes a header element. + * Called from {@link #parseHeaderElement}. + * + * @param nvps the name-value pairs + * + * @return a header element representing the argument + */ + protected HeaderElement createHeaderElement(NameValuePair[] nvps) { + return new BasicHeaderElement(nvps); + } + + + + // non-javadoc, see interface HeaderValueParser + public NameValuePair[] parseParameters(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) { + if (buffer == null) { + throw new IllegalArgumentException + ("Char array buffer may not be null"); + } + if (indexFrom < 0) { + throw new IndexOutOfBoundsException(); + } + if (indexTo > buffer.length()) { + throw new IndexOutOfBoundsException(); + } + if (indexFrom > indexTo) { + throw new IndexOutOfBoundsException(); + } + List params = new ArrayList(); + int cur = indexFrom; + int from = indexFrom; + boolean qouted = false; + boolean escaped = false; + while (cur < indexTo) { + char ch = buffer.charAt(cur); + if (ch == '"' && !escaped) { + qouted = !qouted; + } + NameValuePair param = null; + if (!qouted && ch == ';') { + param = parseNameValuePair(buffer, from, cur); + from = cur + 1; + } else if (cur == indexTo - 1) { + param = parseNameValuePair(buffer, from, indexTo); + } + if (param != null && !(param.getName().length() == 0 && + param.getValue() == null) + ) { + params.add(param); + } + if (escaped) { + escaped = false; + } else { + escaped = qouted && ch == '\\'; + } + cur++; + } + return (NameValuePair[]) + params.toArray(new NameValuePair[params.size()]); + } + + + /** + * Parses a name=value specification, where the = and value are optional. + * + * @param buffer the buffer holding the name-value pair to parse + * + * @return the name-value pair, where the value is null + * if no value is specified + */ + protected NameValuePair parseNameValuePair(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) { + if (buffer == null) { + throw new IllegalArgumentException + ("Char array buffer may not be null"); + } + if (indexFrom < 0) { + throw new IndexOutOfBoundsException(); + } + if (indexTo > buffer.length()) { + throw new IndexOutOfBoundsException(); + } + if (indexFrom > indexTo) { + throw new IndexOutOfBoundsException(); + } + + int eq = buffer.indexOf('=', indexFrom, indexTo); + if (eq < 0) { + return createNameValuePair(buffer.substringTrimmed(indexFrom, indexTo), null); + } + String name = buffer.substringTrimmed(indexFrom, eq); + int i1 = eq + 1; + int i2 = indexTo; + // Trim leading white spaces + while (i1 < i2 && (HTTP.isWhitespace(buffer.charAt(i1)))) { + i1++; + } + // Trim trailing white spaces + while ((i2 > i1) && (HTTP.isWhitespace(buffer.charAt(i2 - 1)))) { + i2--; + } + // Strip away quotes if necessary + if (((i2 - i1) >= 2) + && (buffer.charAt(i1) == '"') + && (buffer.charAt(i2 - 1) == '"')) { + i1++; + i2--; + } + String value = buffer.substring(i1, i2); + return createNameValuePair(name, value); + } + + + /** + * Creates a name-value pair. + * Called from {@link #parseNameValuePair}. + * + * @param name the name + * @param value the value, or null + * + * @return a name-value pair representing the arguments + */ + protected NameValuePair createNameValuePair(String name, String value) { + return new BasicNameValuePair(name, value); + } + + +} + Property changes on: module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.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/BasicHeaderElement.java =================================================================== --- module-main/src/main/java/org/apache/http/message/BasicHeaderElement.java (revision 567629) +++ module-main/src/main/java/org/apache/http/message/BasicHeaderElement.java (working copy) @@ -93,7 +93,7 @@ private final String value; private final NameValuePair[] parameters; - private BasicHeaderElement(final NameValuePair[] nvps) { + public BasicHeaderElement(final NameValuePair[] nvps) { super(); if (nvps.length > 0) { NameValuePair nvp = nvps[0]; Index: module-main/src/main/java/org/apache/http/message/BasicLineParser.java =================================================================== --- module-main/src/main/java/org/apache/http/message/BasicLineParser.java (revision 0) +++ module-main/src/main/java/org/apache/http/message/BasicLineParser.java (revision 0) @@ -0,0 +1,346 @@ +/* + * $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 + * . + * + */ + +package org.apache.http.message; + + +import org.apache.http.HttpStatus; +import org.apache.http.HttpVersion; +import org.apache.http.ProtocolException; +import org.apache.http.RequestLine; +import org.apache.http.StatusLine; +import org.apache.http.Header; +import org.apache.http.protocol.HTTP; +import org.apache.http.util.CharArrayBuffer; + + + +/** + * Basic parser for lines in the head section of an HTTP message. + * There are individual methods for parsing a request line, a + * status line, or a header line. + * The lines to parse are passed in memory, the parser does not depend + * on any specific IO mechanism. + * Instances of this class are stateless and thread-safe. + * Derived classes MUST maintain these properties. + * + *

+ * Note: This class was created by refactoring parsing code located in + * various other classes. The author tags from those other classes have + * been replicated here, although the association with the parsing code + * taken from there has not been traced. + *

+ * + * @author Jeff Dever + * @author Mike Bowler + * @author Oleg Kalnichevski + * @author and others + */ +public class BasicLineParser implements LineParser { + + /** + * A default instance of this class, for use as default or fallback. + * Note that {@link BasicLineParser} is not a singleton, there can + * be many instances of the class itself and of derived classes. + * The instance here provides non-customized, default behavior. + */ + public final static BasicLineParser DEFAULT = new BasicLineParser(); + + + + // public default constructor + + + // non-javadoc, see interface LineParser + public HttpVersion parseProtocolVersion(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) + throws ProtocolException { + + if (buffer == null) { + throw new IllegalArgumentException + ("Char array buffer may not be null"); + } + if (indexFrom < 0) { + throw new IndexOutOfBoundsException(); + } + if (indexTo > buffer.length()) { + throw new IndexOutOfBoundsException(); + } + if (indexFrom > indexTo) { + throw new IndexOutOfBoundsException(); + } + try { + int major, minor; + + int i = indexFrom; + while (HTTP.isWhitespace(buffer.charAt(i))) { + i++; + } + if (buffer.charAt(i ) != 'H' + || buffer.charAt(i + 1) != 'T' + || buffer.charAt(i + 2) != 'T' + || buffer.charAt(i + 3) != 'P' + || buffer.charAt(i + 4) != '/') { + throw new ProtocolException("Not a valid HTTP version string: " + + buffer.substring(indexFrom, indexTo)); + } + i += 5; + int period = buffer.indexOf('.', i, indexTo); + if (period == -1) { + throw new ProtocolException("Invalid HTTP version number: " + + buffer.substring(indexFrom, indexTo)); + } + try { + major = Integer.parseInt(buffer.substringTrimmed(i, period)); + } catch (NumberFormatException e) { + throw new ProtocolException("Invalid HTTP major version number: " + + buffer.substring(indexFrom, indexTo)); + } + try { + minor = Integer.parseInt(buffer.substringTrimmed(period + 1, indexTo)); + } catch (NumberFormatException e) { + throw new ProtocolException("Invalid HTTP minor version number: " + + buffer.substring(indexFrom, indexTo)); + } + return createProtocolVersion(major, minor); + + } catch (IndexOutOfBoundsException e) { + throw new ProtocolException("Invalid HTTP version string: " + + buffer.substring(indexFrom, indexTo)); + } + } // parseProtocolVersion + + + /** + * Creates a protocol version. + * Called from {@link #parseProtocolVersion}. + * + * @param major the major version number, for example 1 in HTTP/1.0 + * @param minor the minor version number, for example 0 in HTTP/1.0 + * + * @return the protocol version + */ + protected HttpVersion createProtocolVersion(int major, int minor) { + return new HttpVersion(major, minor); + } + + + /** + * Parses a request line. + * + * @param buffer a buffer holding the line to parse + * + * @return the parsed request line + * + * @throws ProtocolException in case of a parse error + */ + public RequestLine parseRequestLine(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) + throws ProtocolException { + + if (buffer == null) { + throw new IllegalArgumentException + ("Char array buffer may not be null"); + } + if (indexFrom < 0) { + throw new IndexOutOfBoundsException(); + } + if (indexTo > buffer.length()) { + throw new IndexOutOfBoundsException(); + } + if (indexFrom > indexTo) { + throw new IndexOutOfBoundsException(); + } + + try { + int i = indexFrom; + while (HTTP.isWhitespace(buffer.charAt(i))) { + i++; + } + int blank = buffer.indexOf(' ', i, indexTo); + if (blank < 0) { + throw new ProtocolException("Invalid request line: " + + buffer.substring(indexFrom, indexTo)); + } + String method = buffer.substringTrimmed(i, blank); + i = blank; + while (HTTP.isWhitespace(buffer.charAt(i))) { + i++; + } + blank = buffer.indexOf(' ', i, indexTo); + if (blank < 0) { + throw new ProtocolException("Invalid request line: " + + buffer.substring(indexFrom, indexTo)); + } + String uri = buffer.substringTrimmed(i, blank); + HttpVersion ver = parseProtocolVersion(buffer, blank, indexTo); + return createRequestLine(method, uri, ver); + } catch (IndexOutOfBoundsException e) { + throw new ProtocolException("Invalid request line: " + + buffer.substring(indexFrom, indexTo)); + } + } // parseRequestLine + + + /** + * Instantiates a new request line. + * Called from {@link #parseRequestLine}. + * + * @param method the request method + * @param uri the requested URI + * @param ver the protocol version + * + * @return a new status line with the given data + */ + protected RequestLine createRequestLine(String method, + String uri, + HttpVersion ver) { + return new BasicRequestLine(method, uri, ver); + } + + + // non-javadoc, see interface LineParser + public StatusLine parseStatusLine(final CharArrayBuffer buffer, + final int indexFrom, + final int indexTo) + throws ProtocolException { + + if (buffer == null) { + throw new IllegalArgumentException + ("Char array buffer may not be null"); + } + if (indexFrom < 0) { + throw new IndexOutOfBoundsException(); + } + if (indexTo > buffer.length()) { + throw new IndexOutOfBoundsException(); + } + if (indexFrom > indexTo) { + throw new IndexOutOfBoundsException(); + } + + try { + int i = indexFrom; + //handle the HTTP-Version + while (HTTP.isWhitespace(buffer.charAt(i))) { + i++; + } + int blank = buffer.indexOf(' ', i, indexTo); + if (blank <= 0) { + throw new ProtocolException( + "Unable to parse HTTP-Version from the status line: " + + buffer.substring(indexFrom, indexTo)); + } + HttpVersion ver = parseProtocolVersion(buffer, i, blank); + + i = blank; + //advance through spaces + while (HTTP.isWhitespace(buffer.charAt(i))) { + i++; + } + + //handle the Status-Code + blank = buffer.indexOf(' ', i, indexTo); + if (blank < 0) { + blank = indexTo; + } + int statusCode = 0; + try { + statusCode = + Integer.parseInt(buffer.substringTrimmed(i, blank)); + } catch (NumberFormatException e) { + throw new ProtocolException( + "Unable to parse status code from status line: " + + buffer.substring(indexFrom, indexTo)); + } + //handle the Reason-Phrase + i = blank; + String reasonPhrase = null; + if (i < indexTo) { + reasonPhrase = buffer.substringTrimmed(i, indexTo); + } else { + reasonPhrase = ""; + } + return createStatusLine(ver, statusCode, reasonPhrase); + + } catch (IndexOutOfBoundsException e) { + throw new ProtocolException("Invalid status line: " + + buffer.substring(indexFrom, indexTo)); + } + } // parseStatusLine + + + /** + * Instantiates a new status line. + * Called from {@link #parseStatusLine}. + * + * @param ver the protocol version + * @param status the status code + * @param reason the reason phrase + * + * @return a new status line with the given data + */ + protected StatusLine createStatusLine(HttpVersion ver, + int status, String reason) { + return new BasicStatusLine(ver, status, reason); + } + + + // non-javadoc, see interface LineParser + public Header parseHeader(CharArrayBuffer buffer) + throws ProtocolException { + + Header result = null; + try { + // the actual parser code is in the constructor of BufferedHeader + result = new BufferedHeader(buffer, getHeaderValueParser()); + } catch (IllegalArgumentException iax) { + throw new ProtocolException(iax.getMessage(), iax); + } + return result; + } + + + /** + * Obtains the header value parser to use. + * Called by {@link #parseHeader}. + * + * @return the header value parser, or + * null for the default + */ + protected HeaderValueParser getHeaderValueParser() { + return null; + } + + +} // class BasicLineParser Property changes on: module-main/src/main/java/org/apache/http/message/BasicLineParser.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/BufferedHeader.java =================================================================== --- module-main/src/main/java/org/apache/http/message/BufferedHeader.java (revision 567629) +++ module-main/src/main/java/org/apache/http/message/BufferedHeader.java (working copy) @@ -62,15 +62,22 @@ */ private final int valuePos; + /** + * The parser for the header value, or null. + */ + private HeaderValueParser parser; + /** * Creates a new header from a buffer. * The name of the header will be parsed immediately, * the value only if it is accessed. * * @param buffer the buffer containing the header to represent + * @param parser the header value parser, or null */ - public BufferedHeader(final CharArrayBuffer buffer) { + public BufferedHeader(final CharArrayBuffer buffer, + final HeaderValueParser parser) { super(); if (buffer == null) { throw new IllegalArgumentException("Char array buffer may not be null"); @@ -86,8 +93,14 @@ this.buffer = buffer; this.name = s; this.valuePos = colon + 1; + this.parser = parser; } + public BufferedHeader(final CharArrayBuffer buffer) { + this(buffer, null); + } + + public String getName() { return this.name; } @@ -97,7 +110,11 @@ } public HeaderElement[] getElements() { - return BasicHeaderElement.parseAll(this.buffer, this.valuePos, this.buffer.length()); + HeaderValueParser hvp = this.parser; + if (hvp == null) + hvp = BasicHeaderValueParser.DEFAULT; + return hvp.parseElements(this.buffer, + this.valuePos, this.buffer.length()); } public int getValuePos() { Index: module-main/src/main/java/org/apache/http/impl/io/HttpRequestParser.java =================================================================== --- module-main/src/main/java/org/apache/http/impl/io/HttpRequestParser.java (revision 567629) +++ module-main/src/main/java/org/apache/http/impl/io/HttpRequestParser.java (working copy) @@ -67,7 +67,7 @@ if (i == -1) { throw new ConnectionClosedException("Client closed connection"); } - RequestLine requestline = BasicRequestLine.parse(this.lineBuf, 0, this.lineBuf.length()); + RequestLine requestline = lineParser.parseRequestLine(this.lineBuf, 0, this.lineBuf.length()); return this.requestFactory.newHttpRequest(requestline); } Index: module-main/src/main/java/org/apache/http/impl/io/HttpResponseParser.java =================================================================== --- module-main/src/main/java/org/apache/http/impl/io/HttpResponseParser.java (revision 567629) +++ module-main/src/main/java/org/apache/http/impl/io/HttpResponseParser.java (working copy) @@ -68,7 +68,7 @@ throw new NoHttpResponseException("The target server failed to respond"); } //create the status line from the status string - StatusLine statusline = BasicStatusLine.parse(this.lineBuf, 0, this.lineBuf.length()); + StatusLine statusline = lineParser.parseStatusLine(this.lineBuf, 0, this.lineBuf.length()); return this.responseFactory.newHttpResponse(statusline, null); } 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 567629) +++ module-main/src/main/java/org/apache/http/impl/io/AbstractMessageParser.java (working copy) @@ -41,6 +41,8 @@ import org.apache.http.io.HttpMessageParser; import org.apache.http.io.SessionInputBuffer; import org.apache.http.message.BufferedHeader; +import org.apache.http.message.LineParser; +import org.apache.http.message.BasicLineParser; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.apache.http.util.CharArrayBuffer; @@ -56,7 +58,9 @@ private final SessionInputBuffer sessionBuffer; private final int maxHeaderCount; private final int maxLineLen; + protected final LineParser lineParser; + public AbstractMessageParser( final SessionInputBuffer buffer, final HttpParams params) { @@ -72,6 +76,7 @@ HttpConnectionParams.MAX_HEADER_COUNT, -1); this.maxLineLen = params.getIntParameter( HttpConnectionParams.MAX_LINE_LENGTH, -1); + this.lineParser = BasicLineParser.DEFAULT; //@@@ allow as argument } /** @@ -93,10 +98,16 @@ public static Header[] parseHeaders( final SessionInputBuffer inbuffer, int maxHeaderCount, - int maxLineLen) throws HttpException, IOException { + int maxLineLen, + LineParser parser) + throws HttpException, IOException { + if (inbuffer == null) { throw new IllegalArgumentException("Session input buffer may not be null"); } + if (parser == null) + parser = BasicLineParser.DEFAULT; + ArrayList headerLines = new ArrayList(); CharArrayBuffer current = null; @@ -145,7 +156,7 @@ for (int i = 0; i < headerLines.size(); i++) { CharArrayBuffer buffer = (CharArrayBuffer) headerLines.get(i); try { - headers[i] = new BufferedHeader(buffer); + headers[i] = parser.parseHeader(buffer); } catch (IllegalArgumentException ex) { throw new ProtocolException(ex.getMessage()); } @@ -153,9 +164,16 @@ return headers; } + 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); + return parseHeaders(inbuffer, -1, -1, null); } protected abstract HttpMessage parseHead(SessionInputBuffer sessionBuffer) @@ -166,7 +184,8 @@ Header[] headers = AbstractMessageParser.parseHeaders( this.sessionBuffer, this.maxHeaderCount, - this.maxLineLen); + this.maxLineLen, + this.lineParser); message.setHeaders(headers); return message; }