/*
This file is part of the software framework JStatCom,
a library for building applications for data based analysis.
Copyright (C) 2000-2005 Markus Kraetzig
This library is free software; you can redistribute it and/or modify
it under the terms of the GNU Lesser General Public License as
published by the Free Software Foundation; either version 2.1 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
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307
USA
*/
package com.jstatcom.engine;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.OutputStream;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.Map;
import java.util.Set;
import javolution37.javolution.xml.ObjectReader;
import javolution37.javolution.xml.ObjectWriter;
import javolution37.javolution.xml.XmlElement;
import javolution37.javolution.xml.XmlFormat;
import org.apache.log4j.Logger;
import com.jstatcom.component.StdMessages;
/**
* This class is used by Engine instances to get all information
* that is necessary to run a specific engine. The types of configuration
* settings are defined in the ConfigKeys implementation for the
* underlying engine type. Instances of this class store information according
* to the respective configuration keys.
*
* For every engine type there exists only one instance of this class. Instances
* for engine types are created or referenced by the static factory method
* valueOf.
*
* All information is stored permanently in an XML file defined in the
* respective engine type.
*
* @author Markus Kraetzig
*
* @see com.jstatcom.engine.EngineTypes
* @see com.jstatcom.engine.ConfigKeys
*/
public final class ConfigHolder {
private static final Logger log = Logger.getLogger(ConfigHolder.class);
/**
* Contains the configuration information.
*/
private final Map configMap = new HashMap();
/**
* To make sure, that there is only one ConfigHolder for a certain
* EngineType.
*/
private static final Map configHoldersMap = new HashMap();
/**
* Reference to the EngineType.
*/
private final EngineTypes engineType;
/**
* XML format field for (de)serialization.
*/
public static final XmlFormat ConfigHolder_XML = new XmlFormat(
ConfigHolder.class) {
public void format(ConfigHolder data, XmlElement xml) {
xml.setAttribute("engine", data.engineType.name);
for (Iterator it = data.configMap.keySet().iterator(); it.hasNext();) {
ConfigKeys key = (ConfigKeys) it.next();
Object value = data.configMap.get(key);
xml.add(new KeyValPair(key.name(), value.toString()));
}
}
public ConfigHolder parse(XmlElement xml) {
Object oNam = xml.getAttribute("engine", (String) null);
if (oNam == null)
return null;
EngineTypes type = EngineTypes.valueOf(oNam.toString()
.toUpperCase());
if (type == null)
return null;
ConfigHolder conf = null;
// If instance already exists, use it.
if (configHoldersMap.containsKey(type))
conf = configHoldersMap.get(type);
if (conf == null)
conf = new ConfigHolder(type);
Map confKeys = type.getConfigKeys();
if (confKeys == null)
return conf;
while (xml.hasNext()) {
KeyValPair pair = (KeyValPair) xml.getNext();
Object o = confKeys.get(pair.key);
if (o instanceof ConfigKeys)
conf.setConfig((ConfigKeys) o, pair.value);
}
configHoldersMap.put(type, conf);
return conf;
}
};
/**
* Inner class for storing key value pairs of this collection as XML
* elements.
*/
public static class KeyValPair {
// Fields are directly accessed by enclosing class.
final String key;
final String value;
/**
* XML format field for (de)serialization.
*/
public static final XmlFormat KeyValPair_XML = new XmlFormat(
KeyValPair.class) {
public void format(KeyValPair data, XmlElement xml) {
xml.setAttribute("key", data.key);
xml.setAttribute("value", data.value);
}
public KeyValPair parse(XmlElement xml) {
String nkey = xml.getAttribute("key") + "";
String nvalue = xml.getAttribute("value") + "";
return new KeyValPair(nkey, nvalue);
}
};
public KeyValPair(String key, String value) {
if (key == null || value == null)
throw new IllegalArgumentException("Argument was null");
this.value = value;
this.key = key;
}
};
/**
* Creates a ConfigHolder and initializes it with default
* values.
*
* @param engineType
* @throws IllegalArgumentException
* if (engineType == null)
* @throws IllegalStateException
* if another instance of this class has already been created
* for engineType
*/
private ConfigHolder(EngineTypes engineType) {
if (engineType == null)
throw new IllegalArgumentException("Argument was null");
this.engineType = engineType;
if (configHoldersMap.containsKey(engineType))
throw new IllegalStateException("Instance for " + engineType
+ " already exists.");
Map confKeys = engineType.getConfigKeys();
if (confKeys == null)
return;
Collection allKeys = confKeys.values();
for (Iterator it = allKeys.iterator(); it.hasNext();) {
ConfigKeys key = (ConfigKeys) it.next();
setConfig(key, key.defaultVal());
}
}
/**
* Creates a dialog to change the configuration settings for the respective
* engine. It updates the XML configuration file if the changes were
* successful.
*/
public void adjustConfig() {
if (ConfigDialog.showConfigDialog(this))
saveConfig(); // Update XML file.
}
/**
* Get a configuration value for a key.
*
* @param key
* that defines type of setting
* @return a string containing the setting associated with key
* or null if the key is not contained
* @throws IllegalArgumentException
* if (key == null)
*/
public String getConfig(ConfigKeys key) {
if (key == null)
throw new IllegalArgumentException("Argument was null.");
if (configMap.containsKey(key)) {
Object o = configMap.get(key);
if (o != null)
return o.toString();
}
return null;
}
/**
* Gets a Set of all available ConfigKeys.
*
* @return a set of all keys
*/
public Set getConfigKeys() {
return configMap.keySet();
}
/**
* Returns the engine type associated with this.
*
* @return the engine type
*/
public final EngineTypes getEngineType() {
return engineType;
}
/**
* Serializes this to an XML file.
*/
private void saveConfig() {
try {
OutputStream out = new BufferedOutputStream(new FileOutputStream(
new File(engineType.getConfigFile())));
ObjectWriter objectWriter = new ObjectWriter();
objectWriter.setPackagePrefix("", "com.jstatcom.engine");
objectWriter.setPackagePrefix("jstatcom", "com.jstatcom");
objectWriter.write(this, out); // Uses UTF-8 encoding.
} catch (IOException ivjExc) {
log.error("XML serialization failed", ivjExc);
}
}
/**
* Set a key value pair to be stored by the config holder.
*
* @param configKey
* the key
* @param value
* the value
* @throws IllegalArgumentException
* if (configKey == null) or if
* configKey is not valid for the underlying
* engine type
*/
public void setConfig(ConfigKeys configKey, String value) {
if (configKey == null)
throw new IllegalArgumentException("Argument was null.");
Map confKeys = engineType.getConfigKeys();
if (confKeys == null)
throw new IllegalArgumentException(configKey + " is not valid for "
+ engineType + ".");
if (confKeys.containsValue(configKey))
configMap.put(configKey, value);
else
throw new IllegalArgumentException(configKey + " is not valid for "
+ engineType + ".");
}
/**
* Static initializer to return an instance of ConfigHolder.
* It parses the XML config file if it exists and tries to get all necessary
* configuration information. If the config file does not exist or if
* something is wrong with the settings, an input dialog is shown. The
* configuration file is updated if something has changed.
*
* @param engineType
* to define a specific engine
* @return the initialized instance
* @throws IllegalArgumentException
* if (engineType == null)
* @throws IllegalStateException
* if the user input dialog is cancelled but the settings are
* still invalid
*/
public static ConfigHolder valueOf(EngineTypes engineType) {
if (engineType == null)
throw new IllegalArgumentException("Argument was null.");
if (configHoldersMap.containsKey(engineType))
return configHoldersMap.get(engineType);
// Create configHolder from configFile if it is there.
// Otherwise create empty config holder.
ConfigHolder configHolder = null;
File file = new File(engineType.getConfigFile());
if (file.isFile()) {
ObjectReader constructor = new ObjectReader();
try {
configHolder = (ConfigHolder) constructor
.read(new FileInputStream(file));
} catch (Throwable ex) {
configHolder = null;
}
}
if (configHolder == null)
configHolder = new ConfigHolder(engineType);
// Check input and ask user if something is missing or wrong.
String error = null;
if ((error = engineType.checkConfig(configHolder)) != null) {
StdMessages.error(error, "Error in " + engineType + " Settings");
// Initialization failed because of invalid config info.
if (!ConfigDialog.showConfigDialog(configHolder)) {
configHoldersMap.remove(engineType);
throw new IllegalStateException(
"Config settings are not in a legal state for "
+ engineType + ".");
}
configHolder.saveConfig(); // Update XML file.
}
configHoldersMap.put(engineType, configHolder);
return configHolder;
}
}
Ads help maintain this website.