NIHVIVO-123 Rewrite ConfigurationProperties to use lazy initialization instead of a static initializer -- the exceptions are much more descriptive that way. Also write messages to the log on a variety of error conditions. Add unit tests.
This commit is contained in:
parent
925df8863b
commit
95cffe41b0
3 changed files with 318 additions and 69 deletions
|
@ -42,83 +42,31 @@ import org.apache.log4j.Logger;
|
|||
public class ConfigurationProperties {
|
||||
private static final Logger LOG = Logger
|
||||
.getLogger(ConfigurationProperties.class);
|
||||
|
||||
|
||||
/**
|
||||
* The JNDI naming context where Tomcat stores environment attributes.
|
||||
*/
|
||||
static final String JNDI_BASE = "java:comp/env";
|
||||
|
||||
/**
|
||||
* The name of the JNDI environment mapping for the path to the
|
||||
* configuration file (or resource).
|
||||
*/
|
||||
private static final String PATH_CONFIGURATION = "path.configuration";
|
||||
static final String PATH_CONFIGURATION = "path.configuration";
|
||||
|
||||
/**
|
||||
* The map of the configuration properties.
|
||||
*
|
||||
* This should not be accessed directly, but only through the synchronized
|
||||
* method {@link #getTheMap() (and {@link #reset()} for unit tests).
|
||||
*/
|
||||
private static volatile Map<String, String> theMap;
|
||||
|
||||
static {
|
||||
try {
|
||||
// Obtain our environment naming context
|
||||
Context initCtx = new InitialContext();
|
||||
Context envCtx = (Context) initCtx.lookup("java:comp/env");
|
||||
|
||||
// Get the name of the configuration properties file.
|
||||
String configPath = (String) envCtx.lookup(PATH_CONFIGURATION);
|
||||
if (configPath == null) {
|
||||
throw new IllegalStateException(
|
||||
"Could not find a JNDI Environment naming for '"
|
||||
+ PATH_CONFIGURATION + "'.");
|
||||
}
|
||||
|
||||
InputStream inStream = null;
|
||||
// Try to find this as a file.
|
||||
File file = new File(configPath);
|
||||
try {
|
||||
inStream = new FileInputStream(file);
|
||||
} catch (FileNotFoundException e) {
|
||||
inStream = null;
|
||||
}
|
||||
|
||||
// If no file, try to find it as a resource.
|
||||
if (inStream == null) {
|
||||
inStream = ConfigurationProperties.class.getClassLoader()
|
||||
.getResourceAsStream(configPath);
|
||||
}
|
||||
|
||||
// If neither file nor resource, give up.
|
||||
if (inStream == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Failed to find a configuration properties file at '"
|
||||
+ file.getAbsolutePath()
|
||||
+ "', or a resource at '" + configPath + "'");
|
||||
}
|
||||
|
||||
// Load a properties object - it will handle the syntax of the file.
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(inStream);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Problem while reading the "
|
||||
+ "configuration properties file at '" + configPath
|
||||
+ "'", e);
|
||||
}
|
||||
|
||||
// It's awkward to copy from Properties to a Map.
|
||||
Map<String, String> newMap = new HashMap<String, String>();
|
||||
for (Enumeration<?> keys = props.keys(); keys.hasMoreElements();) {
|
||||
String key = (String) keys.nextElement();
|
||||
newMap.put(key, props.getProperty(key));
|
||||
}
|
||||
|
||||
LOG.info("Configuration properties are: " + newMap);
|
||||
|
||||
// Save an unmodifiable version of the Map
|
||||
theMap = Collections.unmodifiableMap(newMap);
|
||||
} catch (NamingException e) {
|
||||
throw new IllegalStateException(e);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Get an unmodifiable copy of the map of configuration properties.
|
||||
*/
|
||||
public static Map<String, String> getMap() {
|
||||
return theMap;
|
||||
return getTheMap();
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -126,7 +74,7 @@ public class ConfigurationProperties {
|
|||
* property has not been assigned a value.
|
||||
*/
|
||||
public static String getProperty(String key) {
|
||||
return theMap.get(key);
|
||||
return getTheMap().get(key);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -134,11 +82,144 @@ public class ConfigurationProperties {
|
|||
* property has not been assigned a value.
|
||||
*/
|
||||
public static String getProperty(String key, String defaultValue) {
|
||||
String value = theMap.get(key);
|
||||
String value = getTheMap().get(key);
|
||||
if (value == null) {
|
||||
return defaultValue;
|
||||
} else {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Force the map to be reloaded on the next attempt to access it.
|
||||
*
|
||||
* This and {@link #getTheMap()} should be the only access to
|
||||
* {@link ConfigurationProperties#theMap}.
|
||||
*
|
||||
* NOTE: This should only be used in Unit Tests.
|
||||
*/
|
||||
static synchronized void reset() {
|
||||
theMap = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* This and {@link #reset()} should be the only access to {@link #theMap}.
|
||||
*/
|
||||
private static synchronized Map<String, String> getTheMap() {
|
||||
if (theMap == null) {
|
||||
theMap = loadTheMap();
|
||||
}
|
||||
return theMap;
|
||||
}
|
||||
|
||||
/**
|
||||
* The map is null, so find the properties file and load the map.
|
||||
*/
|
||||
private static synchronized Map<String, String> loadTheMap() {
|
||||
String configPath = getConfigurationFilePath();
|
||||
|
||||
InputStream inStream = getConfigurationInputStream(configPath);
|
||||
|
||||
// Load a properties object - it will parse the file easily.
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
props.load(inStream);
|
||||
} catch (IOException e) {
|
||||
throw new IllegalStateException("Problem while reading the "
|
||||
+ "configuration properties file at '" + configPath + "'",
|
||||
e);
|
||||
} finally {
|
||||
try {
|
||||
inStream.close();
|
||||
} catch (IOException e) {
|
||||
LOG.error("Failed to close input stream", e);
|
||||
}
|
||||
}
|
||||
|
||||
// It's awkward to copy from Properties to a Map.
|
||||
Map<String, String> newMap = new HashMap<String, String>();
|
||||
for (Enumeration<?> keys = props.keys(); keys.hasMoreElements();) {
|
||||
String key = (String) keys.nextElement();
|
||||
newMap.put(key, props.getProperty(key));
|
||||
}
|
||||
|
||||
LOG.info("Configuration properties are: " + newMap);
|
||||
|
||||
// Save an unmodifiable version of the Map
|
||||
return Collections.unmodifiableMap(newMap);
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the path to the Configuration properties file.
|
||||
*
|
||||
* @throws IllegalStateException
|
||||
* If we can't find the path.
|
||||
*/
|
||||
private static String getConfigurationFilePath() {
|
||||
String message = "";
|
||||
try {
|
||||
message = "JNDI Lookup on \"" + JNDI_BASE
|
||||
+ "\" failed. Is the context file missing?";
|
||||
Context envCtx = (Context) new InitialContext().lookup(JNDI_BASE);
|
||||
if (envCtx == null) {
|
||||
LOG.error(message);
|
||||
throw new IllegalStateException(message);
|
||||
}
|
||||
|
||||
// Get the name of the configuration properties file.
|
||||
message = "Could not find a JNDI Environment naming for '"
|
||||
+ PATH_CONFIGURATION
|
||||
+ "'. Is the context file set up correctly?";
|
||||
String configPath = (String) envCtx.lookup(PATH_CONFIGURATION);
|
||||
if (configPath == null) {
|
||||
LOG.error(message);
|
||||
throw new IllegalStateException(message);
|
||||
}
|
||||
|
||||
return configPath;
|
||||
} catch (NamingException e) {
|
||||
throw new IllegalStateException(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Find the Configuration properties file.
|
||||
*
|
||||
* First try to interpret the path as a file path (like
|
||||
* /usr/local/config.props).
|
||||
*
|
||||
* If that doesn't work, try it as a resource path (relative to
|
||||
* WEB-INF/classes).
|
||||
*
|
||||
* @throws IllegalArgumentException
|
||||
* If the path fails to locate a file or a resource.
|
||||
*/
|
||||
private static InputStream getConfigurationInputStream(String configPath) {
|
||||
InputStream inStream = null;
|
||||
|
||||
// Try to find this as a file.
|
||||
File file = new File(configPath);
|
||||
try {
|
||||
inStream = new FileInputStream(file);
|
||||
} catch (FileNotFoundException e) {
|
||||
inStream = null;
|
||||
}
|
||||
|
||||
// If no file, try to find it as a resource.
|
||||
if (inStream == null) {
|
||||
inStream = ConfigurationProperties.class.getClassLoader()
|
||||
.getResourceAsStream(configPath);
|
||||
}
|
||||
|
||||
// If neither file nor resource, give up.
|
||||
if (inStream == null) {
|
||||
throw new IllegalArgumentException(
|
||||
"Failed to find a configuration properties file at '"
|
||||
+ file.getAbsolutePath() + "', or a resource at '"
|
||||
+ configPath + "'");
|
||||
}
|
||||
return inStream;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue