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
62d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *
63d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath * @deprecated Please use {@link java.net.URL#openConnection} instead.
64d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
65d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath *     for further details.
66069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project */
67d42abb2fd917184764daf22f5f299e848b8701d7Narayan Kamath@Deprecated
68069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Projectpublic class BasicHeaderValueParser implements HeaderValueParser {
69069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
70069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
71069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * A default instance of this class, for use as default or fallback.
72069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Note that {@link BasicHeaderValueParser} is not a singleton, there
73069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * can be many instances of the class itself and of derived classes.
74069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * The instance here provides non-customized, default behavior.
75069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
76069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final static
77069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        BasicHeaderValueParser DEFAULT = new BasicHeaderValueParser();
78069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
79069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final static char PARAM_DELIMITER                = ';';
80069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final static char ELEM_DELIMITER                 = ',';
81069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private final static char[] ALL_DELIMITERS               = new char[] {
82069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                                                PARAM_DELIMITER,
83069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                                                ELEM_DELIMITER
84069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                                                };
85069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
86069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // public default constructor
87069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
88069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
89069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
90069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Parses elements with the given parser.
91069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
92069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value     the header value to parse
93069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param parser    the parser to use, or <code>null</code> for default
94069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
95069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  array holding the header elements, never <code>null</code>
96069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
97069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final static
98069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        HeaderElement[] parseElements(final String value,
99069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                      HeaderValueParser parser)
100069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        throws ParseException {
101069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
102069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (value == null) {
103069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
104069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Value to parse may not be null");
105069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
106069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
107069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (parser == null)
108069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            parser = BasicHeaderValueParser.DEFAULT;
109069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
110069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CharArrayBuffer buffer = new CharArrayBuffer(value.length());
111069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        buffer.append(value);
112069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ParserCursor cursor = new ParserCursor(0, value.length());
113069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return parser.parseElements(buffer, cursor);
114069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
115069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
116069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
117069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-javadoc, see interface HeaderValueParser
118069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public HeaderElement[] parseElements(final CharArrayBuffer buffer,
119069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                         final ParserCursor cursor) {
120069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
121069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (buffer == null) {
122069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Char array buffer may not be null");
123069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
124069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (cursor == null) {
125069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Parser cursor may not be null");
126069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
127069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
128069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        List elements = new ArrayList();
129069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (!cursor.atEnd()) {
130069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            HeaderElement element = parseHeaderElement(buffer, cursor);
131069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (!(element.getName().length() == 0 && element.getValue() == null)) {
132069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                elements.add(element);
133069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
134069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
135069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (HeaderElement[])
136069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            elements.toArray(new HeaderElement[elements.size()]);
137069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
138069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
139069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
140069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
141069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Parses an element with the given parser.
142069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
143069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value     the header element to parse
144069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param parser    the parser to use, or <code>null</code> for default
145069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
146069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  the parsed header element
147069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
148069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final static
149069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        HeaderElement parseHeaderElement(final String value,
150069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                         HeaderValueParser parser)
151069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        throws ParseException {
152069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
153069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (value == null) {
154069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
155069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Value to parse may not be null");
156069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
157069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
158069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (parser == null)
159069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            parser = BasicHeaderValueParser.DEFAULT;
160069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
161069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CharArrayBuffer buffer = new CharArrayBuffer(value.length());
162069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        buffer.append(value);
163069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ParserCursor cursor = new ParserCursor(0, value.length());
164069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return parser.parseHeaderElement(buffer, cursor);
165069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
166069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
167069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
168069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-javadoc, see interface HeaderValueParser
169069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public HeaderElement parseHeaderElement(final CharArrayBuffer buffer,
170069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                            final ParserCursor cursor) {
171069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
172069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (buffer == null) {
173069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Char array buffer may not be null");
174069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
175069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (cursor == null) {
176069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Parser cursor may not be null");
177069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
178069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
179069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        NameValuePair nvp = parseNameValuePair(buffer, cursor);
180069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        NameValuePair[] params = null;
181069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (!cursor.atEnd()) {
182069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char ch = buffer.charAt(cursor.getPos() - 1);
183069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (ch != ELEM_DELIMITER) {
184069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                params = parseParameters(buffer, cursor);
185069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
186069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
187069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return createHeaderElement(nvp.getName(), nvp.getValue(), params);
188069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
189069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
190069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
191069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
192069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Creates a header element.
193069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Called from {@link #parseHeaderElement}.
194069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
195069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  a header element representing the argument
196069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
197069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected HeaderElement createHeaderElement(
198069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            final String name,
199069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            final String value,
200069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            final NameValuePair[] params) {
201069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return new BasicHeaderElement(name, value, params);
202069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
203069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
204069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
205069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
206069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Parses parameters with the given parser.
207069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
208069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value     the parameter list to parse
209069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param parser    the parser to use, or <code>null</code> for default
210069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
211069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  array holding the parameters, never <code>null</code>
212069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
213069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final static
214069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        NameValuePair[] parseParameters(final String value,
215069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                        HeaderValueParser parser)
216069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        throws ParseException {
217069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
218069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (value == null) {
219069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
220069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Value to parse may not be null");
221069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
222069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
223069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (parser == null)
224069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            parser = BasicHeaderValueParser.DEFAULT;
225069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
226069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CharArrayBuffer buffer = new CharArrayBuffer(value.length());
227069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        buffer.append(value);
228069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ParserCursor cursor = new ParserCursor(0, value.length());
229069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return parser.parseParameters(buffer, cursor);
230069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
231069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
232069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
233069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
234069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-javadoc, see interface HeaderValueParser
235069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public NameValuePair[] parseParameters(final CharArrayBuffer buffer,
236069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                           final ParserCursor cursor) {
237069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
238069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (buffer == null) {
239069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Char array buffer may not be null");
240069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
241069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (cursor == null) {
242069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Parser cursor may not be null");
243069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
244069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
245069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int pos = cursor.getPos();
246069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int indexTo = cursor.getUpperBound();
247069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
248069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (pos < indexTo) {
249069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char ch = buffer.charAt(pos);
250069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (HTTP.isWhitespace(ch)) {
251069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                pos++;
252069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
253069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
254069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
255069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
256069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        cursor.updatePos(pos);
257069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (cursor.atEnd()) {
258069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return new NameValuePair[] {};
259069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
260069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
261069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        List params = new ArrayList();
262069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (!cursor.atEnd()) {
263069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            NameValuePair param = parseNameValuePair(buffer, cursor);
264069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            params.add(param);
265069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char ch = buffer.charAt(cursor.getPos() - 1);
266069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (ch == ELEM_DELIMITER) {
267069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
268069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
269069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
270069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
271069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return (NameValuePair[])
272069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            params.toArray(new NameValuePair[params.size()]);
273069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
274069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
275069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
276069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Parses a name-value-pair with the given parser.
277069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
278069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value     the NVP to parse
279069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param parser    the parser to use, or <code>null</code> for default
280069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
281069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  the parsed name-value pair
282069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
283069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public final static
284069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project       NameValuePair parseNameValuePair(final String value,
285069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                        HeaderValueParser parser)
286069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        throws ParseException {
287069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
288069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (value == null) {
289069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException
290069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                ("Value to parse may not be null");
291069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
292069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
293069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (parser == null)
294069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            parser = BasicHeaderValueParser.DEFAULT;
295069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
296069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        CharArrayBuffer buffer = new CharArrayBuffer(value.length());
297069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        buffer.append(value);
298069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        ParserCursor cursor = new ParserCursor(0, value.length());
299069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return parser.parseNameValuePair(buffer, cursor);
300069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
301069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
302069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
303069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    // non-javadoc, see interface HeaderValueParser
304069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public NameValuePair parseNameValuePair(final CharArrayBuffer buffer,
305069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                            final ParserCursor cursor) {
306069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return parseNameValuePair(buffer, cursor, ALL_DELIMITERS);
307069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
308069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
309069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    private static boolean isOneOf(final char ch, final char[] chs) {
310069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (chs != null) {
311069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            for (int i = 0; i < chs.length; i++) {
312069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                if (ch == chs[i]) {
313069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                    return true;
314069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                }
315069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
316069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
317069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return false;
318069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
319069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
320069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    public NameValuePair parseNameValuePair(final CharArrayBuffer buffer,
321069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                            final ParserCursor cursor,
322069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                                            final char[] delimiters) {
323069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
324069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (buffer == null) {
325069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Char array buffer may not be null");
326069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
327069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (cursor == null) {
328069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            throw new IllegalArgumentException("Parser cursor may not be null");
329069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
330069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
331069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean terminated = false;
332069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
333069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int pos = cursor.getPos();
334069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int indexFrom = cursor.getPos();
335069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int indexTo = cursor.getUpperBound();
336069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
337069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Find name
338069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String name = null;
339069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (pos < indexTo) {
340069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char ch = buffer.charAt(pos);
341069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (ch == '=') {
342069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
343069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
344069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (isOneOf(ch, delimiters)) {
345069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                terminated = true;
346069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
347069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
348069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            pos++;
349069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
350069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
351069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (pos == indexTo) {
352069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            terminated = true;
353069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            name = buffer.substringTrimmed(indexFrom, indexTo);
354069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        } else {
355069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            name = buffer.substringTrimmed(indexFrom, pos);
356069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            pos++;
357069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
358069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
359069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (terminated) {
360069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            cursor.updatePos(pos);
361069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            return createNameValuePair(name, null);
362069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
363069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
364069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Find value
365069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        String value = null;
366069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int i1 = pos;
367069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
368069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean qouted = false;
369069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        boolean escaped = false;
370069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (pos < indexTo) {
371069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            char ch = buffer.charAt(pos);
372069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (ch == '"' && !escaped) {
373069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                qouted = !qouted;
374069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
375069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (!qouted && !escaped && isOneOf(ch, delimiters)) {
376069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                terminated = true;
377069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                break;
378069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
379069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            if (escaped) {
380069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                escaped = false;
381069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            } else {
382069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project                escaped = qouted && ch == '\\';
383069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            }
384069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            pos++;
385069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
386069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
387069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        int i2 = pos;
388069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Trim leading white spaces
389069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while (i1 < i2 && (HTTP.isWhitespace(buffer.charAt(i1)))) {
390069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            i1++;
391069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
392069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Trim trailing white spaces
393069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        while ((i2 > i1) && (HTTP.isWhitespace(buffer.charAt(i2 - 1)))) {
394069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            i2--;
395069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
396069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        // Strip away quotes if necessary
397069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (((i2 - i1) >= 2)
398069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            && (buffer.charAt(i1) == '"')
399069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            && (buffer.charAt(i2 - 1) == '"')) {
400069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            i1++;
401069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            i2--;
402069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
403069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        value = buffer.substring(i1, i2);
404069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        if (terminated) {
405069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project            pos++;
406069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        }
407069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        cursor.updatePos(pos);
408069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return createNameValuePair(name, value);
409069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
410069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
411069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    /**
412069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Creates a name-value pair.
413069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * Called from {@link #parseNameValuePair}.
414069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
415069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param name      the name
416069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @param value     the value, or <code>null</code>
417069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     *
418069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     * @return  a name-value pair representing the arguments
419069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project     */
420069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    protected NameValuePair createNameValuePair(final String name, final String value) {
421069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project        return new BasicNameValuePair(name, value);
422069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project    }
423069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
424069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project}
425069490a5ca2fd1988d29daf45d892f47ad665115The Android Open Source Project
426