You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@turbine.apache.org by Daniel Rall <dl...@finemaltcoding.com> on 2002/02/06 18:49:04 UTC
Re: cvs commit: jakarta-turbine-stratum/src/java/org/apache/stratum/configuration BaseConfiguration.java package.html Configuration.java PropertiesConfiguration.java XmlConfiguration.java AbstractConfiguration.java (1/2)
What's the reasoning for not subclassing ExtendedProperties for the
default implementation?
mpoeschl@apache.org writes:
> mpoeschl 02/02/04 03:31:34
>
> Modified: src/java/org/apache/stratum/configuration Configuration.java
> PropertiesConfiguration.java XmlConfiguration.java
> Added: src/java/org/apache/stratum/configuration
> BaseConfiguration.java package.html
> Removed: src/java/org/apache/stratum/configuration
> AbstractConfiguration.java
> Log:
> new configuration package based on ExtendedProperties
>
> Revision Changes Path
> 1.2 +97 -19 jakarta-turbine-stratum/src/java/org/apache/stratum/configuration/Configuration.java
>
> Index: Configuration.java
> ===================================================================
> RCS file: /home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/configuration/Configuration.java,v
> retrieving revision 1.1
> retrieving revision 1.2
> diff -u -r1.1 -r1.2
> --- Configuration.java 5 Jan 2002 03:22:59 -0000 1.1
> +++ Configuration.java 4 Feb 2002 11:31:34 -0000 1.2
> @@ -1,29 +1,107 @@
> package org.apache.stratum.configuration;
>
> +/* ====================================================================
> + * The Apache Software License, Version 1.1
> + *
> + * Copyright (c) 2001-2002 The Apache Software Foundation. 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. The end-user documentation included with the redistribution,
> + * if any, must include the following acknowledgment:
> + * "This product includes software developed by the
> + * Apache Software Foundation (http://www.apache.org/)."
> + * Alternately, this acknowledgment may appear in the software itself,
> + * if and wherever such third-party acknowledgments normally appear.
> + *
> + * 4. The names "Apache" and "Apache Software Foundation" and
> + * "Apache Turbine" must not be used to endorse or promote products
> + * derived from this software without prior written permission. For
> + * written permission, please contact apache@apache.org.
> + *
> + * 5. Products derived from this software may not be called "Apache",
> + * "Apache Turbine", nor may "Apache" appear in their name, without
> + * prior written permission of the Apache Software Foundation.
> + *
> + * THIS SOFTWARE IS PROVIDED ``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 APACHE SOFTWARE FOUNDATION 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 Apache Software Foundation. For more
> + * information on the Apache Software Foundation, please see
> + * <http://www.apache.org/>.
> + */
> +
> import java.util.Iterator;
> +import java.util.Properties;
> import java.util.Vector;
>
> -// The general idea here is to make something that will work like
> -// our extended properties and be compatible with the preferences
> -// API if at all possible.
> -
> +/**
> + * Configuration interface.
> + * The general idea here is to make something that will work like our
> + * extended properties and be compatible with the preferences API if at all
> + * possible.
> + *
> + * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
> + * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
> + * @version $Id: Configuration.java,v 1.2 2002/02/04 11:31:34 mpoeschl Exp $
> + */
> public interface Configuration
> -{
> - Vector getVector(String key);
> - String getString(String key);
> +{
> + Configuration subset(String prefix);
> +
> + boolean isEmpty();
> + boolean containsKey(String key);
> + void addProperty(String key, Object value);
> + void setProperty(String key, Object value);
> + void clearProperty(String key);
> Iterator getKeys(String key);
> - int getInt(String key, int defaultValue);
> -
> + Iterator getKeys();
> + Properties getProperties();
> +
> // We probably want to at least try to be compatible with
> // the new preferences API.
> -
> - // Iterator getKeys()
> -
> - // byte getByte(String key);
> - // short getShort(String key);
> - // long getLong(String key);
> -
> - // float getFloat(String key);
> - // boolean getBoolean(String key);
> - // double getDouble(String key);
> +
> + boolean getBoolean(String key);
> + boolean getBoolean(String key, boolean defaultValue);
> +// Boolean getBoolean(String key, Boolean defaultValue);
> + byte getByte(String key);
> + double getDouble(String key);
> + float getFloat(String key);
> + int getInt(String key, int defaultValue);
> + Integer getInteger(String key, Integer defaultValue);
> + long getLong(String key);
> + long getLong(String key, long defaultValue);
> +// Long getLong(String key, Long defaultValue);
> + short getShort(String key);
> + String getString(String key);
> + String getString(String key, String defaultValue);
> + String[] getStringArray(String key);
> + Vector getVector(String key);
> + Vector getVector(String key, Vector defaultValue);
> +
> +
> +
> }
>
>
>
> 1.2 +402 -3 jakarta-turbine-stratum/src/java/org/apache/stratum/configuration/PropertiesConfiguration.java
>
> Index: PropertiesConfiguration.java
> ===================================================================
> RCS file: /home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/configuration/PropertiesConfiguration.java,v
> retrieving revision 1.1
> retrieving revision 1.2
> diff -u -r1.1 -r1.2
> --- PropertiesConfiguration.java 18 Jan 2002 22:26:05 -0000 1.1
> +++ PropertiesConfiguration.java 4 Feb 2002 11:31:34 -0000 1.2
> @@ -1,9 +1,408 @@
> package org.apache.stratum.configuration;
>
> +/* ====================================================================
> + * The Apache Software License, Version 1.1
> + *
> + * Copyright (c) 2001-2002 The Apache Software Foundation. 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. The end-user documentation included with the redistribution,
> + * if any, must include the following acknowledgment:
> + * "This product includes software developed by the
> + * Apache Software Foundation (http://www.apache.org/)."
> + * Alternately, this acknowledgment may appear in the software itself,
> + * if and wherever such third-party acknowledgments normally appear.
> + *
> + * 4. The names "Apache" and "Apache Software Foundation" and
> + * "Apache Turbine" must not be used to endorse or promote products
> + * derived from this software without prior written permission. For
> + * written permission, please contact apache@apache.org.
> + *
> + * 5. Products derived from this software may not be called "Apache",
> + * "Apache Turbine", nor may "Apache" appear in their name, without
> + * prior written permission of the Apache Software Foundation.
> + *
> + * THIS SOFTWARE IS PROVIDED ``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 APACHE SOFTWARE FOUNDATION 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 Apache Software Foundation. For more
> + * information on the Apache Software Foundation, please see
> + * <http://www.apache.org/>.
> + */
> +
> +import java.io.File;
> +import java.io.FileInputStream;
> +import java.io.InputStream;
> +import java.io.InputStreamReader;
> +import java.io.IOException;
> +import java.io.LineNumberReader;
> +import java.io.Reader;
> +import java.io.UnsupportedEncodingException;
> +
> // Borrow a lot of the code from ExtendedProperties, but leave
> // the resource handling to the resources package.
>
> -public class PropertiesConfiguration
> - extends AbstractConfiguration
> -{
> +/**
> + * loads the configuration from a properties file. <p>
> + *
> + * <p>The Extended Properties syntax is explained here:
> + *
> + * <ul>
> + * <li>
> + * Each property has the syntax <code>key = value</code>
> + * </li>
> + * <li>
> + * The <i>key</i> may use any character but the equal sign '='.
> + * </li>
> + * <li>
> + * <i>value</i> may be separated on different lines if a backslash
> + * is placed at the end of the line that continues below.
> + * </li>
> + * <li>
> + * If <i>value</i> is a list of strings, each token is separated
> + * by a comma ','.
> + * </li>
> + * <li>
> + * Commas in each token are escaped placing a backslash right before
> + * the comma.
> + * </li>
> + * <li>
> + * If a <i>key</i> is used more than once, the values are appended
> + * like if they were on the same line separated with commas.
> + * </li>
> + * <li>
> + * Blank lines and lines starting with character '#' are skipped.
> + * </li>
> + * <li>
> + * If a property is named "include" (or whatever is defined by
> + * setInclude() and getInclude() and the value of that property is
> + * the full path to a file on disk, that file will be included into
> + * the ConfigurationsRepository. You can also pull in files relative
> + * to the parent configuration file. So if you have something
> + * like the following:
> + *
> + * include = additional.properties
> + *
> + * Then "additional.properties" is expected to be in the same
> + * directory as the parent configuration file.
> + *
> + * Duplicate name values will be replaced, so be careful.
> + *
> + * </li>
> + * </ul>
> + *
> + * <p>Here is an example of a valid extended properties file:
> + *
> + * <p><pre>
> + * # lines starting with # are comments
> + *
> + * # This is the simplest property
> + * key = value
> + *
> + * # A long property may be separated on multiple lines
> + * longvalue = aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa \
> + * aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa
> + *
> + * # This is a property with many tokens
> + * tokens_on_a_line = first token, second token
> + *
> + * # This sequence generates exactly the same result
> + * tokens_on_multiple_lines = first token
> + * tokens_on_multiple_lines = second token
> + *
> + * # commas may be escaped in tokens
> + * commas.excaped = Hi\, what'up?
> + * </pre>
> + *
> + * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
> + * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
> + * @author <a href="mailto:daveb@miceda-data">Dave Bryson</a>
> + * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
> + * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
> + * @author <a href="mailto:kjohnson@transparent.com">Kent Johnson</a>
> + * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
> + * @author <a href="mailto:ipriha@surfeu.fi">Ilkka Priha</a>
> + * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
> + * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
> + * @version $Id: PropertiesConfiguration.java,v 1.2 2002/02/04 11:31:34 mpoeschl Exp $
> + */
> +public class PropertiesConfiguration extends BaseConfiguration
> +{
> +
> + /** File separator. */
> + protected String fileSeparator = System.getProperty("file.separator");
> +
> + /**
> + * Base path of the configuration file used to create this Configuration
> + * object.
> + */
> + protected String basePath;
> +
> + /**
> + * This is the name of the property that can point to other
> + * properties file for including other properties files.
> + */
> + protected static String include = "include";
> +
> +
> + /**
> + * Creates an empty Configuration
> + */
> + public PropertiesConfiguration()
> + {
> + }
> +
> + /**
> + * Creates and loads the extended properties from the specified file.
> + *
> + * @param file A String.
> + * @exception IOException.
> + */
> + public PropertiesConfiguration(String file) throws IOException
> + {
> + this(file, null);
> + }
> +
> + /**
> + * Creates and loads the extended properties from the specified file.
> + *
> + * @param file A String.
> + * @exception IOException.
> + */
> + public PropertiesConfiguration(String file, String defaultFile)
> + throws IOException
> + {
> +// this.file = file;
> +
> + basePath = new File(file).getAbsolutePath();
> + basePath = basePath.substring(0, basePath.lastIndexOf(fileSeparator) + 1);
> +
> + this.load(new FileInputStream(file));
> +
> + if (defaultFile != null)
> + {
> + defaults = (BaseConfiguration)
> + new PropertiesConfiguration(defaultFile);
> + }
> + }
> +
> + /**
> + * Load the properties from the given input stream.
> + *
> + * @param input An InputStream.
> + * @exception IOException.
> + */
> + public void load(InputStream input) throws IOException
> + {
> + load(input, null);
> + }
> +
> + /**
> + * Load the properties from the given input stream and using the specified
> + * encoding.
> + *
> + * @param input An InputStream.
> + * @param enc An encoding.
> + * @exception IOException.
> + */
> + public synchronized void load(InputStream input, String enc)
> + throws IOException
> + {
> + PropertiesReader reader = null;
> + if (enc != null)
> + {
> + try
> + {
> + reader =
> + new PropertiesReader(new InputStreamReader(input, enc));
> + }
> + catch (UnsupportedEncodingException e)
> + {
> + // Get one with the default encoding...
> + }
> + }
> +
> + if (reader == null)
> + {
> + reader =
> + new PropertiesReader(new InputStreamReader(input));
> + }
> +
> + try
> + {
> + while (true)
> + {
> + String line = reader.readProperty();
> + int equalSign = line.indexOf('=');
> +
> + if (equalSign > 0)
> + {
> + String key = line.substring(0, equalSign).trim();
> + String value = line.substring(equalSign + 1).trim();
> +
> + /*
> + * Configure produces lines like this ... just
> + * ignore them.
> + */
> + if ("".equals(value))
> + continue;
> +
> + if (getInclude() != null &&
> + key.equalsIgnoreCase(getInclude()))
> + {
> + /*
> + * Recursively load properties files.
> + */
> + File file = null;
> +
> + if (value.startsWith(fileSeparator))
> + {
> + /*
> + * We have an absolute path so we'll
> + * use this.
> + */
> + file = new File(value);
> + }
> + else
> + {
> + /*
> + * We have a relative path, and we have
> + * two possible forms here. If we have the
> + * "./" form then just strip that off first
> + * before continuing.
> + */
> + if (value.startsWith("." + fileSeparator))
> + {
> + value = value.substring(2);
> + }
> +
> + file = new File(basePath + value);
> + }
> +
> + if (file != null && file.exists() && file.canRead())
> + {
> + load ( new FileInputStream(file));
> + }
> + }
> + else
> + {
> + addProperty(key,value);
> + }
> + }
> + }
> + }
> + catch (NullPointerException e)
> + {
> + /*
> + * Should happen only when EOF is reached.
> + */
> + return;
> + }
> + }
> +
> + /**
> + * Gets the property value for including other properties files.
> + * By default it is "include".
> + *
> + * @return A String.
> + */
> + public String getInclude()
> + {
> + return this.include;
> + }
> +
> + /**
> + * Sets the property value for including other properties files.
> + * By default it is "include".
> + *
> + * @param inc A String.
> + */
> + public void setInclude(String inc)
> + {
> + this.include = inc;
> + }
> +
> +
> + /**
> + * This class is used to read properties lines. These lines do
> + * not terminate with new-line chars but rather when there is no
> + * backslash sign a the end of the line. This is used to
> + * concatenate multiple lines for readability.
> + */
> + class PropertiesReader extends LineNumberReader
> + {
> + /**
> + * Constructor.
> + *
> + * @param reader A Reader.
> + */
> + public PropertiesReader(Reader reader)
> + {
> + super(reader);
> + }
> +
> + /**
> + * Read a property.
> + *
> + * @return A String.
> + * @exception IOException.
> + */
> + public String readProperty() throws IOException
> + {
> + StringBuffer buffer = new StringBuffer();
> +
> + try
> + {
> + while (true)
> + {
> + String line = readLine().trim();
> + if ((line.length() != 0) && (line.charAt(0) != '#'))
> + {
> + if (line.endsWith("\\"))
> + {
> + line = line.substring(0, line.length() - 1);
> + buffer.append(line);
> + }
> + else
> + {
> + buffer.append(line);
> + break;
> + }
> + }
> + }
> + }
> + catch (NullPointerException e)
> + {
> + return null;
> + }
> +
> + return buffer.toString();
> + }
> + } // class PropertiesReader
> +
> +
> }
>
>
>
> 1.2 +3 -3 jakarta-turbine-stratum/src/java/org/apache/stratum/configuration/XmlConfiguration.java
>
> Index: XmlConfiguration.java
> ===================================================================
> RCS file: /home/cvs/jakarta-turbine-stratum/src/java/org/apache/stratum/configuration/XmlConfiguration.java,v
> retrieving revision 1.1
> retrieving revision 1.2
> diff -u -r1.1 -r1.2
> --- XmlConfiguration.java 18 Jan 2002 22:26:05 -0000 1.1
> +++ XmlConfiguration.java 4 Feb 2002 11:31:34 -0000 1.2
> @@ -1,5 +1,6 @@
> package org.apache.stratum.configuration;
>
> +
> /**
> * <configuration>
> * <entries>
> @@ -11,7 +12,6 @@
> * </configuration>
> *
> */
> -public class XmlConfiguration
> - extends AbstractConfiguration
> -{
> +public class XmlConfiguration extends BaseConfiguration
> +{
> }
>
>
>
> 1.1 jakarta-turbine-stratum/src/java/org/apache/stratum/configuration/BaseConfiguration.java
>
> Index: BaseConfiguration.java
> ===================================================================
> package org.apache.stratum.configuration;
>
> /* ====================================================================
> * The Apache Software License, Version 1.1
> *
> * Copyright (c) 2001-2002 The Apache Software Foundation. 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. The end-user documentation included with the redistribution,
> * if any, must include the following acknowledgment:
> * "This product includes software developed by the
> * Apache Software Foundation (http://www.apache.org/)."
> * Alternately, this acknowledgment may appear in the software itself,
> * if and wherever such third-party acknowledgments normally appear.
> *
> * 4. The names "Apache" and "Apache Software Foundation" and
> * "Apache Turbine" must not be used to endorse or promote products
> * derived from this software without prior written permission. For
> * written permission, please contact apache@apache.org.
> *
> * 5. Products derived from this software may not be called "Apache",
> * "Apache Turbine", nor may "Apache" appear in their name, without
> * prior written permission of the Apache Software Foundation.
> *
> * THIS SOFTWARE IS PROVIDED ``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 APACHE SOFTWARE FOUNDATION 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 Apache Software Foundation. For more
> * information on the Apache Software Foundation, please see
> * <http://www.apache.org/>.
> */
>
> import java.util.ArrayList;
> import java.util.Hashtable;
> import java.util.Iterator;
> import java.util.NoSuchElementException;
> import java.util.Properties;
> import java.util.StringTokenizer;
> import java.util.Vector;
>
> /**
> * Basic configuration classe. Stores the configuration data but does not
> * provide any load or save functions. If you want to load your Configuration
> * from a file use PropertiesConfiguration or XmlConfiguration.
> *
> * This class extends normal Java properties by adding the possibility
> * to use the same key many times concatenating the value strings
> * instead of overwriting them.
> *
> * @author <a href="mailto:stefano@apache.org">Stefano Mazzocchi</a>
> * @author <a href="mailto:jon@latchkey.com">Jon S. Stevens</a>
> * @author <a href="mailto:daveb@miceda-data">Dave Bryson</a>
> * @author <a href="mailto:geirm@optonline.net">Geir Magnusson Jr.</a>
> * @author <a href="mailto:leon@opticode.co.za">Leon Messerschmidt</a>
> * @author <a href="mailto:kjohnson@transparent.com">Kent Johnson</a>
> * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
> * @author <a href="mailto:ipriha@surfeu.fi">Ilkka Priha</a>
> * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
> * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
> * @version $Id: BaseConfiguration.java,v 1.1 2002/02/04 11:31:34 mpoeschl Exp $
> */
> public class BaseConfiguration
> {
>
> /* stores the configuration key-value pairs */
> private Hashtable store = new Hashtable();
>
> /* stores the configuration key-value pairs */
> protected BaseConfiguration defaults = null;
>
> /**
> * These are the keys in the order they listed in the configuration file.
> * This is useful when you wish to perform operations with configuration
> * information in a particular order.
> */
> protected ArrayList keysAsListed = new ArrayList();
>
> protected final static String START_TOKEN = "${";
> protected final static String END_TOKEN = "}";
>
> /**
> * Add a property to the configuration. If it already exists then the value
> * stated here will be added to the configuration entry. For example, if
> *
> * resource.loader = file
> *
> * is already present in the configuration and you
> *
> * addProperty("resource.loader", "classpath")
> *
> * Then you will end up with a Vector like the following:
> *
> * ["file", "classpath"]
> *
> * @param String key
> * @param String value
> */
> public void addProperty(String key, Object token)
> {
> Object o = store.get(key);
>
> /*
> * $$$ GMJ
> * FIXME : post 1.0 release, we need to not assume
> * that a scalar is a String - it can be an Object
> * so we should make a little vector-like class
> * say, Foo that wraps (not extends Vector),
> * so we can do things like
> * if ( !( o instanceof Foo) )
> * so we know it's our 'vector' container
> *
> * This applies throughout
> */
> if (o instanceof String)
> {
> Vector v = new Vector(2);
> v.addElement(o);
> v.addElement(token);
> store.put(key, v);
> }
> else if (o instanceof Vector)
> {
> ((Vector) o).addElement(token);
> }
> else
> {
> /*
> * This is the first time that we have seen request to place an
> * object in the configuration with the key 'key'. So we just want
> * to place it directly into the configuration ... but we are going
> * to make a special exception for String objects that contain ","
> * characters. We will take CSV lists and turn the list into a
> * vector of Strings before placing it in the configuration.
> * This is a concession for Properties and the like that cannot
> * parse multiple same key values.
> */
> if (token instanceof String &&
> ((String)token).indexOf(PropertiesTokenizer.DELIMITER) > 0)
> {
> PropertiesTokenizer tokenizer =
> new PropertiesTokenizer((String)token);
>
> while (tokenizer.hasMoreTokens())
> {
> String value = tokenizer.nextToken();
>
> /*
> * we know this is a string, so make sure it just goes in
> * rather than risking vectorization if it contains an
> * escaped comma
> */
> addStringProperty(key, value);
> }
> }
> else
> {
> /*
> * We want to keep track of the order the keys are parsed, or
> * dynamically entered into the configuration. So when we see a
> * key for the first time we will place it in an ArrayList so
> * that if a client class needs to perform operations with
> * configuration in a definite order it will be possible.
> */
> addPropertyDirect(key, token);
> }
> }
> }
>
> /**
> * Adds a key/value pair to the map. This routine does no magic morphing.
> * It ensures the keylist is maintained
> *
> * @param key key to use for mapping
> * @param obj object to store
> */
> protected void addPropertyDirect(String key, Object obj)
> {
> // safety check
> if(! store.containsKey(key))
> {
> keysAsListed.add(key);
> }
>
> // and the value
> store.put(key, obj);
> }
>
> /**
> * Sets a string property w/o checking for commas - used internally when a
> * property has been broken up into strings that could contain escaped
> * commas to prevent the inadvertant vectorization.
> */
> private void addStringProperty(String key, String token)
> {
> Object o = store.get(key);
>
> /*
> * $$$ GMJ
> * FIXME : post 1.0 release, we need to not assume
> * that a scalar is a String - it can be an Object
> * so we should make a little vector-like class
> * say, Foo that wraps (not extends Vector),
> * so we can do things like
> * if ( !( o instanceof Foo) )
> * so we know it's our 'vector' container
> *
> * This applies throughout
> */
>
> /*
> * do the usual thing - if we have a value and
> * it's scalar, make a vector, otherwise add to the vector
> */
> if (o instanceof String)
> {
> Vector v = new Vector(2);
> v.addElement(o);
> v.addElement(token);
> store.put(key, v);
> }
> else if (o instanceof Vector)
> {
> ((Vector) o).addElement(token);
> }
> else
> {
> addPropertyDirect(key, token);
> }
> }
>
> /**
> * interpolate key names to handle ${key} stuff
> */
> protected String interpolate(String base)
> {
> if (base == null)
> {
> return null;
> }
>
> int begin = -1;
> int end = -1;
> int prec = 0 - END_TOKEN.length();
> String variable = null;
> StringBuffer result = new StringBuffer();
>
> // FIXME: we should probably allow the escaping of the start token
> while ( ((begin = base.indexOf(START_TOKEN, prec + END_TOKEN.length())) >-1)
> && ((end = base.indexOf(END_TOKEN, begin)) > -1) )
> {
> result.append(base.substring(prec + END_TOKEN.length(), begin));
> variable = base.substring(begin + START_TOKEN.length(), end);
> if (store.get(variable) != null)
> {
> result.append(store.get(variable));
> }
> prec = end;
> }
> result.append(base.substring(prec + END_TOKEN.length(), base.length()));
>
> return result.toString();
> }
>
> /**
> * Test whether the string represent by value maps to a boolean
> * value or not. We will allow <code>true</code>, <code>on</code>,
> * and <code>yes</code> for a <code>true</code> boolean value, and
> * <code>false</code>, <code>off</code>, and <code>no</code> for
> * <code>false</code> boolean values. Case of value to test for
> * boolean status is ignored.
> *
> * @param String The value to test for boolean state.
> * @return <code>true</code> or <code>false</code> if the supplied
> * text maps to a boolean value, or <code>null</code> otherwise.
> */
> public String testBoolean(String value)
> {
> String s = ((String)value).toLowerCase();
>
> if (s.equals("true") || s.equals("on") || s.equals("yes"))
> {
> return "true";
> }
> else if (s.equals("false") || s.equals("off") || s.equals("no"))
> {
> return "false";
> }
> else
> {
> return null;
> }
> }
>
> /**
> * Create an ExtendedProperties object that is a subset
> * of this one. Take into account duplicate keys
> * by using the setProperty() in ExtendedProperties.
> *
> * @param String prefix
> */
> public Configuration subset(String prefix)
> {
> PropertiesConfiguration c = new PropertiesConfiguration();
> Iterator keys = this.getKeys();
> boolean validSubset = false;
>
> while( keys.hasNext() )
> {
> Object key = keys.next();
>
> if( key instanceof String && ((String) key).startsWith(prefix) )
> {
> if (!validSubset)
> {
> validSubset = true;
> }
>
> String newKey = null;
>
> /*
> * Check to make sure that c.subset(prefix) doesn't blow up when
> * there is only a single property with the key prefix. This is
> * not a useful subset but it is a valid subset.
> */
> if ( ((String)key).length() == prefix.length())
> {
> newKey = prefix;
> }
> else
> {
> newKey = ((String)key).substring(prefix.length() + 1);
> }
>
> /*
> * use addPropertyDirect() - this will plug the data as is into
> * the Map, but will also do the right thing re key accounting
> */
> c.addPropertyDirect(newKey, store.get(key));
> }
> }
>
> if (validSubset)
> {
> return (Configuration) c;
> }
> else
> {
> return null;
> }
> }
>
--
To unsubscribe, e-mail: <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>