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