package org.jacorb.config;
/*
* JacORB - a free Java ORB
*
* Copyright (C) 1997-2014 Gerald Brose / The JacORB Team.
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Library General Public
* License as published by the Free Software Foundation; either
* version 2 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Library General Public License for more details.
*
* You should have received a copy of the GNU Library General Public
* License along with this library; if not, write to the Free
* Software Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.Collections;
import java.util.Iterator;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.Properties;
import java.util.StringTokenizer;
import java.util.concurrent.ConcurrentHashMap;
import java.util.logging.Level;
import org.jacorb.orb.ORB;
import org.jacorb.util.ObjectUtil;
import org.jacorb.util.Version;
import org.omg.CORBA.NO_IMPLEMENT;
import org.slf4j.Logger;
/**
* The Class JacORBConfiguration.
*
* @author Gerald Brose
*/
public class JacORBConfiguration implements Configuration
{
/**
* The Constant fileSuffix.
*/
private static final String fileSuffix = ".properties";
/**
* The Constant COMMON_PROPS.
*/
private static final String COMMON_PROPS = "orb" + fileSuffix;
/**
* The Constant TRUE.
*/
private static final String TRUE = "true";
/**
* The Constant ON.
*/
private static final String ON = "on";
/**
* The Constant ATTR_LOGGING_INITIALIZER.
*/
private static final String ATTR_LOGGING_INITIALIZER = "jacorb.log.initializer";
/**
* <code>useTCCL</code> controls which class loader policy JacORB should use throughout
* the codebase. By default it will attempt to load using the Thread Context Class Loader.
* To support integration in some deployment scenarios it is also possible to use Class.forName.
* This may be set by setting jacorb.classloaderpolicy system property to either tccl or forname.
*
* Note that this is duplicated within org.omg.CORBA.ORBSingleton
* (to avoid cross-dependencies)
*/
public static final boolean useTCCL;
static
{
String clpolicy = System.getProperty ("jacorb.classloaderpolicy", "tccl");
if (clpolicy.equalsIgnoreCase ("forname"))
{
useTCCL = false;
}
else
{
useTCCL = true;
}
}
/**
* Contains the actual configuration data.
*
* To speed up the access of frequently requested configuration values a set
* of dedicated hashmaps provide String, Boolean and Number storage.
*/
private ConcurrentHashMap<String,String> stringAttributes = new ConcurrentHashMap<String,String>(16, 0.9f, 1);
/**
* The boolean attributes.
*/
private ConcurrentHashMap<String,Boolean> booleanAttributes = new ConcurrentHashMap<String,Boolean>(16, 0.9f, 1);
/**
* The number attributes.
*/
private ConcurrentHashMap<String, Number> numberAttributes = new ConcurrentHashMap<String, Number> (16, 0.9f, 1);
/**
* The orb.
*/
private final ORB orb;
/**
* The logger.
*/
private Logger logger;
/**
* The li.
*/
private LoggingInitializer li;
/**
* Factory method.
*
* @param props the props
* @param orb the orb
* @param isApplet the is applet
* @return the configuration
* @throws ConfigurationException the configuration exception
*/
public static Configuration getConfiguration(Properties props,
org.omg.CORBA.ORB orb,
boolean isApplet)
throws ConfigurationException
{
if ( ! (orb instanceof ORB))
{
throw new ConfigurationException("ORB must not be null and must be a JacORB ORB " + (orb == null ? "<null>" : orb.getClass().getName()));
}
return getConfiguration (props, (org.jacorb.orb.ORB)orb, null, isApplet);
}
/**
* Factory method.
*
* @param props the props
* @param orb the orb
* @param orbid the orb_id (if set)
* @param isApplet the is applet
* @return the configuration
* @throws ConfigurationException the configuration exception
*/
public static Configuration getConfiguration(Properties props,
ORB orb,
String orbid,
boolean isApplet)
throws ConfigurationException
{
// determine the ORBId, if set, so we can locate the corresponding
// configuration
String orbID = Version.orbId; // default id
String myOrbID = null;
if ( !isApplet )
{
try
{
myOrbID = System.getProperty("ORBid");
}
catch ( SecurityException e )
{
isApplet = true;
System.err.println ("Could not access system property 'ORBid' - will use default...");
}
}
// ORB props and args override system props.
if ( orbid != null && orbid.length () > 0)
{
myOrbID = orbid;
}
if (myOrbID != null && !myOrbID.equals(""))
{
// check for legal values
if (myOrbID.equals("orb") || myOrbID.equals(Version.orbId))
{
throw new ConfigurationException("Illegal orbID, <" +
myOrbID + "> is reserved");
}
orbID = myOrbID;
}
return new JacORBConfiguration(orbID, props, orb, isApplet);
}
/**
* Create a configuration using the properties passed
* into ORB.init()
*
* @param name the name
* @param orbProperties the orb properties
* @param orb the orb
* @param isApplet the is applet
* @throws ConfigurationException the configuration exception
*/
private JacORBConfiguration(String name,
Properties orbProperties,
ORB orb,
boolean isApplet)
throws ConfigurationException
{
super();
this.orb = orb;
LinkedHashMap<Level,String> delayedLogging = new LinkedHashMap<Level,String> ();
if (isApplet)
{
initApplet(delayedLogging, name, orbProperties);
}
else
{
init(delayedLogging, name, orbProperties);
}
initLogging();
logger = getLogger ("org.jacorb.config");
// This delays logging out any information about the loading of the properties
// or configuration until any logging subsystem has been setup.
for (Entry<Level, String> e : delayedLogging.entrySet())
{
if (e.getKey () == Level.INFO)
{
logger.info (e.getValue ());
}
else if (e.getKey () == Level.WARNING)
{
logger.warn (e.getValue ());
}
else if (e.getKey () == Level.FINE)
{
logger.debug (e.getValue ());
}
else
{
throw new NO_IMPLEMENT("Only info/warn delayed logging implemented.");
}
}
}
/**
* loads properties from files.
*
* Properties are loaded in the following order, with later
* properties overriding earlier ones: 1) System properties
* (incl. command line), to get properties that affect further
* property loading 2) orb.properties file 3) specific
* configuration file for the ORB (if any) 4) System properties
* again, so that command line args take precedence over the above
* 5) the ORB properties set in the client code and passed in
* through ORB.init().
* (Note that these will thus always take effect!)
*
* @param delayedLogging the delayed logging
* @param name the name for the ORB instance, may not be null.
* @param orbProperties the orb properties
* @throws ConfigurationException the configuration exception
*/
private void init(LinkedHashMap<Level, String> delayedLogging, String name, Properties orbProperties)
throws ConfigurationException
{
if( name == null )
{
throw new ConfigurationException("Illegal null value for ORB name!");
}
String separator = System.getProperty("file.separator");
String home = System.getProperty("user.home");
String lib = System.getProperty("java.home");
boolean loaded = false;
// 1) load system properties to grab any command line properties
// that will influence further property loading
setAttributes(System.getProperties());
// 1.5) load passed-in properties that might influence further
// property loading. This will allow me to pass in jacorb.home,
// jacorb.config.dir, and jacorb.config.log.verbosity.
if (orbProperties != null)
{
loaded = true;
setAttributes(orbProperties);
}
// 2) look for orb.properties
// look for common properties files in java.home/lib first
String propFile = lib + separator + "lib" + separator + COMMON_PROPS;
Properties commonProps = loadPropertiesFromFile (propFile);
if (commonProps!= null)
{
setAttributes(commonProps);
loaded = true;
delayedLogging.put (Level.FINE, "base configuration loaded from file " + propFile);
}
// look for common properties files in user.home next
propFile = home + separator + COMMON_PROPS;
commonProps = loadPropertiesFromFile (propFile);
if (commonProps!= null)
{
setAttributes(commonProps);
loaded = true;
delayedLogging.put (Level.FINE, "base configuration loaded from file " + propFile);
}
// look for common properties files on the classpath next
commonProps = loadPropertiesFromClassPath( COMMON_PROPS );
if (commonProps!= null)
{
loaded = true;
setAttributes(commonProps);
delayedLogging.put (Level.FINE, "base configuration loaded from classpath " + COMMON_PROPS);
}
// 3) look for specific properties file
String configDir = getAttribute("jacorb.config.dir", "");
if (configDir.length() == 0)
{
configDir = getAttribute ("jacorb.home", "");
if (configDir.length() != 0 )
{
configDir += separator + "etc";
}
else
{
delayedLogging.put (Level.FINE, "jacorb.home unset! Will use '.'");
configDir = ".";
}
}
propFile = configDir + separator + name + fileSuffix;
// now load properties file from file system
Properties orbConfig = loadPropertiesFromFile (propFile);
if (orbConfig!= null)
{
setAttributes(orbConfig);
loaded = true;
delayedLogging.put (Level.FINE, "configuration " + name + " loaded from file " + propFile +
(orb == null ? " for ORBSingleton" : " for " + orb));
}
// now load properties file from classpath
orbConfig = loadPropertiesFromClassPath (name + fileSuffix);
if (orbConfig!= null)
{
setAttributes(orbConfig);
loaded = true;
delayedLogging.put (Level.FINE, "configuration " + name + " loaded from classpath" +
(orb == null ? " for ORBSingleton" : " for " + orb));
}
// 4) look for additional custom properties files
List<String> customPropFileNames = getAttributeList("custom.props");
if (!customPropFileNames.isEmpty())
{
for (String fileName : customPropFileNames)
{
Properties customProps = loadPropertiesFromFile(fileName);
if (customProps!= null)
{
setAttributes(customProps);
loaded = true;
delayedLogging.put (Level.FINE, "custom properties loaded from file " + fileName);
}
else
{
delayedLogging.put (Level.WARNING, "custom properties not found in " + fileName);
}
}
}
// 5) load system properties again, so that
// command line args override properties from files
setAttributes( System.getProperties() );
// 6) load properties passed to ORB.init() again, these will override any
// settings in config files or system properties!
if (orbProperties != null)
{
loaded = true;
setAttributes(orbProperties);
// This is in case ORBClass/ORBSingleton are not in system properties
// and have been specified via ORB.init props. If this is not done
// and JacORB jars are not in bootclasspath/endorsed then it is possible
// that a Sun Singleton is created by mistake in the config init.
if (orbProperties.containsKey ("org.omg.CORBA.ORBClass") &&
System.getProperty ("org.omg.CORBA.ORBClass") == null)
{
System.setProperty
(
"org.omg.CORBA.ORBClass",
orbProperties.getProperty ("org.omg.CORBA.ORBClass")
);
}
if (orbProperties.containsKey ("org.omg.CORBA.ORBSingletonClass") &&
System.getProperty ("org.omg.CORBA.ORBSingletonClass") == null)
{
System.setProperty
(
"org.omg.CORBA.ORBSingletonClass",
orbProperties.getProperty ("org.omg.CORBA.ORBSingletonClass")
);
}
}
if (!loaded)
{
delayedLogging.put (Level.FINE, "no properties found for configuration " + name);
}
}
/**
* loads properties via classloader.
*
* Properties are loaded in the following order, with later properties
* overriding earlier ones: 1) Properties from ORB.init(), to get
* properties that affect further property loading 2) orb.properties 3)
* specific configuration file for the ORB (if any) 4) the ORB properties
* set in the client code and passed in through ORB.init(). (Note that
* these will thus always take effect!)
*
* @param delayedLogging the delayed logging
* @param name the name for the ORB instance, may not be null.
* @param orbProperties the orb properties
* @throws ConfigurationException the configuration exception
*/
private void initApplet(LinkedHashMap<Level, String> delayedLogging, String name, Properties orbProperties)
throws ConfigurationException
{
if( name == null )
{
throw new ConfigurationException("Illegal null value for ORB name!");
}
boolean loaded = false;
// 1) load system properties to grab any command line properties
// that will influence further property loading
if ( orbProperties != null )
{
setAttributes(orbProperties);
}
// 2) look for orb.properties
// look for common properties files on the classpath next
Properties commonProps = loadPropertiesFromClassPath (COMMON_PROPS);
if (commonProps!= null)
{
setAttributes(commonProps);
loaded = true;
delayedLogging.put (Level.FINE, "base configuration loaded from classpath " + COMMON_PROPS);
}
// 3) look for specific properties file
String propFile = name + fileSuffix;
Properties orbConfig = loadPropertiesFromClassPath (propFile);
if (orbConfig!= null)
{
setAttributes(orbConfig);
loaded = true;
delayedLogging.put (Level.FINE, "configuration " + name + " loaded from classpath " + propFile);
}
else
{
delayedLogging.put (Level.WARNING, "File " + propFile +
" for configuration " + name +
" not found in classpath");
}
// 4) look for additional custom properties files
List<String> customPropFileNames = getAttributeList("custom.props");
if (!customPropFileNames.isEmpty())
{
for (String fileName : customPropFileNames)
{
Properties customProps = loadPropertiesFromClassPath(fileName);
if (customProps!= null)
{
setAttributes(customProps);
loaded = true;
delayedLogging.put (Level.FINE, "custom properties loaded from classpath " + fileName);
}
else
{
delayedLogging.put (Level.WARNING, "custom properties " + fileName + " not found in classpath");
}
}
}
// 5) load properties passed to ORB.init(), these will override any
// settings in config files or system properties!
if (orbProperties != null)
{
loaded = true;
setAttributes(orbProperties);
}
if (!loaded)
{
delayedLogging.put (Level.WARNING, "no properties found for configuration " + name);
}
}
/**
* Sets the value of a single attribute.
*
* @param key the key
* @param value the value
*/
@Override
public void setAttribute(String key, String value)
{
stringAttributes.put(key, value);
}
/* (non-Javadoc)
* @see org.jacorb.config.Configuration#setAttribute(java.lang.String, int)
*/
@Override
public void setAttribute(String key, int value)
{
numberAttributes.put(key, value);
}
/**
* set attributes of this configuration using properties.
*
* @param properties the new attributes
*/
@Override
public void setAttributes(Properties properties)
{
// Some lunatics illegally put non String objects into System props
// as keys / values - we ignore them.
Iterator<String> keyIt = properties.stringPropertyNames().iterator();
while (keyIt.hasNext())
{
String key = keyIt.next();
setAttribute(key, properties.getProperty(key));
}
}
/**
* Loads properties from a file.
*
* @param fileName the name of a properties file
* @return a properties object or null, if fileName not found
*/
private Properties loadPropertiesFromFile(String fileName)
{
try
{
InputStream stream = new FileInputStream(fileName);
try
{
Properties result = new Properties();
result.load(stream);
return result;
}
finally
{
stream.close();
}
}
catch (java.io.FileNotFoundException e)
{
// It's okay to ignore this silently: There was just no
// config file there, so the caller is going to look elsewhere.
return null;
}
catch (java.io.IOException e)
{
// This is probably a more severe problem with the config file.
// Write to the terminal, because we have no logging yet.
System.err.println("could not read config file: " + fileName);
e.printStackTrace();
return null;
}
}
/**
* load properties file from classpath.
*
* @param name the name of the properties file.
* @return a properties object or null, if name not found
*/
private Properties loadPropertiesFromClassPath(String name)
{
Properties result = null;
try
{
final ClassLoader clazzLoader;
if (Thread.currentThread().getContextClassLoader() != null)
{
clazzLoader = Thread.currentThread().getContextClassLoader();
}
else
{
clazzLoader = JacORBConfiguration.class.getClassLoader();
}
java.net.URL url = clazzLoader.getResource(name);
if (url!=null)
{
result = new Properties();
final InputStream stream = url.openStream();
try
{
result.load(stream);
}
finally
{
stream.close();
}
}
}
catch (FileNotFoundException ex)
{
// It's okay to ignore this silently: the caller will just look
// elsewhere.
}
catch (java.io.IOException ioe)
{
// This is a more severe problem: write to the terminal, because
// we have no logging yet.
System.err.println("could not read config file: " + name);
ioe.printStackTrace();
}
return result;
}
/**
* Configures the external logging backend from within JacORB,
* but only if the backend is JDK, and if one of the legacy logging
* properties, jacorb.log.default.verbosity or jacorb.logfile, is set.
* This is only meant to ease the transition as we move to SLF4J.
* Normally, configuration of the logging backend is completely
* external to JacORB and left to the user.
*
* @throws ConfigurationException the configuration exception
*/
private void initLogging() throws ConfigurationException
{
li = (LoggingInitializer)getAttributeAsObject
(
ATTR_LOGGING_INITIALIZER,
"org.jacorb.config.JdkLoggingInitializer"
);
li.init (this);
}
/**
* Calls shutdown on the logging sub-system. This may be a no-op
* depending upon the logging backend.
*/
public void shutdownLogging ()
{
li.shutdownLogging ();
}
/**
* Gets the ORB.
*
* @return the ORB for which this configuration was created
*/
@Override
public org.jacorb.orb.ORB getORB()
{
return orb;
}
/**
* Returns a Logger that logs JacORB system messages. This uses
* the SLF4J logging facade. The actual logging backend is chosen
* at deployment time, by putting a corresponding SLF4J adapter
* jar on the classpath.
* <p>
* The JacORB root logger is named "jacorb". Sublogger names all
* start with this prefix. If the property jacorb.implname is set,
* and the property jacorb.log.split_on_implname is true, then
* all loggers for that particular ORB instance are rooted in
* <code>{@literal jacorb.<implname>}</code>
* <p>
* Here's a guideline how to use logging levels in the code:
* <p>
* error Conditions that indicate a bug in JacORB or user code,
* or a wrong configuration. This includes, but is not
* limited to, errors that will lead to termination of the
* program (fatal errors).
* <p>
* warn Conditions that demand attention, but are handled properly
* according to the CORBA spec. For example, abnormal termination
* of a connection, reaching of a resource limit (queue full).
* <p>
* info Start/stop of subsystems, establishing and closing of connections,
* registering objects with a POA.
* <p>
* debug Information that might be needed for finding bugs in JacORB
* or user code. Anything that relates to the normal processing
* of individual messages should come under this level. For each
* CORBA message, there should at least one debug message when
* subsystem boundaries are crossed (e.g. GIOPConnection -> POA
* -> User Code).
*
* @param name the name
* @return the logger
*/
@Override
public org.slf4j.Logger getLogger (String name)
{
String loggerName = name;
if (getAttributeAsBoolean ("jacorb.log.split_on_implname", false))
{
String implName = getAttribute ("jacorb.implname", null);
if (implName != null && implName.length() > 0)
{
if (name.equals (Version.orbId))
{
loggerName = LoggingInitializer.ATTR_LOG_NAME + '.' + implName;
}
else if (name.startsWith (LoggingInitializer.ATTR_LOG_NAME + '.'))
{
loggerName = LoggingInitializer.ATTR_LOG_NAME + '.' + implName + "." + name.substring (11);
}
}
}
return org.slf4j.LoggerFactory.getLogger (loggerName);
}
@Override
public boolean isAttributeSet(String key) throws ConfigurationException
{
return stringAttributes.containsKey(key);
}
/**
* Gets the attribute
*
* @param key the key
* @return the attribute
* @throws ConfigurationException the configuration exception
* @see org.jacorb.config.Configuration#getAttribute(java.lang.String)
*/
@Override
public String getAttribute(String key) throws ConfigurationException
{
String result = getAttribute (key, null);
if (result == null)
{
throw new ConfigurationException
(
"attribute " + key + " is not defined"
);
}
return result;
}
/**
* getAttribute
* @see org.jacorb.config.Configuration#getAttribute(java.lang.String, java.lang.String)
*/
@Override
public String getAttribute(String key, String defaultValue)
{
String result = stringAttributes.get (key);
if (result == null && defaultValue != null)
{
stringAttributes.put (key, defaultValue);
result = defaultValue;
}
else if ( result != null )
{
result = result.trim();
}
return result;
}
/**
* Gets the attribute as integer.
*
* @param key the key
* @param defaultValue the default value
* @return the attribute as integer
* @throws ConfigurationException the configuration exception
* @see org.jacorb.config.Configuration#getAttributeAsInteger(java.lang.String, int, int)
*/
@Override
public int getAttributeAsInteger(String key, int defaultValue) throws ConfigurationException
{
return getAttributeAsInteger (key, defaultValue, 10);
}
/**
* Returns the integer value of the specified key.
*
* @param key the key
* @param defaultValue the default value
* @param radix the radix
* @return the attribute as integer
* @throws ConfigurationException the configuration exception
*/
@Override
public int getAttributeAsInteger(String key, int defaultValue, int radix) throws ConfigurationException
{
Number result = numberAttributes.get (key);
if (result == null)
{
// This used to be .remove but removing it from the string
// cache can cause inconsistency if another caller uses
// getAttribute.
String value = stringAttributes.get (key);
if (value == null)
{
result = Integer.valueOf (defaultValue);
}
else if (value.trim().length() < 1)
{
// treat empty values as non-defined (null)
result = Integer.valueOf (defaultValue);
}
else
{
try
{
result = Integer.parseInt (value.trim(), radix);
}
catch (NumberFormatException ex)
{
throw new ConfigurationException
(
"value for attribute " + key + " is not numeric: " + value
);
}
}
numberAttributes.put (key, result);
}
return result.intValue ();
}
/**
* Validates the key exists and then returns the value.
*
* @param key the key
* @return the attribute as integer
* @throws ConfigurationException the configuration exception
*/
@Override
public int getAttributeAsInteger(String key) throws ConfigurationException
{
if ( ! stringAttributes.containsKey (key) && ! numberAttributes.containsKey (key))
{
throw new ConfigurationException
(
"Value for attribute " + key + " is not set"
);
}
return getAttributeAsInteger (key, -1, 10);
}
/**
* Gets the attribute as long.
*
* @param key the key
* @param defaultValue the default value
* @return the attribute as long
* @throws ConfigurationException the configuration exception
* @see org.jacorb.config.Configuration#getAttributeAsLong(java.lang.String, long)
*/
@Override
public long getAttributeAsLong(String key, long defaultValue) throws ConfigurationException
{
Number result = numberAttributes.get (key);
if (result == null)
{
// This used to be .remove but removing it from the string
// cache can cause inconsistency if another caller uses
// getAttribute.
String value = stringAttributes.get (key);
if (value == null)
{
result = Long.valueOf (defaultValue);
}
else if (value.trim().length() < 1)
{
// treat empty values as non-defined (null)
result = Long.valueOf (defaultValue);
}
else
{
try
{
result = Long.parseLong (value.trim());
}
catch (NumberFormatException ex)
{
throw new ConfigurationException
(
"value for attribute " + key + " is not numeric: " + value
);
}
}
numberAttributes.put (key, result);
}
return result.longValue ();
}
/**
* Gets the attribute list.
*
* @param key the key
* @return the attribute list
* @see org.jacorb.config.Configuration#getAttributeList(java.lang.String)
*/
@Override
public List<String> getAttributeList(String key)
{
List<String> result = new ArrayList<String>();
String value = null;
try
{
value = getAttribute(key);
}
catch( ConfigurationException ce)
{
// ignore
}
if (value != null)
{
StringTokenizer tok = new StringTokenizer(value, ",");
while (tok.hasMoreTokens())
{
result.add(tok.nextToken().trim());
}
}
return result;
}
@Override
public String[] getAttributeAsStringsArray(String key)
{
String value = null;
try
{
value = getAttribute(key);
}
catch( ConfigurationException ce)
{
// ignore
}
if (value == null)
{
return null;
}
List<String> values = getAttributeList (key);
// Return null if key is defined but has empty value
if (values.size () < 1)
{
return null;
}
return values.toArray (new String[values.size ()]);
}
/**
* New instance.
*
* @param key the key
* @param className the class name
* @return the object
* @throws ConfigurationException the configuration exception
*/
private Object newInstance(String key, String className) throws ConfigurationException
{
try
{
Class<?> clazz = ObjectUtil.classForName(className);
final Object instance = clazz.newInstance();
if (instance instanceof Configurable)
{
((Configurable)instance).configure(this);
}
return instance;
}
catch( Exception e )
{
throw new ConfigurationException( "Unable to build class from key >" +
key +"<: " + e );
}
}
/**
* Gets the attribute as object.
*
* @param key the key
* @return the attribute as object
* @throws ConfigurationException the configuration exception
* @see org.jacorb.config.Configuration#getAttributeAsObject(java.lang.String)
*/
@Override
public Object getAttributeAsObject( String key )
throws ConfigurationException
{
return getAttributeAsObject(key, "");
}
/**
* Gets the attribute as object.
*
* @param key the key
* @param defaultClass the default class
* @return the attribute as object
* @throws ConfigurationException the configuration exception
* @see org.jacorb.config.Configuration#getAttributeAsObject(java.lang.String, java.lang.String)
*/
@Override
public Object getAttributeAsObject(String key, String defaultClass) throws ConfigurationException
{
Object result = null;
String classname = getAttribute (key, "");
if (classname.length() > 0 )
{
result = newInstance(key, classname);
}
else if (defaultClass != null && defaultClass.length () > 0)
{
result = newInstance("default", defaultClass);
}
return result;
}
/**
* Return the attribute as a boolean. A default value must be supplied and the
* key/value is cached.
*
* @param key the key
* @param defaultValue the default value
* @return the attribute as boolean
*/
@Override
public boolean getAttributeAsBoolean(String key, boolean defaultValue)
{
Boolean result = booleanAttributes.get (key);
if (result == null)
{
// This used to be .remove but removing it from the string
// cache can cause inconsistency if another caller uses
// getAttribute.
String value = stringAttributes.get (key);
if (value == null)
{
result = Boolean.valueOf (defaultValue);
}
else if (value.trim().length() < 1)
{
// treat empty values as non-defined (null)
result = Boolean.valueOf (defaultValue);
}
else
{
value = value.trim().toLowerCase();
result = Boolean.valueOf ((ON.equals(value) || TRUE.equals(value)));
}
booleanAttributes.put (key, result);
}
return result;
}
/**
* Gets the attribute names.
*
* @return the attribute names
*/
private String[] getAttributeNames()
{
return (stringAttributes.keySet().toArray (new String[]{}));
}
/**
* Gets the attribute names with prefix.
*
* @param prefix the prefix
* @return the attribute names with prefix
* @see org.jacorb.config.Configuration#getAttributeNamesWithPrefix(java.lang.String)
*/
@Override
public List<String> getAttributeNamesWithPrefix(String prefix)
{
final ArrayList<String> attributesWithPrefix = new ArrayList<String>();
final String[] allAttributes = getAttributeNames();
for (int x = 0; x < allAttributes.length; ++x)
{
if (allAttributes[x].startsWith(prefix))
{
attributesWithPrefix.add(allAttributes[x]);
}
}
return Collections.unmodifiableList(attributesWithPrefix);
}
/* (non-Javadoc)
* @see org.jacorb.config.Configuration#getAttributeAsFloat(java.lang.String, double)
*/
@Override
public double getAttributeAsFloat (String key, double defaultValue) throws ConfigurationException
{
Number result = numberAttributes.get (key);
if (result == null)
{
// This used to be .remove but removing it from the string
// cache can cause inconsistency if another caller uses
// getAttribute.
String value = stringAttributes.get (key);
if (value == null)
{
result = Double.valueOf (defaultValue);
}
else if (value.trim().length() < 1)
{
// treat empty values as non-defined (null)
result = Double.valueOf (defaultValue);
}
else
{
try
{
result = Double.parseDouble (value.trim());
}
catch (NumberFormatException ex)
{
throw new ConfigurationException
(
"value for attribute " + key + " is not numeric: " + value
);
}
}
numberAttributes.put (key, result);
}
return result.doubleValue ();
}
}