package org.talend.esb.mep.requestcallback.impl; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.net.URL; import java.util.Collection; import java.util.Collections; import java.util.Dictionary; import java.util.Enumeration; import java.util.HashMap; import java.util.Map; import java.util.Properties; import java.util.Set; import java.util.logging.Level; import java.util.logging.Logger; import javax.xml.namespace.QName; import org.apache.cxf.common.logging.LogUtils; import org.talend.esb.mep.requestcallback.feature.RequestCallbackFeature; public class ConfigurationImpl extends AbstractConfiguration { private static final Logger LOGGER = LogUtils.getL7dLogger(ConfigurationImpl.class); private Map<String, Object> userMap = null; private Map<String, Object> dynamicMap = null; private Map<String, Object> staticMap = null; private Map<String, Object> mergedMap = null; private ChangeListener changeListener = null; private final QName configurationName; private final String configurationId; private final String alternateConfigId; public ConfigurationImpl(QName configurationName) { super(); this.configurationName = configurationName; configurationId = asConfigIdentifier(configurationName); if (configurationName == null) { alternateConfigId = null; } else { final String cfgid = asConfigIdentifier(configurationName.getLocalPart()); alternateConfigId = configurationId.equals(cfgid) ? null : cfgid; } } @Override public synchronized int size() { return getMergedMap().size(); } @Override public synchronized boolean isEmpty() { if (mergedMap != null) { return mergedMap.isEmpty(); } if (staticMap != null && !staticMap.isEmpty()) { return false; } if (dynamicMap != null && !dynamicMap.isEmpty()) { return false; } if (userMap != null && !userMap.isEmpty()) { return false; } return true; } @Override public synchronized boolean containsKey(Object key) { if (mergedMap != null) { return mergedMap.containsKey(key); } if (staticMap != null && staticMap.containsKey(key)) { return true; } if (dynamicMap != null && dynamicMap.containsKey(key)) { return true; } if (userMap != null && userMap.containsKey(key)) { return true; } return false; } @Override public synchronized boolean containsValue(Object value) { return getMergedMap().containsValue(value); } @Override public synchronized Object get(Object key) { if (mergedMap != null) { return mergedMap.get(key); } if (userMap != null) { final Object res = userMap.get(key); if (res != null) { return res; } } if (dynamicMap != null) { final Object res = dynamicMap.get(key); if (res != null) { return res; } } if (staticMap != null) { final Object res = staticMap.get(key); if (res != null) { return res; } } return null; } @Override public synchronized Object put(String key, Object value) { if (userMap == null) { userMap = new HashMap<String, Object>(); } mergedMap = null; return userMap.put(key, value); } @Override public synchronized Object remove(Object key) { if (userMap == null) { return null; } final Object result = userMap.remove(key); if (result != null) { mergedMap = null; if (userMap.isEmpty()) { userMap = null; } } return result; } @Override public synchronized void putAll(Map<? extends String, ? extends Object> m) { if (userMap == null) { userMap = new HashMap<String, Object>(); } mergedMap = null; userMap.putAll(m); } @Override public synchronized void clear() { if (userMap != null) { userMap = null; mergedMap = null; } } @Override public synchronized Set<String> keySet() { return getMergedMap().keySet(); } @Override public synchronized Collection<Object> values() { return getMergedMap().values(); } @Override public synchronized Set<Entry<String, Object>> entrySet() { return getMergedMap().entrySet(); } @Override public synchronized void updateDynamicConfiguration( Map<?, ?> updateMap, boolean replaceCurrent) { if (updateMap == null || updateMap.isEmpty()) { if (replaceCurrent) { mergedMap = null; dynamicMap = null; if (changeListener != null) { changeListener.changed(this); } } return; } mergedMap = null; Map<String, Object> dynMap = dynamicMap == null || replaceCurrent ? new HashMap<String, Object>() : dynamicMap; for (Entry<?, ?> entry : updateMap.entrySet()) { dynMap.put(entry.getKey().toString(), entry.getValue()); } dynamicMap = dynMap; if (changeListener != null) { changeListener.changed(this); } } @Override public synchronized void updateDynamicConfiguration( Dictionary<?, ?> updateDict, boolean replaceCurrent) { if (updateDict == null || updateDict.isEmpty()) { if (replaceCurrent) { mergedMap = null; dynamicMap = null; if (changeListener != null) { changeListener.changed(this); } } return; } mergedMap = null; Map<String, Object> dynMap = dynamicMap == null || replaceCurrent ? new HashMap<String, Object>() : dynamicMap; for (Enumeration<?> keys = updateDict.keys(); keys.hasMoreElements(); ) { Object key = keys.nextElement(); dynMap.put(key.toString(), updateDict.get(key)); } dynamicMap = dynMap; if (changeListener != null) { changeListener.changed(this); } } @Override public synchronized void refreshStaticConfiguration() { staticMap = null; mergedMap = null; final String cfgFileName = configurationId + ".properties"; final String altFileName = alternateConfigId == null ? null : alternateConfigId + ".properties"; Properties staticProps = null; Properties loadedProps = null; InputStream is = getClass().getClassLoader().getResourceAsStream(cfgFileName); loadedProps = loadProps(staticProps, is); if (loadedProps == null && altFileName != null) { is = getClass().getClassLoader().getResourceAsStream(altFileName); loadedProps = loadProps(staticProps, is); } if (loadedProps != null) { staticProps = loadedProps; } String sysprop = System.getProperty( RequestCallbackFeature.REQUEST_CALLBACK_CONFIGURATION_SYSTEM_PROPERTY); if (sysprop != null) { try { if (sysprop.startsWith("file:/") || sysprop.contains("://")) { String cfgURLName = sysprop.endsWith("/") ? sysprop + cfgFileName : sysprop + "/" + cfgFileName; try { URL configURL = new URL(cfgURLName); is = configURL.openStream(); } catch (Exception e) { if (LOGGER.isLoggable(Level.FINER)) { LOGGER.log(Level.FINER, "Exception caught: ", e); } is = null; } loadedProps = loadProps(staticProps, is); if (loadedProps == null && altFileName != null) { cfgURLName = sysprop.endsWith("/") ? sysprop + altFileName : sysprop + "/" + altFileName; try { URL configURL = new URL(cfgURLName); is = configURL.openStream(); } catch (Exception e) { if (LOGGER.isLoggable(Level.FINER)) { LOGGER.log(Level.FINER, "Exception caught: ", e); } is = null; } loadedProps = loadProps(staticProps, is); } } else { File configDir = new File(sysprop); if (configDir.canRead() && configDir.isDirectory()) { File cfgFile = new File(configDir, cfgFileName); if (cfgFile.isFile() && cfgFile.canRead()) { is = new FileInputStream(cfgFile); loadedProps = loadProps(staticProps, is); } else if (altFileName != null) { cfgFile = new File(configDir, altFileName); if (cfgFile.isFile() && cfgFile.canRead()) { is = new FileInputStream(cfgFile); loadedProps = loadProps(staticProps, is); } } } } } catch (Exception e) { if (LOGGER.isLoggable(Level.FINER)) { LOGGER.log(Level.FINER, "Exception caught: ", e); } loadedProps = null; } if (loadedProps != null) { staticProps = loadedProps; } } if (staticProps != null) { Map<String, Object> statMap = new HashMap<String, Object>(); for (Entry<Object, Object> e : staticProps.entrySet()) { statMap.put(e.getKey().toString(), e.getValue()); } staticMap = statMap; } if (changeListener != null) { changeListener.changed(this); } } @Override public synchronized void fillProperties( String prefix, Map<? super String, Object> properties) { if (mergedMap != null) { transferProperties(prefix, mergedMap, properties); return; } if (staticMap != null) { transferProperties(prefix, staticMap, properties); } if (dynamicMap != null) { transferProperties(prefix, dynamicMap, properties); } if (userMap != null) { transferProperties(prefix, userMap, properties); } } @Override public synchronized void fillExpandedProperties( String prefix, Map<? super String, Object> properties) { final Map<String, Object> source = getMergedMap(); transferExpandedProperties(prefix, source, properties, source); } @Override public QName getConfigurationName() { return configurationName; } @Override public String getConfigurationIdentifier() { return configurationId; } @Override public String getAlternateConfigurationIdentifier() { return alternateConfigId; } @Override public ChangeListener getChangeListener() { return changeListener; } @Override public void setChangeListener(ChangeListener changeListener) { this.changeListener = changeListener; } private Map<String, Object> getMergedMap() { if (mergedMap == null) { Map<String, Object> result = new HashMap<String, Object>(); if (staticMap != null) { result.putAll(staticMap); } if (dynamicMap != null) { result.putAll(dynamicMap); } if (userMap != null) { result.putAll(userMap); } mergedMap = Collections.unmodifiableMap(result); } return mergedMap; } private static Properties loadProps(Properties props, InputStream is) { if (is == null) { return null; } try { Properties result = props == null ? new Properties() : props; result.load(is); return result; } catch (Exception e) { if (LOGGER.isLoggable(Level.FINER)) { LOGGER.log(Level.FINER, "Exception caught: ", e); } return null; } finally { try { is.close(); } catch (Exception e) { if (LOGGER.isLoggable(Level.FINER)) { LOGGER.log(Level.FINER, "Exception caught: ", e); } // ignore } } } }