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 }