org.apache.commons.collections.ExtendedProperties Maven / Gradle / Ivy
/*
* Copyright 1999-2004 The Apache Software Foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.commons.collections;
import java.io.IOException;
import java.io.File;
import java.io.FileInputStream;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.LineNumberReader;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.io.Reader;
import java.io.UnsupportedEncodingException;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Iterator;
import java.util.NoSuchElementException;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.Vector;
/**
* 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.
*
* The Extended Properties syntax is explained here:
*
*
* -
* Each property has the syntax
key = value
*
* -
* The key may use any character but the equal sign '='.
*
* -
* value may be separated on different lines if a backslash
* is placed at the end of the line that continues below.
*
* -
* If value is a list of strings, each token is separated
* by a comma ','.
*
* -
* Commas in each token are escaped placing a backslash right before
* the comma.
*
* -
* If a key is used more than once, the values are appended
* like if they were on the same line separated with commas.
*
* -
* Blank lines and lines starting with character '#' are skipped.
*
* -
* 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.
*
*
*
*
* Here is an example of a valid extended properties file:
*
*
* # 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?
*
*
* NOTE: this class has not been written for
* performance nor low memory usage. In fact, it's way slower than it
* could be and generates too much memory garbage. But since
* performance is not an issue during intialization (and there is not
* much time to improve it), I wrote it this way. If you don't like
* it, go ahead and tune it up!
*
*
* @since 1.0
* @author Stefano Mazzocchi
* @author Jon S. Stevens
* @author Dave Bryson
* @author Jason van Zyl
* @author Geir Magnusson Jr.
* @author Leon Messerschmidt
* @author Kent Johnson
* @author Daniel Rall
* @author Ilkka Priha
* @version $Id: ExtendedProperties.java,v 1.7.2.1 2004/05/22 12:14:02 scolebourne Exp $
*/
public class ExtendedProperties extends Hashtable
{
/**
* Default configurations repository.
*/
private ExtendedProperties defaults;
/**
* The file connected to this repository (holding comments and
* such).
*
* @serial
*/
protected String file;
/**
* Base path of the configuration file used to create
* this ExtendedProperties object.
*/
protected String basePath;
/**
* File separator.
*/
protected String fileSeparator = System.getProperty("file.separator");
/**
* Has this configuration been intialized.
*/
protected boolean isInitialized = false;
/**
* This is the name of the property that can point to other
* properties file for including other properties files.
*/
protected static String include = "include";
/**
* 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="}";
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 (get(variable)!=null)
{
result.append(get(variable));
}
prec=end;
}
result.append(base.substring(prec+END_TOKEN.length(),base.length()));
return result.toString();
}
/**
* 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();
}
}
/**
* This class divides into tokens a property value. Token
* separator is "," but commas into the property value are escaped
* using the backslash in front.
*/
class PropertiesTokenizer extends StringTokenizer
{
/**
* The property delimiter used while parsing (a comma).
*/
static final String DELIMITER = ",";
/**
* Constructor.
*
* @param string A String.
*/
public PropertiesTokenizer(String string)
{
super(string, DELIMITER);
}
/**
* Check whether the object has more tokens.
*
* @return True if the object has more tokens.
*/
public boolean hasMoreTokens()
{
return super.hasMoreTokens();
}
/**
* Get next token.
*
* @return A String.
*/
public String nextToken()
{
StringBuffer buffer = new StringBuffer();
while (hasMoreTokens())
{
String token = super.nextToken();
if (token.endsWith("\\"))
{
buffer.append(token.substring(0, token.length() - 1));
buffer.append(DELIMITER);
}
else
{
buffer.append(token);
break;
}
}
return buffer.toString().trim();
}
}
/**
* Creates an empty extended properties object.
*/
public ExtendedProperties()
{
super();
}
/**
* Creates and loads the extended properties from the specified
* file.
*
* @param file A String.
* @exception IOException.
*/
public ExtendedProperties(String file) throws IOException
{
this(file,null);
}
/**
* Creates and loads the extended properties from the specified
* file.
*
* @param file A String.
* @exception IOException.
*/
public ExtendedProperties(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 = new ExtendedProperties(defaultFile);
}
}
/**
* Private initializer method that sets up the generic
* resources.
*
* @exception IOException, if there was an I/O problem.
*/
private void init( ExtendedProperties exp ) throws IOException
{
isInitialized = true;
}
/**
* Indicate to client code whether property
* resources have been initialized or not.
*/
public boolean isInitialized()
{
return isInitialized;
}
/**
* 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;
}
/**
* 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 a property from the configuration.
*
* @param key property to retrieve
* @return value as object. Will return user value if exists,
* if not then default value if exists, otherwise null
*/
public Object getProperty( String key)
{
/*
* first, try to get from the 'user value' store
*/
Object o = this.get(key);
if ( o == null)
{
/*
* if there isn't a value there, get it from the
* defaults if we have them
*/
if (defaults != null)
{
o = defaults.get(key);
}
}
return o;
}
/**
* 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 = this.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);
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
*/
private void addPropertyDirect( String key, Object obj )
{
/*
* safety check
*/
if( !containsKey( key ) )
{
keysAsListed.add(key);
}
/*
* and the value
*/
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.
*
* Thanks to Leon Messerschmidt for this one.
*
*/
private void addStringProperty(String key, String token)
{
Object o = this.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);
put(key, v);
}
else if (o instanceof Vector)
{
((Vector) o).addElement(token);
}
else
{
addPropertyDirect( key, token );
}
}
/**
* Set a property, this will replace any previously
* set values. Set values is implicitly a call
* to clearProperty(key), addProperty(key,value).
*
* @param String key
* @param String value
*/
public void setProperty(String key, Object value)
{
clearProperty(key);
addProperty(key,value);
}
/**
* Save the properties to the given outputstream.
*
* @param output An OutputStream.
* @param header A String.
* @exception IOException.
*/
public synchronized void save(OutputStream output,
String Header)
throws IOException
{
if(output != null)
{
PrintWriter theWrtr = new PrintWriter(output);
if(Header != null)
{
theWrtr.println(Header);
}
Enumeration theKeys = keys();
while(theKeys.hasMoreElements())
{
String key = (String) theKeys.nextElement();
Object value = get((Object) key);
if(value != null)
{
if(value instanceof String)
{
StringBuffer currentOutput = new StringBuffer();
currentOutput.append(key);
currentOutput.append("=");
currentOutput.append((String) value);
theWrtr.println(currentOutput.toString());
}
else if(value instanceof Vector)
{
Vector values = (Vector) value;
Enumeration valuesEnum = values.elements();
while(valuesEnum.hasMoreElements())
{
String currentElement =
(String) valuesEnum.nextElement();
StringBuffer currentOutput = new StringBuffer();
currentOutput.append(key);
currentOutput.append("=");
currentOutput.append(currentElement);
theWrtr.println(currentOutput.toString());
}
}
}
theWrtr.println();
theWrtr.flush();
}
}
}
/**
* Combines an existing Hashtable with this Hashtable.
*
* Warning: It will overwrite previous entries without warning.
*
* @param ExtendedProperties
*/
public void combine( ExtendedProperties c )
{
for (Iterator i = c.getKeys() ; i.hasNext() ;)
{
String key = (String) i.next();
setProperty( key, c.get(key) );
}
}
/**
* Clear a property in the configuration.
*
* @param String key to remove along with corresponding value.
*/
public void clearProperty(String key)
{
if (containsKey(key))
{
/*
* we also need to rebuild the keysAsListed or else
* things get *very* confusing
*/
for(int i = 0; i < keysAsListed.size(); i++)
{
if ( ( (String) keysAsListed.get(i)).equals( key ) )
{
keysAsListed.remove(i);
break;
}
}
remove(key);
}
}
/**
* Get the list of the keys contained in the configuration
* repository.
*
* @return An Iterator.
*/
public Iterator getKeys()
{
return keysAsListed.iterator();
}
/**
* 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 Iterator of keys that match the prefix.
*/
public Iterator getKeys(String prefix)
{
Iterator keys = getKeys();
ArrayList matchingKeys = new ArrayList();
while( keys.hasNext() )
{
Object key = keys.next();
if( key instanceof String && ((String) key).startsWith(prefix) )
{
matchingKeys.add(key);
}
}
return matchingKeys.iterator();
}
/**
* 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 ExtendedProperties subset(String prefix)
{
ExtendedProperties c = new ExtendedProperties();
Iterator keys = 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, get(key) );
}
}
if (validSubset)
{
return c;
}
else
{
return null;
}
}
/**
* Display the configuration for debugging
* purposes.
*/
public void display()
{
Iterator i = getKeys();
while (i.hasNext())
{
String key = (String) i.next();
Object value = get(key);
System.out.println(key + " => " + value);
}
}
/**
* 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 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 = get(key);
if (value instanceof String)
{
return (String) interpolate((String)value);
}
else if (value == null)
{
if (defaults != null)
{
return interpolate(defaults.getString(key, defaultValue));
}
else
{
return interpolate(defaultValue);
}
}
else if (value instanceof Vector)
{
return interpolate((String) ((Vector) value).get(0));
}
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 = 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 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 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 = get(key);
if (value instanceof Vector)
{
return (Vector) value;
}
else if (value instanceof String)
{
Vector v = new Vector(1);
v.addElement((String) value);
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 = 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 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 = get(key);
if (value instanceof Boolean)
{
return (Boolean) value;
}
else if (value instanceof String)
{
String s = testBoolean((String)value);
Boolean b = new Boolean(s);
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");
}
}
/**
* Test whether the string represent by value maps to a boolean
* value or not. We will allow true, on,
* and yes for a true boolean value, and
* false, off, and no for
* false boolean values. Case of value to test for
* boolean status is ignored.
*
* @param String The value to test for boolean state.
* @return true or false if the supplied
* text maps to a boolean value, or null 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;
}
}
/**
* 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 = 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 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 = get(key);
if (value instanceof Byte)
{
return (Byte) value;
}
else if (value instanceof String)
{
Byte b = new Byte((String) value);
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 = 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 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 = get(key);
if (value instanceof Short)
{
return (Short) value;
}
else if (value instanceof String)
{
Short s = new Short((String) value);
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");
}
}
/**
* The purpose of this method is to get the configuration resource
* with the given name as an integer.
*
* @param name The resource name.
* @return The value of the resource as an integer.
*/
public int getInt(String name)
{
return getInteger(name);
}
/**
* The purpose of this method is to get the configuration resource
* with the given name as an integer, or a default value.
*
* @param name The resource name
* @param def The default value of the resource.
* @return The value of the resource as an integer.
*/
public int getInt(String name,
int def)
{
return getInteger(name, def);
}
/**
* 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 = 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)
{
Integer i = getInteger(key, null);
if (i == null)
{
return defaultValue;
}
return i.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 = get(key);
if (value instanceof Integer)
{
return (Integer) value;
}
else if (value instanceof String)
{
Integer i = new Integer((String) value);
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 = 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 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 = get(key);
if (value instanceof Long)
{
return (Long) value;
}
else if (value instanceof String)
{
Long l = new Long((String) value);
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 = 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 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 = get(key);
if (value instanceof Float)
{
return (Float) value;
}
else if (value instanceof String)
{
Float f = new Float((String) value);
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 = 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 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 = get(key);
if (value instanceof Double)
{
return (Double) value;
}
else if (value instanceof String)
{
Double d = new Double((String) value);
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");
}
}
/**
* Convert a standard properties class into a configuration
* class.
*
* @param p properties object to convert into
* a ExtendedProperties object.
*
* @return ExtendedProperties configuration created from the
* properties object.
*/
public static ExtendedProperties convertProperties(Properties p)
{
ExtendedProperties c = new ExtendedProperties();
for (Enumeration e = p.keys(); e.hasMoreElements() ; )
{
String s = (String) e.nextElement();
c.setProperty(s, p.getProperty(s));
}
return c;
}
}