View Javadoc

1   /*
2    * Licensed to the Apache Software Foundation (ASF) under one or more
3    * contributor license agreements.  See the NOTICE file distributed with
4    * this work for additional information regarding copyright ownership.
5    * The ASF licenses this file to You under the Apache License, Version 2.0
6    * (the "License"); you may not use this file except in compliance with
7    * the License.  You may obtain a copy of the License at
8    *
9    *     http://www.apache.org/licenses/LICENSE-2.0
10   *
11   * Unless required by applicable law or agreed to in writing, software
12   * distributed under the License is distributed on an "AS IS" BASIS,
13   * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14   * See the License for the specific language governing permissions and
15   * limitations under the License.
16   */
17  
18  package org.apache.commons.configuration;
19  
20  import java.awt.Color;
21  import java.math.BigDecimal;
22  import java.math.BigInteger;
23  import java.net.URL;
24  import java.util.ArrayList;
25  import java.util.Calendar;
26  import java.util.Collection;
27  import java.util.Date;
28  import java.util.Iterator;
29  import java.util.List;
30  import java.util.Locale;
31  import java.io.Serializable;
32  
33  import org.apache.commons.collections.CollectionUtils;
34  import org.apache.commons.lang.ArrayUtils;
35  import org.apache.commons.lang.StringUtils;
36  
37  /***
38   * Decorator providing additional getters for any Configuration. This extended
39   * Configuration supports more types: URL, Locale, Date, Calendar, Color, as
40   * well as lists and arrays for all types.
41   *
42   * <p>Let us know if you find this useful, the most frequently used getters
43   * are likely to be integrated in the Configuration interface in a future
44   * version.</p>
45   *
46   * @author <a href="ebourg@apache.org">Emmanuel Bourg</a>
47   * @version $Revision: 439648 $, $Date: 2006-09-02 22:42:10 +0200 (Sa, 02 Sep 2006) $
48   * @since 1.1
49   */
50  public class DataConfiguration extends AbstractConfiguration implements Serializable
51  {
52      /*** The key of the property storing the user defined date format. */
53      public static final String DATE_FORMAT_KEY = "org.apache.commons.configuration.format.date";
54  
55      /*** The default format for dates. */
56      public static final String DEFAULT_DATE_FORMAT = "yyyy-MM-dd HH:mm:ss";
57  
58      /***
59       * The serial version UID.
60       */
61      private static final long serialVersionUID = -69011336405718640L;
62  
63      /*** Stores the wrapped configuration.*/
64      protected Configuration configuration;
65  
66      /***
67       * Creates a new instance of <code>DataConfiguration</code> and sets the
68       * wrapped configuration.
69       *
70       * @param configuration the wrapped configuration
71       */
72      public DataConfiguration(Configuration configuration)
73      {
74          this.configuration = configuration;
75      }
76  
77      /***
78       * Return the configuration decorated by this DataConfiguration.
79       *
80       * @return the wrapped configuration
81       */
82      public Configuration getConfiguration()
83      {
84          return configuration;
85      }
86  
87      public Object getProperty(String key)
88      {
89          return configuration.getProperty(key);
90      }
91  
92      protected void addPropertyDirect(String key, Object obj)
93      {
94          configuration.addProperty(key, obj);
95      }
96  
97      public boolean isEmpty()
98      {
99          return configuration.isEmpty();
100     }
101 
102     public boolean containsKey(String key)
103     {
104         return configuration.containsKey(key);
105     }
106 
107     public void clearProperty(String key)
108     {
109         configuration.clearProperty(key);
110     }
111 
112     public Iterator getKeys()
113     {
114         return configuration.getKeys();
115     }
116 
117     /***
118      * Get a list of Boolean objects associated with the given
119      * configuration key. If the key doesn't map to an existing object
120      * an empty list is returned.
121      *
122      * @param key The configuration key.
123      * @return The associated Boolean list if the key is found.
124      *
125      * @throws ConversionException is thrown if the key maps to an
126      *         object that is not a list of booleans.
127      */
128     public List getBooleanList(String key)
129     {
130         return getBooleanList(key, new ArrayList());
131     }
132 
133     /***
134      * Get a list of Boolean objects associated with the given
135      * configuration key. If the key doesn't map to an existing object,
136      * the default value is returned.
137      *
138      * @param key The configuration key.
139      * @param defaultValue The default value.
140      * @return The associated List of strings.
141      *
142      * @throws ConversionException is thrown if the key maps to an
143      *         object that is not a list of booleans.
144      */
145     public List getBooleanList(String key, List defaultValue)
146     {
147         Object value = getProperty(key);
148 
149         List list;
150 
151         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
152         {
153             list = defaultValue;
154         }
155         else if (value instanceof boolean[])
156         {
157             list = new ArrayList();
158             CollectionUtils.addAll(list, ArrayUtils.toObject((boolean[]) value));
159         }
160         else if (value instanceof Boolean[])
161         {
162             list = new ArrayList();
163             CollectionUtils.addAll(list, (Boolean[]) value);
164         }
165         else if (value instanceof Collection)
166         {
167             Collection values = (Collection) value;
168             list = new ArrayList();
169 
170             Iterator it = values.iterator();
171             while (it.hasNext())
172             {
173                 list.add(PropertyConverter.toBoolean(interpolate(it.next())));
174             }
175         }
176         else
177         {
178             try
179             {
180                 // attempt to convert a single value
181                 list = new ArrayList();
182                 list.add(PropertyConverter.toBoolean(interpolate(value)));
183             }
184             catch (ConversionException e)
185             {
186                 throw new ConversionException('\'' + key + "' doesn't map to a list of booleans", e);
187             }
188         }
189 
190         return list;
191     }
192 
193     /***
194      * Get an array of boolean primitives associated with the given
195      * configuration key. If the key doesn't map to an existing object
196      * an empty array is returned.
197      *
198      * @param key The configuration key.
199      * @return The associated boolean array if the key is found.
200      *
201      * @throws ConversionException is thrown if the key maps to an
202      *         object that is not a list of booleans.
203      */
204     public boolean[] getBooleanArray(String key)
205     {
206         return getBooleanArray(key, new boolean[0]);
207     }
208 
209     /***
210      * Get an array of boolean primitives associated with the given
211      * configuration key. If the key doesn't map to an existing object,
212      * the default value is returned.
213      *
214      * @param key          The configuration key.
215      * @param defaultValue The default value.
216      * @return The associated boolean array if the key is found.
217      *
218      * @throws ConversionException is thrown if the key maps to an
219      *         object that is not a list of booleans.
220      */
221     public boolean[] getBooleanArray(String key, boolean[] defaultValue)
222     {
223         Object value = getProperty(key);
224 
225         boolean[] array;
226 
227         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
228         {
229             array = defaultValue;
230         }
231         else if (value instanceof boolean[])
232         {
233             array = (boolean[]) value;
234         }
235         else if (value instanceof Boolean[])
236         {
237             array = ArrayUtils.toPrimitive((Boolean[]) value);
238         }
239         else if (value instanceof Collection)
240         {
241             Collection values = (Collection) value;
242             array = new boolean[values.size()];
243 
244             int i = 0;
245             Iterator it = values.iterator();
246             while (it.hasNext())
247             {
248                 array[i++] = PropertyConverter.toBoolean(interpolate(it.next())).booleanValue();
249             }
250         }
251         else
252         {
253             try
254             {
255                 // attempt to convert a single value
256                 array = new boolean[1];
257                 array[0] = PropertyConverter.toBoolean(interpolate(value)).booleanValue();
258             }
259             catch (ConversionException e)
260             {
261                 throw new ConversionException('\'' + key + "' doesn't map to a list of booleans", e);
262             }
263         }
264 
265         return array;
266     }
267 
268     /***
269      * Get a list of Byte objects associated with the given configuration key.
270      * If the key doesn't map to an existing object an empty list is returned.
271      *
272      * @param key The configuration key.
273      * @return The associated Byte list if the key is found.
274      *
275      * @throws ConversionException is thrown if the key maps to an
276      *         object that is not a list of bytes.
277      */
278     public List getByteList(String key)
279     {
280         return getByteList(key, new ArrayList());
281     }
282 
283     /***
284      * Get a list of Byte objects associated with the given configuration key.
285      * If the key doesn't map to an existing object, the default value is
286      * returned.
287      *
288      * @param key The configuration key.
289      * @param defaultValue The default value.
290      * @return The associated List of Bytes.
291      *
292      * @throws ConversionException is thrown if the key maps to an
293      *         object that is not a list of bytes.
294      */
295     public List getByteList(String key, List defaultValue)
296     {
297         Object value = getProperty(key);
298 
299         List list;
300 
301         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
302         {
303             list = defaultValue;
304         }
305         else if (value instanceof byte[])
306         {
307             list = new ArrayList();
308             CollectionUtils.addAll(list, ArrayUtils.toObject((byte[]) value));
309         }
310         else if (value instanceof Byte[])
311         {
312             list = new ArrayList();
313             CollectionUtils.addAll(list, (Byte[]) value);
314         }
315         else if (value instanceof Collection)
316         {
317             Collection values = (Collection) value;
318             list = new ArrayList();
319 
320             Iterator it = values.iterator();
321             while (it.hasNext())
322             {
323                 list.add(PropertyConverter.toByte(interpolate(it.next())));
324             }
325         }
326         else
327         {
328             try
329             {
330                 // attempt to convert a single value
331                 list = new ArrayList();
332                 list.add(PropertyConverter.toByte(interpolate(value)));
333             }
334             catch (ConversionException e)
335             {
336                 throw new ConversionException('\'' + key + "' doesn't map to a list of bytes", e);
337             }
338         }
339 
340         return list;
341     }
342 
343     /***
344      * Get an array of byte primitives associated with the given
345      * configuration key. If the key doesn't map to an existing object
346      * an empty array is returned.
347      *
348      * @param key The configuration key.
349      * @return The associated byte array if the key is found.
350      *
351      * @throws ConversionException is thrown if the key maps to an
352      *         object that is not a list of bytes.
353      */
354     public byte[] getByteArray(String key)
355     {
356         return getByteArray(key, new byte[0]);
357     }
358 
359     /***
360      * Get an array of byte primitives associated with the given
361      * configuration key. If the key doesn't map to an existing object
362      * an empty array is returned.
363      *
364      * @param key The configuration key.
365      * @param defaultValue the default value, which will be returned if the property is not found
366      * @return The associated byte array if the key is found.
367      *
368      * @throws ConversionException is thrown if the key maps to an
369      *         object that is not a list of bytes.
370      */
371     public byte[] getByteArray(String key, byte[] defaultValue)
372     {
373         Object value = getProperty(key);
374 
375         byte[] array;
376 
377         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
378         {
379             array = defaultValue;
380         }
381         else if (value instanceof byte[])
382         {
383             array = (byte[]) value;
384         }
385         else if (value instanceof Byte[])
386         {
387             array = ArrayUtils.toPrimitive((Byte[]) value);
388         }
389         else if (value instanceof Collection)
390         {
391             Collection values = (Collection) value;
392             array = new byte[values.size()];
393 
394             int i = 0;
395             Iterator it = values.iterator();
396             while (it.hasNext())
397             {
398                 array[i++] = PropertyConverter.toByte(interpolate(it.next())).byteValue();
399             }
400         }
401         else
402         {
403             try
404             {
405                 // attempt to convert a single value
406                 array = new byte[1];
407                 array[0] = PropertyConverter.toByte(interpolate(value)).byteValue();
408             }
409             catch (ConversionException e)
410             {
411                 throw new ConversionException('\'' + key + "' doesn't map to a list of bytes", e);
412             }
413         }
414 
415         return array;
416     }
417 
418     /***
419      * Get a list of Short objects associated with the given configuration key.
420      * If the key doesn't map to an existing object an empty list is returned.
421      *
422      * @param key The configuration key.
423      * @return The associated Short list if the key is found.
424      *
425      * @throws ConversionException is thrown if the key maps to an
426      *         object that is not a list of shorts.
427      */
428     public List getShortList(String key)
429     {
430         return getShortList(key, new ArrayList());
431     }
432 
433     /***
434      * Get a list of Short objects associated with the given configuration key.
435      * If the key doesn't map to an existing object, the default value is
436      * returned.
437      *
438      * @param key The configuration key.
439      * @param defaultValue The default value.
440      * @return The associated List of Shorts.
441      *
442      * @throws ConversionException is thrown if the key maps to an
443      *         object that is not a list of shorts.
444      */
445     public List getShortList(String key, List defaultValue)
446     {
447         Object value = getProperty(key);
448 
449         List list;
450 
451         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
452         {
453             list = defaultValue;
454         }
455         else if (value instanceof short[])
456         {
457             list = new ArrayList();
458             CollectionUtils.addAll(list, ArrayUtils.toObject((short[]) value));
459         }
460         else if (value instanceof Short[])
461         {
462             list = new ArrayList();
463             CollectionUtils.addAll(list, (Short[]) value);
464         }
465         else if (value instanceof Collection)
466         {
467             Collection values = (Collection) value;
468             list = new ArrayList();
469 
470             Iterator it = values.iterator();
471             while (it.hasNext())
472             {
473                 list.add(PropertyConverter.toShort(interpolate(it.next())));
474             }
475         }
476         else
477         {
478             try
479             {
480                 // attempt to convert a single value
481                 list = new ArrayList();
482                 list.add(PropertyConverter.toShort(interpolate(value)));
483             }
484             catch (ConversionException e)
485             {
486                 throw new ConversionException('\'' + key + "' doesn't map to a list of shorts", e);
487             }
488         }
489 
490         return list;
491     }
492 
493     /***
494      * Get an array of short primitives associated with the given
495      * configuration key. If the key doesn't map to an existing object
496      * an empty array is returned.
497      *
498      * @param key The configuration key.
499      * @return The associated short array if the key is found.
500      *
501      * @throws ConversionException is thrown if the key maps to an
502      *         object that is not a list of shorts.
503      */
504     public short[] getShortArray(String key)
505     {
506         return getShortArray(key, new short[0]);
507     }
508 
509     /***
510      * Get an array of short primitives associated with the given
511      * configuration key. If the key doesn't map to an existing object
512      * an empty array is returned.
513      *
514      * @param key The configuration key.
515      * @param defaultValue the default value, which will be returned if the property is not found
516      * @return The associated short array if the key is found.
517      *
518      * @throws ConversionException is thrown if the key maps to an
519      *         object that is not a list of shorts.
520      */
521     public short[] getShortArray(String key, short[] defaultValue)
522     {
523         Object value = getProperty(key);
524 
525         short[] array;
526 
527         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
528         {
529             array = defaultValue;
530         }
531         else if (value instanceof short[])
532         {
533             array = (short[]) value;
534         }
535         else if (value instanceof Short[])
536         {
537             array = ArrayUtils.toPrimitive((Short[]) value);
538         }
539         else if (value instanceof Collection)
540         {
541             Collection values = (Collection) value;
542             array = new short[values.size()];
543 
544             int i = 0;
545             Iterator it = values.iterator();
546             while (it.hasNext())
547             {
548                 array[i++] = PropertyConverter.toShort(interpolate(it.next())).shortValue();
549             }
550         }
551         else
552         {
553             try
554             {
555                 // attempt to convert a single value
556                 array = new short[1];
557                 array[0] = PropertyConverter.toShort(interpolate(value)).shortValue();
558             }
559             catch (ConversionException e)
560             {
561                 throw new ConversionException('\'' + key + "' doesn't map to a list of shorts", e);
562             }
563         }
564 
565         return array;
566     }
567 
568     /***
569      * Get a list of Integer objects associated with the given
570      * configuration key. If the key doesn't map to an existing object
571      * an empty list is returned.
572      *
573      * @param key The configuration key.
574      * @return The associated Integer list if the key is found.
575      *
576      * @throws ConversionException is thrown if the key maps to an
577      *         object that is not a list of integers.
578      */
579     public List getIntegerList(String key)
580     {
581         return getIntegerList(key, new ArrayList());
582     }
583 
584     /***
585      * Get a list of Integer objects associated with the given
586      * configuration key. If the key doesn't map to an existing object,
587      * the default value is returned.
588      *
589      * @param key The configuration key.
590      * @param defaultValue The default value.
591      * @return The associated List of Integers.
592      *
593      * @throws ConversionException is thrown if the key maps to an
594      *         object that is not a list of integers.
595      */
596     public List getIntegerList(String key, List defaultValue)
597     {
598         Object value = getProperty(key);
599 
600         List list;
601 
602         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
603         {
604             list = defaultValue;
605         }
606         else if (value instanceof int[])
607         {
608             list = new ArrayList();
609             CollectionUtils.addAll(list, ArrayUtils.toObject((int[]) value));
610         }
611         else if (value instanceof Integer[])
612         {
613             list = new ArrayList();
614             CollectionUtils.addAll(list, (Integer[]) value);
615         }
616         else if (value instanceof Collection)
617         {
618             Collection values = (Collection) value;
619             list = new ArrayList();
620 
621             Iterator it = values.iterator();
622             while (it.hasNext())
623             {
624                 list.add(PropertyConverter.toInteger(interpolate(it.next())));
625             }
626         }
627         else
628         {
629             try
630             {
631                 // attempt to convert a single value
632                 list = new ArrayList();
633                 list.add(PropertyConverter.toInteger(interpolate(value)));
634             }
635             catch (ConversionException e)
636             {
637                 throw new ConversionException('\'' + key + "' doesn't map to a list of integers", e);
638             }
639         }
640 
641         return list;
642     }
643 
644     /***
645      * Get an array of int primitives associated with the given
646      * configuration key. If the key doesn't map to an existing object
647      * an empty array is returned.
648      *
649      * @param key The configuration key.
650      * @return The associated int array if the key is found.
651      *
652      * @throws ConversionException is thrown if the key maps to an
653      *         object that is not a list of integers.
654      */
655     public int[] getIntArray(String key)
656     {
657         return getIntArray(key, new int[0]);
658     }
659 
660     /***
661      * Get an array of int primitives associated with the given
662      * configuration key. If the key doesn't map to an existing object
663      * an empty array is returned.
664      *
665      * @param key The configuration key.
666      * @param defaultValue the default value, which will be returned if the property is not found
667      * @return The associated int array if the key is found.
668      *
669      * @throws ConversionException is thrown if the key maps to an
670      *         object that is not a list of integers.
671      */
672     public int[] getIntArray(String key, int[] defaultValue)
673     {
674         Object value = getProperty(key);
675 
676         int[] array;
677 
678         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
679         {
680             array = defaultValue;
681         }
682         else if (value instanceof int[])
683         {
684             array = (int[]) value;
685         }
686         else if (value instanceof Integer[])
687         {
688             array = ArrayUtils.toPrimitive((Integer[]) value);
689         }
690         else if (value instanceof Collection)
691         {
692             Collection values = (Collection) value;
693             array = new int[values.size()];
694 
695             int i = 0;
696             Iterator it = values.iterator();
697             while (it.hasNext())
698             {
699                 array[i++] = PropertyConverter.toInteger(interpolate(it.next())).intValue();
700             }
701         }
702         else
703         {
704             try
705             {
706                 // attempt to convert a single value
707                 array = new int[1];
708                 array[0] = PropertyConverter.toInteger(interpolate(value)).intValue();
709             }
710             catch (ConversionException e)
711             {
712                 throw new ConversionException('\'' + key + "' doesn't map to a list of integers", e);
713             }
714         }
715 
716         return array;
717     }
718 
719     /***
720      * Get a list of Long objects associated with the given configuration key.
721      * If the key doesn't map to an existing object an empty list is returned.
722      *
723      * @param key The configuration key.
724      * @return The associated Long list if the key is found.
725      *
726      * @throws ConversionException is thrown if the key maps to an
727      *         object that is not a list of longs.
728      */
729     public List getLongList(String key)
730     {
731         return getLongList(key, new ArrayList());
732     }
733 
734     /***
735      * Get a list of Long objects associated with the given configuration key.
736      * If the key doesn't map to an existing object, the default value is
737      * returned.
738      *
739      * @param key The configuration key.
740      * @param defaultValue The default value.
741      * @return The associated List of Longs.
742      *
743      * @throws ConversionException is thrown if the key maps to an
744      *         object that is not a list of longs.
745      */
746     public List getLongList(String key, List defaultValue)
747     {
748         Object value = getProperty(key);
749 
750         List list;
751 
752         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
753         {
754             list = defaultValue;
755         }
756         else if (value instanceof long[])
757         {
758             list = new ArrayList();
759             CollectionUtils.addAll(list, ArrayUtils.toObject((long[]) value));
760         }
761         else if (value instanceof Long[])
762         {
763             list = new ArrayList();
764             CollectionUtils.addAll(list, (Long[]) value);
765         }
766         else if (value instanceof Collection)
767         {
768             Collection values = (Collection) value;
769             list = new ArrayList();
770 
771             Iterator it = values.iterator();
772             while (it.hasNext())
773             {
774                 list.add(PropertyConverter.toLong(interpolate(it.next())));
775             }
776         }
777         else
778         {
779             try
780             {
781                 // attempt to convert a single value
782                 list = new ArrayList();
783                 list.add(PropertyConverter.toLong(interpolate(value)));
784             }
785             catch (ConversionException e)
786             {
787                 throw new ConversionException('\'' + key + "' doesn't map to a list of longs", e);
788             }
789         }
790 
791         return list;
792     }
793 
794     /***
795      * Get an array of long primitives associated with the given
796      * configuration key. If the key doesn't map to an existing object
797      * an empty array is returned.
798      *
799      * @param key The configuration key.
800      * @return The associated long array if the key is found.
801      *
802      * @throws ConversionException is thrown if the key maps to an
803      *         object that is not a list of longs.
804      */
805     public long[] getLongArray(String key)
806     {
807         return getLongArray(key, new long[0]);
808     }
809 
810     /***
811      * Get an array of long primitives associated with the given
812      * configuration key. If the key doesn't map to an existing object
813      * an empty array is returned.
814      *
815      * @param key The configuration key.
816      * @param defaultValue the default value, which will be returned if the property is not found
817      * @return The associated long array if the key is found.
818      *
819      * @throws ConversionException is thrown if the key maps to an
820      *         object that is not a list of longs.
821      */
822     public long[] getLongArray(String key, long[] defaultValue)
823     {
824         Object value = getProperty(key);
825 
826         long[] array;
827 
828         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
829         {
830             array = defaultValue;
831         }
832         else if (value instanceof long[])
833         {
834             array = (long[]) value;
835         }
836         else if (value instanceof Long[])
837         {
838             array = ArrayUtils.toPrimitive((Long[]) value);
839         }
840         else if (value instanceof Collection)
841         {
842             Collection values = (Collection) value;
843             array = new long[values.size()];
844 
845             int i = 0;
846             Iterator it = values.iterator();
847             while (it.hasNext())
848             {
849                 array[i++] = PropertyConverter.toLong(interpolate(it.next())).longValue();
850             }
851         }
852         else
853         {
854             try
855             {
856                 // attempt to convert a single value
857                 array = new long[1];
858                 array[0] = PropertyConverter.toLong(interpolate(value)).longValue();
859             }
860             catch (ConversionException e)
861             {
862                 throw new ConversionException('\'' + key + "' doesn't map to a list of longs", e);
863             }
864         }
865 
866         return array;
867     }
868 
869     /***
870      * Get a list of Float objects associated with the given configuration key.
871      * If the key doesn't map to an existing object an empty list is returned.
872      *
873      * @param key The configuration key.
874      * @return The associated Float list if the key is found.
875      *
876      * @throws ConversionException is thrown if the key maps to an
877      *         object that is not a list of floats.
878      */
879     public List getFloatList(String key)
880     {
881         return getFloatList(key, new ArrayList());
882     }
883 
884     /***
885      * Get a list of Float objects associated with the given
886      * configuration key. If the key doesn't map to an existing object,
887      * the default value is returned.
888      *
889      * @param key The configuration key.
890      * @param defaultValue The default value.
891      * @return The associated List of Floats.
892      *
893      * @throws ConversionException is thrown if the key maps to an
894      *         object that is not a list of floats.
895      */
896     public List getFloatList(String key, List defaultValue)
897     {
898         Object value = getProperty(key);
899 
900         List list;
901 
902         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
903         {
904             list = defaultValue;
905         }
906         else if (value instanceof float[])
907         {
908             list = new ArrayList();
909             CollectionUtils.addAll(list, ArrayUtils.toObject((float[]) value));
910         }
911         else if (value instanceof Float[])
912         {
913             list = new ArrayList();
914             CollectionUtils.addAll(list, (Float[]) value);
915         }
916         else if (value instanceof Collection)
917         {
918             Collection values = (Collection) value;
919             list = new ArrayList();
920 
921             Iterator it = values.iterator();
922             while (it.hasNext())
923             {
924                 list.add(PropertyConverter.toFloat(interpolate(it.next())));
925             }
926         }
927         else
928         {
929             try
930             {
931                 // attempt to convert a single value
932                 list = new ArrayList();
933                 list.add(PropertyConverter.toFloat(interpolate(value)));
934             }
935             catch (ConversionException e)
936             {
937                 throw new ConversionException('\'' + key + "' doesn't map to a list of floats", e);
938             }
939         }
940 
941         return list;
942     }
943 
944     /***
945      * Get an array of float primitives associated with the given
946      * configuration key. If the key doesn't map to an existing object
947      * an empty array is returned.
948      *
949      * @param key The configuration key.
950      * @return The associated float array if the key is found.
951      *
952      * @throws ConversionException is thrown if the key maps to an
953      *         object that is not a list of floats.
954      */
955     public float[] getFloatArray(String key)
956     {
957         return getFloatArray(key, new float[0]);
958     }
959 
960     /***
961      * Get an array of float primitives associated with the given
962      * configuration key. If the key doesn't map to an existing object
963      * an empty array is returned.
964      *
965      * @param key The configuration key.
966      * @param defaultValue the default value, which will be returned if the property is not found
967      * @return The associated float array if the key is found.
968      *
969      * @throws ConversionException is thrown if the key maps to an
970      *         object that is not a list of floats.
971      */
972     public float[] getFloatArray(String key, float[] defaultValue)
973     {
974         Object value = getProperty(key);
975 
976         float[] array;
977 
978         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
979         {
980             array = defaultValue;
981         }
982         else if (value instanceof float[])
983         {
984             array = (float[]) value;
985         }
986         else if (value instanceof Float[])
987         {
988             array = ArrayUtils.toPrimitive((Float[]) value);
989         }
990         else if (value instanceof Collection)
991         {
992             Collection values = (Collection) value;
993             array = new float[values.size()];
994 
995             int i = 0;
996             Iterator it = values.iterator();
997             while (it.hasNext())
998             {
999                 array[i++] = PropertyConverter.toFloat(interpolate(it.next())).floatValue();
1000             }
1001         }
1002         else
1003         {
1004             try
1005             {
1006                 // attempt to convert a single value
1007                 array = new float[1];
1008                 array[0] = PropertyConverter.toFloat(interpolate(value)).floatValue();
1009             }
1010             catch (ConversionException e)
1011             {
1012                 throw new ConversionException('\'' + key + "' doesn't map to a list of floats", e);
1013             }
1014         }
1015 
1016         return array;
1017     }
1018 
1019     /***
1020      * Get a list of Double objects associated with the given
1021      * configuration key. If the key doesn't map to an existing object
1022      * an empty list is returned.
1023      *
1024      * @param key The configuration key.
1025      * @return The associated Double list if the key is found.
1026      *
1027      * @throws ConversionException is thrown if the key maps to an
1028      *         object that is not a list of doubles.
1029      */
1030     public List getDoubleList(String key)
1031     {
1032         return getDoubleList(key, new ArrayList());
1033     }
1034 
1035     /***
1036      * Get a list of Double objects associated with the given
1037      * configuration key. If the key doesn't map to an existing object,
1038      * the default value is returned.
1039      *
1040      * @param key The configuration key.
1041      * @param defaultValue The default value.
1042      * @return The associated List of Doubles.
1043      *
1044      * @throws ConversionException is thrown if the key maps to an
1045      *         object that is not a list of doubles.
1046      */
1047     public List getDoubleList(String key, List defaultValue)
1048     {
1049         Object value = getProperty(key);
1050 
1051         List list;
1052 
1053         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
1054         {
1055             list = defaultValue;
1056         }
1057         else if (value instanceof double[])
1058         {
1059             list = new ArrayList();
1060             CollectionUtils.addAll(list, ArrayUtils.toObject((double[]) value));
1061         }
1062         else if (value instanceof Double[])
1063         {
1064             list = new ArrayList();
1065             CollectionUtils.addAll(list, (Double[]) value);
1066         }
1067         else if (value instanceof Collection)
1068         {
1069             Collection values = (Collection) value;
1070             list = new ArrayList();
1071 
1072             Iterator it = values.iterator();
1073             while (it.hasNext())
1074             {
1075                 list.add(PropertyConverter.toDouble(interpolate(it.next())));
1076             }
1077         }
1078         else
1079         {
1080             try
1081             {
1082                 // attempt to convert a single value
1083                 list = new ArrayList();
1084                 list.add(PropertyConverter.toDouble(interpolate(value)));
1085             }
1086             catch (ConversionException e)
1087             {
1088                 throw new ConversionException('\'' + key + "' doesn't map to a list of doubles", e);
1089             }
1090         }
1091 
1092         return list;
1093     }
1094 
1095     /***
1096      * Get an array of double primitives associated with the given
1097      * configuration key. If the key doesn't map to an existing object
1098      * an empty array is returned.
1099      *
1100      * @param key The configuration key.
1101      * @return The associated double array if the key is found.
1102      *
1103      * @throws ConversionException is thrown if the key maps to an
1104      *         object that is not a list of doubles.
1105      */
1106     public double[] getDoubleArray(String key)
1107     {
1108         return getDoubleArray(key, new double[0]);
1109     }
1110 
1111     /***
1112      * Get an array of double primitives associated with the given
1113      * configuration key. If the key doesn't map to an existing object
1114      * an empty array is returned.
1115      *
1116      * @param key The configuration key.
1117      * @param defaultValue the default value, which will be returned if the property is not found
1118      * @return The associated double array if the key is found.
1119      *
1120      * @throws ConversionException is thrown if the key maps to an
1121      *         object that is not a list of doubles.
1122      */
1123     public double[] getDoubleArray(String key, double[] defaultValue)
1124     {
1125         Object value = getProperty(key);
1126 
1127         double[] array;
1128 
1129         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
1130         {
1131             array = defaultValue;
1132         }
1133         else if (value instanceof double[])
1134         {
1135             array = (double[]) value;
1136         }
1137         else if (value instanceof Double[])
1138         {
1139             array = ArrayUtils.toPrimitive((Double[]) value);
1140         }
1141         else if (value instanceof Collection)
1142         {
1143             Collection values = (Collection) value;
1144             array = new double[values.size()];
1145 
1146             int i = 0;
1147             Iterator it = values.iterator();
1148             while (it.hasNext())
1149             {
1150                 array[i++] = PropertyConverter.toDouble(interpolate(it.next())).doubleValue();
1151             }
1152         }
1153         else
1154         {
1155             try
1156             {
1157                 // attempt to convert a single value
1158                 array = new double[1];
1159                 array[0] = PropertyConverter.toDouble(interpolate(value)).doubleValue();
1160             }
1161             catch (ConversionException e)
1162             {
1163                 throw new ConversionException('\'' + key + "' doesn't map to a list of doubles", e);
1164             }
1165         }
1166 
1167         return array;
1168     }
1169 
1170     /***
1171      * Get a list of BigIntegers associated with the given configuration key.
1172      * If the key doesn't map to an existing object an empty list is returned.
1173      *
1174      * @param key The configuration key.
1175      * @return The associated BigInteger list if the key is found.
1176      *
1177      * @throws ConversionException is thrown if the key maps to an
1178      *         object that is not a list of BigIntegers.
1179      */
1180     public List getBigIntegerList(String key)
1181     {
1182         return getBigIntegerList(key, new ArrayList());
1183     }
1184 
1185     /***
1186      * Get a list of BigIntegers associated with the given configuration key.
1187      * If the key doesn't map to an existing object, the default value is
1188      * returned.
1189      *
1190      * @param key The configuration key.
1191      * @param defaultValue The default value.
1192      * @return The associated List of BigIntegers.
1193      *
1194      * @throws ConversionException is thrown if the key maps to an
1195      *         object that is not a list of BigIntegers.
1196      */
1197     public List getBigIntegerList(String key, List defaultValue)
1198     {
1199         Object value = getProperty(key);
1200 
1201         List list;
1202 
1203         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
1204         {
1205             list = defaultValue;
1206         }
1207         else if (value instanceof BigInteger[])
1208         {
1209             list = new ArrayList();
1210             CollectionUtils.addAll(list, (BigInteger[]) value);
1211         }
1212         else if (value instanceof Collection)
1213         {
1214             Collection values = (Collection) value;
1215             list = new ArrayList();
1216 
1217             Iterator it = values.iterator();
1218             while (it.hasNext())
1219             {
1220                 list.add(PropertyConverter.toBigInteger(interpolate(it.next())));
1221             }
1222         }
1223         else
1224         {
1225             try
1226             {
1227                 // attempt to convert a single value
1228                 list = new ArrayList();
1229                 list.add(PropertyConverter.toBigInteger(interpolate(value)));
1230             }
1231             catch (ConversionException e)
1232             {
1233                 throw new ConversionException('\'' + key + "' doesn't map to a list of big integers", e);
1234             }
1235         }
1236 
1237         return list;
1238     }
1239 
1240     /***
1241      * Get an array of BigIntegers associated with the given
1242      * configuration key. If the key doesn't map to an existing object
1243      * an empty array is returned.
1244      *
1245      * @param key The configuration key.
1246      * @return The associated BigInteger array if the key is found.
1247      *
1248      * @throws ConversionException is thrown if the key maps to an
1249      *         object that is not a list of BigIntegers.
1250      */
1251     public BigInteger[] getBigIntegerArray(String key)
1252     {
1253         return getBigIntegerArray(key, new BigInteger[0]);
1254     }
1255 
1256     /***
1257      * Get an array of BigIntegers associated with the given
1258      * configuration key. If the key doesn't map to an existing object
1259      * an empty array is returned.
1260      *
1261      * @param key The configuration key.
1262      * @param defaultValue the default value, which will be returned if the property is not found
1263      * @return The associated BigInteger array if the key is found.
1264      *
1265      * @throws ConversionException is thrown if the key maps to an
1266      *         object that is not a list of BigIntegers.
1267      */
1268     public BigInteger[] getBigIntegerArray(String key, BigInteger[] defaultValue)
1269     {
1270         List list = getBigIntegerList(key);
1271         if (list.isEmpty())
1272         {
1273             return defaultValue;
1274         }
1275         else
1276         {
1277             return (BigInteger[]) list.toArray(new BigInteger[list.size()]);
1278         }
1279     }
1280 
1281     /***
1282      * Get a list of BigDecimals associated with the given configuration key.
1283      * If the key doesn't map to an existing object an empty list is returned.
1284      *
1285      * @param key The configuration key.
1286      * @return The associated BigDecimal list if the key is found.
1287      *
1288      * @throws ConversionException is thrown if the key maps to an
1289      *         object that is not a list of BigDecimals.
1290      */
1291     public List getBigDecimalList(String key)
1292     {
1293         return getBigDecimalList(key, new ArrayList());
1294     }
1295 
1296     /***
1297      * Get a list of BigDecimals associated with the given configuration key.
1298      * If the key doesn't map to an existing object, the default value is
1299      * returned.
1300      *
1301      * @param key The configuration key.
1302      * @param defaultValue The default value.
1303      * @return The associated List of BigDecimals.
1304      *
1305      * @throws ConversionException is thrown if the key maps to an
1306      *         object that is not a list of BigDecimals.
1307      */
1308     public List getBigDecimalList(String key, List defaultValue)
1309     {
1310         Object value = getProperty(key);
1311 
1312         List list;
1313 
1314         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
1315         {
1316             list = defaultValue;
1317         }
1318         else if (value instanceof BigDecimal[])
1319         {
1320             list = new ArrayList();
1321             CollectionUtils.addAll(list, (BigDecimal[]) value);
1322         }
1323         else if (value instanceof Collection)
1324         {
1325             Collection values = (Collection) value;
1326             list = new ArrayList();
1327 
1328             Iterator it = values.iterator();
1329             while (it.hasNext())
1330             {
1331                 list.add(PropertyConverter.toBigDecimal(interpolate(it.next())));
1332             }
1333         }
1334         else
1335         {
1336             try
1337             {
1338                 // attempt to convert a single value
1339                 list = new ArrayList();
1340                 list.add(PropertyConverter.toBigDecimal(interpolate(value)));
1341             }
1342             catch (ConversionException e)
1343             {
1344                 throw new ConversionException('\'' + key + "' doesn't map to a list of big decimals", e);
1345             }
1346         }
1347 
1348         return list;
1349     }
1350 
1351     /***
1352      * Get an array of BigDecimals associated with the given
1353      * configuration key. If the key doesn't map to an existing object
1354      * an empty array is returned.
1355      *
1356      * @param key The configuration key.
1357      * @return The associated BigDecimal array if the key is found.
1358      *
1359      * @throws ConversionException is thrown if the key maps to an
1360      *         object that is not a list of BigDecimals.
1361      */
1362     public BigDecimal[] getBigDecimalArray(String key)
1363     {
1364         return getBigDecimalArray(key, new BigDecimal[0]);
1365     }
1366 
1367     /***
1368      * Get an array of BigDecimals associated with the given
1369      * configuration key. If the key doesn't map to an existing object
1370      * an empty array is returned.
1371      *
1372      * @param key The configuration key.
1373      * @param defaultValue the default value, which will be returned if the property is not found
1374      * @return The associated BigDecimal array if the key is found.
1375      *
1376      * @throws ConversionException is thrown if the key maps to an
1377      *         object that is not a list of BigDecimals.
1378      */
1379     public BigDecimal[] getBigDecimalArray(String key, BigDecimal[] defaultValue)
1380     {
1381         List list = getBigDecimalList(key);
1382         if (list.isEmpty())
1383         {
1384             return defaultValue;
1385         }
1386         else
1387         {
1388             return (BigDecimal[]) list.toArray(new BigDecimal[list.size()]);
1389         }
1390     }
1391 
1392     /***
1393      * Get an URL associated with the given configuration key.
1394      *
1395      * @param key The configuration key.
1396      * @return The associated URL.
1397      *
1398      * @throws ConversionException is thrown if the key maps to an
1399      *         object that is not an URL.
1400      */
1401     public URL getURL(String key)
1402     {
1403         return getURL(key, null);
1404     }
1405 
1406     /***
1407      * Get an URL associated with the given configuration key.
1408      * If the key doesn't map to an existing object, the default value
1409      * is returned.
1410      *
1411      * @param key          The configuration key.
1412      * @param defaultValue The default value.
1413      * @return The associated URL.
1414      *
1415      * @throws ConversionException is thrown if the key maps to an
1416      *         object that is not an URL.
1417      */
1418     public URL getURL(String key, URL defaultValue)
1419     {
1420         Object value = resolveContainerStore(key);
1421 
1422         if (value == null)
1423         {
1424             return defaultValue;
1425         }
1426         else
1427         {
1428             try
1429             {
1430                 return PropertyConverter.toURL(interpolate(value));
1431             }
1432             catch (ConversionException e)
1433             {
1434                 throw new ConversionException('\'' + key + "' doesn't map to an URL", e);
1435             }
1436         }
1437     }
1438 
1439     /***
1440      * Get a list of URLs associated with the given configuration key.
1441      * If the key doesn't map to an existing object an empty list is returned.
1442      *
1443      * @param key The configuration key.
1444      * @return The associated URL list if the key is found.
1445      *
1446      * @throws ConversionException is thrown if the key maps to an
1447      *         object that is not a list of URLs.
1448      */
1449     public List getURLList(String key)
1450     {
1451         return getURLList(key, new ArrayList());
1452     }
1453 
1454     /***
1455      * Get a list of URLs associated with the given configuration key.
1456      * If the key doesn't map to an existing object, the default value is
1457      * returned.
1458      *
1459      * @param key The configuration key.
1460      * @param defaultValue The default value.
1461      * @return The associated List of URLs.
1462      *
1463      * @throws ConversionException is thrown if the key maps to an
1464      *         object that is not a list of URLs.
1465      */
1466     public List getURLList(String key, List defaultValue)
1467     {
1468         Object value = getProperty(key);
1469 
1470         List list;
1471 
1472         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
1473         {
1474             list = defaultValue;
1475         }
1476         else if (value instanceof URL[])
1477         {
1478             list = new ArrayList();
1479             CollectionUtils.addAll(list, (URL[]) value);
1480         }
1481         else if (value instanceof Collection)
1482         {
1483             Collection values = (Collection) value;
1484             list = new ArrayList();
1485 
1486             Iterator it = values.iterator();
1487             while (it.hasNext())
1488             {
1489                 list.add(PropertyConverter.toURL(interpolate(it.next())));
1490             }
1491         }
1492         else
1493         {
1494             try
1495             {
1496                 // attempt to convert a single value
1497                 list = new ArrayList();
1498                 list.add(PropertyConverter.toURL(interpolate(value)));
1499             }
1500             catch (ConversionException e)
1501             {
1502                 throw new ConversionException('\'' + key + "' doesn't map to a list of URLs", e);
1503             }
1504         }
1505 
1506         return list;
1507     }
1508 
1509     /***
1510      * Get an array of URLs associated with the given configuration key.
1511      * If the key doesn't map to an existing object an empty array is returned.
1512      *
1513      * @param key The configuration key.
1514      * @return The associated URL array if the key is found.
1515      *
1516      * @throws ConversionException is thrown if the key maps to an
1517      *         object that is not a list of URLs.
1518      */
1519     public URL[] getURLArray(String key)
1520     {
1521         return getURLArray(key, new URL[0]);
1522     }
1523 
1524     /***
1525      * Get an array of URLs associated with the given configuration key.
1526      * If the key doesn't map to an existing object an empty array is returned.
1527      *
1528      * @param key The configuration key.
1529      * @param defaultValue the default value, which will be returned if the property is not found
1530      * @return The associated URL array if the key is found.
1531      *
1532      * @throws ConversionException is thrown if the key maps to an
1533      *         object that is not a list of URLs.
1534      */
1535     public URL[] getURLArray(String key, URL[] defaultValue)
1536     {
1537         List list = getURLList(key);
1538         if (list.isEmpty())
1539         {
1540             return defaultValue;
1541         }
1542         else
1543         {
1544             return (URL[]) list.toArray(new URL[list.size()]);
1545         }
1546     }
1547 
1548     /***
1549      * Get a Date associated with the given configuration key. If the property
1550      * is a String, it will be parsed with the format defined by the user in
1551      * the {@link #DATE_FORMAT_KEY} property, or if it's not defined with the
1552      * {@link #DEFAULT_DATE_FORMAT} pattern.
1553      *
1554      * @param key The configuration key.
1555      * @return The associated Date.
1556      *
1557      * @throws ConversionException is thrown if the key maps to an
1558      *         object that is not a Date.
1559      */
1560     public Date getDate(String key)
1561     {
1562         return getDate(key, getDefaultDateFormat());
1563     }
1564 
1565     /***
1566      * Get a Date associated with the given configuration key. If the property
1567      * is a String, it will be parsed with the specified format pattern.
1568      *
1569      * @param key    The configuration key.
1570      * @param format The non-localized {@link java.text.DateFormat} pattern.
1571      * @return The associated Date
1572      *
1573      * @throws ConversionException is thrown if the key maps to an
1574      *         object that is not a Date.
1575      */
1576     public Date getDate(String key, String format)
1577     {
1578         return getDate(key, null, format);
1579     }
1580 
1581     /***
1582      * Get a Date associated with the given configuration key. If the property
1583      * is a String, it will be parsed with the format defined by the user in
1584      * the {@link #DATE_FORMAT_KEY} property, or if it's not defined with the
1585      * {@link #DEFAULT_DATE_FORMAT} pattern. If the key doesn't map to an
1586      * existing object, the default value is returned.
1587      *
1588      * @param key          The configuration key.
1589      * @param defaultValue The default value.
1590      * @return The associated Date.
1591      *
1592      * @throws ConversionException is thrown if the key maps to an
1593      *         object that is not a Date.
1594      */
1595     public Date getDate(String key, Date defaultValue)
1596     {
1597         return getDate(key, defaultValue, getDefaultDateFormat());
1598     }
1599 
1600     /***
1601      * Get a Date associated with the given configuration key. If the property
1602      * is a String, it will be parsed with the specified format pattern.
1603      * If the key doesn't map to an existing object, the default value
1604      * is returned.
1605      *
1606      * @param key          The configuration key.
1607      * @param defaultValue The default value.
1608      * @param format       The non-localized {@link java.text.DateFormat} pattern.
1609      * @return The associated Date.
1610      *
1611      * @throws ConversionException is thrown if the key maps to an
1612      *         object that is not a Date.
1613      */
1614     public Date getDate(String key, Date defaultValue, String format)
1615     {
1616         Object value = resolveContainerStore(key);
1617 
1618         if (value == null)
1619         {
1620             return defaultValue;
1621         }
1622         else
1623         {
1624             try
1625             {
1626                 return PropertyConverter.toDate(interpolate(value), format);
1627             }
1628             catch (ConversionException e)
1629             {
1630                 throw new ConversionException('\'' + key + "' doesn't map to a Date", e);
1631             }
1632         }
1633     }
1634 
1635     /***
1636      * Get a list of Dates associated with the given configuration key.
1637      * If the property is a list of Strings, they will be parsed with the
1638      * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1639      * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1640      * If the key doesn't map to an existing object an empty list is returned.
1641      *
1642      * @param key The configuration key.
1643      * @return The associated Date list if the key is found.
1644      *
1645      * @throws ConversionException is thrown if the key maps to an
1646      *         object that is not a list of Dates.
1647      */
1648     public List getDateList(String key)
1649     {
1650         return getDateList(key, new ArrayList());
1651     }
1652 
1653     /***
1654      * Get a list of Dates associated with the given configuration key.
1655      * If the property is a list of Strings, they will be parsed with the
1656      * specified format pattern. If the key doesn't map to an existing object
1657      * an empty list is returned.
1658      *
1659      * @param key    The configuration key.
1660      * @param format The non-localized {@link java.text.DateFormat} pattern.
1661      * @return The associated Date list if the key is found.
1662      *
1663      * @throws ConversionException is thrown if the key maps to an
1664      *         object that is not a list of Dates.
1665      */
1666     public List getDateList(String key, String format)
1667     {
1668         return getDateList(key, new ArrayList(), format);
1669     }
1670 
1671     /***
1672      * Get a list of Dates associated with the given configuration key.
1673      * If the property is a list of Strings, they will be parsed with the
1674      * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1675      * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1676      * If the key doesn't map to an existing object, the default value is
1677      * returned.
1678      *
1679      * @param key          The configuration key.
1680      * @param defaultValue The default value.
1681      * @return The associated Date list if the key is found.
1682      *
1683      * @throws ConversionException is thrown if the key maps to an
1684      *         object that is not a list of Dates.
1685      */
1686     public List getDateList(String key, List defaultValue)
1687     {
1688         return getDateList(key, defaultValue, getDefaultDateFormat());
1689     }
1690 
1691     /***
1692      * Get a list of Dates associated with the given configuration key.
1693      * If the property is a list of Strings, they will be parsed with the
1694      * specified format pattern. If the key doesn't map to an existing object,
1695      * the default value is returned.
1696      *
1697      * @param key          The configuration key.
1698      * @param defaultValue The default value.
1699      * @param format       The non-localized {@link java.text.DateFormat} pattern.
1700      * @return The associated Date list if the key is found.
1701      *
1702      * @throws ConversionException is thrown if the key maps to an
1703      *         object that is not a list of Dates.
1704      */
1705     public List getDateList(String key, List defaultValue, String format)
1706     {
1707         Object value = getProperty(key);
1708 
1709         List list;
1710 
1711         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
1712         {
1713             list = defaultValue;
1714         }
1715         else if (value instanceof Date[])
1716         {
1717             list = new ArrayList();
1718             CollectionUtils.addAll(list, (Date[]) value);
1719         }
1720         else if (value instanceof Calendar[])
1721         {
1722             list = new ArrayList();
1723             Calendar[] values = (Calendar[]) value;
1724 
1725             for (int i = 0; i < values.length; i++)
1726             {
1727                 list.add(values[i].getTime());
1728             }
1729         }
1730         else if (value instanceof Collection)
1731         {
1732             Collection values = (Collection) value;
1733             list = new ArrayList();
1734 
1735             Iterator it = values.iterator();
1736             while (it.hasNext())
1737             {
1738                 list.add(PropertyConverter.toDate(interpolate(it.next()), format));
1739             }
1740         }
1741         else
1742         {
1743             try
1744             {
1745                 // attempt to convert a single value
1746                 list = new ArrayList();
1747                 list.add(PropertyConverter.toDate(interpolate(value), format));
1748             }
1749             catch (ConversionException e)
1750             {
1751                 throw new ConversionException('\'' + key + "' doesn't map to a list of Dates", e);
1752             }
1753         }
1754 
1755         return list;
1756     }
1757 
1758     /***
1759      * Get an array of Dates associated with the given configuration key.
1760      * If the property is a list of Strings, they will be parsed with the
1761      * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1762      * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1763      * If the key doesn't map to an existing object an empty array is returned.
1764      *
1765      * @param key The configuration key.
1766      * @return The associated Date array if the key is found.
1767      *
1768      * @throws ConversionException is thrown if the key maps to an
1769      *         object that is not a list of Dates.
1770      */
1771     public Date[] getDateArray(String key)
1772     {
1773         return getDateArray(key, new Date[0]);
1774     }
1775 
1776     /***
1777      * Get an array of Dates associated with the given configuration key.
1778      * If the property is a list of Strings, they will be parsed with the
1779      * specified format pattern. If the key doesn't map to an existing object
1780      * an empty array is returned.
1781      *
1782      * @param key    The configuration key.
1783      * @param format The non-localized {@link java.text.DateFormat} pattern.
1784      * @return The associated Date array if the key is found.
1785      *
1786      * @throws ConversionException is thrown if the key maps to an
1787      *         object that is not a list of Dates.
1788      */
1789     public Date[] getDateArray(String key, String format)
1790     {
1791         return getDateArray(key, new Date[0], format);
1792     }
1793 
1794     /***
1795      * Get an array of Dates associated with the given configuration key.
1796      * If the property is a list of Strings, they will be parsed with the
1797      * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1798      * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1799      * If the key doesn't map to an existing object an empty array is returned.
1800      *
1801      * @param key The configuration key.
1802      * @param defaultValue the default value, which will be returned if the property is not found
1803      * @return The associated Date array if the key is found.
1804      *
1805      * @throws ConversionException is thrown if the key maps to an
1806      *         object that is not a list of Dates.
1807      */
1808     public Date[] getDateArray(String key, Date[] defaultValue)
1809     {
1810         return getDateArray(key, defaultValue, getDefaultDateFormat());
1811     }
1812 
1813     /***
1814      * Get an array of Dates associated with the given configuration key.
1815      * If the property is a list of Strings, they will be parsed with the
1816      * specified format pattern. If the key doesn't map to an existing object,
1817      * the default value is returned.
1818      *
1819      * @param key          The configuration key.
1820      * @param defaultValue The default value.
1821      * @param format       The non-localized {@link java.text.DateFormat} pattern.
1822      * @return The associated Date array if the key is found.
1823      *
1824      * @throws ConversionException is thrown if the key maps to an
1825      *         object that is not a list of Dates.
1826      */
1827     public Date[] getDateArray(String key, Date[] defaultValue, String format)
1828     {
1829         List list = getDateList(key, format);
1830         if (list.isEmpty())
1831         {
1832             return defaultValue;
1833         }
1834         else
1835         {
1836             return (Date[]) list.toArray(new Date[list.size()]);
1837         }
1838     }
1839 
1840     /***
1841      * Get a Calendar associated with the given configuration key. If the
1842      * property is a String, it will be parsed with the format defined by the
1843      * user in the {@link #DATE_FORMAT_KEY} property, or if it's not defined
1844      * with the {@link #DEFAULT_DATE_FORMAT} pattern.
1845      *
1846      * @param key The configuration key.
1847      * @return The associated Calendar.
1848      *
1849      * @throws ConversionException is thrown if the key maps to an
1850      *         object that is not a Calendar.
1851      */
1852     public Calendar getCalendar(String key)
1853     {
1854         return getCalendar(key, getDefaultDateFormat());
1855     }
1856 
1857     /***
1858      * Get a Calendar associated with the given configuration key. If the
1859      * property is a String, it will be parsed with the specified format
1860      * pattern.
1861      *
1862      * @param key    The configuration key.
1863      * @param format The non-localized {@link java.text.DateFormat} pattern.
1864      * @return The associated Calendar
1865      *
1866      * @throws ConversionException is thrown if the key maps to an
1867      *         object that is not a Calendar.
1868      */
1869     public Calendar getCalendar(String key, String format)
1870     {
1871         return getCalendar(key, null, format);
1872     }
1873 
1874     /***
1875      * Get a Calendar associated with the given configuration key. If the
1876      * property is a String, it will be parsed with the format defined by the
1877      * user in the {@link #DATE_FORMAT_KEY} property, or if it's not defined
1878      * with the {@link #DEFAULT_DATE_FORMAT} pattern. If the key doesn't map
1879      * to an existing object, the default value is returned.
1880      *
1881      * @param key          The configuration key.
1882      * @param defaultValue The default value.
1883      * @return The associated Calendar.
1884      *
1885      * @throws ConversionException is thrown if the key maps to an
1886      *         object that is not a Calendar.
1887      */
1888     public Calendar getCalendar(String key, Calendar defaultValue)
1889     {
1890         return getCalendar(key, defaultValue, getDefaultDateFormat());
1891     }
1892 
1893     /***
1894      * Get a Calendar associated with the given configuration key. If the
1895      * property is a String, it will be parsed with the specified format
1896      * pattern. If the key doesn't map to an existing object, the default
1897      * value is returned.
1898      *
1899      * @param key          The configuration key.
1900      * @param defaultValue The default value.
1901      * @param format       The non-localized {@link java.text.DateFormat} pattern.
1902      * @return The associated Calendar.
1903      *
1904      * @throws ConversionException is thrown if the key maps to an
1905      *         object that is not a Calendar.
1906      */
1907     public Calendar getCalendar(String key, Calendar defaultValue, String format)
1908     {
1909         Object value = resolveContainerStore(key);
1910 
1911         if (value == null)
1912         {
1913             return defaultValue;
1914         }
1915         else
1916         {
1917             try
1918             {
1919                 return PropertyConverter.toCalendar(interpolate(value), format);
1920             }
1921             catch (ConversionException e)
1922             {
1923                 throw new ConversionException('\'' + key + "' doesn't map to a Calendar", e);
1924             }
1925         }
1926     }
1927 
1928     /***
1929      * Get a list of Calendars associated with the given configuration key.
1930      * If the property is a list of Strings, they will be parsed with the
1931      * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1932      * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1933      * If the key doesn't map to an existing object an empty list is returned.
1934      *
1935      * @param key The configuration key.
1936      * @return The associated Calendar list if the key is found.
1937      *
1938      * @throws ConversionException is thrown if the key maps to an
1939      *         object that is not a list of Calendars.
1940      */
1941     public List getCalendarList(String key)
1942     {
1943         return getCalendarList(key, new ArrayList());
1944     }
1945 
1946     /***
1947      * Get a list of Calendars associated with the given configuration key.
1948      * If the property is a list of Strings, they will be parsed with the
1949      * specified format pattern. If the key doesn't map to an existing object
1950      * an empty list is returned.
1951      *
1952      * @param key    The configuration key.
1953      * @param format The non-localized {@link java.text.DateFormat} pattern.
1954      * @return The associated Calendar list if the key is found.
1955      *
1956      * @throws ConversionException is thrown if the key maps to an
1957      *         object that is not a list of Calendars.
1958      */
1959     public List getCalendarList(String key, String format)
1960     {
1961         return getCalendarList(key, new ArrayList(), format);
1962     }
1963 
1964     /***
1965      * Get a list of Calendars associated with the given configuration key.
1966      * If the property is a list of Strings, they will be parsed with the
1967      * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
1968      * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
1969      * If the key doesn't map to an existing object, the default value is
1970      * returned.
1971      *
1972      * @param key The configuration key.
1973      * @param defaultValue The default value.
1974      * @return The associated Calendar list if the key is found.
1975      *
1976      * @throws ConversionException is thrown if the key maps to an
1977      *         object that is not a list of Calendars.
1978      */
1979     public List getCalendarList(String key, List defaultValue)
1980     {
1981         return getCalendarList(key, defaultValue, getDefaultDateFormat());
1982     }
1983 
1984     /***
1985      * Get a list of Calendars associated with the given configuration key.
1986      * If the property is a list of Strings, they will be parsed with the
1987      * specified format pattern. If the key doesn't map to an existing object,
1988      * the default value is returned.
1989      *
1990      * @param key          The configuration key.
1991      * @param defaultValue The default value.
1992      * @param format       The non-localized {@link java.text.DateFormat} pattern.
1993      * @return The associated Calendar list if the key is found.
1994      *
1995      * @throws ConversionException is thrown if the key maps to an
1996      *         object that is not a list of Calendars.
1997      */
1998     public List getCalendarList(String key, List defaultValue, String format)
1999     {
2000         Object value = getProperty(key);
2001 
2002         List list;
2003 
2004         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
2005         {
2006             list = defaultValue;
2007         }
2008         else if (value instanceof Calendar[])
2009         {
2010             list = new ArrayList();
2011             CollectionUtils.addAll(list, (Calendar[]) value);
2012         }
2013         else if (value instanceof Date[])
2014         {
2015             list = new ArrayList();
2016             Date[] values = (Date[]) value;
2017 
2018             for (int i = 0; i < values.length; i++)
2019             {
2020                 Calendar calendar = Calendar.getInstance();
2021                 calendar.setTime(values[i]);
2022                 list.add(calendar);
2023             }
2024         }
2025         else if (value instanceof Collection)
2026         {
2027             Collection values = (Collection) value;
2028             list = new ArrayList();
2029 
2030             Iterator it = values.iterator();
2031             while (it.hasNext())
2032             {
2033                 list.add(PropertyConverter.toCalendar(interpolate(it.next()), format));
2034             }
2035         }
2036         else
2037         {
2038             try
2039             {
2040                 // attempt to convert a single value
2041                 list = new ArrayList();
2042                 list.add(PropertyConverter.toCalendar(interpolate(value), format));
2043             }
2044             catch (ConversionException e)
2045             {
2046                 throw new ConversionException('\'' + key + "' doesn't map to a list of Calendars", e);
2047             }
2048         }
2049 
2050         return list;
2051     }
2052 
2053     /***
2054      * Get an array of Calendars associated with the given configuration key.
2055      * If the property is a list of Strings, they will be parsed with the
2056      * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
2057      * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
2058      * If the key doesn't map to an existing object an empty array is returned.
2059      *
2060      * @param key The configuration key.
2061      * @return The associated Calendar array if the key is found.
2062      *
2063      * @throws ConversionException is thrown if the key maps to an
2064      *         object that is not a list of Calendars.
2065      */
2066     public Calendar[] getCalendarArray(String key)
2067     {
2068         return getCalendarArray(key, new Calendar[0]);
2069     }
2070 
2071     /***
2072      * Get an array of Calendars associated with the given configuration key.
2073      * If the property is a list of Strings, they will be parsed with the
2074      * specified format pattern. If the key doesn't map to an existing object
2075      * an empty array is returned.
2076      *
2077      * @param key    The configuration key.
2078      * @param format The non-localized {@link java.text.DateFormat} pattern.
2079      * @return The associated Calendar array if the key is found.
2080      *
2081      * @throws ConversionException is thrown if the key maps to an
2082      *         object that is not a list of Calendars.
2083      */
2084     public Calendar[] getCalendarArray(String key, String format)
2085     {
2086         return getCalendarArray(key, new Calendar[0], format);
2087     }
2088 
2089     /***
2090      * Get an array of Calendars associated with the given configuration key.
2091      * If the property is a list of Strings, they will be parsed with the
2092      * format defined by the user in the {@link #DATE_FORMAT_KEY} property,
2093      * or if it's not defined with the {@link #DEFAULT_DATE_FORMAT} pattern.
2094      * If the key doesn't map to an existing object an empty array is returned.
2095      *
2096      * @param key The configuration key.
2097      * @param defaultValue the default value, which will be returned if the property is not found
2098      * @return The associated Calendar array if the key is found.
2099      *
2100      * @throws ConversionException is thrown if the key maps to an
2101      *         object that is not a list of Calendars.
2102      */
2103     public Calendar[] getCalendarArray(String key, Calendar[] defaultValue)
2104     {
2105         return getCalendarArray(key, defaultValue, getDefaultDateFormat());
2106     }
2107 
2108     /***
2109      * Get an array of Calendars associated with the given configuration key.
2110      * If the property is a list of Strings, they will be parsed with the
2111      * specified format pattern. If the key doesn't map to an existing object,
2112      * the default value is returned.
2113      *
2114      * @param key          The configuration key.
2115      * @param defaultValue The default value.
2116      * @param format       The non-localized {@link java.text.DateFormat} pattern.
2117      * @return The associated Calendar array if the key is found.
2118      *
2119      * @throws ConversionException is thrown if the key maps to an
2120      *         object that is not a list of Calendars.
2121      */
2122     public Calendar[] getCalendarArray(String key, Calendar[] defaultValue, String format)
2123     {
2124         List list = getCalendarList(key, format);
2125         if (list.isEmpty())
2126         {
2127             return defaultValue;
2128         }
2129         else
2130         {
2131             return (Calendar[]) list.toArray(new Calendar[list.size()]);
2132         }
2133     }
2134 
2135     /***
2136      * Returns the date format specified by the user in the DATE_FORMAT_KEY
2137      * property, or the default format otherwise.
2138      *
2139      * @return the default date format
2140      */
2141     private String getDefaultDateFormat()
2142     {
2143         return getString(DATE_FORMAT_KEY, DEFAULT_DATE_FORMAT);
2144     }
2145 
2146     /***
2147      * Get a Locale associated with the given configuration key.
2148      *
2149      * @param key The configuration key.
2150      * @return The associated Locale.
2151      *
2152      * @throws ConversionException is thrown if the key maps to an
2153      *         object that is not a Locale.
2154      */
2155     public Locale getLocale(String key)
2156     {
2157         return getLocale(key, null);
2158     }
2159 
2160     /***
2161      * Get a Locale associated with the given configuration key.
2162      * If the key doesn't map to an existing object, the default value
2163      * is returned.
2164      *
2165      * @param key          The configuration key.
2166      * @param defaultValue The default value.
2167      * @return The associated Locale.
2168      *
2169      * @throws ConversionException is thrown if the key maps to an
2170      *         object that is not a Locale.
2171      */
2172     public Locale getLocale(String key, Locale defaultValue)
2173     {
2174         Object value = resolveContainerStore(key);
2175 
2176         if (value == null)
2177         {
2178             return defaultValue;
2179         }
2180         else
2181         {
2182             try
2183             {
2184                 return PropertyConverter.toLocale(interpolate(value));
2185             }
2186             catch (ConversionException e)
2187             {
2188                 throw new ConversionException('\'' + key + "' doesn't map to a Locale", e);
2189             }
2190         }
2191     }
2192 
2193     /***
2194      * Get a list of Locales associated with the given configuration key.
2195      * If the key doesn't map to an existing object an empty list is returned.
2196      *
2197      * @param key The configuration key.
2198      * @return The associated Locale list if the key is found.
2199      *
2200      * @throws ConversionException is thrown if the key maps to an
2201      *         object that is not a list of Locales.
2202      */
2203     public List getLocaleList(String key)
2204     {
2205         return getLocaleList(key, new ArrayList());
2206     }
2207 
2208     /***
2209      * Get a list of Locales associated with the given configuration key.
2210      * If the key doesn't map to an existing object, the default value is
2211      * returned.
2212      *
2213      * @param key The configuration key.
2214      * @param defaultValue The default value.
2215      * @return The associated List of Locales.
2216      *
2217      * @throws ConversionException is thrown if the key maps to an
2218      *         object that is not a list of Locales.
2219      */
2220     public List getLocaleList(String key, List defaultValue)
2221     {
2222         Object value = getProperty(key);
2223 
2224         List list;
2225 
2226         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
2227         {
2228             list = defaultValue;
2229         }
2230         else if (value instanceof Locale[])
2231         {
2232             list = new ArrayList();
2233             CollectionUtils.addAll(list, (Locale[]) value);
2234         }
2235         else if (value instanceof Collection)
2236         {
2237             Collection values = (Collection) value;
2238             list = new ArrayList();
2239 
2240             Iterator it = values.iterator();
2241             while (it.hasNext())
2242             {
2243                 list.add(PropertyConverter.toLocale(interpolate(it.next())));
2244             }
2245         }
2246         else
2247         {
2248             try
2249             {
2250                 // attempt to convert a single value
2251                 list = new ArrayList();
2252                 list.add(PropertyConverter.toLocale(interpolate(value)));
2253             }
2254             catch (ConversionException e)
2255             {
2256                 throw new ConversionException('\'' + key + "' doesn't map to a list of Locales", e);
2257             }
2258         }
2259 
2260         return list;
2261     }
2262 
2263     /***
2264      * Get an array of Locales associated with the given
2265      * configuration key. If the key doesn't map to an existing object
2266      * an empty array is returned.
2267      *
2268      * @param key The configuration key.
2269      * @return The associated Locale array if the key is found.
2270      *
2271      * @throws ConversionException is thrown if the key maps to an
2272      *         object that is not a list of Locales.
2273      */
2274     public Locale[] getLocaleArray(String key)
2275     {
2276         return getLocaleArray(key, new Locale[0]);
2277     }
2278 
2279     /***
2280      * Get an array of Locales associated with the given
2281      * configuration key. If the key doesn't map to an existing object
2282      * an empty array is returned.
2283      *
2284      * @param key The configuration key.
2285      * @param defaultValue the default value, which will be returned if the property is not found
2286      * @return The associated Locale array if the key is found.
2287      *
2288      * @throws ConversionException is thrown if the key maps to an
2289      *         object that is not a list of Locales.
2290      */
2291     public Locale[] getLocaleArray(String key, Locale[] defaultValue)
2292     {
2293         List list = getLocaleList(key);
2294         if (list.isEmpty())
2295         {
2296             return defaultValue;
2297         }
2298         else
2299         {
2300             return (Locale[]) list.toArray(new Locale[list.size()]);
2301         }
2302     }
2303 
2304     /***
2305      * Get a Color associated with the given configuration key.
2306      *
2307      * @param key The configuration key.
2308      * @return The associated Color.
2309      *
2310      * @throws ConversionException is thrown if the key maps to an
2311      *         object that is not a Color.
2312      */
2313     public Color getColor(String key)
2314     {
2315         return getColor(key, null);
2316     }
2317 
2318     /***
2319      * Get a Color associated with the given configuration key.
2320      * If the key doesn't map to an existing object, the default value
2321      * is returned.
2322      *
2323      * @param key          The configuration key.
2324      * @param defaultValue The default value.
2325      * @return The associated Color.
2326      *
2327      * @throws ConversionException is thrown if the key maps to an
2328      *         object that is not a Color.
2329      */
2330     public Color getColor(String key, Color defaultValue)
2331     {
2332         Object value = resolveContainerStore(key);
2333 
2334         if (value == null)
2335         {
2336             return defaultValue;
2337         }
2338         else
2339         {
2340             try
2341             {
2342                 return PropertyConverter.toColor(interpolate(value));
2343             }
2344             catch (ConversionException e)
2345             {
2346                 throw new ConversionException('\'' + key + "' doesn't map to a Color", e);
2347             }
2348         }
2349     }
2350 
2351     /***
2352      * Get a list of Colors associated with the given configuration key.
2353      * If the key doesn't map to an existing object an empty list is returned.
2354      *
2355      * @param key The configuration key.
2356      * @return The associated Color list if the key is found.
2357      *
2358      * @throws ConversionException is thrown if the key maps to an
2359      *         object that is not a list of Colors.
2360      */
2361     public List getColorList(String key)
2362     {
2363         return getColorList(key, new ArrayList());
2364     }
2365 
2366     /***
2367      * Get a list of Colors associated with the given configuration key.
2368      * If the key doesn't map to an existing object, the default value is
2369      * returned.
2370      *
2371      * @param key The configuration key.
2372      * @param defaultValue The default value.
2373      * @return The associated List of Colors.
2374      *
2375      * @throws ConversionException is thrown if the key maps to an
2376      *         object that is not a list of Colors.
2377      */
2378     public List getColorList(String key, List defaultValue)
2379     {
2380         Object value = getProperty(key);
2381 
2382         List list;
2383 
2384         if (value == null || (value instanceof String && StringUtils.isEmpty((String) value)))
2385         {
2386             list = defaultValue;
2387         }
2388         else if (value instanceof Color[])
2389         {
2390             list = new ArrayList();
2391             CollectionUtils.addAll(list, (Color[]) value);
2392         }
2393         else if (value instanceof Collection)
2394         {
2395             Collection values = (Collection) value;
2396             list = new ArrayList();
2397 
2398             Iterator it = values.iterator();
2399             while (it.hasNext())
2400             {
2401                 list.add(PropertyConverter.toColor(interpolate(it.next())));
2402             }
2403         }
2404         else
2405         {
2406             try
2407             {
2408                 // attempt to convert a single value
2409                 list = new ArrayList();
2410                 list.add(PropertyConverter.toColor(interpolate(value)));
2411             }
2412             catch (ConversionException e)
2413             {
2414                 throw new ConversionException('\'' + key + "' doesn't map to a list of Colors", e);
2415             }
2416         }
2417 
2418         return list;
2419     }
2420 
2421     /***
2422      * Get an array of Colors associated with the given
2423      * configuration key. If the key doesn't map to an existing object
2424      * an empty array is returned.
2425      *
2426      * @param key The configuration key.
2427      * @return The associated Color array if the key is found.
2428      *
2429      * @throws ConversionException is thrown if the key maps to an
2430      *         object that is not a list of Colors.
2431      */
2432     public Color[] getColorArray(String key)
2433     {
2434         return getColorArray(key, new Color[0]);
2435     }
2436 
2437     /***
2438      * Get an array of Colors associated with the given
2439      * configuration key. If the key doesn't map to an existing object
2440      * an empty array is returned.
2441      *
2442      * @param key The configuration key.
2443      * @param defaultValue the default value, which will be returned if the property is not found
2444      * @return The associated Color array if the key is found.
2445      *
2446      * @throws ConversionException is thrown if the key maps to an
2447      *         object that is not a list of Colors.
2448      */
2449     public Color[] getColorArray(String key, Color[] defaultValue)
2450     {
2451         List list = getColorList(key);
2452         if (list.isEmpty())
2453         {
2454             return defaultValue;
2455         }
2456         else
2457         {
2458             return (Color[]) list.toArray(new Color[list.size()]);
2459         }
2460     }
2461 
2462 }