KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > Ostermiller > util > CGIParser


1 /*
2  * Parse CGI query data.
3  * Copyright (C) 2001-2004 Stephen Ostermiller
4  * http://ostermiller.org/contact.pl?regarding=Java+Utilities
5  *
6  * This program is free software; you can redistribute it and/or modify
7  * it under the terms of the GNU General Public License as published by
8  * the Free Software Foundation; either version 2 of the License, or
9  * (at your option) any later version.
10  *
11  * This program is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14  * GNU General Public License for more details.
15  *
16  * See COPYING.TXT for details.
17  */

18
19 package com.Ostermiller.util;
20 import java.util.*;
21 import java.io.*;
22 import java.net.URLEncoder JavaDoc;
23 import java.net.URLDecoder JavaDoc;
24
25 /**
26  * Parses query string data from a CGI request into name value pairs.
27  * <p>
28  * More information about this class is available from <a target="_top" HREF=
29  * "http://ostermiller.org/utils/CGIParser.html">ostermiller.org</a>.
30  *
31  * @author Stephen Ostermiller http://ostermiller.org/contact.pl?regarding=Java+Utilities
32  * @since ostermillerutils 1.00.00
33  */

34 public class CGIParser {
35
36     /**
37      * Hash of names to Array Lists of values.
38      */

39     private HashMap<String JavaDoc,ArrayList<String JavaDoc>> nameValuePairHash = new HashMap<String JavaDoc,ArrayList<String JavaDoc>>();
40
41     /**
42      * Array list of NameValuePair objects.
43      */

44     private LinkedList<NameValuePair> nameValuePairList = new LinkedList<NameValuePair>();
45
46     /**
47      * Extract the name, value pairs from the given input stream and
48      * make them available for retrieval.
49      * <p>
50      * The stream is read until the stream contains no more bytes.
51      * <p>
52      * Byte to character conversion on the stream is done according the platforms
53      * default character encoding.
54      *
55      * @param in Stream containing CGI Encoded name value pairs.
56      * @deprecated This method does not decode URLEncoded values properly. Please use a method that specifies a character set.
57      *
58      * @since ostermillerutils 1.00.00
59      */

60     public CGIParser(InputStream in) throws IOException {
61         if (in == null) return;
62         CGILexer lex = new CGILexer(in);
63         parse(lex, "ISO-8859-1");
64     }
65
66     /**
67      * Extract the name, value pairs from the given input stream and
68      * make them available for retrieval.
69      * <p>
70      * The stream is read until the stream contains no more bytes.
71      * <p>
72      * The character set is used both when converting the byte stream to
73      * a character stream and when decoding URL decoded parameters.
74      *
75      * @param in Stream containing CGI Encoded name value pairs.
76      * @param charset Character encoding to use when converting bytes to characters
77      *
78      * @since ostermillerutils 1.03.00
79      */

80     public CGIParser(InputStream in, String JavaDoc charset) throws IOException, UnsupportedEncodingException {
81         if (in == null) return;
82         CGILexer lex = new CGILexer(new InputStreamReader(in, charset));
83         parse(lex, charset);
84     }
85
86     /**
87      * Extract the name, value pairs from the given reader and
88      * make them available for retrieval.
89      * <p>
90      * The reader is read until the stream contains no more characters.
91      *
92      * @param in Reader containing CGI Encoded name value pairs.
93      * @deprecated This method does not decode URLEncoded values properly. Please use a method that specifies a character set.
94      *
95      * @since ostermillerutils 1.00.00
96      */

97     public CGIParser(Reader in) throws IOException {
98         if (in == null) return;
99         CGILexer lex = new CGILexer(in);
100         parse(lex, "ISO-8859-1");
101     }
102
103     /**
104      * Extract the name, value pairs from the given reader and
105      * make them available for retrieval.
106      * <p>
107      * The reader is read until the stream contains no more characters.
108      *
109      * @param in Reader containing CGI Encoded name value pairs.
110      * @param charset Character encoding to use when converting bytes to characters
111      *
112      * @since ostermillerutils 1.03.00
113      */

114     public CGIParser(Reader in, String JavaDoc charset) throws IOException, UnsupportedEncodingException {
115         if (in == null) return;
116         CGILexer lex = new CGILexer(in);
117         parse(lex, charset);
118     }
119
120     /**
121      * Extract the name, value pairs from the given string and
122      * make them available for retrieval.
123      *
124      * @param s CGI Encoded name value pairs.
125      * @deprecated This method does not decode URLEncoded values properly. Please use a method that specifies a character set.
126      *
127      * @since ostermillerutils 1.00.00
128      */

129     public CGIParser(String JavaDoc s){
130         if (s == null) return;
131         try {
132             CGILexer lex = new CGILexer(new StringReader(s));
133             parse(lex, "ISO-8859-1");
134         } catch (IOException x){
135             // This shouldn't be able to happen from a string.
136
throw new RuntimeException JavaDoc(x);
137         }
138     }
139
140     /**
141      * Extract the name, value pairs from the given string and
142      * make them available for retrieval.
143      *
144      * @param s CGI Encoded name value pairs.
145      * @param charset Character encoding to use when converting bytes to characters
146      *
147      * @since ostermillerutils 1.03.00
148      */

149     public CGIParser(String JavaDoc s, String JavaDoc charset) throws IOException, UnsupportedEncodingException {
150         if (s == null) return;
151         try {
152             CGILexer lex = new CGILexer(new StringReader(s));
153             parse(lex, charset);
154         } catch (IOException x){
155             // This shouldn't be able to happen from a string.
156
throw new RuntimeException JavaDoc(x);
157         }
158     }
159
160     /**
161      * Retrieve the name value pairs from the lexer and hash
162      * them in the cgi hashtable.
163      *
164      * @param lex Lexer that will return the tokens.
165      *
166      * @since ostermillerutils 1.00.00
167      */

168     private void parse(CGILexer lex, String JavaDoc charset) throws IOException, UnsupportedEncodingException {
169         String JavaDoc nameValue, name, value;
170         while ((nameValue = lex.nextToken()) != null) {
171             int equalInd = nameValue.indexOf("=");
172             if (equalInd == -1){
173                 name = nameValue;
174                 value = "";
175             } else {
176                 name = nameValue.substring(0, equalInd);
177                 value = nameValue.substring(equalInd+1, nameValue.length());
178             }
179             try {
180                 name = URLDecoder.decode(name, charset);
181             } catch (IllegalArgumentException JavaDoc iax){
182                 // May be thrown for for illegal escape sequences such as %s
183
name = "";
184             }
185             try {
186                 value = URLDecoder.decode(value, charset);
187             } catch (IllegalArgumentException JavaDoc iax){
188                 // May be thrown for for illegal escape sequences such as %s
189
value = "";
190             }
191
192             // Hash
193
ArrayList<String JavaDoc> values = (ArrayList<String JavaDoc>)nameValuePairHash.get(name);
194             if (values == null){
195                 values = new ArrayList<String JavaDoc>();
196             }
197             values.add(value);
198             nameValuePairHash.put(name, values);
199
200             // List
201
nameValuePairList.add(new NameValuePair(name, value));
202         }
203     }
204
205     /**
206      * Returns an array of String objects containing all of the values the given request
207      * parameter has, or null if the parameter does not exist.
208      * <p>
209      * If the parameter has a single value, the array has a length of 1.
210      * @param name a String containing the name of the parameter whose value is requested
211      * @return an array of String objects containing the parameter's values
212      *
213      * @since ostermillerutils 1.00.00
214      */

215     public String JavaDoc[] getParameterValues(String JavaDoc name){
216         ArrayList<String JavaDoc> values = (ArrayList<String JavaDoc>)nameValuePairHash.get(name);
217         if (values == null){
218             return null;
219         }
220         String JavaDoc[] valArray = new String JavaDoc[values.size()];
221         return (String JavaDoc[])(values.toArray(valArray));
222     }
223
224     /**
225      * Set a name value pair as used in a URL.
226      * This method will replace any previously defined values with the single
227      * value specified. If the value is null, the name is removed.
228      *
229      * @param name a String specifying the name of the parameter.
230      * @param value a String specifying the value of the single parameter, or null to remove.
231      *
232      * @since ostermillerutils 1.02.15
233      */

234     public void setParameter(String JavaDoc name, String JavaDoc value){
235         Iterator listIterator = nameValuePairList.iterator();
236         while (listIterator.hasNext()){
237             NameValuePair nameValuePair = (NameValuePair)listIterator.next();
238             if (nameValuePair.getName().equals(name)){
239                 listIterator.remove();
240             }
241         }
242
243         if (value == null){
244             nameValuePairHash.remove(name);
245             return;
246         }
247         ArrayList<String JavaDoc> values = (ArrayList<String JavaDoc>)nameValuePairHash.get(name);
248         if (values == null){
249             values = new ArrayList<String JavaDoc>();
250         }
251         values.clear();
252         values.add(value);
253         nameValuePairHash.put(name, values);
254         nameValuePairList.add(new NameValuePair(name, value));
255     }
256
257     /**
258      * Set a name value pair as used in a URL.
259      * This method will replace any previously defined values with the single
260      * value specified. If values is null or empty, the name is removed.
261      *
262      * @param name a String specifying the name of the parameter.
263      * @param values a String array specifying the values for the parameter, or null to remove.
264      * @throws NullPointerException if any of the values is null.
265      *
266      * @since ostermillerutils 1.02.15
267      */

268     public void setParameter(String JavaDoc name, String JavaDoc[] values){
269         Iterator listIterator = nameValuePairList.iterator();
270         while (listIterator.hasNext()){
271             NameValuePair nameValuePair = (NameValuePair)listIterator.next();
272             if (nameValuePair.getName().equals(name)){
273                 listIterator.remove();
274             }
275         }
276
277         if (values == null || values.length == 0){
278             nameValuePairHash.remove(name);
279             return;
280         }
281         for (int i=0; i<values.length; i++){
282             if (values[i] == null) throw new NullPointerException JavaDoc();
283         }
284         ArrayList<String JavaDoc> valuesVec = (ArrayList<String JavaDoc>)nameValuePairHash.get(name);
285         if (valuesVec == null){
286             valuesVec = new ArrayList<String JavaDoc>();
287         }
288         valuesVec.clear();
289         for (int i=0; i<values.length; i++){
290             valuesVec.add(values[i]);
291             nameValuePairList.add(new NameValuePair(name, values[i]));
292         }
293         nameValuePairHash.put(name, valuesVec);
294     }
295
296     /**
297      * Set a name value pair as used in a URL.
298      * This method will add to any previously defined values the values
299      * specified. If value is null, this method has no effect.
300      *
301      * @param name a String specifying the name of the parameter.
302      * @param value a String specifying the value of the single parameter, or null to remove.
303      *
304      * @since ostermillerutils 1.02.15
305      */

306     public void addParameter(String JavaDoc name, String JavaDoc value){
307         if (value == null){
308             return;
309         }
310         ArrayList<String JavaDoc> values = (ArrayList<String JavaDoc>)nameValuePairHash.get(name);
311         if (values == null){
312             values = new ArrayList<String JavaDoc>();
313         }
314         values.add(value);
315         nameValuePairHash.put(name, values);
316         nameValuePairList.add(new NameValuePair(name, value));
317     }
318
319     /**
320      * Set a name value pair as used in a URL.
321      * This method will add to any previously defined values the values
322      * specified. If values is null, this method has no effect.
323      *
324      * @param name a String specifying the name of the parameter.
325      * @param values a String array specifying the values of the parameter, or null to remove.
326      * @throws NullPointerException if any of the values is null.
327      *
328      * @since ostermillerutils 1.02.15
329      */

330     public void addParameter(String JavaDoc name, String JavaDoc[] values){
331         if (values == null || values.length == 0){
332             return;
333         }
334         for (int i=0; i<values.length; i++){
335             if (values[i] == null) throw new NullPointerException JavaDoc();
336         }
337         ArrayList<String JavaDoc> valuesVec = (ArrayList<String JavaDoc>)nameValuePairHash.get(name);
338         if (valuesVec == null){
339             valuesVec = new ArrayList<String JavaDoc>();
340         }
341         for (int i=0; i<values.length; i++){
342             valuesVec.add(values[i]);
343             nameValuePairList.add(new NameValuePair(name, values[i]));
344         }
345         nameValuePairHash.put(name, valuesVec);
346     }
347
348     /**
349      * Returns the value of a request parameter as a String, or null if the parameter does
350      * not exist. Request parameters are extra information sent with the request.
351      * <p>
352      * You should only use this method when you are sure the parameter has only one value.
353      * If the parameter might have more than one value, use getParameterValues(java.lang.String).
354      * <P>
355      * If you use this method with a multivalued parameter, the value returned is equal to
356      * the first value in the array returned by getParameterValues.
357      *
358      * @param name a String specifying the name of the parameter
359      * @return a String representing the single value of the parameter
360      *
361      * @since ostermillerutils 1.00.00
362      */

363     public String JavaDoc getParameter(String JavaDoc name){
364         ArrayList<String JavaDoc> values = (ArrayList<String JavaDoc>)nameValuePairHash.get(name);
365         if (values == null){
366             return null;
367         }
368         return (String JavaDoc)(values.get(0));
369     }
370
371     /**
372      * Returns an Enumeration of String objects containing the names of the
373      * parameters contained in this request. If the request has no parameters,
374      * the method returns an empty Enumeration.
375      *
376      * @return an Enumeration of String objects, each String containing the name
377      * of a request parameter; or an empty Enumeration if the request has
378      * no parameters
379      *
380      * @since ostermillerutils 1.00.00
381      */

382     public Enumeration<String JavaDoc> getParameterNames(){
383         return (Enumeration<String JavaDoc>)new IteratorEnumeration<String JavaDoc>(nameValuePairHash.keySet().iterator());
384     }
385
386     /**
387      * Returns the names of the
388      * parameters contained in this request. If the request has no parameters,
389      * the method returns an empty String array. Each name will appear only
390      * once, even if it was contained in the request multiple times. The order
391      * of the names may not match the order from the request.
392      *
393      * @return An array of Strings, each of which is the name
394      * of a request parameter; or an array of length zero if the request has
395      * no parameters
396      *
397      * @since ostermillerutils 1.03.00
398      */

399     public String JavaDoc[] getParameterNameList(){
400         return (String JavaDoc[])nameValuePairHash.keySet().toArray(new String JavaDoc[0]);
401     }
402
403     /**
404      * Get the all the parameters in the order in which they were added.
405      *
406      * @return array of all name value pairs.
407      */

408     public NameValuePair[] getParameters(){
409         return (NameValuePair[])nameValuePairList.toArray(new NameValuePair[0]);
410     }
411
412     /**
413      * Returns the name value pairs properly escaped and written in URL format.
414      *
415      * @param enc Character encoding to use when escaping characters.
416      * @return URLEncoded name value pairs.
417      * @throws UnsupportedEncodingException If the named encoding is not supported.
418      *
419      * @since ostermillerutils 1.00.00
420      */

421     public String JavaDoc toString(String JavaDoc enc) throws UnsupportedEncodingException {
422         StringBuffer JavaDoc sb = new StringBuffer JavaDoc();
423         boolean bFirst = true;
424         Iterator listIterator = nameValuePairList.iterator();
425         while (listIterator.hasNext()){
426             NameValuePair nameValuePair = (NameValuePair)listIterator.next();
427             if (!bFirst) sb.append('&');
428             bFirst = false;
429             sb.append(nameValuePair.toString(enc));
430         }
431         return sb.toString();
432     }
433
434     /**
435      * Returns the name value pairs properly escaped and written in URL format
436      * with UTF-8 URL encoding.
437      *
438      * @return URLEncoded name value pairs.
439      *
440      * @since ostermillerutils 1.03.00
441      */

442     public String JavaDoc toString() {
443         try {
444             return toString("UTF-8");
445         } catch (UnsupportedEncodingException uex){
446             // UTF-8 should be supported
447
throw new RuntimeException JavaDoc(uex);
448         }
449     }
450 }
451
Popular Tags