Home | History | Annotate | Download | only in message
      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 (at) interlog.com">B.C. Holmes</a>
     52  * @author <a href="mailto:jericho (at) thinkfree.com">Park, Sung-Gu</a>
     53  * @author <a href="mailto:mbowler (at) 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
     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
    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
    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
    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      */
    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
    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
    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
    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
    304     public NameValuePair parseNameValuePair(final CharArrayBuffer buffer,
    305                                             final ParserCursor cursor) {
    306         return parseNameValuePair(buffer, cursor, ALL_DELIMITERS);
    307     }
    308 
    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 
    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      */
    420     protected NameValuePair createNameValuePair(final String name, final String value) {
    421         return new BasicNameValuePair(name, value);
    422     }
    423 
    424 }
    425 
    426