package scigest.configuration;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.ArrayList;
import java.util.Iterator;
import org.apache.commons.configuration.CompositeConfiguration;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.configuration.ConfigurationException;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This class handles multiple configuration sources
* <p>
*
* Global Configuration:
* resources/application.properties
*
* <p>
* Local Configuration:
* $HOME/.scigest/my.properties
*
*
*
* @author Feiyi Wang
*
*/
public class ScigestConfiguration {
private final static Logger logger = LoggerFactory.getLogger(ScigestConfiguration.class);
private final static String SCIGEST_HOME = "SCIGEST_HOME";
private final static String SITE_CONF_FILE="application.properties";
private final static String USER_CONF_FILE="my.properties";
private final static String CATALOG_FILE="catalog.txt";
private File userConfPath;
private File siteConfFile;
private File userConfFile;
private PropertiesConfiguration siteConfiguration;
private PropertiesConfiguration userConfiguration;
private CompositeConfiguration cc;
private final ArrayList<String> keyList;
private static String scigestHomeDir;
public ScigestConfiguration() throws IOException, ConfigurationException {
scigestHomeDir = System.getenv(SCIGEST_HOME);
if (scigestHomeDir == null) {
// now check user.home
scigestHomeDir = System.getProperty("user.home") + "/" + "scigest";
if (! new File(scigestHomeDir).exists()) {
logger.error("SCIGEST_HOME is missing, quit now");
System.exit(1);
}
}
logger.debug("SCIGEST_HOME is set to {}", scigestHomeDir);
// check if the site-wide properties available
siteConfFile = new File(scigestHomeDir + "/resources/" + SITE_CONF_FILE);
userConfPath = new File(System.getProperty("user.home") + "/.scigest");
userConfFile = new File(userConfPath, USER_CONF_FILE);
if (!siteConfFile.exists()) {
logger.error("{} is missing, quit now.", siteConfFile.getPath());
System.exit(1);
}
if (!userConfPath.exists()) {
logger.debug("{} does not exist, creating one now", userConfPath.getPath());
userConfPath.mkdirs();
}
// create a new file if necessary
if (! userConfFile.createNewFile()) {
logger.debug("Detect exisiting user configurations {}", userConfFile.getPath());
}
this.siteConfiguration = new PropertiesConfiguration(siteConfFile);
this.userConfiguration = new PropertiesConfiguration(userConfFile);
this.cc = new CompositeConfiguration();
cc.addConfiguration(this.userConfiguration);
cc.addConfiguration(this.siteConfiguration);
keyList = new ArrayList<String>();
Iterator<?> it = cc.getKeys();
while (it.hasNext()) {
keyList.add((String) it.next());
}
}
/**
* Get the directory where user's configuration file stays
*
* @return
*/
public File getUserConfPath() {
return this.userConfPath;
}
/**
*
* Get the full path on catalog file
*
* @return
*/
public File getCatalogFile() {
return new File(this.userConfPath, CATALOG_FILE);
}
public Configuration getSiteConfiguration() {
return this.siteConfiguration;
}
public Configuration getUserConfiguration() {
return this.userConfiguration;
}
public Configuration getCompositeConfiguration() {
return this.cc;
}
public CompositeConfiguration getCC() {
return this.cc;
}
private URL getClassLocation() {
// derive it from how it is invoked
String classLocation = this.getClass().getName().replace(".", "/") + ".class";
URL classURL = ScigestConfiguration.class.getClassLoader().getResource(classLocation);
return classURL;
}
public String[] getKeys() {
String[] keyArr = new String[keyList.size()];
return keyList.toArray(keyArr);
}
public String getString(String key) {
return cc.getString(key);
}
public int getNumOfProps() {
return keyList.size();
}
/**
* Given a key, and if the value is different from default,
* this method will update the property as part of user's local settings.
*
* @param key
* @param val
* @return
* @throws ConfigurationException
*/
public boolean setString(String key, String val) throws ConfigurationException{
if (! keyList.contains(key)) {
logger.debug("Can't locate key: [{}], setting is disallowed", key);
return false;
}
String defaultVal = siteConfiguration.getString(key);
if (! defaultVal.equals(val)) {
userConfiguration.setProperty(key, val);
userConfiguration.save();
}
return true;
}
/**
* Restore default value
* @throws ConfigurationException
*/
public void reset() throws ConfigurationException {
userConfiguration.clear();
userConfiguration.save();
}
public String[] getLocalKeys() {
Iterator<?> it = userConfiguration.getKeys();
ArrayList<String> localKeyList = new ArrayList<String>();
while (it.hasNext()) {
localKeyList.add((String) it.next());
}
String[] keyArr = new String[localKeyList.size()];
return localKeyList.toArray(keyArr);
}
/**
* Provide local property value given a local property key
*
* @param key
* @return
*/
public String getLocalVal(String key) {
return userConfiguration.getString(key);
}
/**
* Print composite configurations, for debugging purpose mostly.
*
*/
public void dumpCompositeConfiguration() {
Iterator<?> it = cc.getKeys();
ArrayList<String> keyList = new ArrayList<String>();
while (it.hasNext()) {
keyList.add((String) it.next());
}
System.out.println("");
for (String key: keyList) {
System.out.printf("%s=%s\n", key, cc.getString(key));
}
System.out.println("");
}
}