package de.skuzzle.polly.core.configuration; import java.io.File; import java.io.FileNotFoundException; import java.io.IOException; import java.util.Map; import java.util.WeakHashMap; import javax.naming.ConfigurationException; import org.apache.log4j.Logger; import de.skuzzle.jeve.EventProvider; import de.skuzzle.polly.sdk.Configuration; import de.skuzzle.polly.sdk.ConfigurationProvider; import de.skuzzle.polly.sdk.ConfigurationValidator; import de.skuzzle.polly.sdk.eventlistener.ConfigurationEvent; import de.skuzzle.polly.sdk.eventlistener.ConfigurationListener; public class ConfigurationProviderImpl implements ConfigurationProvider { public final static ConfigurationValidator NOP_VALIDATOR = new ConfigurationValidator() { @Override public void validate(Configuration config) { // do nothing! } }; private final static Logger logger = Logger.getLogger( ConfigurationProviderImpl.class.getName()); private File configDir; private File pluginConfigDir; private Map<File, ConfigurationImpl> cfgCache; private Configuration rootCfg; private EventProvider eventProvider; public ConfigurationProviderImpl(File configDir) { this.configDir = configDir; this.pluginConfigDir = new File(configDir, "pluginconfigs"); //$NON-NLS-1$ this.cfgCache = new WeakHashMap<File, ConfigurationImpl>(); this.eventProvider = EventProvider.newDefaultEventProvider(); } public Configuration open(String cfgName, boolean isRoot, ConfigurationValidator validator) throws FileNotFoundException, IOException, ConfigurationException { logger.trace("Trying to locate '" + cfgName + "'"); //$NON-NLS-1$ //$NON-NLS-2$ File cfgFile = this.searchFor(cfgName); ConfigurationImpl cached = this.cfgCache.get(cfgFile.getCanonicalFile()); if (cached == null) { cached = new ConfigurationImpl(cfgFile, this); validator.validate(cached); cached.setValidator(validator); this.cfgCache.put(cfgFile.getCanonicalFile(), cached); logger.info("Loaded configuration into memory\n" + cached.toString()); //$NON-NLS-1$ } else { logger.trace("Configuration restored from cache"); //$NON-NLS-1$ } if (isRoot) { logger.info("Setting new root configuration"); //$NON-NLS-1$ this.rootCfg = cached; } return cached; } @Override public Configuration open(String cfgName, ConfigurationValidator validator) throws FileNotFoundException, IOException, ConfigurationException { return this.open(cfgName, false, validator); } @Override public Configuration open(String cfgName) throws FileNotFoundException, IOException { try { return this.open(cfgName, NOP_VALIDATOR); } catch (ConfigurationException e) { // HACK: this can not happen! throw new RuntimeException(e); } } @Override public Configuration emptyConfiguration() { return new ConfigurationImpl(this); } public Configuration createConfiguration(String name) throws IOException { final File target = new File(this.configDir, name); target.createNewFile(); return this.open(name); } @Override public Configuration getRootConfiguration() { return this.rootCfg; } private File searchFor(String cfgName) throws FileNotFoundException { File cfgFile = new File(this.configDir, cfgName); if (!cfgFile.exists()) { cfgFile = new File(this.pluginConfigDir, cfgName); if (!cfgFile.exists()) { throw new FileNotFoundException(cfgName); } } return cfgFile; } @Override public void addConfigurationListener(ConfigurationListener listener) { this.eventProvider.addListener(ConfigurationListener.class, listener); } @Override public void removeConfigurationListener(ConfigurationListener listener) { this.eventProvider.removeListener(ConfigurationListener.class, listener); } public void fireConfigurationChanged(ConfigurationEvent e) { this.eventProvider.dispatch(ConfigurationListener.class, e, ConfigurationListener::configurationChange); } }