Created
June 11, 2014 05:40
-
-
Save wendelicious/3015d304a2d04a5f8941 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
package com.dietsodasoftware.configuration.archaius; | |
import com.netflix.config.ConfigurationManager; | |
import com.netflix.config.PollResult; | |
import com.netflix.config.PolledConfigurationSource; | |
import com.netflix.config.sources.URLConfigurationSource; | |
import com.netflix.config.util.ConfigurationUtils; | |
import org.slf4j.Logger; | |
import org.slf4j.LoggerFactory; | |
import java.io.IOException; | |
import java.net.URL; | |
import java.util.ArrayList; | |
import java.util.Arrays; | |
import java.util.Collections; | |
import java.util.HashMap; | |
import java.util.HashSet; | |
import java.util.List; | |
import java.util.Map; | |
import java.util.Map.Entry; | |
import java.util.Properties; | |
/** | |
* A polled configuration source based on a set of config names. For each poll, | |
* it always returns the complete union of properties defined in all files. If one property | |
* is defined in more than one config file, the value in file later on the list will override | |
* the value in the previous one. The content of the config file should conform to the properties file format. | |
* | |
* @author wendel.schultz | |
* | |
*/ | |
public class NamedConfigurationSource implements PolledConfigurationSource { | |
private final String[] configNames; | |
/** | |
* System property name to define a set of config names to be used by the | |
* default constructor. | |
*/ | |
public static final String CONFIG_NAMES = "dietsoda.configurationSource.additionalNames"; | |
/** | |
* Default configuration file name to be used by default constructor. This file should | |
* be on the classpath. The file name can be overridden by the value of system property | |
* <code>archaius.configurationSource.defaultFileName</code> | |
*/ | |
public static final String DEFAULT_CONFIG_FILE_FROM_CLASSPATH = URLConfigurationSource.DEFAULT_CONFIG_FILE_FROM_CLASSPATH; | |
private static final Logger logger = LoggerFactory.getLogger(NamedConfigurationSource.class); | |
/** | |
* Create an instance with a list of names to be used. | |
* | |
* @param names list of names to be used | |
*/ | |
public NamedConfigurationSource(String... names) { | |
configNames = names; | |
} | |
/** | |
* Create the instance for the default list of names, which is composed by the following order | |
* | |
* <ul> | |
* <li>A configuration file (default name to be <code>config.properties</code>, see {@link #DEFAULT_CONFIG_FILE_FROM_CLASSPATH}) on the classpath | |
* <li>A list of names defined by system property {@value #CONFIG_NAMES} with values separated by comma <code>","</code>. | |
* </ul> | |
*/ | |
public NamedConfigurationSource() { | |
List<String> nameList = new ArrayList<>(); | |
String configFromClasspath = getConfigFileNameFromClasspath(); | |
if (configFromClasspath != null) { | |
nameList.add(configFromClasspath); | |
} | |
String[] fileNames = getDefaultFileSources(); | |
if (fileNames.length != 0) { | |
nameList.addAll(Arrays.asList(fileNames)); | |
} | |
if (nameList.size() == 0) { | |
configNames = new String[0]; | |
logger.warn("No configs will be polled as dynamic configuration sources."); | |
logger.info("To enable configs as dynamic configuration sources, define System property " | |
+ CONFIG_NAMES + " or make " + DEFAULT_CONFIG_FILE_FROM_CLASSPATH + " available on classpath."); | |
} else { | |
configNames = nameList.toArray(new String[nameList.size()]); | |
logger.info("Config names to be used as dynamic configuration source: " + nameList); | |
} | |
} | |
private String getConfigFileNameFromClasspath() { | |
URL url = null; | |
// attempt to load from the context classpath | |
ClassLoader loader = Thread.currentThread().getContextClassLoader(); | |
if (loader != null) { | |
url = loader.getResource(DEFAULT_CONFIG_FILE_FROM_CLASSPATH); | |
} | |
if (url == null) { | |
// attempt to load from the system classpath | |
url = ClassLoader.getSystemResource(DEFAULT_CONFIG_FILE_FROM_CLASSPATH); | |
} | |
if (url == null) { | |
// attempt to load from the system classpath | |
url = URLConfigurationSource.class.getResource(DEFAULT_CONFIG_FILE_FROM_CLASSPATH); | |
} | |
if(url == null){ | |
return null; | |
} | |
return DEFAULT_CONFIG_FILE_FROM_CLASSPATH.replace(".properties", ""); | |
} | |
public List<String> getConfigNames() { | |
return Collections.unmodifiableList(Arrays.asList(configNames)); | |
} | |
private static final String[] getDefaultFileSources() { | |
String name = System.getProperty(CONFIG_NAMES); | |
String[] fileNames; | |
if (name != null) { | |
fileNames = name.split(","); | |
for(int i = 0; i < fileNames.length; i++){ | |
fileNames[i] = fileNames[i].replace(".properties", ""); | |
} | |
} else { | |
fileNames = new String[0]; | |
} | |
return fileNames; | |
} | |
/** | |
* Retrieve the content of the property files. For each poll, it always | |
* returns the complete union of properties defined in all configs. If one | |
* property is defined in content of more than one config, the value in file later on the | |
* list will override the value in the previous one. | |
* | |
* @param initial this parameter is ignored by the implementation | |
* @param checkPoint this parameter is ignored by the implementation | |
* @throws java.io.IOException IOException occurred in file operation | |
*/ | |
@Override | |
public PollResult poll(boolean initial, Object checkPoint) | |
throws IOException { | |
if (configNames == null || configNames.length == 0) { | |
return PollResult.createFull(null); | |
} | |
ConfigurationManager.getConfigInstance(); | |
Map<String, Object> map = new HashMap<String, Object>(); | |
for (String configName: configNames) { | |
String defaultConfigFileName = configName + ".properties"; | |
ClassLoader loader = Thread.currentThread().getContextClassLoader(); | |
URL url = loader.getResource(defaultConfigFileName); | |
if (url == null) { | |
throw new IOException("Cannot locate " + defaultConfigFileName + " as a classpath resource."); | |
} | |
Properties props = ConfigurationUtils.getPropertiesFromFile(url, new HashSet<String>(), ConfigurationManager.PROP_NEXT_LOAD); | |
String environment = ConfigurationManager.getDeploymentContext().getDeploymentEnvironment(); | |
if (environment != null && environment.length() > 0) { | |
String envConfigFileName = configName + "-" + environment + ".properties"; | |
url = loader.getResource(envConfigFileName); | |
if (url != null) { | |
Properties envProps = ConfigurationManager.getPropertiesFromFile(url); | |
if (envProps != null) { | |
props.putAll(envProps); | |
} | |
} | |
} | |
for (Entry<Object, Object> entry: props.entrySet()) { | |
map.put((String) entry.getKey(), entry.getValue()); | |
} | |
} | |
return PollResult.createFull(map); | |
} | |
@Override | |
public String toString() { | |
return "NamedConfigurationSource [configNames=" + Arrays.toString(configNames) | |
+ "]"; | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment