1069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/*
2069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.java $
3069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Revision: 595670 $
4069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * $Date: 2007-11-16 06:15:01 -0800 (Fri, 16 Nov 2007) $
5069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
6069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
7069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Licensed to the Apache Software Foundation (ASF) under one
8069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * or more contributor license agreements.  See the NOTICE file
9069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * distributed with this work for additional information
10069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * regarding copyright ownership.  The ASF licenses this file
11069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * to you under the Apache License, Version 2.0 (the
12069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "License"); you may not use this file except in compliance
13069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * with the License.  You may obtain a copy of the License at
14069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
15069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *   http://www.apache.org/licenses/LICENSE-2.0
16069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
17069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Unless required by applicable law or agreed to in writing,
18069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * software distributed under the License is distributed on an
19069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * KIND, either express or implied.  See the License for the
21069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * specific language governing permissions and limitations
22069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * under the License.
23069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * ====================================================================
24069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
25069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * This software consists of voluntary contributions made by many
26069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * individuals on behalf of the Apache Software Foundation.  For more
27069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * information on the Apache Software Foundation, please see
28069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <http://www.apache.org/>.
29069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
30069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
31069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
32069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpackage org.apache.http.message;
33069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
34069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
35069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.List;
36069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport java.util.ArrayList;
37069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
38069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.HeaderElement;
39069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.NameValuePair;
40069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.ParseException;
41069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.protocol.HTTP;
42069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectimport org.apache.http.util.CharArrayBuffer;
43069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
44069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
45069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
46069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project/**
47069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Basic implementation for parsing header values into elements.
48069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Instances of this class are stateless and thread-safe.
49069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * Derived classes are expected to maintain these properties.
50069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
51069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author <a href="mailto:bcholmes@interlog.com">B.C. Holmes</a>
52069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author <a href="mailto:jericho@thinkfree.com">Park, Sung-Gu</a>
53069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
54069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author <a href="mailto:oleg at ural.com">Oleg Kalnichevski</a>
55069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @author and others
56069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
57069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
58069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * <!-- empty lines above to avoid 'svn diff' context problems -->
59069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @version $Revision: 595670 $
60069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project *
61069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project * @since 4.0
62069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
63069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic class BasicHeaderValueParser implements HeaderValueParser {
64069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
65069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * A default instance of this class, for use as default or fallback.
67069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Note that {@link BasicHeaderValueParser} is not a singleton, there
68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * can be many instances of the class itself and of derived classes.
69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The instance here provides non-customized, default behavior.
70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final static
72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        BasicHeaderValueParser DEFAULT = new BasicHeaderValueParser();
73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final static char PARAM_DELIMITER                = ';';
75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final static char ELEM_DELIMITER                 = ',';
76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final static char[] ALL_DELIMITERS               = new char[] {
77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                                                PARAM_DELIMITER,
78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                                                ELEM_DELIMITER
79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                                                };
80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // public default constructor
82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Parses elements with the given parser.
86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value     the header value to parse
88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param parser    the parser to use, or <code>null</code> for default
89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  array holding the header elements, never <code>null</code>
91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final static
93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        HeaderElement[] parseElements(final String value,
94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                      HeaderValueParser parser)
95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        throws ParseException {
96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (value == null) {
98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Value to parse may not be null");
100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (parser == null)
103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            parser = BasicHeaderValueParser.DEFAULT;
104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CharArrayBuffer buffer = new CharArrayBuffer(value.length());
106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        buffer.append(value);
107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ParserCursor cursor = new ParserCursor(0, value.length());
108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return parser.parseElements(buffer, cursor);
109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-javadoc, see interface HeaderValueParser
113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public HeaderElement[] parseElements(final CharArrayBuffer buffer,
114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                         final ParserCursor cursor) {
115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (buffer == null) {
117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Char array buffer may not be null");
118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (cursor == null) {
120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Parser cursor may not be null");
121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        List elements = new ArrayList();
124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (!cursor.atEnd()) {
125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            HeaderElement element = parseHeaderElement(buffer, cursor);
126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (!(element.getName().length() == 0 && element.getValue() == null)) {
127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                elements.add(element);
128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (HeaderElement[])
131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            elements.toArray(new HeaderElement[elements.size()]);
132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Parses an element with the given parser.
137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value     the header element to parse
139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param parser    the parser to use, or <code>null</code> for default
140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  the parsed header element
142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final static
144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        HeaderElement parseHeaderElement(final String value,
145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                         HeaderValueParser parser)
146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        throws ParseException {
147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (value == null) {
149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Value to parse may not be null");
151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (parser == null)
154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            parser = BasicHeaderValueParser.DEFAULT;
155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CharArrayBuffer buffer = new CharArrayBuffer(value.length());
157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        buffer.append(value);
158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ParserCursor cursor = new ParserCursor(0, value.length());
159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return parser.parseHeaderElement(buffer, cursor);
160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-javadoc, see interface HeaderValueParser
164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public HeaderElement parseHeaderElement(final CharArrayBuffer buffer,
165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                            final ParserCursor cursor) {
166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (buffer == null) {
168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Char array buffer may not be null");
169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (cursor == null) {
171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Parser cursor may not be null");
172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        NameValuePair nvp = parseNameValuePair(buffer, cursor);
175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        NameValuePair[] params = null;
176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (!cursor.atEnd()) {
177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char ch = buffer.charAt(cursor.getPos() - 1);
178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (ch != ELEM_DELIMITER) {
179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                params = parseParameters(buffer, cursor);
180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return createHeaderElement(nvp.getName(), nvp.getValue(), params);
183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Creates a header element.
188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Called from {@link #parseHeaderElement}.
189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  a header element representing the argument
191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected HeaderElement createHeaderElement(
193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            final String name,
194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            final String value,
195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            final NameValuePair[] params) {
196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return new BasicHeaderElement(name, value, params);
197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Parses parameters with the given parser.
202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value     the parameter list to parse
204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param parser    the parser to use, or <code>null</code> for default
205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  array holding the parameters, never <code>null</code>
207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final static
209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        NameValuePair[] parseParameters(final String value,
210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                        HeaderValueParser parser)
211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        throws ParseException {
212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (value == null) {
214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Value to parse may not be null");
216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (parser == null)
219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            parser = BasicHeaderValueParser.DEFAULT;
220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CharArrayBuffer buffer = new CharArrayBuffer(value.length());
222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        buffer.append(value);
223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ParserCursor cursor = new ParserCursor(0, value.length());
224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return parser.parseParameters(buffer, cursor);
225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-javadoc, see interface HeaderValueParser
230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public NameValuePair[] parseParameters(final CharArrayBuffer buffer,
231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                           final ParserCursor cursor) {
232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (buffer == null) {
234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Char array buffer may not be null");
235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (cursor == null) {
237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Parser cursor may not be null");
238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int pos = cursor.getPos();
241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int indexTo = cursor.getUpperBound();
242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (pos < indexTo) {
244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char ch = buffer.charAt(pos);
245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (HTTP.isWhitespace(ch)) {
246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                pos++;
247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        cursor.updatePos(pos);
252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (cursor.atEnd()) {
253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return new NameValuePair[] {};
254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        List params = new ArrayList();
257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (!cursor.atEnd()) {
258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            NameValuePair param = parseNameValuePair(buffer, cursor);
259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            params.add(param);
260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char ch = buffer.charAt(cursor.getPos() - 1);
261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (ch == ELEM_DELIMITER) {
262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (NameValuePair[])
267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            params.toArray(new NameValuePair[params.size()]);
268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Parses a name-value-pair with the given parser.
272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value     the NVP to parse
274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param parser    the parser to use, or <code>null</code> for default
275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  the parsed name-value pair
277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final static
279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project       NameValuePair parseNameValuePair(final String value,
280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                        HeaderValueParser parser)
281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        throws ParseException {
282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (value == null) {
284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Value to parse may not be null");
286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (parser == null)
289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            parser = BasicHeaderValueParser.DEFAULT;
290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CharArrayBuffer buffer = new CharArrayBuffer(value.length());
292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        buffer.append(value);
293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ParserCursor cursor = new ParserCursor(0, value.length());
294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return parser.parseNameValuePair(buffer, cursor);
295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-javadoc, see interface HeaderValueParser
299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public NameValuePair parseNameValuePair(final CharArrayBuffer buffer,
300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                            final ParserCursor cursor) {
301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return parseNameValuePair(buffer, cursor, ALL_DELIMITERS);
302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static boolean isOneOf(final char ch, final char[] chs) {
305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (chs != null) {
306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            for (int i = 0; i < chs.length; i++) {
307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (ch == chs[i]) {
308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    return true;
309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return false;
313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public NameValuePair parseNameValuePair(final CharArrayBuffer buffer,
316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                            final ParserCursor cursor,
317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                            final char[] delimiters) {
318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (buffer == null) {
320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Char array buffer may not be null");
321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (cursor == null) {
323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Parser cursor may not be null");
324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean terminated = false;
327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int pos = cursor.getPos();
329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int indexFrom = cursor.getPos();
330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int indexTo = cursor.getUpperBound();
331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Find name
333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String name = null;
334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (pos < indexTo) {
335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char ch = buffer.charAt(pos);
336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (ch == '=') {
337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
338069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
339069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isOneOf(ch, delimiters)) {
340069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                terminated = true;
341069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
342069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
343069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            pos++;
344069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
345069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
346069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (pos == indexTo) {
347069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            terminated = true;
348069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            name = buffer.substringTrimmed(indexFrom, indexTo);
349069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
350069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            name = buffer.substringTrimmed(indexFrom, pos);
351069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            pos++;
352069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
353069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
354069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (terminated) {
355069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            cursor.updatePos(pos);
356069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return createNameValuePair(name, null);
357069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
358069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
359069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Find value
360069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String value = null;
361069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int i1 = pos;
362069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
363069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean qouted = false;
364069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean escaped = false;
365069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (pos < indexTo) {
366069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char ch = buffer.charAt(pos);
367069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (ch == '"' && !escaped) {
368069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                qouted = !qouted;
369069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
370069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (!qouted && !escaped && isOneOf(ch, delimiters)) {
371069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                terminated = true;
372069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
373069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
374069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (escaped) {
375069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                escaped = false;
376069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
377069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                escaped = qouted && ch == '\\';
378069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
379069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            pos++;
380069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
381069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
382069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int i2 = pos;
383069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Trim leading white spaces
384069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (i1 < i2 && (HTTP.isWhitespace(buffer.charAt(i1)))) {
385069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            i1++;
386069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
387069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Trim trailing white spaces
388069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while ((i2 > i1) && (HTTP.isWhitespace(buffer.charAt(i2 - 1)))) {
389069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            i2--;
390069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
391069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Strip away quotes if necessary
392069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (((i2 - i1) >= 2)
393069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            && (buffer.charAt(i1) == '"')
394069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            && (buffer.charAt(i2 - 1) == '"')) {
395069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            i1++;
396069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            i2--;
397069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
398069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        value = buffer.substring(i1, i2);
399069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (terminated) {
400069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            pos++;
401069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
402069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        cursor.updatePos(pos);
403069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return createNameValuePair(name, value);
404069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
405069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
406069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
407069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Creates a name-value pair.
408069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Called from {@link #parseNameValuePair}.
409069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
410069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param name      the name
411069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value     the value, or <code>null</code>
412069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
413069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  a name-value pair representing the arguments
414069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
415069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected NameValuePair createNameValuePair(final String name, final String value) {
416069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return new BasicNameValuePair(name, value);
417069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
418069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
419069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project}
420069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
421