diff options
Diffstat (limited to 'src/org/apache/http/message/BasicHeaderValueParser.java')
-rw-r--r-- | src/org/apache/http/message/BasicHeaderValueParser.java | 420 |
1 files changed, 420 insertions, 0 deletions
diff --git a/src/org/apache/http/message/BasicHeaderValueParser.java b/src/org/apache/http/message/BasicHeaderValueParser.java new file mode 100644 index 0000000..5216196 --- /dev/null +++ b/src/org/apache/http/message/BasicHeaderValueParser.java @@ -0,0 +1,420 @@ +/* + * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.java $ + * $Revision: 595670 $ + * $Date: 2007-11-16 06:15:01 -0800 (Fri, 16 Nov 2007) $ + * + * ==================================================================== + * 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 + * <http://www.apache.org/>. + * + */ + +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.ParseException; +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 <a href="mailto:bcholmes@interlog.com">B.C. Holmes</a> + * @author <a href="mailto:jericho@thinkfree.com">Park, Sung-Gu</a> + * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a> + * @author <a href="mailto:oleg at ural.com">Oleg Kalnichevski</a> + * @author and others + * + * + * <!-- empty lines above to avoid 'svn diff' context problems --> + * @version $Revision: 595670 $ + * + * @since 4.0 + */ +public class BasicHeaderValueParser implements HeaderValueParser { + + /** + * A default instance of this class, for use as default or fallback. + * Note that {@link BasicHeaderValueParser} 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(); + + private final static char PARAM_DELIMITER = ';'; + private final static char ELEM_DELIMITER = ','; + private final static char[] ALL_DELIMITERS = new char[] { + PARAM_DELIMITER, + ELEM_DELIMITER + }; + + // public default constructor + + + /** + * Parses elements with the given parser. + * + * @param value the header value to parse + * @param parser the parser to use, or <code>null</code> for default + * + * @return array holding the header elements, never <code>null</code> + */ + public final static + HeaderElement[] parseElements(final String value, + HeaderValueParser parser) + throws ParseException { + + if (value == null) { + throw new IllegalArgumentException + ("Value to parse may not be null"); + } + + if (parser == null) + parser = BasicHeaderValueParser.DEFAULT; + + CharArrayBuffer buffer = new CharArrayBuffer(value.length()); + buffer.append(value); + ParserCursor cursor = new ParserCursor(0, value.length()); + return parser.parseElements(buffer, cursor); + } + + + // non-javadoc, see interface HeaderValueParser + public HeaderElement[] parseElements(final CharArrayBuffer buffer, + final ParserCursor cursor) { + + if (buffer == null) { + throw new IllegalArgumentException("Char array buffer may not be null"); + } + if (cursor == null) { + throw new IllegalArgumentException("Parser cursor may not be null"); + } + + List elements = new ArrayList(); + while (!cursor.atEnd()) { + HeaderElement element = parseHeaderElement(buffer, cursor); + if (!(element.getName().length() == 0 && element.getValue() == null)) { + elements.add(element); + } + } + return (HeaderElement[]) + elements.toArray(new HeaderElement[elements.size()]); + } + + + /** + * Parses an element with the given parser. + * + * @param value the header element to parse + * @param parser the parser to use, or <code>null</code> for default + * + * @return the parsed header element + */ + public final static + HeaderElement parseHeaderElement(final String value, + HeaderValueParser parser) + throws ParseException { + + if (value == null) { + throw new IllegalArgumentException + ("Value to parse may not be null"); + } + + if (parser == null) + parser = BasicHeaderValueParser.DEFAULT; + + CharArrayBuffer buffer = new CharArrayBuffer(value.length()); + buffer.append(value); + ParserCursor cursor = new ParserCursor(0, value.length()); + return parser.parseHeaderElement(buffer, cursor); + } + + + // non-javadoc, see interface HeaderValueParser + public HeaderElement parseHeaderElement(final CharArrayBuffer buffer, + final ParserCursor cursor) { + + if (buffer == null) { + throw new IllegalArgumentException("Char array buffer may not be null"); + } + if (cursor == null) { + throw new IllegalArgumentException("Parser cursor may not be null"); + } + + NameValuePair nvp = parseNameValuePair(buffer, cursor); + NameValuePair[] params = null; + if (!cursor.atEnd()) { + char ch = buffer.charAt(cursor.getPos() - 1); + if (ch != ELEM_DELIMITER) { + params = parseParameters(buffer, cursor); + } + } + return createHeaderElement(nvp.getName(), nvp.getValue(), params); + } + + + /** + * Creates a header element. + * Called from {@link #parseHeaderElement}. + * + * @return a header element representing the argument + */ + protected HeaderElement createHeaderElement( + final String name, + final String value, + final NameValuePair[] params) { + return new BasicHeaderElement(name, value, params); + } + + + /** + * Parses parameters with the given parser. + * + * @param value the parameter list to parse + * @param parser the parser to use, or <code>null</code> for default + * + * @return array holding the parameters, never <code>null</code> + */ + public final static + NameValuePair[] parseParameters(final String value, + HeaderValueParser parser) + throws ParseException { + + if (value == null) { + throw new IllegalArgumentException + ("Value to parse may not be null"); + } + + if (parser == null) + parser = BasicHeaderValueParser.DEFAULT; + + CharArrayBuffer buffer = new CharArrayBuffer(value.length()); + buffer.append(value); + ParserCursor cursor = new ParserCursor(0, value.length()); + return parser.parseParameters(buffer, cursor); + } + + + + // non-javadoc, see interface HeaderValueParser + public NameValuePair[] parseParameters(final CharArrayBuffer buffer, + final ParserCursor cursor) { + + if (buffer == null) { + throw new IllegalArgumentException("Char array buffer may not be null"); + } + if (cursor == null) { + throw new IllegalArgumentException("Parser cursor may not be null"); + } + + int pos = cursor.getPos(); + int indexTo = cursor.getUpperBound(); + + while (pos < indexTo) { + char ch = buffer.charAt(pos); + if (HTTP.isWhitespace(ch)) { + pos++; + } else { + break; + } + } + cursor.updatePos(pos); + if (cursor.atEnd()) { + return new NameValuePair[] {}; + } + + List params = new ArrayList(); + while (!cursor.atEnd()) { + NameValuePair param = parseNameValuePair(buffer, cursor); + params.add(param); + char ch = buffer.charAt(cursor.getPos() - 1); + if (ch == ELEM_DELIMITER) { + break; + } + } + + return (NameValuePair[]) + params.toArray(new NameValuePair[params.size()]); + } + + /** + * Parses a name-value-pair with the given parser. + * + * @param value the NVP to parse + * @param parser the parser to use, or <code>null</code> for default + * + * @return the parsed name-value pair + */ + public final static + NameValuePair parseNameValuePair(final String value, + HeaderValueParser parser) + throws ParseException { + + if (value == null) { + throw new IllegalArgumentException + ("Value to parse may not be null"); + } + + if (parser == null) + parser = BasicHeaderValueParser.DEFAULT; + + CharArrayBuffer buffer = new CharArrayBuffer(value.length()); + buffer.append(value); + ParserCursor cursor = new ParserCursor(0, value.length()); + return parser.parseNameValuePair(buffer, cursor); + } + + + // non-javadoc, see interface HeaderValueParser + public NameValuePair parseNameValuePair(final CharArrayBuffer buffer, + final ParserCursor cursor) { + return parseNameValuePair(buffer, cursor, ALL_DELIMITERS); + } + + private static boolean isOneOf(final char ch, final char[] chs) { + if (chs != null) { + for (int i = 0; i < chs.length; i++) { + if (ch == chs[i]) { + return true; + } + } + } + return false; + } + + public NameValuePair parseNameValuePair(final CharArrayBuffer buffer, + final ParserCursor cursor, + final char[] delimiters) { + + if (buffer == null) { + throw new IllegalArgumentException("Char array buffer may not be null"); + } + if (cursor == null) { + throw new IllegalArgumentException("Parser cursor may not be null"); + } + + boolean terminated = false; + + int pos = cursor.getPos(); + int indexFrom = cursor.getPos(); + int indexTo = cursor.getUpperBound(); + + // Find name + String name = null; + while (pos < indexTo) { + char ch = buffer.charAt(pos); + if (ch == '=') { + break; + } + if (isOneOf(ch, delimiters)) { + terminated = true; + break; + } + pos++; + } + + if (pos == indexTo) { + terminated = true; + name = buffer.substringTrimmed(indexFrom, indexTo); + } else { + name = buffer.substringTrimmed(indexFrom, pos); + pos++; + } + + if (terminated) { + cursor.updatePos(pos); + return createNameValuePair(name, null); + } + + // Find value + String value = null; + int i1 = pos; + + boolean qouted = false; + boolean escaped = false; + while (pos < indexTo) { + char ch = buffer.charAt(pos); + if (ch == '"' && !escaped) { + qouted = !qouted; + } + if (!qouted && !escaped && isOneOf(ch, delimiters)) { + terminated = true; + break; + } + if (escaped) { + escaped = false; + } else { + escaped = qouted && ch == '\\'; + } + pos++; + } + + int i2 = pos; + // 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--; + } + value = buffer.substring(i1, i2); + if (terminated) { + pos++; + } + cursor.updatePos(pos); + return createNameValuePair(name, value); + } + + /** + * Creates a name-value pair. + * Called from {@link #parseNameValuePair}. + * + * @param name the name + * @param value the value, or <code>null</code> + * + * @return a name-value pair representing the arguments + */ + protected NameValuePair createNameValuePair(final String name, final String value) { + return new BasicNameValuePair(name, value); + } + +} + |