View Javadoc

1   /* 
2    * Copyright 2002-2004 The Apache Software Foundation
3    * Licensed  under the  Apache License,  Version 2.0  (the "License");
4    * you may not use  this file  except in  compliance with the License.
5    * You may obtain a copy of the License at 
6    * 
7    *   http://www.apache.org/licenses/LICENSE-2.0
8    * 
9    * Unless required by applicable law or agreed to in writing, software
10   * distributed  under the  License is distributed on an "AS IS" BASIS,
11   * WITHOUT  WARRANTIES OR CONDITIONS  OF ANY KIND, either  express  or
12   * implied.
13   * 
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  package org.apache.struts.flow.core.source;
18  
19  import java.io.Serializable;
20  import java.util.ArrayList;
21  import java.util.HashMap;
22  import java.util.Iterator;
23  import java.util.Map;
24  import java.util.StringTokenizer;
25  
26  /***
27   * This class holds parameters for a <code>Source</code> object.
28   * It differs from the usual Parameters object because it can hold
29   * more than one value for a parameter, as is the case for HTTP
30   * request parameters.
31   * <p>
32   * Only particular kinds of <code>Source</code> implementations, such as
33   * {@link org.apache.struts.flow.core.source.impl.URLSource} support this kind of
34   * parameters, passed as the {@link SourceResolver#URI_PARAMETERS} entry
35   * in the <code>parameters</code> argument of
36   * {@link SourceResolver#resolveURI(String, String, Map)}.
37   *
38   * @author <a href="mailto:dev@avalon.apache.org">Avalon Development Team</a>
39   * @version $Id: SourceParameters.java,v 1.5 2004/03/12 13:02:55 cziegeler Exp $
40   */
41  public final class SourceParameters
42      implements Serializable, Cloneable
43  {
44      /*** The parameter names are the keys and the value is a List object */
45      private Map names = new HashMap( 5 );
46  
47      /***
48       * Decode the string
49       */
50      private String parseName( String s )
51      {
52          StringBuffer sb = new StringBuffer();
53          for( int i = 0; i < s.length(); i++ )
54          {
55              char c = s.charAt( i );
56              switch( c )
57              {
58                  case '+':
59                      sb.append( ' ' );
60                      break;
61                  case '%':
62                      try
63                      {
64                          sb.append( (char)Integer.parseInt( s.substring( i + 1, i + 3 ),
65                                                             16 ) );
66                          i += 2;
67                      }
68                      catch( NumberFormatException e )
69                      {
70                          throw new IllegalArgumentException();
71                      }
72                      catch( StringIndexOutOfBoundsException e )
73                      {
74                          String rest = s.substring( i );
75                          sb.append( rest );
76                          if( rest.length() == 2 )
77                              i++;
78                      }
79  
80                      break;
81                  default:
82                      sb.append( c );
83                      break;
84              }
85          }
86          return sb.toString();
87      }
88  
89      /***
90       * Standard Constructor creating an empty parameters object
91       */
92      public SourceParameters()
93      {
94      }
95  
96      /***
97       * Construct a new object from a queryString
98       */
99      public SourceParameters( String queryString )
100     {
101         if( queryString != null )
102         {
103             StringTokenizer st = new StringTokenizer( queryString, "&" );
104             while( st.hasMoreTokens() )
105             {
106                 String pair = st.nextToken();
107                 int pos = pair.indexOf( '=' );
108                 if( pos != -1 )
109                 {
110                     setParameter( parseName( pair.substring( 0, pos ) ),
111                                   parseName( pair.substring( pos + 1, pair.length() ) ) );
112                 }
113             }
114         }
115     }
116 
117     /***
118      * Add a parameter.
119      * The parameter is added with the given value.
120      * @param name   The name of the parameter.
121      * @param value  The value of the parameter.
122      */
123     public void setParameter( String name, String value )
124     {
125         ArrayList list;
126         if( names.containsKey( name ) == true )
127         {
128             list = (ArrayList)names.get( name );
129         }
130         else
131         {
132             list = new ArrayList( 3 );
133             names.put( name, list );
134         }
135         list.add( value );
136     }
137 
138     /***
139      * Get the value of a parameter.
140      * @param name   The name of the parameter.
141      * @return       The value of the first parameter with the name
142      *               or <CODE>null</CODE>
143      */
144     public String getParameter( String name )
145     {
146         if( names.containsKey( name ) == true )
147         {
148             return (String)( (ArrayList)names.get( name ) ).get( 0 );
149         }
150         return null;
151     }
152 
153     /***
154      * Get the value of a parameter.
155      * @param name   The name of the parameter.
156      * @param defaultValue The default value if the parameter does not exist.
157      * @return       The value of the first parameter with the name
158      *               or <CODE>defaultValue</CODE>
159      */
160     public String getParameter( String name, String defaultValue )
161     {
162         if( names.containsKey( name ) == true )
163         {
164             return (String)( (ArrayList)names.get( name ) ).get( 0 );
165         }
166         return defaultValue;
167     }
168 
169     /***
170      * Get the integer value of a parameter.
171      * @param name   The name of the parameter.
172      * @param defaultValue The default value if the parameter does not exist.
173      * @return       The value of the first parameter with the name
174      *               or <CODE>defaultValue</CODE>
175      */
176     public int getParameterAsInteger( String name, int defaultValue )
177     {
178         if( names.containsKey( name ) == true )
179         {
180             return new Integer( (String)( (ArrayList)names.get( name ) ).get( 0 ) ).intValue();
181         }
182         return defaultValue;
183     }
184 
185     /***
186      * Get the boolean value of a parameter.
187      * @param name   The name of the parameter.
188      * @param defaultValue The default value if the parameter does not exist.
189      * @return       The value of the first parameter with the name
190      *               or <CODE>defaultValue</CODE>
191      */
192     public boolean getParameterAsBoolean( String name, boolean defaultValue )
193     {
194         if( names.containsKey( name ) == true )
195         {
196             return new Boolean( (String)( (ArrayList)names.get( name ) ).get( 0 ) ).booleanValue();
197         }
198         return defaultValue;
199     }
200 
201     /***
202      * Test if a value for this parameter exists.
203      * @param name   The name of the parameter.
204      * @return       <CODE>true</CODE> if a value exists, otherwise <CODE>false</CODE>
205      */
206     public boolean containsParameter( String name )
207     {
208         return names.containsKey( name );
209     }
210 
211     /***
212      * Get all values of a parameter.
213      * @param name   The name of the parameter.
214      * @return       Iterator for the (String) values or null if the parameter
215      *               is not defined.
216      */
217     public Iterator getParameterValues( String name )
218     {
219         if( names.containsKey( name ) == true )
220         {
221             ArrayList list = (ArrayList)names.get( name );
222             return list.iterator();
223         }
224         return null;
225     }
226 
227     /***
228      * Get all values of a parameter.
229      * @param name   The name of the parameter.
230      * @return       An Array for the (String) values or null.
231      */
232     public String[] getParameterValuesAsArray( String name )
233     {
234         if( names.containsKey( name ) == true )
235         {
236             ArrayList list = (ArrayList)names.get( name );
237             String[] values = new String[list.size()];
238             for(int i=0;i<values.length;i++)
239             {
240                 values[i] = (String)list.get(i);
241             }
242             return values;
243         }
244         return null;
245     }
246 
247     /***
248      * Get all parameter names.
249      * @return  Iterator for the (String) parameter names.
250      */
251     public Iterator getParameterNames()
252     {
253         return names.keySet().iterator();
254     }
255 
256     /***
257      * Build a query string.
258      * The query string can e.g. be used for http connections.
259      * @return A query string which contains for each parameter/value pair
260      *         a part, like "parameter=value" separated by "&".
261      *         If no parameter is defined <CODE>null</CODE> is returned.
262      */
263     public String getQueryString()
264     {
265         StringBuffer result = new StringBuffer();
266         Iterator iter = this.names.keySet().iterator();
267         Iterator listIterator;
268         String key;
269         String value;
270         boolean first = true;
271         while( iter.hasNext() == true )
272         {
273             key = (String)iter.next();
274             listIterator = ( (ArrayList)names.get( key ) ).iterator();
275             while( listIterator.hasNext() == true )
276             {
277                 if( first == false ) result.append( '&' );
278                 value = (String)listIterator.next();
279                 result.append( key ).append( '=' ).append( value );
280                 first = false;
281             }
282         }
283         return ( result.length() == 0 ? null : result.toString() );
284     }
285 
286     /***
287      * Build a query string and encode each parameter value.
288      * The query string can e.g. be used for http connections.
289      * @return A query string which contains for each parameter/value pair
290      *         a part, like "parameter=value" separated by "&".
291      *         If no parameter is defined <CODE>null</CODE> is returned.
292      */
293     public String getEncodedQueryString()
294     {
295         StringBuffer result = new StringBuffer();
296         Iterator iter = this.names.keySet().iterator();
297         Iterator listIterator;
298         String key;
299         String value;
300         boolean first = true;
301         while( iter.hasNext() == true )
302         {
303             key = (String)iter.next();
304             listIterator = ( (ArrayList)names.get( key ) ).iterator();
305             while( listIterator.hasNext() == true )
306             {
307                 if( first == false ) result.append( '&' );
308                 value = (String)listIterator.next();
309                 result.append( key ).append( '=' ).append( SourceUtil.encode( value ) );
310                 first = false;
311             }
312         }
313         return ( result.length() == 0 ? null : result.toString() );
314     }
315 
316     /***
317      * Add all parameters from the incoming parameters object.
318      */
319     public void add( SourceParameters parameters )
320     {
321         if( null != parameters )
322         {
323             Iterator names = parameters.getParameterNames();
324             Iterator values;
325             String name;
326             String value;
327             while( names.hasNext() == true )
328             {
329                 name = (String)names.next();
330                 values = parameters.getParameterValues( name );
331                 while( values.hasNext() == true )
332                 {
333                     value = (String)values.next();
334                     this.setParameter( name, value );
335                 }
336             }
337         }
338     }
339 
340     /***
341      * Overriding toString
342      */
343     public String toString()
344     {
345         StringBuffer buffer = new StringBuffer( "SourceParameters: {" );
346         Iterator names = this.getParameterNames();
347         String name;
348         boolean firstName = true;
349         Iterator values;
350         String value;
351         boolean firstValue;
352         while( names.hasNext() == true )
353         {
354             name = (String)names.next();
355             if( firstName == false )
356             {
357                 buffer.append( ", " );
358             }
359             else
360             {
361                 firstName = false;
362             }
363             buffer.append( name ).append( " = (" );
364             values = this.getParameterValues( name );
365             firstValue = true;
366             while( values.hasNext() == true )
367             {
368                 value = (String)values.next();
369                 if( firstValue == false )
370                 {
371                     buffer.append( ", " );
372                 }
373                 else
374                 {
375                     firstValue = false;
376                 }
377                 buffer.append( value );
378             }
379             buffer.append( ')' );
380         }
381         buffer.append( '}' );
382         return buffer.toString();
383     }
384 
385     /***
386      * Returns a copy of the parameters object.
387      */
388     public Object clone()
389     {
390         SourceParameters newObject = new SourceParameters();
391         Iterator names = this.getParameterNames();
392         Iterator values;
393         String name, value;
394         while( names.hasNext() )
395         {
396             name = (String)names.next();
397             values = this.getParameterValues( name );
398             while( values.hasNext() )
399             {
400                 value = (String)values.next();
401                 newObject.setParameter( name, value );
402             }
403         }
404         return newObject;
405     }
406 
407     /***
408      * Test if there are any parameters.
409      */
410     public boolean hasParameters()
411     {
412         return ( this.names.size() > 0 );
413     }
414 
415     /***
416      * Set the value of this parameter to the given value.
417      * Remove all other values for this parameter.
418      */
419     public void setSingleParameterValue( String name, String value )
420     {
421         this.removeParameter( name );
422         this.setParameter( name, value );
423     }
424 
425     /***
426      * Remove all values for this parameter
427      */
428     public void removeParameter( String name )
429     {
430         if( this.names.containsKey( name ) )
431         {
432             this.names.remove( name );
433         }
434     }
435     
436     /***
437      * Returns an immutable java.util.Map containing parameter names as keys and 
438      * parameter values as map values. The keys in the parameter map are of type String. 
439      * The values in the parameter map are of type String array.
440      */
441     public Map getParameterMap() 
442     {
443         final Map m = new HashMap(this.names);
444         Iterator entries = m.entrySet().iterator();
445         while (entries.hasNext()) 
446         {
447             Map.Entry entry = (Map.Entry)entries.next();
448             ArrayList list = (ArrayList)entry.getValue();
449             String[] values = new String[list.size()];
450             for(int i=0;i<values.length;i++)
451             {
452                 values[i] = (String)list.get(i);
453             }
454             entry.setValue(values);
455         }
456         return m;
457     }
458 }