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: 345737 $
4    * $Date: 2005-11-20 07:30:47 -0500 (Sun, 20 Nov 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         boolean charEscaped = false;
146         while (hasChar()) {
147             ch = chars[pos];
148             if (!quoted && isOneOf(ch, terminators)) {
149                 break;
150             }
151             if (!charEscaped && ch == '"') {
152                 quoted = !quoted;
153             }
154             charEscaped = (!charEscaped && ch == '//');
155             i2++;
156             pos++;
157 
158         }
159         return getToken(true);
160     }
161     
162     /*** 
163      * Extracts a list of {@link NameValuePair}s from the given string.
164      *
165      * @param str the string that contains a sequence of name/value pairs
166      * @return a list of {@link NameValuePair}s
167      * 
168      */
169     public List parse(final String str, char separator) {
170 
171         if (str == null) {
172             return new ArrayList();
173         }
174         return parse(str.toCharArray(), separator);
175     }
176 
177     /*** 
178      * Extracts a list of {@link NameValuePair}s from the given array of 
179      * characters.
180      *
181      * @param chars the array of characters that contains a sequence of 
182      * name/value pairs
183      * 
184      * @return a list of {@link NameValuePair}s
185      */
186     public List parse(final char[] chars, char separator) {
187 
188         if (chars == null) {
189             return new ArrayList();
190         }
191         return parse(chars, 0, chars.length, separator);
192     }
193 
194 
195     /*** 
196      * Extracts a list of {@link NameValuePair}s from the given array of 
197      * characters.
198      *
199      * @param chars the array of characters that contains a sequence of 
200      * name/value pairs
201      * @param offset - the initial offset.
202      * @param length - the length.
203      * 
204      * @return a list of {@link NameValuePair}s
205      */
206     public List parse(final char[] chars, int offset, int length, char separator) {
207 
208         if (chars == null) {
209             return new ArrayList();
210         }
211         List params = new ArrayList();
212         this.chars = chars;
213         this.pos = offset;
214         this.len = length;
215         
216         String paramName = null;
217         String paramValue = null;
218         while (hasChar()) {
219             paramName = parseToken(new char[] {'=', separator});
220             paramValue = null;
221             if (hasChar() && (chars[pos] == '=')) {
222                 pos++; // skip '='
223                 paramValue = parseQuotedToken(new char[] {separator});
224             }
225             if (hasChar() && (chars[pos] == separator)) {
226                 pos++; // skip separator
227             }
228             if (paramName != null && !(paramName.equals("") && paramValue == null)) {
229                 params.add(new NameValuePair(paramName, paramValue));
230             }
231         }        
232         return params;
233     }
234 }