You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@velocity.apache.org by da...@locus.apache.org on 2000/11/02 03:51:26 UTC

cvs commit: jakarta-velocity/src/java/org/apache/velocity/runtime/configuration Configurations.java

daveb       00/11/01 18:51:26

  Added:       src/java/org/apache/velocity/runtime/configuration
                        Configurations.java
  Log:
  Moved.
  
  Revision  Changes    Path
  1.1                  jakarta-velocity/src/java/org/apache/velocity/runtime/configuration/Configurations.java
  
  Index: Configurations.java
  ===================================================================
  package org.apache.velocity.runtime.configuration;
  
  /*
   * Copyright (c) 1997-2000 The Java Apache Project.  All rights reserved.
   *
   * Redistribution and use in source and binary forms, with or without
   * modification, are permitted provided that the following conditions
   * are met:
   *
   * 1. Redistributions of source code must retain the above copyright
   *    notice, this list of conditions and the following disclaimer.
   *
   * 2. Redistributions in binary form must reproduce the above copyright
   *    notice, this list of conditions and the following disclaimer in
   *    the documentation and/or other materials provided with the
   *    distribution.
   *
   * 3. All advertising materials mentioning features or use of this
   *    software must display the following acknowledgment:
   *    "This product includes software developed by the Java Apache
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *
   * 4. The names "Apache JServ", "Apache JServ Servlet Engine", "Turbine",
   *    "Apache Turbine", "Turbine Project", "Apache Turbine Project" and
   *    "Java Apache Project" must not be used to endorse or promote products
   *    derived from this software without prior written permission.
   *
   * 5. Products derived from this software may not be called "Apache JServ"
   *    nor may "Apache" nor "Apache JServ" appear in their names without
   *    prior written permission of the Java Apache Project.
   *
   * 6. Redistributions of any form whatsoever must retain the following
   *    acknowledgment:
   *    "This product includes software developed by the Java Apache
   *    Project for use in the Apache JServ servlet engine project
   *    <http://java.apache.org/>."
   *
   * THIS SOFTWARE IS PROVIDED BY THE JAVA APACHE PROJECT "AS IS" AND ANY
   * EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
   * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
   * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE JAVA APACHE PROJECT OR
   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
   * NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
   * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
   * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
   * STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
   * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
   * OF THE POSSIBILITY OF SUCH DAMAGE.
   *
   * This software consists of voluntary contributions made by many
   * individuals on behalf of the Java Apache Group. For more information
   * on the Java Apache Project and the Apache JServ Servlet Engine project,
   * please see <http://java.apache.org/>.
   *
   */
  
  // Java stuff.
  import java.util.*;
  import java.io.*;
  
  /**
   * This class is used to encapsulate properties and addresses the need
   * for a flexible, portable and fast configurations repository.
   *
   * <p>While properties are just considered as strings, configurations
   * have methods to return different types such as <b>int</b> and
   * <b>long</b>.
   *
   * <p>Performance is needed to avoid the use of properties only at
   * startup to fill variables: configurations encapsulate properties in
   * the sense that objects retrieved by parsing property strings are
   * stored for faster reuse.  This allows a program to use
   * configurations instead of global variables in a central repository,
   * that, if updated, will reflect instantly the changes throughout the
   * whole application.
   *
   * <p>The behavior of this class is syntax-independent because it's
   * only an encapsulator.  This allows greater flexibility through the
   * use of syntax abstraction and faster transition between different
   * configuration syntax.
   *
   * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
   * @version $Id: Configurations.java,v 1.1 2000/11/02 02:51:26 daveb Exp $
   */
  public class Configurations
  {
      /**
       * Default configurations repository.
       */
      private Configurations defaults;
  
      /**
       * Configuration repository.
       */
      private ConfigurationsRepository repository;
  
      /**
       * Creates an empty configuration repository with no default
       * values.
       */
      public Configurations()
      {
          this(null, null);
      }
  
      /**
       * Creates a configuration repository encapsulating the given
       * properties with no default values.
       *
       * @param properties The properties to encapsulate.
       */
      public Configurations(ConfigurationsRepository properties)
      {
          this(properties, null);
      }
  
      /**
       * Creates an empty configuration repository with the specified
       * defaults.
       *
       * @param defaults The default values repository.
       */
      public Configurations(Configurations defaults)
      {
          this(null, defaults);
      }
  
      /**
       * Merge the given properties object as configurations.
       *
       * @param properties The properties file to merge.
       * @param defaults The default values repository.
       */
      public Configurations(ConfigurationsRepository properties,
                            Configurations defaults)
      {
          this.repository = properties;
          this.defaults = defaults;
      }
  
      /**
       * Get encapsulated configuration repository.
       *
       * @return A Hashtable.
       */
      public Hashtable getRepository()
      {
          return this.repository;
      }
  
      /**
       * Get the list of the keys contained in the configuration
       * repository.
       *
       * @return An Enumeration.
       */
      public Enumeration getKeys()
      {
          return this.repository.keys();
      }
  
      /**
       * Get the list of the keys contained in the configuration
       * repository that match the specified prefix.
       *
       * @param prefix The prefix to test against.
       * @return An Enumeration of keys that match the prefix.
       */
      public Enumeration getKeys(String prefix)
      {
          Enumeration keys = this.repository.keys();
          Vector matchingKeys = new Vector();
          while( keys.hasMoreElements() )
          {
              Object key = keys.nextElement();
              if( key instanceof String &&
                  ((String) key).startsWith(prefix) )
              {
                  matchingKeys.addElement(key);
              }
          }
          return matchingKeys.elements();
      }
  
      /**
       * Get a string associated with the given configuration key.
       *
       * @param key The configuration key.
       * @return The associated string.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a String.
       */
      public String getString(String key)
      {
          return this.getString(key, null);
      }
  
      /**
       * Get a string associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated string if key is found,
       * default value otherwise.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a String.
       */
      public String getString(String key,
                              String defaultValue)
      {
          Object value = repository.get(key);
  
          if (value instanceof String)
          {
              return (String) value;
          }
          else if (value == null)
          {
              if (defaults != null)
              {
                  return defaults.getString(key, defaultValue);
              }
              else
              {
                  return defaultValue;
              }
          }
          else
          {
              throw new ClassCastException(key +
                                           " doesn't map to a String object");
          }
      }
  
      /**
       * Get a list of properties associated with the given
       * configuration key.
       *
       * @param key The configuration key.
       * @return The associated properties if key is found.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a String/Vector.
       * @exception IllegalArgumentException if one of the tokens is
       * malformed (does not contain an equals sign).
       */
      public Properties getProperties(String key)
      {
          return getProperties(key, new Properties());
      }
  
      /**
       * Get a list of properties associated with the given
       * configuration key.
       *
       * @param key The configuration key.
       * @return The associated properties if key is found.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a String/Vector.
       * @exception IllegalArgumentException if one of the tokens is
       * malformed (does not contain an equals sign).
       */
      public Properties getProperties(String key,
                                      Properties defaults)
      {
          // Grab an array of the tokens for this key.
          String[] tokens = getStringArray(key);
  
          // Each token is of the form 'key=value'.
          Properties props = new Properties(defaults);
          for (int i = 0; i < tokens.length; i++)
          {
              String token = tokens[i];
              int equalSign = token.indexOf('=');
              if (equalSign > 0)
              {
                  String pkey = token.substring(0, equalSign).trim();
                  String pvalue = token.substring(equalSign + 1).trim();
                  props.put(pkey, pvalue);
              }
              else
              {
                  throw new IllegalArgumentException("'" +
                                                     token +
                                                     "' does not contain " +
                                                     "an equals sign");
              }
          }
          return props;
      }
  
      /**
       * Get an array of strings associated with the given configuration
       * key.
       *
       * @param key The configuration key.
       * @return The associated string array if key is found.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a String/Vector.
       */
      public String[] getStringArray(String key)
      {
          Object value = repository.get(key);
  
          // What's your vector, Victor?
          Vector vector;
          if (value instanceof String)
          {
              vector = new Vector(1);
              vector.addElement(value);
          }
          else if (value instanceof Vector)
          {
              vector = (Vector)value;
          }
          else if (value == null)
          {
              if (defaults != null)
              {
                  return defaults.getStringArray(key);
              }
              else
              {
                  return new String[0];
              }
          }
          else
          {
              throw new ClassCastException(key +
                                           " doesn't map to a" +
                                           " String/Vector object");
          }
  
          String[] tokens = new String[vector.size()];
          for (int i = 0; i < tokens.length; i++)
          tokens[i] = (String)vector.elementAt(i);
  
          return tokens;
      }
  
      /**
       * Get a list of strings associated with the given configuration
       * key.
       *
       * @param key The configuration key.
       * @return The associated Enumeration.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Vector.
       */
      public Enumeration getList(String key)
      {
          return this.getVector(key, null).elements();
      }
  
      /**
       * Get a Vector of strings associated with the given configuration
       * key.
       *
       * @param key The configuration key.
       * @return The associated Vector.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Vector.
       */
      public Vector getVector(String key)
      {
          return this.getVector(key, null);
      }
  
      /**
       * Get a Vector of strings associated with the given configuration
       * key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated Vector.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Vector.
       */
      public Vector getVector(String key,
                              Vector defaultValue)
      {
          Object value = repository.get(key);
  
          if (value instanceof Vector)
          {
              return (Vector) value;
          }
          else if (value instanceof String)
          {
              Vector v = new Vector(1);
              v.addElement((String) value);
              repository.put(key, v);
              return v;
          }
          else if (value == null)
          {
              if (defaults != null)
              {
                  return defaults.getVector(key, defaultValue);
              }
              else
              {
                  return ((defaultValue == null) ?
                          new Vector() : defaultValue);
              }
          }
          else
          {
              throw new ClassCastException(key +
                                           " doesn't map to a Vector object");
          }
      }
  
      /**
       * Get a boolean associated with the given configuration key.
       *
       * @param key The configuration key.
       * @return The associated boolean.
       * @exception NoSuchElementException is thrown if the key doesn't
       * map to an existing object.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Boolean.
       */
      public boolean getBoolean(String key)
      {
          Boolean b = this.getBoolean(key, (Boolean) null);
          if (b != null)
          {
              return b.booleanValue();
          }
          else
          {
              throw new NoSuchElementException(key +
                                               " doesn't map to an" +
                                               " existing object");
          }
      }
  
      /**
       * Get a boolean associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated boolean.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Boolean.
       */
      public boolean getBoolean(String key,
                                boolean defaultValue)
      {
          return this.getBoolean(key,
                                 new Boolean(defaultValue)).booleanValue();
      }
  
      /**
       * Get a boolean associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated boolean if key is found and has valid
       * format, default value otherwise.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Boolean.
       */
      public Boolean getBoolean(String key,
                                Boolean defaultValue)
      {
          Object value = repository.get(key);
  
          if (value instanceof Boolean)
          {
              return (Boolean) value;
          }
          else if (value instanceof String)
          {
              Boolean b = new Boolean((String) value);
              repository.put(key, b);
              return b;
          }
          else if (value == null)
          {
              if (defaults != null)
              {
                  return defaults.getBoolean(key, defaultValue);
              }
              else
              {
                  return defaultValue;
              }
          }
          else
          {
              throw new ClassCastException(key +
                                           " doesn't map to a Boolean object");
          }
      }
  
      /**
       * Get a byte associated with the given configuration key.
       *
       * @param key The configuration key.
       * @return The associated byte.
       * @exception NoSuchElementException is thrown if the key doesn't
       * map to an existing object.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Byte.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public byte getByte(String key)
      {
          Byte b = this.getByte(key, null);
          if (b != null)
          {
              return b.byteValue();
          }
          else
          {
              throw new NoSuchElementException(key +
                                               " doesn't map to an" +
                                               " existing object");
          }
      }
  
      /**
       * Get a byte associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated byte.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Byte.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public byte getByte(String key,
                          byte defaultValue)
      {
          return this.getByte(key, new Byte(defaultValue)).byteValue();
      }
  
      /**
       * Get a byte associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated byte if key is found and has valid
       * format, default value otherwise.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Byte.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public Byte getByte(String key,
                          Byte defaultValue)
      {
          Object value = repository.get(key);
  
          if (value instanceof Byte)
          {
              return (Byte) value;
          }
          else if (value instanceof String)
          {
              Byte b = new Byte((String) value);
              repository.put(key, b);
              return b;
          }
          else if (value == null)
          {
              if (defaults != null)
              {
                  return defaults.getByte(key, defaultValue);
              }
              else
              {
                  return defaultValue;
              }
          }
          else
          {
              throw new ClassCastException(key +
                                           " doesn't map to a Byte object");
          }
      }
  
      /**
       * Get a short associated with the given configuration key.
       *
       * @param key The configuration key.
       * @return The associated short.
       * @exception NoSuchElementException is thrown if the key doesn't
       * map to an existing object.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Short.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public short getShort(String key)
      {
          Short s = this.getShort(key, null);
          if (s != null)
          {
              return s.shortValue();
          }
          else
          {
              throw new NoSuchElementException(key +
                                               " doesn't map to an" +
                                               " existing object");
          }
      }
  
      /**
       * Get a short associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated short.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Short.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public short getShort(String key,
                            short defaultValue)
      {
          return this.getShort(key, new Short(defaultValue)).shortValue();
      }
  
      /**
       * Get a short associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated short if key is found and has valid
       * format, default value otherwise.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Short.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public Short getShort(String key,
                            Short defaultValue)
      {
          Object value = repository.get(key);
  
          if (value instanceof Short)
          {
              return (Short) value;
          }
          else if (value instanceof String)
          {
              Short s = new Short((String) value);
              repository.put(key, s);
              return s;
          }
          else if (value == null)
          {
              if (defaults != null)
              {
                  return defaults.getShort(key, defaultValue);
              }
              else
              {
                  return defaultValue;
              }
          }
          else
          {
              throw new ClassCastException(key +
                                           " doesn't map to a Short object");
          }
      }
  
      /**
       * Get a int associated with the given configuration key.
       *
       * @param key The configuration key.
       * @return The associated int.
       * @exception NoSuchElementException is thrown if the key doesn't
       * map to an existing object.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Integer.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public int getInteger(String key)
      {
          Integer i = this.getInteger(key, null);
          if (i != null)
          {
              return i.intValue();
          }
          else
          {
              throw new NoSuchElementException(key +
                                               " doesn't map to an" +
                                               " existing object");
          }
      }
  
      /**
       * Get a int associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated int.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Integer.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public int getInteger(String key,
                            int defaultValue)
      {
          return this.getInteger(key, new Integer(defaultValue)).intValue();
      }
  
      /**
       * Get a int associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated int if key is found and has valid
       * format, default value otherwise.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Integer.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public Integer getInteger(String key,
                                Integer defaultValue)
      {
          Object value = repository.get(key);
  
          if (value instanceof Integer)
          {
              return (Integer) value;
          }
          else if (value instanceof String)
          {
              Integer i = new Integer((String) value);
              repository.put(key, i);
              return i;
          }
          else if (value == null)
          {
              if (defaults != null)
              {
                  return defaults.getInteger(key, defaultValue);
              }
              else
              {
                  return defaultValue;
              }
          }
          else
          {
              throw new ClassCastException(key +
                                           " doesn't map to a Integer object");
          }
      }
  
      /**
       * Get a long associated with the given configuration key.
       *
       * @param key The configuration key.
       * @return The associated long.
       * @exception NoSuchElementException is thrown if the key doesn't
       * map to an existing object.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Long.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public long getLong(String key)
      {
          Long l = this.getLong(key, null);
          if (l != null)
          {
              return l.longValue();
          }
          else
          {
              throw new NoSuchElementException(key +
                                               " doesn't map to an" +
                                               " existing object");
          }
      }
  
      /**
       * Get a long associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated long.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Long.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public long getLong(String key,
                          long defaultValue)
      {
          return this.getLong(key, new Long(defaultValue)).longValue();
      }
  
      /**
       * Get a long associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated long if key is found and has valid
       * format, default value otherwise.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Long.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public Long getLong(String key,
                          Long defaultValue)
      {
          Object value = repository.get(key);
  
          if (value instanceof Long)
          {
              return (Long) value;
          }
          else if (value instanceof String)
          {
              Long l = new Long((String) value);
              repository.put(key, l);
              return l;
          }
          else if (value == null)
          {
              if (defaults != null)
              {
                  return defaults.getLong(key, defaultValue);
              }
              else
              {
                  return defaultValue;
              }
          }
          else
          {
              throw new ClassCastException(key +
                                           " doesn't map to a Long object");
          }
      }
  
      /**
       * Get a float associated with the given configuration key.
       *
       * @param key The configuration key.
       * @return The associated float.
       * @exception NoSuchElementException is thrown if the key doesn't
       * map to an existing object.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Float.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public float getFloat(String key)
      {
          Float f = this.getFloat(key, null);
          if (f != null)
          {
              return f.floatValue();
          }
          else
          {
              throw new NoSuchElementException(key +
                                               " doesn't map to an" +
                                               " existing object");
          }
      }
  
      /**
       * Get a float associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated float.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Float.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public float getFloat(String key,
                            float defaultValue)
      {
          return this.getFloat(key, new Float(defaultValue)).floatValue();
      }
  
      /**
       * Get a float associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated float if key is found and has valid
       * format, default value otherwise.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Float.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public Float getFloat(String key,
                            Float defaultValue)
      {
          Object value = repository.get(key);
  
          if (value instanceof Float)
          {
              return (Float) value;
          }
          else if (value instanceof String)
          {
              Float f = new Float((String) value);
              repository.put(key, f);
              return f;
          }
          else if (value == null)
          {
              if (defaults != null)
              {
                  return defaults.getFloat(key, defaultValue);
              }
              else
              {
                  return defaultValue;
              }
          }
          else
          {
              throw new ClassCastException(key +
                                           " doesn't map to a Float object");
          }
      }
  
      /**
       * Get a double associated with the given configuration key.
       *
       * @param key The configuration key.
       * @return The associated double.
       * @exception NoSuchElementException is thrown if the key doesn't
       * map to an existing object.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Double.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public double getDouble(String key)
      {
          Double d = this.getDouble(key, null);
          if (d != null)
          {
              return d.doubleValue();
          }
          else
          {
              throw new NoSuchElementException(key +
                                               " doesn't map to an" +
                                               " existing object");
          }
      }
  
      /**
       * Get a double associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated double.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Double.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public double getDouble(String key,
                              double defaultValue)
      {
          return this.getDouble(key, new Double(defaultValue)).doubleValue();
      }
  
      /**
       * Get a double associated with the given configuration key.
       *
       * @param key The configuration key.
       * @param defaultValue The default value.
       * @return The associated double if key is found and has valid
       * format, default value otherwise.
       * @exception ClassCastException is thrown if the key maps to an
       * object that is not a Double.
       * @exception NumberFormatException is thrown if the value mapped
       * by the key has not a valid number format.
       */
      public Double getDouble(String key,
                              Double defaultValue)
      {
          Object value = repository.get(key);
  
          if (value instanceof Double)
          {
              return (Double) value;
          }
          else if (value instanceof String)
          {
              Double d = new Double((String) value);
              repository.put(key, d);
              return d;
          }
          else if (value == null)
          {
              if (defaults != null)
              {
                  return defaults.getDouble(key, defaultValue);
              }
              else
              {
                  return defaultValue;
              }
          }
          else
          {
              throw new ClassCastException(key +
                                           " doesn't map to a Double object");
          }
      }
  }