package com.yahoo.dtf.config;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Set;
import java.util.Map.Entry;
import com.yahoo.dtf.components.PropertyState;
import com.yahoo.dtf.config.Config;
import com.yahoo.dtf.config.DynamicProperty;
import com.yahoo.dtf.DTFProperties;
import com.yahoo.dtf.exception.DTFException;
import com.yahoo.dtf.exception.ParseException;
import com.yahoo.dtf.exception.PropertyException;
import com.yahoo.dtf.logger.DTFLogger;
/**
*
* @author Rodney Gomes
*/
public final class Config implements Cloneable {
private static DTFLogger _log = DTFLogger.getLogger(Config.class);
// Static Properties
private Properties _properties = null;
private static HashMap<String, DynamicProperty> _dynamic =
new HashMap<String, DynamicProperty>();
public Config() throws DTFException {
this(true);
}
private Config(boolean init) throws DTFException {
if (init) init();
}
public static void registerDynamicProperty(String key, DynamicProperty dyn) throws DTFException {
if ( _dynamic.containsKey(key) )
throw new DTFException("Dynamic property with the name [" + key +
"] already exists");
if ( _log.isDebugEnabled() )
_log.debug("Registering dynamic property [" + key + "]");
_dynamic.put(key,dyn);
PropertyState.addPropertiesToIgnore(key);
}
public static Set<String> getDynamicProperties() {
return _dynamic.keySet();
}
private void init() throws DTFException {
_properties = new Properties();
java.util.Properties aux = (java.util.Properties)
System.getProperties();
for (Entry<Object, Object> entry : aux.entrySet())
_properties.put(entry.getKey(), entry.getValue());
String home = getProperty(DTFProperties.DTF_HOME);
File config = new File(home + File.separatorChar + "dtf.properties");
if (config.exists()) {
FileInputStream fis;
try {
fis = new FileInputStream(config);
loadProperties(fis,false);
} catch (FileNotFoundException e) {
throw new DTFException("Bad config.",e);
}
}
initDTFProperties();
}
public void initDTFProperties() throws ParseException {
/*
* Dynamic properties that are used internally in the DTF framework.
*/
Iterator<String> iterator = _dynamic.keySet().iterator();
while ( iterator.hasNext() ) {
String key = iterator.next();
put(key,_dynamic.get(key));
}
// add default properties
if (getProperty(DTFProperties.DTF_XML_FILENAME) != null) {
String pathToXML = new File(getProperty(DTFProperties.DTF_XML_FILENAME)).getParent();
if (pathToXML == null)
pathToXML = "";
_properties.put(DTFProperties.DTF_XML_PATH, pathToXML);
}
}
public void put(String key, DynamicProperty property) {
_properties.put(key, property);
}
public String callDynamicProperty(String key, String args) throws ParseException {
Object result = _properties.get(key);
if (result instanceof DynamicProperty) {
return ((DynamicProperty)result).getValue(args);
} else {
throw new ParseException("No dynamic property named [" + key + "]");
}
}
public <T extends Object> boolean isType(String key, Class<T> c) {
return c.isInstance(_properties.get(key));
}
public boolean isStream(String key) {
return _properties.get(key) instanceof DTFStream;
}
public <T> T getPropertyAs(String key) throws ParseException {
try {
return (T) _properties.get(key);
} catch (ClassCastException e) {
// no easy way to do instanceOf on a generic type, since it only
// exists at runtime but we can catch the ClassCastException and
// give back a better error message.
throw new ParseException("Property [" + key +
"] not of the specified type.",e);
}
}
public DTFStream getPropertyAsStream(String key) {
return (DTFStream) _properties.get(key);
}
public String getProperty(String key) throws ParseException {
Object result = _properties.get(key);
if (result instanceof DynamicProperty) {
/*
* Normal dynamic property without arguments
*/
return ((DynamicProperty)result).getValue(null);
} else {
return (String) result;
}
}
public String getProperty(String key, String defaultValue) throws ParseException {
String result = getProperty(key);
if (result == null)
return defaultValue;
else
return result;
}
public int getPropertyAsInt(String key, int defaultValue) throws PropertyException, ParseException {
String result = getProperty(key);
try {
if (result == null)
return defaultValue;
else
return new Integer(result).intValue();
} catch (NumberFormatException e) {
throw new PropertyException("Invalid int value for property '" +
key + "'",e);
}
}
public Boolean getPropertyAsBoolean(String key,
Boolean defaultValue) throws ParseException {
String result = getProperty(key);
if (result == null)
return defaultValue;
else
return Boolean.valueOf(result);
}
public int getPropertyAsInt(String key) throws PropertyException, ParseException {
String result = getProperty(key);
try {
if (result == null)
return -1;
else
return new Integer(result).intValue();
} catch (NumberFormatException e) {
throw new PropertyException("Invalid int value for property '" +
key + "'",e);
}
}
public synchronized boolean contains(Object value) {
return _properties.contains(value);
}
public synchronized boolean containsKey(Object key) {
return _properties.containsKey(key);
}
public void loadProperties(InputStream is, boolean overwrite) throws DTFException {
loadProperties(is,overwrite,null);
}
public void loadProperties(InputStream is,
boolean overwrite,
String encoding) throws DTFException {
try {
// DTF default file encoding
if ( encoding == null )
encoding = "UTF-8";
java.util.Properties properties = new java.util.Properties();
properties.load(is);
Enumeration keys = properties.keys();
while (keys.hasMoreElements()) {
Object key = keys.nextElement();
Object value = properties.get(key);
if ( overwrite || !containsKey(key)) {
if ( encoding != null ) {
key = new String(((String)key).
getBytes(encoding),encoding);
value = new String(((String)value).
getBytes(encoding),encoding);
}
_properties.put(key, value);
}
}
} catch (IOException e) {
throw new DTFException("Unable to load properties from specified stream.",e);
}
}
public Properties getProperties() { return _properties; }
public Object setProperty(String key, String value) {
return _properties.put(key, value);
}
public Object setProperty(String key, long value) {
return _properties.put(key, "" + value);
}
public Object setProperty(String key, String value, boolean overwrite) {
if ( overwrite ) {
return _properties.put(key, value);
} else if (!containsKey(key)) {
return _properties.put(key, value);
}
return _properties.get(key);
}
public Object clone() {
if ( _log.isDebugEnabled() )
_log.debug("cloning " + _properties.size() + " properties.");
Config config;
try {
config = new Config(false);
} catch (DTFException e) {
throw new RuntimeException("Unable to clone.",e);
}
config._properties = (Properties)this._properties.clone();
return config;
}
public synchronized Object remove(Object key) {
return _properties.remove(key);
}
}