• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*
2  * $HeadURL: http://svn.apache.org/repos/asf/httpcomponents/httpcore/trunk/module-main/src/main/java/org/apache/http/message/BasicHeaderValueParser.java $
3  * $Revision: 595670 $
4  * $Date: 2007-11-16 06:15:01 -0800 (Fri, 16 Nov 2007) $
5  *
6  * ====================================================================
7  * Licensed to the Apache Software Foundation (ASF) under one
8  * or more contributor license agreements.  See the NOTICE file
9  * distributed with this work for additional information
10  * regarding copyright ownership.  The ASF licenses this file
11  * to you under the Apache License, Version 2.0 (the
12  * "License"); you may not use this file except in compliance
13  * with the License.  You may obtain a copy of the License at
14  *
15  *   http://www.apache.org/licenses/LICENSE-2.0
16  *
17  * Unless required by applicable law or agreed to in writing,
18  * software distributed under the License is distributed on an
19  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
20  * KIND, either express or implied.  See the License for the
21  * specific language governing permissions and limitations
22  * under the License.
23  * ====================================================================
24  *
25  * This software consists of voluntary contributions made by many
26  * individuals on behalf of the Apache Software Foundation.  For more
27  * information on the Apache Software Foundation, please see
28  * <http://www.apache.org/>.
29  *
30  */
31 
32 package org.apache.http.message;
33 
34 
35 import java.util.List;
36 import java.util.ArrayList;
37 
38 import org.apache.http.HeaderElement;
39 import org.apache.http.NameValuePair;
40 import org.apache.http.ParseException;
41 import org.apache.http.protocol.HTTP;
42 import org.apache.http.util.CharArrayBuffer;
43 
44 
45 
46 /**
47  * Basic implementation for parsing header values into elements.
48  * Instances of this class are stateless and thread-safe.
49  * Derived classes are expected to maintain these properties.
50  *
51  * @author <a href="mailto:bcholmes@interlog.com">B.C. Holmes</a>
52  * @author <a href="mailto:jericho@thinkfree.com">Park, Sung-Gu</a>
53  * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
54  * @author <a href="mailto:oleg at ural.com">Oleg Kalnichevski</a>
55  * @author and others
56  *
57  *
58  * <!-- empty lines above to avoid 'svn diff' context problems -->
59  * @version $Revision: 595670 $
60  *
61  * @since 4.0
62  *
63  * @deprecated Please use {@link java.net.URL#openConnection} instead.
64  *     Please visit <a href="http://android-developers.blogspot.com/2011/09/androids-http-clients.html">this webpage</a>
65  *     for further details.
66  */
67 @Deprecated
68 public class BasicHeaderValueParser implements HeaderValueParser {
69 
70     /**
71      * A default instance of this class, for use as default or fallback.
72      * Note that {@link BasicHeaderValueParser} is not a singleton, there
73      * can be many instances of the class itself and of derived classes.
74      * The instance here provides non-customized, default behavior.
75      */
76     public final static
77         BasicHeaderValueParser DEFAULT = new BasicHeaderValueParser();
78 
79     private final static char PARAM_DELIMITER                = ';';
80     private final static char ELEM_DELIMITER                 = ',';
81     private final static char[] ALL_DELIMITERS               = new char[] {
82                                                                 PARAM_DELIMITER,
83                                                                 ELEM_DELIMITER
84                                                                 };
85 
86     // public default constructor
87 
88 
89     /**
90      * Parses elements with the given parser.
91      *
92      * @param value     the header value to parse
93      * @param parser    the parser to use, or <code>null</code> for default
94      *
95      * @return  array holding the header elements, never <code>null</code>
96      */
97     public final static
parseElements(final String value, HeaderValueParser parser)98         HeaderElement[] parseElements(final String value,
99                                       HeaderValueParser parser)
100         throws ParseException {
101 
102         if (value == null) {
103             throw new IllegalArgumentException
104                 ("Value to parse may not be null");
105         }
106 
107         if (parser == null)
108             parser = BasicHeaderValueParser.DEFAULT;
109 
110         CharArrayBuffer buffer = new CharArrayBuffer(value.length());
111         buffer.append(value);
112         ParserCursor cursor = new ParserCursor(0, value.length());
113         return parser.parseElements(buffer, cursor);
114     }
115 
116 
117     // non-javadoc, see interface HeaderValueParser
parseElements(final CharArrayBuffer buffer, final ParserCursor cursor)118     public HeaderElement[] parseElements(final CharArrayBuffer buffer,
119                                          final ParserCursor cursor) {
120 
121         if (buffer == null) {
122             throw new IllegalArgumentException("Char array buffer may not be null");
123         }
124         if (cursor == null) {
125             throw new IllegalArgumentException("Parser cursor may not be null");
126         }
127 
128         List elements = new ArrayList();
129         while (!cursor.atEnd()) {
130             HeaderElement element = parseHeaderElement(buffer, cursor);
131             if (!(element.getName().length() == 0 && element.getValue() == null)) {
132                 elements.add(element);
133             }
134         }
135         return (HeaderElement[])
136             elements.toArray(new HeaderElement[elements.size()]);
137     }
138 
139 
140     /**
141      * Parses an element with the given parser.
142      *
143      * @param value     the header element to parse
144      * @param parser    the parser to use, or <code>null</code> for default
145      *
146      * @return  the parsed header element
147      */
148     public final static
parseHeaderElement(final String value, HeaderValueParser parser)149         HeaderElement parseHeaderElement(final String value,
150                                          HeaderValueParser parser)
151         throws ParseException {
152 
153         if (value == null) {
154             throw new IllegalArgumentException
155                 ("Value to parse may not be null");
156         }
157 
158         if (parser == null)
159             parser = BasicHeaderValueParser.DEFAULT;
160 
161         CharArrayBuffer buffer = new CharArrayBuffer(value.length());
162         buffer.append(value);
163         ParserCursor cursor = new ParserCursor(0, value.length());
164         return parser.parseHeaderElement(buffer, cursor);
165     }
166 
167 
168     // non-javadoc, see interface HeaderValueParser
parseHeaderElement(final CharArrayBuffer buffer, final ParserCursor cursor)169     public HeaderElement parseHeaderElement(final CharArrayBuffer buffer,
170                                             final ParserCursor cursor) {
171 
172         if (buffer == null) {
173             throw new IllegalArgumentException("Char array buffer may not be null");
174         }
175         if (cursor == null) {
176             throw new IllegalArgumentException("Parser cursor may not be null");
177         }
178 
179         NameValuePair nvp = parseNameValuePair(buffer, cursor);
180         NameValuePair[] params = null;
181         if (!cursor.atEnd()) {
182             char ch = buffer.charAt(cursor.getPos() - 1);
183             if (ch != ELEM_DELIMITER) {
184                 params = parseParameters(buffer, cursor);
185             }
186         }
187         return createHeaderElement(nvp.getName(), nvp.getValue(), params);
188     }
189 
190 
191     /**
192      * Creates a header element.
193      * Called from {@link #parseHeaderElement}.
194      *
195      * @return  a header element representing the argument
196      */
createHeaderElement( final String name, final String value, final NameValuePair[] params)197     protected HeaderElement createHeaderElement(
198             final String name,
199             final String value,
200             final NameValuePair[] params) {
201         return new BasicHeaderElement(name, value, params);
202     }
203 
204 
205     /**
206      * Parses parameters with the given parser.
207      *
208      * @param value     the parameter list to parse
209      * @param parser    the parser to use, or <code>null</code> for default
210      *
211      * @return  array holding the parameters, never <code>null</code>
212      */
213     public final static
parseParameters(final String value, HeaderValueParser parser)214         NameValuePair[] parseParameters(final String value,
215                                         HeaderValueParser parser)
216         throws ParseException {
217 
218         if (value == null) {
219             throw new IllegalArgumentException
220                 ("Value to parse may not be null");
221         }
222 
223         if (parser == null)
224             parser = BasicHeaderValueParser.DEFAULT;
225 
226         CharArrayBuffer buffer = new CharArrayBuffer(value.length());
227         buffer.append(value);
228         ParserCursor cursor = new ParserCursor(0, value.length());
229         return parser.parseParameters(buffer, cursor);
230     }
231 
232 
233 
234     // non-javadoc, see interface HeaderValueParser
parseParameters(final CharArrayBuffer buffer, final ParserCursor cursor)235     public NameValuePair[] parseParameters(final CharArrayBuffer buffer,
236                                            final ParserCursor cursor) {
237 
238         if (buffer == null) {
239             throw new IllegalArgumentException("Char array buffer may not be null");
240         }
241         if (cursor == null) {
242             throw new IllegalArgumentException("Parser cursor may not be null");
243         }
244 
245         int pos = cursor.getPos();
246         int indexTo = cursor.getUpperBound();
247 
248         while (pos < indexTo) {
249             char ch = buffer.charAt(pos);
250             if (HTTP.isWhitespace(ch)) {
251                 pos++;
252             } else {
253                 break;
254             }
255         }
256         cursor.updatePos(pos);
257         if (cursor.atEnd()) {
258             return new NameValuePair[] {};
259         }
260 
261         List params = new ArrayList();
262         while (!cursor.atEnd()) {
263             NameValuePair param = parseNameValuePair(buffer, cursor);
264             params.add(param);
265             char ch = buffer.charAt(cursor.getPos() - 1);
266             if (ch == ELEM_DELIMITER) {
267                 break;
268             }
269         }
270 
271         return (NameValuePair[])
272             params.toArray(new NameValuePair[params.size()]);
273     }
274 
275     /**
276      * Parses a name-value-pair with the given parser.
277      *
278      * @param value     the NVP to parse
279      * @param parser    the parser to use, or <code>null</code> for default
280      *
281      * @return  the parsed name-value pair
282      */
283     public final static
parseNameValuePair(final String value, HeaderValueParser parser)284        NameValuePair parseNameValuePair(final String value,
285                                         HeaderValueParser parser)
286         throws ParseException {
287 
288         if (value == null) {
289             throw new IllegalArgumentException
290                 ("Value to parse may not be null");
291         }
292 
293         if (parser == null)
294             parser = BasicHeaderValueParser.DEFAULT;
295 
296         CharArrayBuffer buffer = new CharArrayBuffer(value.length());
297         buffer.append(value);
298         ParserCursor cursor = new ParserCursor(0, value.length());
299         return parser.parseNameValuePair(buffer, cursor);
300     }
301 
302 
303     // non-javadoc, see interface HeaderValueParser
parseNameValuePair(final CharArrayBuffer buffer, final ParserCursor cursor)304     public NameValuePair parseNameValuePair(final CharArrayBuffer buffer,
305                                             final ParserCursor cursor) {
306         return parseNameValuePair(buffer, cursor, ALL_DELIMITERS);
307     }
308 
isOneOf(final char ch, final char[] chs)309     private static boolean isOneOf(final char ch, final char[] chs) {
310         if (chs != null) {
311             for (int i = 0; i < chs.length; i++) {
312                 if (ch == chs[i]) {
313                     return true;
314                 }
315             }
316         }
317         return false;
318     }
319 
parseNameValuePair(final CharArrayBuffer buffer, final ParserCursor cursor, final char[] delimiters)320     public NameValuePair parseNameValuePair(final CharArrayBuffer buffer,
321                                             final ParserCursor cursor,
322                                             final char[] delimiters) {
323 
324         if (buffer == null) {
325             throw new IllegalArgumentException("Char array buffer may not be null");
326         }
327         if (cursor == null) {
328             throw new IllegalArgumentException("Parser cursor may not be null");
329         }
330 
331         boolean terminated = false;
332 
333         int pos = cursor.getPos();
334         int indexFrom = cursor.getPos();
335         int indexTo = cursor.getUpperBound();
336 
337         // Find name
338         String name = null;
339         while (pos < indexTo) {
340             char ch = buffer.charAt(pos);
341             if (ch == '=') {
342                 break;
343             }
344             if (isOneOf(ch, delimiters)) {
345                 terminated = true;
346                 break;
347             }
348             pos++;
349         }
350 
351         if (pos == indexTo) {
352             terminated = true;
353             name = buffer.substringTrimmed(indexFrom, indexTo);
354         } else {
355             name = buffer.substringTrimmed(indexFrom, pos);
356             pos++;
357         }
358 
359         if (terminated) {
360             cursor.updatePos(pos);
361             return createNameValuePair(name, null);
362         }
363 
364         // Find value
365         String value = null;
366         int i1 = pos;
367 
368         boolean qouted = false;
369         boolean escaped = false;
370         while (pos < indexTo) {
371             char ch = buffer.charAt(pos);
372             if (ch == '"' && !escaped) {
373                 qouted = !qouted;
374             }
375             if (!qouted && !escaped && isOneOf(ch, delimiters)) {
376                 terminated = true;
377                 break;
378             }
379             if (escaped) {
380                 escaped = false;
381             } else {
382                 escaped = qouted && ch == '\\';
383             }
384             pos++;
385         }
386 
387         int i2 = pos;
388         // Trim leading white spaces
389         while (i1 < i2 && (HTTP.isWhitespace(buffer.charAt(i1)))) {
390             i1++;
391         }
392         // Trim trailing white spaces
393         while ((i2 > i1) && (HTTP.isWhitespace(buffer.charAt(i2 - 1)))) {
394             i2--;
395         }
396         // Strip away quotes if necessary
397         if (((i2 - i1) >= 2)
398             && (buffer.charAt(i1) == '"')
399             && (buffer.charAt(i2 - 1) == '"')) {
400             i1++;
401             i2--;
402         }
403         value = buffer.substring(i1, i2);
404         if (terminated) {
405             pos++;
406         }
407         cursor.updatePos(pos);
408         return createNameValuePair(name, value);
409     }
410 
411     /**
412      * Creates a name-value pair.
413      * Called from {@link #parseNameValuePair}.
414      *
415      * @param name      the name
416      * @param value     the value, or <code>null</code>
417      *
418      * @return  a name-value pair representing the arguments
419      */
createNameValuePair(final String name, final String value)420     protected NameValuePair createNameValuePair(final String name, final String value) {
421         return new BasicNameValuePair(name, value);
422     }
423 
424 }
425 
426