View Javadoc

    1   /*
    2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/util/ParameterParser.java,v 1.5 2004/05/13 04:01:22 mbecke Exp $
    3    * $Revision: 480424 $
    4    * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
    5    *
    6    * ====================================================================
    7    *
    8    *  Licensed to the Apache Software Foundation (ASF) under one or more
    9    *  contributor license agreements.  See the NOTICE file distributed with
    10   *  this work for additional information regarding copyright ownership.
    11   *  The ASF licenses this file to You under the Apache License, Version 2.0
    12   *  (the "License"); you may not use this file except in compliance with
    13   *  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, software
    18   *  distributed under the License is distributed on an "AS IS" BASIS,
    19   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    20   *  See the License for the specific language governing permissions and
    21   *  limitations under the License.
    22   * ====================================================================
    23   *
    24   * This software consists of voluntary contributions made by many
    25   * individuals on behalf of the Apache Software Foundation.  For more
    26   * information on the Apache Software Foundation, please see
    27   * <http://www.apache.org/>.
    28   *
    29   */
    30
    31  package org.apache.commons.httpclient.util;
    32  import java.util.ArrayList;
    33  import java.util.List;
    34
    35  import org.apache.commons.httpclient.NameValuePair;
    36
    37  /**
    38   * A simple parser intended to parse sequences of name/value pairs.
    39   * Parameter values are exptected to be enclosed in quotes if they
    40   * contain unsafe characters, such as '=' characters or separators.
    41   * Parameter values are optional and can be omitted.
    42   *
    43   * <p>
    44   *  <code>param1 = value; param2 = "anything goes; really"; param3</code>
    45   * </p>
    46   *
    47   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
    48   *
    49   * @since 3.0
    50   */
    51  public class ParameterParser {
    52
    53      /** String to be parsed */
    54      private char[] chars = null;
    55
    56      /** Current position in the string */
    57      private int pos = 0;
    58
    59      /** Maximum position in the string */
    60      private int len = 0;
    61
    62      /** Start of a token */
    63      private int i1 = 0;
    64
    65      /** End of a token */
    66      private int i2 = 0;
    67
    68      /** Default ParameterParser constructor */
    69      public ParameterParser() {
    70          super();
    71      }
    72
    73
    74      /** Are there any characters left to parse? */
    75      private boolean hasChar() {
    76          return this.pos < this.len;
    77      }
    78
    79
    80      /** A helper method to process the parsed token. */
    81      private String getToken(boolean quoted) {
    82          // Trim leading white spaces
    83          while ((i1 < i2) && (Character.isWhitespace(chars[i1]))) {
    84              i1++;
    85          }
    86          // Trim trailing white spaces
    87          while ((i2 > i1) && (Character.isWhitespace(chars[i2 - 1]))) {
    88              i2--;
    89          }
    90          // Strip away quotes if necessary
    91          if (quoted) {
    92              if (((i2 - i1) >= 2)
    93                  && (chars[i1] == '"')
    94                  && (chars[i2 - 1] == '"')) {
    95                  i1++;
    96                  i2--;
    97              }
    98          }
    99          String result = null;
    100         if (i2 >= i1) {
    101             result = new String(chars, i1, i2 - i1);
    102         }
    103         return result;
    104     }
    105
    106
    107     /** Is given character present in the array of characters? */
    108     private boolean isOneOf(char ch, char[] charray) {
    109         boolean result = false;
    110         for (int i = 0; i < charray.length; i++) {
    111             if (ch == charray[i]) {
    112                 result = true;
    113                 break;
    114             }
    115         }
    116         return result;
    117     }
    118
    119
    120     /** Parse out a token until any of the given terminators
    121      * is encountered. */
    122     private String parseToken(final char[] terminators) {
    123         char ch;
    124         i1 = pos;
    125         i2 = pos;
    126         while (hasChar()) {
    127             ch = chars[pos];
    128             if (isOneOf(ch, terminators)) {
    129                 break;
    130             }
    131             i2++;
    132             pos++;
    133         }
    134         return getToken(false);
    135     }
    136
    137
    138     /** Parse out a token until any of the given terminators
    139      * is encountered. Special characters in quoted tokens
    140      * are escaped. */
    141     private String parseQuotedToken(final char[] terminators) {
    142         char ch;
    143         i1 = pos;
    144         i2 = pos;
    145         boolean quoted = false;
    146         boolean charEscaped = false;
    147         while (hasChar()) {
    148             ch = chars[pos];
    149             if (!quoted && isOneOf(ch, terminators)) {
    150                 break;
    151             }
    152             if (!charEscaped && ch == '"') {
    153                 quoted = !quoted;
    154             }
    155             charEscaped = (!charEscaped && ch == '\\');
    156             i2++;
    157             pos++;
    158
    159         }
    160         return getToken(true);
    161     }
    162
    163     /**
    164      * Extracts a list of {@link NameValuePair}s from the given string.
    165      *
    166      * @param str the string that contains a sequence of name/value pairs
    167      * @return a list of {@link NameValuePair}s
    168      *
    169      */
    170     public List parse(final String str, char separator) {
    171
    172         if (str == null) {
    173             return new ArrayList();
    174         }
    175         return parse(str.toCharArray(), separator);
    176     }
    177
    178     /**
    179      * Extracts a list of {@link NameValuePair}s from the given array of
    180      * characters.
    181      *
    182      * @param chars the array of characters that contains a sequence of
    183      * name/value pairs
    184      *
    185      * @return a list of {@link NameValuePair}s
    186      */
    187     public List parse(final char[] chars, char separator) {
    188
    189         if (chars == null) {
    190             return new ArrayList();
    191         }
    192         return parse(chars, 0, chars.length, separator);
    193     }
    194
    195
    196     /**
    197      * Extracts a list of {@link NameValuePair}s from the given array of
    198      * characters.
    199      *
    200      * @param chars the array of characters that contains a sequence of
    201      * name/value pairs
    202      * @param offset - the initial offset.
    203      * @param length - the length.
    204      *
    205      * @return a list of {@link NameValuePair}s
    206      */
    207     public List parse(final char[] chars, int offset, int length, char separator) {
    208
    209         if (chars == null) {
    210             return new ArrayList();
    211         }
    212         List params = new ArrayList();
    213         this.chars = chars;
    214         this.pos = offset;
    215         this.len = length;
    216
    217         String paramName = null;
    218         String paramValue = null;
    219         while (hasChar()) {
    220             paramName = parseToken(new char[] {'=', separator});
    221             paramValue = null;
    222             if (hasChar() && (chars[pos] == '=')) {
    223                 pos++; // skip '='
    224                 paramValue = parseQuotedToken(new char[] {separator});
    225             }
    226             if (hasChar() && (chars[pos] == separator)) {
    227                 pos++; // skip separator
    228             }
    229             if (paramName != null && !(paramName.equals("") && paramValue == null)) {
    230                 params.add(new NameValuePair(paramName, paramValue));
    231             }
    232         }
    233         return params;
    234     }
    235 }