1 package org.apache.turbine.util.parser;
2
3 /* ====================================================================
4 * The Apache Software License, Version 1.1
5 *
6 * Copyright (c) 2001 The Apache Software Foundation. All rights
7 * reserved.
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
12 *
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 *
16 * 2. Redistributions in binary form must reproduce the above copyright
17 * notice, this list of conditions and the following disclaimer in
18 * the documentation and/or other materials provided with the
19 * distribution.
20 *
21 * 3. The end-user documentation included with the redistribution,
22 * if any, must include the following acknowledgment:
23 * "This product includes software developed by the
24 * Apache Software Foundation (http://www.apache.org/)."
25 * Alternately, this acknowledgment may appear in the software itself,
26 * if and wherever such third-party acknowledgments normally appear.
27 *
28 * 4. The names "Apache" and "Apache Software Foundation" and
29 * "Apache Turbine" must not be used to endorse or promote products
30 * derived from this software without prior written permission. For
31 * written permission, please contact apache@apache.org.
32 *
33 * 5. Products derived from this software may not be called "Apache",
34 * "Apache Turbine", nor may "Apache" appear in their name, without
35 * prior written permission of the Apache Software Foundation.
36 *
37 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48 * SUCH DAMAGE.
49 * ====================================================================
50 *
51 * This software consists of voluntary contributions made by many
52 * individuals on behalf of the Apache Software Foundation. For more
53 * information on the Apache Software Foundation, please see
54 * <http://www.apache.org/>.
55 */
56
57 import java.beans.IndexedPropertyDescriptor;
58 import java.beans.Introspector;
59 import java.beans.PropertyDescriptor;
60
61 import java.io.UnsupportedEncodingException;
62
63 import java.lang.reflect.Method;
64
65 import java.math.BigDecimal;
66
67 import java.text.DateFormat;
68 import java.text.ParseException;
69
70 import java.util.Calendar;
71 import java.util.Date;
72 import java.util.Enumeration;
73 import java.util.GregorianCalendar;
74 import java.util.Hashtable;
75
76 import org.apache.torque.om.NumberKey;
77 import org.apache.torque.om.StringKey;
78
79 import org.apache.turbine.services.resources.TurbineResources;
80
81 import org.apache.turbine.util.DateSelector;
82 import org.apache.turbine.util.StringUtils;
83 import org.apache.turbine.util.TimeSelector;
84 import org.apache.turbine.util.ValueParser;
85 import org.apache.turbine.util.pool.Recyclable;
86 import org.apache.turbine.util.pool.RecyclableSupport;
87
88 /***
89 * BaseValueParser is a base class for classes that need to parse
90 * name/value Parameters, for example GET/POST data or Cookies
91 * (DefaultParameterParser and DefaultCookieParser)
92 *
93 * <p>It can also be used standalone, for an example see DataStreamParser.
94 *
95 * <p>NOTE: The name= portion of a name=value pair may be converted
96 * to lowercase or uppercase when the object is initialized and when
97 * new data is added. This behaviour is determined by the url.case.folding
98 * property in TurbineResources.properties. Adding a name/value pair may
99 * overwrite existing name=value pairs if the names match:
100 *
101 * <pre>
102 * ValueParser vp = new BaseValueParser();
103 * vp.add("ERROR",1);
104 * vp.add("eRrOr",2);
105 * int result = vp.getInt("ERROR");
106 * </pre>
107 *
108 * In the above example, result is 2.
109 *
110 * @author <a href="mailto:ilkka.priha@simsoft.fi">Ilkka Priha</a>
111 * @author <a href="mailto:jon@clearink.com">Jon S. Stevens</a>
112 * @author <a href="mailto:sean@informage.net">Sean Legassick</a>
113 * @author <a href="mailto:jvanzyl@periapt.com">Jason van Zyl</a>
114 * @version $Id: BaseValueParser.java,v 1.5 2002/07/11 07:16:43 mpoeschl Exp $
115 */
116 public class BaseValueParser
117 extends RecyclableSupport
118 implements ValueParser,
119 Recyclable
120 {
121 /***
122 * Random access storage for parameter data.
123 */
124 protected Hashtable parameters = new Hashtable();
125 /***
126 * The character encoding to use when converting to byte arrays
127 */
128 private String characterEncoding = "US-ASCII";
129
130 /***
131 * A static version of the convert method, which
132 * trims the string data and applies the conversion specified in
133 * the property given by URL_CASE_FOLDING. It returns a new
134 * string so that it does not destroy the value data.
135 *
136 * @param value A String to be processed.
137 * @return A new String converted to lowercase and trimmed.
138 */
139 public static String convertAndTrim ( String value )
140 {
141 String tmp = value.trim();
142 String fold =
143 TurbineResources.getString(URL_CASE_FOLDING, "")
144 .toLowerCase();
145 if ((fold == null) ||
146 (fold.equals("")) ||
147 (fold.equals(URL_CASE_FOLDING_LOWER)))
148 return (tmp.toLowerCase());
149 else if (fold.equals(URL_CASE_FOLDING_UPPER))
150 return (tmp.toUpperCase());
151
152 return (tmp);
153 }
154
155 /***
156 * Default constructor
157 */
158 public BaseValueParser()
159 {
160 super();
161 }
162
163 /***
164 * Constructor that takes a character encoding
165 */
166 public BaseValueParser(String characterEncoding)
167 {
168 super();
169 recycle(characterEncoding);
170 }
171
172 /***
173 * Recycles the parser.
174 */
175 public void recycle()
176 {
177 recycle("US-ASCII");
178 }
179
180 /***
181 * Recycles the parser with a character encoding.
182 *
183 * @param characterEncoding the character encoding.
184 */
185 public void recycle(String characterEncoding)
186 {
187 setCharacterEncoding(characterEncoding);
188 if (!isDisposed())
189 super.recycle();
190 }
191
192 /***
193 * Disposes the parser.
194 */
195 public void dispose()
196 {
197 clear();
198 super.dispose();
199 }
200
201 /***
202 * Clear all name/value pairs out of this object.
203 */
204 public void clear()
205 {
206 parameters.clear();
207 }
208
209 /***
210 * Set the character encoding that will be used by this ValueParser.
211 */
212 public void setCharacterEncoding (String s)
213 {
214 characterEncoding = s;
215 }
216
217 /***
218 * Get the character encoding that will be used by this ValueParser.
219 */
220 public String getCharacterEncoding ()
221 {
222 return characterEncoding;
223 }
224
225 /***
226 * Add a name/value pair into this object.
227 *
228 * @param name A String with the name.
229 * @param value A double with the value.
230 */
231 public void add ( String name,
232 double value )
233 {
234 add ( name, Double.toString(value));
235 }
236
237 /***
238 * Add a name/value pair into this object.
239 *
240 * @param name A String with the name.
241 * @param value An int with the value.
242 */
243 public void add ( String name,
244 int value )
245 {
246 add ( name, Integer.toString(value));
247 }
248
249 /***
250 * Add a name/value pair into this object.
251 *
252 * @param name A String with the name.
253 * @param value An Integer with the value.
254 */
255 public void add ( String name,
256 Integer value )
257 {
258 add ( name, value.toString());
259 }
260
261 /***
262 * Add a name/value pair into this object.
263 *
264 * @param name A String with the name.
265 * @param value A long with the value.
266 */
267 public void add ( String name,
268 long value )
269 {
270 add ( name, Long.toString(value));
271 }
272
273 /***
274 * Add a name/value pair into this object.
275 *
276 * @param name A String with the name.
277 * @param value A long with the value.
278 */
279 public void add ( String name,
280 String value )
281 {
282 append ( name, value);
283 }
284
285 /***
286 * Add a String parameters. If there are any Strings already
287 * associated with the name, append to the array. This is used
288 * for handling parameters from mulitipart POST requests.
289 *
290 * @param name A String with the name.
291 * @param value A String with the value.
292 */
293 public void append( String name,
294 String value )
295 {
296 String[] items = this.getStrings(name);
297 if(items == null)
298 {
299 items = new String[1];
300 items[0] = value;
301 parameters.put( convert(name), items );
302 }
303 else
304 {
305 String[] newItems = new String[items.length+1];
306 System.arraycopy(items, 0, newItems, 0, items.length);
307 newItems[items.length] = value;
308 parameters.put( convert(name), newItems );
309 }
310 }
311
312 /***
313 * Removes the named parameter from the contained hashtable. Wraps to the
314 * contained <code>Hashtable.remove()</code>.
315 *
316 *
317 * @return The value that was mapped to the key (a <code>String[]</code>)
318 * or <code>null</code> if the key was not mapped.
319 */
320 public Object remove(String name)
321 {
322 return parameters.remove( convert(name) );
323 }
324
325 /***
326 * Trims the string data and applies the conversion specified in
327 * the property given by URL_CASE_FOLDING. It returns a new
328 * string so that it does not destroy the value data.
329 *
330 * @param value A String to be processed.
331 * @return A new String converted to lowercase and trimmed.
332 */
333 public String convert ( String value )
334 {
335 return convertAndTrim(value);
336 }
337
338 /***
339 * Determine whether a given key has been inserted. All keys are
340 * stored in lowercase strings, so override method to account for
341 * this.
342 *
343 * @param key An Object with the key to search for.
344 * @return True if the object is found.
345 */
346 public boolean containsKey( Object key )
347 {
348 return parameters.containsKey(convert((String)key));
349 }
350
351 /***
352 * Check for existence of key_day, key_month and key_year
353 * parameters (as returned by DateSelector generated HTML).
354 *
355 * @param key A String with the selector name.
356 * @return True if keys are found.
357 */
358 public boolean containsDateSelectorKeys(String key)
359 {
360 return (containsKey(key + DateSelector.DAY_SUFFIX) &&
361 containsKey(key + DateSelector.MONTH_SUFFIX) &&
362 containsKey(key + DateSelector.YEAR_SUFFIX));
363 }
364
365 /***
366 * Check for existence of key_hour, key_minute and key_second
367 * parameters (as returned by TimeSelector generated HTML).
368 *
369 * @param key A String with the selector name.
370 * @return True if keys are found.
371 */
372 public boolean containsTimeSelectorKeys(String key)
373 {
374 return (containsKey(key + TimeSelector.HOUR_SUFFIX) &&
375 containsKey(key + TimeSelector.MINUTE_SUFFIX) &&
376 containsKey(key + TimeSelector.SECOND_SUFFIX));
377 }
378
379
380 /*
381 * Get an enumerator for the parameter keys. Wraps to the
382 * contained <code>Hashtable.keys()</code>.
383 *
384 * @return An <code>enumerator</code> of the keys.
385 */
386 public Enumeration keys()
387 {
388 return parameters.keys();
389 }
390
391 /*
392 * Returns all the available parameter names.
393 *
394 * @return A object array with the keys.
395 */
396 public Object[] getKeys()
397 {
398 return parameters.keySet().toArray();
399 }
400
401 /***
402 * Return a boolean for the given name. If the name does not
403 * exist, return defaultValue.
404 *
405 * @param name A String with the name.
406 * @param defaultValue The default value.
407 * @return A boolean.
408 */
409 public boolean getBoolean(String name,
410 boolean defaultValue)
411 {
412 boolean value = defaultValue;
413 Object object = parameters.get(convert(name));
414 if (object != null)
415 {
416 String tmp = getString(name);
417 if ( tmp.equalsIgnoreCase ("1") ||
418 tmp.equalsIgnoreCase ("true") ||
419 tmp.equalsIgnoreCase ("on") )
420 {
421 value = true;
422 }
423 if ( tmp.equalsIgnoreCase ("0") ||
424 tmp.equalsIgnoreCase ("false") )
425 {
426 value = false;
427 }
428 }
429 return value;
430 }
431
432 /***
433 * Return a boolean for the given name. If the name does not
434 * exist, return false.
435 *
436 * @param name A String with the name.
437 * @return A boolean.
438 */
439 public boolean getBoolean(String name)
440 {
441 return getBoolean(name, false);
442 }
443
444 /***
445 * Return a Boolean for the given name. If the name does not
446 * exist, return defaultValue.
447 *
448 * @param name A String with the name.
449 * @param defaultValue The default value.
450 * @return A Boolean.
451 */
452 public Boolean getBool(String name,
453 boolean defaultValue)
454 {
455 return new Boolean(getBoolean(name, defaultValue));
456 }
457
458 /***
459 * Return a Boolean for the given name. If the name does not
460 * exist, return false.
461 *
462 * @param name A String with the name.
463 * @return A Boolean.
464 */
465 public Boolean getBool(String name)
466 {
467 return new Boolean(getBoolean(name, false));
468 }
469
470 /***
471 * Return a double for the given name. If the name does not
472 * exist, return defaultValue.
473 *
474 * @param name A String with the name.
475 * @param defaultValue The default value.
476 * @return A double.
477 */
478 public double getDouble(String name,
479 double defaultValue)
480 {
481 double value = defaultValue;
482 try
483 {
484 Object object = parameters.get(convert(name));
485 if (object != null)
486 value = Double.valueOf(((String[])object)[0]).doubleValue();
487 }
488 catch (NumberFormatException exception)
489 {
490 }
491 return value;
492 }
493
494 /***
495 * Return a double for the given name. If the name does not
496 * exist, return 0.0.
497 *
498 * @param name A String with the name.
499 * @return A double.
500 */
501 public double getDouble(String name)
502 {
503 return getDouble(name, 0.0);
504 }
505
506 /***
507 * Return a float for the given name. If the name does not
508 * exist, return defaultValue.
509 *
510 * @param name A String with the name.
511 * @param defaultValue The default value.
512 * @return A float.
513 */
514 public float getFloat(String name,
515 float defaultValue)
516 {
517 float value = defaultValue;
518 try
519 {
520 Object object = parameters.get(convert(name));
521 if (object != null)
522 value = Float.valueOf(((String[])object)[0]).floatValue();
523 }
524 catch (NumberFormatException exception)
525 {
526 }
527 return value;
528 }
529
530
531 /***
532 * Return a float for the given name. If the name does not
533 * exist, return 0.0.
534 *
535 * @param name A String with the name.
536 * @return A float.
537 */
538 public float getFloat(String name)
539 {
540 return getFloat(name, 0.0f);
541 }
542
543 /***
544 * Return a BigDecimal for the given name. If the name does not
545 * exist, return 0.0.
546 *
547 * @param name A String with the name.
548 * @param defaultValue The default value.
549 * @return A BigDecimal.
550 */
551 public BigDecimal getBigDecimal(String name,
552 BigDecimal defaultValue)
553 {
554 BigDecimal value = defaultValue;
555 try
556 {
557 Object object = parameters.get(convert(name));
558 if (object != null)
559 {
560 String temp = ((String[])object)[0];
561 if (temp.length() > 0)
562 {
563 value = new BigDecimal(((String[])object)[0]);
564 }
565 }
566 }
567 catch (NumberFormatException exception)
568 {
569 }
570 return value;
571 }
572
573 /***
574 * Return a BigDecimal for the given name. If the name does not
575 * exist, return 0.0.
576 *
577 * @param name A String with the name.
578 * @return A BigDecimal.
579 */
580 public BigDecimal getBigDecimal(String name)
581 {
582 return getBigDecimal(name, new BigDecimal(0.0));
583 }
584
585 /***
586 * Return an array of BigDecimals for the given name. If the name
587 * does not exist, return null.
588 *
589 * @param name A String with the name.
590 * @return A BigDecimal[].
591 */
592 public BigDecimal[] getBigDecimals(String name)
593 {
594 BigDecimal[] value = null;
595 Object object = getStrings(convert(name));
596 if (object != null)
597 {
598 String[] temp = (String[])object;
599 value = new BigDecimal[temp.length];
600 for (int i=0; i<temp.length; i++)
601 value[i] = new BigDecimal( temp[i] );
602 }
603 return value;
604 }
605
606 /***
607 * Return an int for the given name. If the name does not exist,
608 * return defaultValue.
609 *
610 * @param name A String with the name.
611 * @param defaultValue The default value.
612 * @return An int.
613 */
614 public int getInt(String name,
615 int defaultValue )
616 {
617 int value = defaultValue;
618 try
619 {
620 Object object = parameters.get(convert(name));
621 if (object != null)
622 value = Integer.valueOf(((String[])object)[0]).intValue();
623 }
624 catch (NumberFormatException exception)
625 {
626 }
627 return value;
628 }
629
630 /***
631 * Return an int for the given name. If the name does not exist,
632 * return 0.
633 *
634 * @param name A String with the name.
635 * @return An int.
636 */
637 public int getInt(String name)
638 {
639 return getInt(name, 0);
640 }
641
642 /***
643 * Return an Integer for the given name. If the name does not
644 * exist, return defaultValue.
645 *
646 * @param name A String with the name.
647 * @param defaultValue The default value.
648 * @return An Integer.
649 */
650 public Integer getInteger(String name,
651 int defaultValue)
652 {
653 return new Integer(getInt(name, defaultValue));
654 }
655
656 /***
657 * Return an Integer for the given name. If the name does not
658 * exist, return defaultValue. You cannot pass in a null here for
659 * the default value.
660 *
661 * @param name A String with the name.
662 * @param defaultValue The default value.
663 * @return An Integer.
664 */
665 public Integer getInteger(String name,
666 Integer def)
667 {
668 return new Integer(getInt(name, def.intValue()));
669 }
670
671 /***
672 * Return an Integer for the given name. If the name does not
673 * exist, return 0.
674 *
675 * @param name A String with the name.
676 * @return An Integer.
677 */
678 public Integer getInteger(String name)
679 {
680 return new Integer(getInt(name, 0));
681 }
682
683 /***
684 * Return an array of ints for the given name. If the name does
685 * not exist, return null.
686 *
687 * @param name A String with the name.
688 * @return An int[].
689 */
690 public int[] getInts(String name)
691 {
692 int[] value = null;
693 Object object = getStrings(convert(name));
694 if (object != null)
695 {
696 String[] temp = (String[])object;
697 value = new int[temp.length];
698 for (int i=0; i<temp.length; i++)
699 value[i] = Integer.parseInt( temp[i] );
700 }
701 return value;
702 }
703
704 /***
705 * Return an array of Integers for the given name. If the name
706 * does not exist, return null.
707 *
708 * @param name A String with the name.
709 * @return An Integer[].
710 */
711 public Integer[] getIntegers(String name)
712 {
713 Integer[] value = null;
714 Object object = getStrings(convert(name));
715 if (object != null)
716 {
717 String[] temp = (String[])object;
718 value = new Integer[temp.length];
719 for (int i=0; i<temp.length; i++)
720 value[i] = Integer.valueOf( temp[i] );
721 }
722 return value;
723 }
724
725 /***
726 * Return a long for the given name. If the name does not exist,
727 * return defaultValue.
728 *
729 * @param name A String with the name.
730 * @param defaultValue The default value.
731 * @return A long.
732 */
733 public long getLong(String name,
734 long defaultValue )
735 {
736 long value = defaultValue;
737 try
738 {
739 Object object = parameters.get(convert(name));
740 if (object != null)
741 value = Long.valueOf(((String[])object)[0]).longValue();
742 }
743 catch (NumberFormatException exception)
744 {
745 }
746 return value;
747 }
748
749 /***
750 * Return a long for the given name. If the name does not exist,
751 * return 0.
752 *
753 * @param name A String with the name.
754 * @return A long.
755 */
756 public long getLong(String name)
757 {
758 return getLong(name, 0);
759 }
760
761 /***
762 * Return an array of longs for the given name. If the name does
763 * not exist, return null.
764 *
765 * @param name A String with the name.
766 * @return A long[].
767 */
768 public long[] getLongs(String name)
769 {
770 long[] value = null;
771 Object object = getStrings(convert(name));
772 if (object != null)
773 {
774 String[] temp = (String[])object;
775 value = new long[temp.length];
776 for (int i=0; i<temp.length; i++)
777 value[i] = Long.parseLong( temp[i] );
778 }
779 return value;
780 }
781
782 /***
783 * Return an array of Longs for the given name. If the name does
784 * not exist, return null.
785 *
786 * @param name A String with the name.
787 * @return A Long[].
788 */
789 public Long[] getLongObjects(String name)
790 {
791 Long[] value = null;
792 Object object = getStrings(convert(name));
793 if (object != null)
794 {
795 String[] temp = (String[])object;
796 value = new Long[temp.length];
797 for (int i=0; i<temp.length; i++)
798 value[i] = Long.valueOf( temp[i] );
799 }
800 return value;
801 }
802
803 /***
804 * Return a byte for the given name. If the name does not exist,
805 * return defaultValue.
806 *
807 * @param name A String with the name.
808 * @param defaultValue The default value.
809 * @return A byte.
810 */
811 public byte getByte(String name,
812 byte defaultValue )
813 {
814 byte value = defaultValue;
815 try
816 {
817 Object object = parameters.get(convert(name));
818 if (object != null)
819 value = Byte.valueOf(((String[])object)[0]).byteValue();
820 }
821 catch (NumberFormatException exception)
822 {
823 }
824 return value;
825 }
826
827 /***
828 * Return a byte for the given name. If the name does not exist,
829 * return 0.
830 *
831 * @param name A String with the name.
832 * @return A byte.
833 */
834 public byte getByte(String name)
835 {
836 return getByte(name, (byte) 0);
837 }
838
839 /***
840 * Return an array of bytes for the given name. If the name does
841 * not exist, return null. The array is returned according to the
842 * HttpRequest's character encoding.
843 *
844 * @param name A String with the name.
845 * @return A byte[].
846 * @exception UnsupportedEncodingException.
847 */
848 public byte[] getBytes(String name)
849 throws UnsupportedEncodingException
850 {
851 String tempStr = getString(name);
852 if ( tempStr != null )
853 return tempStr.getBytes(characterEncoding);
854 return null;
855 }
856
857 /***
858 * Return a String for the given name. If the name does not
859 * exist, return null.
860 *
861 * @param name A String with the name.
862 * @return A String.
863 */
864 public String getString(String name)
865 {
866 try
867 {
868 String value = null;
869 Object object = parameters.get(convert(name));
870 if (object != null)
871 value = ((String[])object)[0];
872 if (value == null || value.equals("null"))
873 return null;
874 return value;
875 }
876 catch ( ClassCastException e )
877 {
878 return null;
879 }
880 }
881
882 /***
883 * Return a String for the given name. If the name does not
884 * exist, return null. It is the same as the getString() method
885 * however has been added for simplicity when working with
886 * template tools such as Velocity which allow you to do
887 * something like this:
888 *
889 * <code>$data.Parameters.form_variable_name</code>
890 *
891 * @param name A String with the name.
892 * @return A String.
893 */
894 public String get (String name)
895 {
896 return getString(name);
897 }
898
899 /***
900 * Return a String for the given name. If the name does not
901 * exist, return the defaultValue.
902 *
903 * @param name A String with the name.
904 * @param defaultValue The default value.
905 * @return A String.
906 */
907 public String getString(String name,
908 String defaultValue)
909 {
910 String value = getString(name);
911 if (value == null ||
912 value.length() == 0 ||
913 value.equals("null"))
914 return defaultValue;
915 else
916 return value;
917 }
918
919 /***
920 * Set a parameter to a specific value.
921 *
922 * This is useful if you want your action to override the values
923 * of the parameters for the screen to use.
924 * @param name The name of the parameter.
925 * @param value The value to set.
926 */
927 public void setString(String name, String value)
928 {
929 if(value != null)
930 {
931 parameters.put(convert(name), new String[] {value} );
932 }
933 }
934
935 /***
936 * Return an array of Strings for the given name. If the name
937 * does not exist, return null.
938 *
939 * @param name A String with the name.
940 * @return A String[].
941 */
942 public String[] getStrings(String name)
943 {
944 String[] value = null;
945 Object object = parameters.get(convert(name));
946 if (object != null)
947 value = ((String[])object);
948 return value;
949 }
950
951 /***
952 * Return an array of Strings for the given name. If the name
953 * does not exist, return the defaultValue.
954 *
955 * @param name A String with the name.
956 * @param defaultValue The default value.
957 * @return A String[].
958 */
959 public String[] getStrings(String name,
960 String[] defaultValue)
961 {
962 String[] value = getStrings(name);
963 if (value == null ||
964 value.length == 0)
965 return defaultValue;
966 else
967 return value;
968 }
969
970 /***
971 * Set a parameter to a specific value.
972 *
973 * This is useful if you want your action to override the values
974 * of the parameters for the screen to use.
975 * @param name The name of the parameter.
976 * @param values The value to set.
977 */
978 public void setStrings(String name, String[] values)
979 {
980 if(values != null)
981 {
982 parameters.put(convert(name), values);
983 }
984 }
985
986 /***
987 * Return an Object for the given name. If the name does not
988 * exist, return null.
989 *
990 * @param name A String with the name.
991 * @return An Object.
992 */
993 public Object getObject(String name)
994 {
995 try
996 {
997 Object value = null;
998 Object object = parameters.get(convert(name));
999 if (object != null)
1000 value = ((Object[])object)[0];
1001 return value;
1002 }
1003 catch ( ClassCastException e )
1004 {
1005 return null;
1006 }
1007 }
1008
1009 /***
1010 * Return an array of Objects for the given name. If the name
1011 * does not exist, return null.
1012 *
1013 * @param name A String with the name.
1014 * @return An Object[].
1015 */
1016 public Object[] getObjects(String name)
1017 {
1018 try
1019 {
1020 return (Object[])parameters.get(convert(name));
1021 }
1022 catch ( ClassCastException e )
1023 {
1024 return null;
1025 }
1026 }
1027
1028 /***
1029 * Returns a {@link java.util.Date} object. String is parsed by supplied
1030 * DateFormat. If the name does not exist, return the
1031 * defaultValue.
1032 *
1033 * @param name A String with the name.
1034 * @param df A DateFormat.
1035 * @param defaultValue The default value.
1036 * @return A Date.
1037 */
1038 public Date getDate(String name,
1039 DateFormat df,
1040 Date defaultValue)
1041 {
1042 Date date = null;
1043
1044 if (containsKey(name))
1045 {
1046 try
1047 {
1048 // Reject invalid dates.
1049 df.setLenient(false);
1050 date = df.parse(getString(name));
1051 }
1052 catch (ParseException e)
1053 {
1054 // Thrown if couldn't parse date.
1055 date = defaultValue;
1056 }
1057 }
1058 else
1059 date = defaultValue;
1060
1061 return date;
1062 }
1063
1064 /***
1065 * Returns a {@link java.util.Date} object. If there are DateSelector or
1066 * TimeSelector style parameters then these are used. If not and there
1067 * is a parameter 'name' then this is parsed by DateFormat. If the
1068 * name does not exist, return null.
1069 *
1070 * @param name A String with the name.
1071 * @return A Date.
1072 */
1073 public Date getDate(String name)
1074 {
1075 Date date = null;
1076
1077 if (containsDateSelectorKeys(name))
1078 {
1079 try
1080 {
1081 Calendar cal = new GregorianCalendar(
1082 getInt(name + DateSelector.YEAR_SUFFIX),
1083 getInt(name + DateSelector.MONTH_SUFFIX),
1084 getInt(name + DateSelector.DAY_SUFFIX));
1085
1086 // Reject invalid dates.
1087 cal.setLenient(false);
1088 date = cal.getTime();
1089 }
1090 catch (IllegalArgumentException e)
1091 {
1092 // Thrown if an invalid date.
1093 }
1094 }
1095 else if (containsTimeSelectorKeys(name))
1096 {
1097 try
1098 {
1099 String ampm = getString(name + TimeSelector.AMPM_SUFFIX);
1100 int hour = getInt(name + TimeSelector.HOUR_SUFFIX);
1101
1102 // Convert from 12 to 24hr format if appropriate
1103 if (ampm != null)
1104 {
1105 if ( hour == 12 )
1106 {
1107 hour = (Integer.parseInt(ampm) == Calendar.PM) ? 12 : 0;
1108 }
1109 else if (Integer.parseInt(ampm) == Calendar.PM)
1110 {
1111 hour += 12;
1112 }
1113 }
1114 Calendar cal = new GregorianCalendar( 1, 1, 1,
1115 hour,
1116 getInt(name + TimeSelector.MINUTE_SUFFIX),
1117 getInt(name + TimeSelector.SECOND_SUFFIX));
1118
1119 // Reject invalid dates.
1120 cal.setLenient(false);
1121 date = cal.getTime();
1122 }
1123 catch (IllegalArgumentException e)
1124 {
1125 // Thrown if an invalid date.
1126 }
1127 }
1128 else
1129 {
1130 DateFormat df = DateFormat.getDateInstance();
1131 date = getDate(name, df, null);
1132 }
1133
1134 return date;
1135 }
1136
1137 /***
1138 * Returns a {@link java.util.Date} object. String is parsed by supplied
1139 * DateFormat. If the name does not exist, return null.
1140 *
1141 * @param name A String with the name.
1142 * @param df A DateFormat.
1143 * @return A Date.
1144 */
1145 public Date getDate(String name,
1146 DateFormat df)
1147 {
1148 return getDate(name, df, null);
1149 }
1150
1151 /***
1152 * Return an NumberKey for the given name. If the name does not
1153 * exist, return null.
1154 *
1155 * @param name A String with the name.
1156 * @return A NumberKey, or <code>null</code> if unparsable.
1157 */
1158 public NumberKey getNumberKey(String name)
1159 {
1160 try
1161 {
1162 String value = null;
1163 Object object = parameters.get(convert(name));
1164 if (object != null)
1165 {
1166 value = ((String[])object)[0];
1167 }
1168 return (StringUtils.isValid(value) ? new NumberKey(value) : null);
1169 }
1170 catch ( ClassCastException e )
1171 {
1172 return null;
1173 }
1174 }
1175
1176 /***
1177 * Return an StringKey for the given name. If the name does not
1178 * exist, return null.
1179 *
1180 * @param name A String with the name.
1181 * @return A StringKey, or <code>null</code> if unparsable.
1182 */
1183 public StringKey getStringKey(String name)
1184 {
1185 try
1186 {
1187 String value = null;
1188 Object object = parameters.get(convert(name));
1189 if (object != null)
1190 {
1191 value = ((String[])object)[0];
1192 }
1193 return (StringUtils.isValid(value) ? new StringKey(value) : null);
1194 }
1195 catch ( ClassCastException e )
1196 {
1197 return null;
1198 }
1199 }
1200
1201 /***
1202 * Uses bean introspection to set writable properties of bean from
1203 * the parameters, where a (case-insensitive) name match between
1204 * the bean property and the parameter is looked for.
1205 *
1206 * @param bean An Object.
1207 * @exception Exception, a generic exception.
1208 */
1209 public void setProperties(Object bean)
1210 throws Exception
1211 {
1212 Class beanClass = bean.getClass();
1213 PropertyDescriptor[] props
1214 = Introspector.getBeanInfo(beanClass).getPropertyDescriptors();
1215
1216 for (int i = 0; i < props.length; i++)
1217 {
1218 String propname = props[i].getName();
1219 Method setter = props[i].getWriteMethod();
1220 if (setter != null &&
1221 (containsKey(propname) ||
1222 containsDateSelectorKeys(propname) ||
1223 containsTimeSelectorKeys(propname)))
1224 {
1225 setProperty(bean, props[i]);
1226 }
1227 }
1228 }
1229
1230 /***
1231 * Simple method that attempts to get a textual representation of
1232 * this object's name/value pairs. String[] handling is currently
1233 * a bit rough.
1234 *
1235 * @return A textual representation of the parsed name/value pairs.
1236 */
1237 public String toString()
1238 {
1239 StringBuffer sb = new StringBuffer();
1240 for (Enumeration e = parameters.keys() ; e.hasMoreElements() ;)
1241 {
1242 String name = (String) e.nextElement();
1243 try
1244 {
1245 sb.append ('{');
1246 sb.append(name);
1247 sb.append('=');
1248 String[] params = this.getStrings(name);
1249 if ( params.length <= 1 )
1250 {
1251 sb.append(params[0]);
1252 }
1253 else
1254 {
1255 for ( int i=0; i<params.length; i++ )
1256 {
1257 if ( i != 0 )
1258 {
1259 sb.append(", ");
1260 }
1261 sb.append('[')
1262 .append(params[i])
1263 .append(']');
1264 }
1265 }
1266 sb.append ("}\n");
1267 }
1268 catch ( Exception ee)
1269 {
1270 try
1271 {
1272 sb.append ('{');
1273 sb.append(name);
1274 sb.append('=');
1275 sb.append ("ERROR?");
1276 sb.append ("}\n");
1277 }
1278 catch ( Exception eee )
1279 {
1280 }
1281 }
1282 }
1283 return sb.toString();
1284 }
1285
1286 /***
1287 * Set the property 'prop' in the bean to the value of the
1288 * corresponding parameters. Supports all types supported by
1289 * getXXX methods plus a few more that come for free because
1290 * primitives have to be wrapped before being passed to invoke
1291 * anyway.
1292 *
1293 * @param bean An Object.
1294 * @param prop A PropertyDescriptor.
1295 * @exception Exception, a generic exception.
1296 */
1297 protected void setProperty(Object bean,
1298 PropertyDescriptor prop)
1299 throws Exception
1300 {
1301 if (prop instanceof IndexedPropertyDescriptor)
1302 {
1303 throw new Exception(prop.getName() +
1304 " is an indexed property (not supported)");
1305 }
1306
1307 Method setter = prop.getWriteMethod();
1308 if (setter == null)
1309 {
1310 throw new Exception(prop.getName() +
1311 " is a read only property");
1312 }
1313
1314 Class propclass = prop.getPropertyType();
1315 Object[] args = { null };
1316
1317 if (propclass == String.class)
1318 {
1319 args[0] = getString(prop.getName());
1320 }
1321 else if (propclass == Integer.class || propclass == Integer.TYPE)
1322 {
1323 args[0] = getInteger(prop.getName());
1324 }
1325 else if (propclass == Long.class || propclass == Long.TYPE)
1326 {
1327 args[0] = new Long(getLong(prop.getName()));
1328 }
1329 else if (propclass == Boolean.class || propclass == Boolean.TYPE)
1330 {
1331 args[0] = getBool(prop.getName());
1332 }
1333 else if (propclass == Double.class || propclass == Double.TYPE)
1334 {
1335 args[0] = new Double(getDouble(prop.getName()));
1336 }
1337 else if (propclass == BigDecimal.class)
1338 {
1339 args[0] = getBigDecimal(prop.getName());
1340 }
1341 else if (propclass == String[].class)
1342 {
1343 args[0] = getStrings(prop.getName());
1344 }
1345 else if (propclass == Object.class)
1346 {
1347 args[0] = getObject(prop.getName());
1348 }
1349 else if (propclass == int[].class)
1350 {
1351 args[0] = getInts(prop.getName());
1352 }
1353 else if (propclass == Integer[].class)
1354 {
1355 args[0] = getIntegers(prop.getName());
1356 }
1357 else if (propclass == Date.class)
1358 {
1359 args[0] = getDate(prop.getName());
1360 }
1361 else if (propclass == NumberKey.class)
1362 {
1363 args[0] = getNumberKey(prop.getName());
1364 }
1365 else if (propclass == StringKey.class)
1366 {
1367 args[0] = getStringKey(prop.getName());
1368 }
1369 else
1370 {
1371 throw new Exception("property "
1372 + prop.getName()
1373 + " is of unsupported type "
1374 + propclass.toString());
1375 }
1376
1377 setter.invoke(bean, args);
1378 }
1379 }
This page was automatically generated by Maven