package org.test4j.module.core.utility;
import java.util.Properties;
import org.test4j.module.Test4JException;
import org.test4j.tools.commons.ConfigHelper;
import org.test4j.tools.commons.PropertiesReader;
import ext.test4j.apache.commons.lang.text.StrSubstitutor;
/**
* test4j配置文件加载器<br>
* 默认先加载test4j-default.properties文件中的配置项<br>
* 根据 {@link #PROPKEY_CUSTOM_CONFIGURATION} 加载用户级的配置文件<br>
* 根据 {@link #PROPKEY_LOCAL_CONFIGURATION} 加载项目级的配置文件
*/
public class ConfigurationLoader {
/**
* Name of the fixed configuration file that contains all defaults
*/
public static final String DEFAULT_PROPERTIES_FILE_NAME = "test4j-default.properties";
/**
* Property in the defaults configuration file that contains the name of the
* custom configuration file
*/
public static final String PROPKEY_CUSTOM_CONFIGURATION = "test4j.configuration.customFileName";
/**
* Property in the defaults and/or custom configuration file that contains
* the name of the user local configuration file
*/
public static final String PROPKEY_LOCAL_CONFIGURATION = "test4j.configuration.localFileName";
/**
* reads properties from configuration file
*/
private final PropertiesReader propertiesReader = new PropertiesReader();
private static Properties properties = null;
/**
* loading the test4j configuration. <br>
* Include test4j-default.properties, test4j.properties,
* test4j-local.properties
*
* @return the settings, not null
*/
public static synchronized Properties loading() {
if (properties == null) {
ConfigurationLoader loader = new ConfigurationLoader();
properties = new Properties();
loader.loadDefaultConfiguration(properties);
loader.loadCustomConfiguration(properties);
loader.loadLocalConfiguration(properties);
loader.loadSystemProperties(properties);
loader.expandPropertyValues(properties);
}
return properties;
}
private ConfigurationLoader() {
}
/**
* Load the default properties file (test4j-default.properties)
*
* @param properties The instance to add to loaded properties to, not null
*/
private void loadDefaultConfiguration(Properties properties) {
Properties defaultProperties = propertiesReader.loadPropertiesFileFromClasspath(DEFAULT_PROPERTIES_FILE_NAME);
if (defaultProperties == null) {
throw new Test4JException("Configuration file: " + DEFAULT_PROPERTIES_FILE_NAME
+ " not found in classpath.");
}
properties.putAll(defaultProperties);
}
/**
* Load the custom project level configuration file (test4j.properties)
*
* @param properties The instance to add to loaded properties to, not null
*/
private void loadCustomConfiguration(Properties properties) {
String customConfigurationFileName = getConfigurationFileName(PROPKEY_CUSTOM_CONFIGURATION, properties);
Properties customProperties = propertiesReader.loadPropertiesFileFromClasspath(customConfigurationFileName);
if (customProperties == null) {
MessageHelper.warn("No custom configuration file " + customConfigurationFileName + " found.");
} else {
properties.putAll(customProperties);
}
}
/**
* Load the local configuration file from the user home, or from the
* classpath
*
* @param properties The instance to add to loaded properties to, not null
*/
private void loadLocalConfiguration(Properties properties) {
String localConfigurationFileName = getConfigurationFileName(PROPKEY_LOCAL_CONFIGURATION, properties);
Properties localProperties = propertiesReader.loadPropertiesFileFromClasspath(localConfigurationFileName);
if (localProperties == null) {
localProperties = propertiesReader.loadPropertiesFileFromUserHome(localConfigurationFileName);
}
if (localProperties == null) {
MessageHelper.info("No local configuration file " + localConfigurationFileName + " found.");
} else {
properties.putAll(localProperties);
}
}
/**
* Load the environment properties.
*
* @param properties The instance to add to loaded properties to, not null
*/
private void loadSystemProperties(Properties properties) {
properties.putAll(System.getProperties());
}
/**
* Expands all property place holders to actual values.<br>
* <br>
* For example suppose you have a property defined as follows:
* root.dir=/usr/home <br>
* Expanding following ${root.dir}/somesubdir will then give following
* result: /usr/home/somesubdir
*
* @param properties The properties, not null
*/
private void expandPropertyValues(Properties properties) {
for (Object key : properties.keySet()) {
Object value = properties.get(key);
try {
String expandedValue = StrSubstitutor.replace(value, properties);
properties.put(key, expandedValue);
} catch (Throwable e) {
throw new Test4JException("Unable to load configuration. Could not expand property value for key: "
+ key + ", value " + value, e);
}
}
}
/**
* Gets the configuration file name from the system properties or if not
* defined, from the given loaded properties. An exception is raised if no
* value is defined.
*
* @param propertyName The name of the property that defines the
* local/custom file name, not null
* @param properties The propertis that were already loaded, not null
* @return The property value, not null
*/
private String getConfigurationFileName(String propertyName, Properties properties) {
String configurationFileName = System.getProperty(propertyName);
if (configurationFileName != null) {
return configurationFileName;
}
return ConfigHelper.getString(properties, propertyName);
}
}