NIHVIVO-1261 Add the new ConfigurationProperties classes, and add the setup to web.xml
This commit is contained in:
parent
3134054f7b
commit
b7510fa355
6 changed files with 533 additions and 0 deletions
|
@ -39,6 +39,11 @@
|
||||||
|
|
||||||
<!-- Listeners ****************************************************** -->
|
<!-- Listeners ****************************************************** -->
|
||||||
|
|
||||||
|
<!-- Reads deploy.properties. Needs to run before almost all other listeners. -->
|
||||||
|
<listener>
|
||||||
|
<listener-class>edu.cornell.mannlib.vitro.webapp.config.ConfigurationPropertiesSetup</listener-class>
|
||||||
|
</listener>
|
||||||
|
|
||||||
<listener>
|
<listener>
|
||||||
<listener-class>edu.cornell.mannlib.vitro.webapp.config.RevisionInfoSetup</listener-class>
|
<listener-class>edu.cornell.mannlib.vitro.webapp.config.RevisionInfoSetup</listener-class>
|
||||||
</listener>
|
</listener>
|
||||||
|
|
|
@ -0,0 +1,145 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.config;
|
||||||
|
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.ServletConfig;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletRequest;
|
||||||
|
import javax.servlet.http.HttpServlet;
|
||||||
|
import javax.servlet.http.HttpServletRequest;
|
||||||
|
import javax.servlet.http.HttpSession;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Provides an mechanism for modules to read the configuration properties that
|
||||||
|
* are attached to the servlet context.
|
||||||
|
*
|
||||||
|
* The customary behavior is for ConfigurationPropertiesSetup to create a
|
||||||
|
* ConfigurationPropertiesImpl, which will parse the deploy.properties file for
|
||||||
|
* these properties.
|
||||||
|
*/
|
||||||
|
public abstract class ConfigurationProperties {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(ConfigurationProperties.class);
|
||||||
|
|
||||||
|
/** The bean is attached to the session by this name. */
|
||||||
|
private static final String ATTRIBUTE_NAME = ConfigurationProperties.class
|
||||||
|
.getName();
|
||||||
|
|
||||||
|
/** If they ask for a bean before one has been set, they get this. */
|
||||||
|
private static final ConfigurationProperties DUMMY_PROPERTIES = new DummyConfigurationProperties();
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// static methods
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
public static ConfigurationProperties getBean(ServletRequest request) {
|
||||||
|
if (request == null) {
|
||||||
|
throw new NullPointerException("request may not be null.");
|
||||||
|
}
|
||||||
|
if (!(request instanceof HttpServletRequest)) {
|
||||||
|
throw new IllegalArgumentException(
|
||||||
|
"request must be an HttpServletRequest");
|
||||||
|
}
|
||||||
|
HttpServletRequest httpRequest = (HttpServletRequest) request;
|
||||||
|
return getBean(httpRequest.getSession());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConfigurationProperties getBean(HttpSession session) {
|
||||||
|
if (session == null) {
|
||||||
|
throw new NullPointerException("session may not be null.");
|
||||||
|
}
|
||||||
|
return getBean(session.getServletContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConfigurationProperties getBean(HttpServlet servlet) {
|
||||||
|
if (servlet == null) {
|
||||||
|
throw new NullPointerException("servlet may not be null.");
|
||||||
|
}
|
||||||
|
return getBean(servlet.getServletContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConfigurationProperties getBean(ServletContextEvent sce) {
|
||||||
|
if (sce == null) {
|
||||||
|
throw new NullPointerException("sce may not be null.");
|
||||||
|
}
|
||||||
|
return getBean(sce.getServletContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConfigurationProperties getBean(ServletConfig servletConfig) {
|
||||||
|
if (servletConfig == null) {
|
||||||
|
throw new NullPointerException("servletConfig may not be null.");
|
||||||
|
}
|
||||||
|
return getBean(servletConfig.getServletContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
public static ConfigurationProperties getBean(ServletContext context) {
|
||||||
|
if (context == null) {
|
||||||
|
throw new NullPointerException("context may not be null.");
|
||||||
|
}
|
||||||
|
|
||||||
|
Object o = context.getAttribute(ATTRIBUTE_NAME);
|
||||||
|
if (o == null) {
|
||||||
|
log.error("ConfigurationProperties bean has not been set.");
|
||||||
|
return DUMMY_PROPERTIES;
|
||||||
|
} else if (!(o instanceof ConfigurationProperties)) {
|
||||||
|
log.error("Error: ConfigurationProperties was set to an "
|
||||||
|
+ "invalid object: " + o);
|
||||||
|
return DUMMY_PROPERTIES;
|
||||||
|
}
|
||||||
|
|
||||||
|
return (ConfigurationProperties) o;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Protected access, so the Stub class can call it for unit tests.
|
||||||
|
* Otherwise, this should only be called by ConfigurationPropertiesSetup.
|
||||||
|
*/
|
||||||
|
protected static void setBean(ServletContext context,
|
||||||
|
ConfigurationProperties bean) {
|
||||||
|
if (context == null) {
|
||||||
|
throw new NullPointerException("context may not be null.");
|
||||||
|
}
|
||||||
|
if (bean == null) {
|
||||||
|
throw new NullPointerException("bean may not be null.");
|
||||||
|
}
|
||||||
|
context.setAttribute(ATTRIBUTE_NAME, bean);
|
||||||
|
log.info(bean);
|
||||||
|
}
|
||||||
|
|
||||||
|
/** Package access, so unit tests can call it. */
|
||||||
|
static void removeBean(ServletContext context) {
|
||||||
|
if (context == null) {
|
||||||
|
throw new NullPointerException("context may not be null.");
|
||||||
|
}
|
||||||
|
context.removeAttribute(ATTRIBUTE_NAME);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// The interface
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the property, or <code>null</code> if the property has
|
||||||
|
* not been assigned a value.
|
||||||
|
*/
|
||||||
|
public abstract String getProperty(String key);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get the value of the property, or use the default value if the property
|
||||||
|
* has not been assigned a value.
|
||||||
|
*/
|
||||||
|
public abstract String getProperty(String key, String defaultValue);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Get a copy of the map of the configuration properties and their settings.
|
||||||
|
* Because this is a copy, it cannot be used to modify the settings.
|
||||||
|
*/
|
||||||
|
public abstract Map<String, String> getPropertyMap();
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,90 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.config;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Enumeration;
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
import java.util.Properties;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The basic implementation of ConfigurationProperties. It loads the
|
||||||
|
* configuration properties from a properties file and stores them in a map.
|
||||||
|
*
|
||||||
|
* Leading and trailing white space are trimmed from the property values.
|
||||||
|
*
|
||||||
|
* Once the properties have been parsed and stored, they are immutable.
|
||||||
|
*/
|
||||||
|
public class ConfigurationPropertiesImpl extends ConfigurationProperties {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(ConfigurationPropertiesImpl.class);
|
||||||
|
|
||||||
|
private final Map<String, String> propertyMap;
|
||||||
|
|
||||||
|
public ConfigurationPropertiesImpl(InputStream stream) {
|
||||||
|
Properties props = loadFromPropertiesFile(stream);
|
||||||
|
Map<String, String> map = copyPropertiesToMap(props);
|
||||||
|
trimWhiteSpaceFromValues(map);
|
||||||
|
this.propertyMap = Collections.unmodifiableMap(map);
|
||||||
|
|
||||||
|
log.debug("Configuration properties are: " + map);
|
||||||
|
}
|
||||||
|
|
||||||
|
private Properties loadFromPropertiesFile(InputStream stream) {
|
||||||
|
Properties props = new Properties();
|
||||||
|
try {
|
||||||
|
props.load(stream);
|
||||||
|
} catch (IOException e) {
|
||||||
|
throw new IllegalStateException(
|
||||||
|
"Failed to parse the configuration properties file.", e);
|
||||||
|
}
|
||||||
|
return props;
|
||||||
|
}
|
||||||
|
|
||||||
|
private Map<String, String> copyPropertiesToMap(Properties props) {
|
||||||
|
Map<String, String> map = new HashMap<String, String>();
|
||||||
|
for (Enumeration<?> keys = props.keys(); keys.hasMoreElements();) {
|
||||||
|
String key = (String) keys.nextElement();
|
||||||
|
String value = props.getProperty(key);
|
||||||
|
map.put(key, value);
|
||||||
|
}
|
||||||
|
return map;
|
||||||
|
}
|
||||||
|
|
||||||
|
private void trimWhiteSpaceFromValues(Map<String, String> map) {
|
||||||
|
for (String key : map.keySet()) {
|
||||||
|
map.put(key, map.get(key).trim());
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProperty(String key) {
|
||||||
|
return propertyMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProperty(String key, String defaultValue) {
|
||||||
|
if (propertyMap.containsKey(key)) {
|
||||||
|
return propertyMap.get(key);
|
||||||
|
} else {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getPropertyMap() {
|
||||||
|
return new HashMap<String, String>(propertyMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ConfigurationPropertiesImpl[propertyMap=" + propertyMap + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,186 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.config;
|
||||||
|
|
||||||
|
import java.io.File;
|
||||||
|
import java.io.FileInputStream;
|
||||||
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
|
|
||||||
|
import javax.naming.Context;
|
||||||
|
import javax.naming.InitialContext;
|
||||||
|
import javax.naming.NamingException;
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
import javax.servlet.ServletContextEvent;
|
||||||
|
import javax.servlet.ServletContextListener;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.servlet.setup.AbortStartup;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Reads the configuration properties from a file and stores them in the servlet
|
||||||
|
* context.
|
||||||
|
*
|
||||||
|
* This must be invoked before any listener that requires configuration
|
||||||
|
* properties.
|
||||||
|
*
|
||||||
|
* The path to the file can be specified by an Environment name in the Context,
|
||||||
|
* like this:
|
||||||
|
*
|
||||||
|
* <pre>
|
||||||
|
*
|
||||||
|
* <Context override="true">
|
||||||
|
* <Environment name="path.configuration"
|
||||||
|
* value="/wherever/the/file/lives/deploy.properties"
|
||||||
|
* type="java.lang.String"
|
||||||
|
* override="false" />
|
||||||
|
* </Context>
|
||||||
|
*
|
||||||
|
* </pre>
|
||||||
|
*
|
||||||
|
* We look in this environment variable to find the path to the properties file.
|
||||||
|
* If there is no such environment variable, the default path is used.
|
||||||
|
*
|
||||||
|
* Once the path has been determined, we will use it to look for a resource in
|
||||||
|
* the classpath. So if the path is "deploy.properties", it might be found in
|
||||||
|
* "tomcat/webapps/vivo/WEB-INF/classes/deploy.properties". Of course, it might
|
||||||
|
* also be found in any other portion of the classpath as well.
|
||||||
|
*
|
||||||
|
* If we can't find the resource in the classpath, we will use it to look for an
|
||||||
|
* external file. So, one might reasonably set this value to something like
|
||||||
|
* "/usr/local/vitro/stuff/my.deploy.properties".
|
||||||
|
*
|
||||||
|
* If neither a resource nor an external file can be found, we throw an
|
||||||
|
* exception and set AbortStartup.
|
||||||
|
*/
|
||||||
|
public class ConfigurationPropertiesSetup implements ServletContextListener {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(ConfigurationPropertiesSetup.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).
|
||||||
|
*/
|
||||||
|
static final String PATH_CONFIGURATION = "path.configuration";
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we don't find the path to the config properties from a JNDI mapping,
|
||||||
|
* use this. Not final, so we can jigger it for unit tests.
|
||||||
|
*/
|
||||||
|
private static String DEFAULT_CONFIG_PATH = "deploy.properties";
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextInitialized(ServletContextEvent sce) {
|
||||||
|
if (AbortStartup.isStartupAborted(sce.getServletContext())) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
|
ServletContext ctx = sce.getServletContext();
|
||||||
|
|
||||||
|
try {
|
||||||
|
InputStream stream = null;
|
||||||
|
try {
|
||||||
|
stream = locatePropertiesFile();
|
||||||
|
ConfigurationProperties.setBean(ctx,
|
||||||
|
new ConfigurationPropertiesImpl(stream));
|
||||||
|
} finally {
|
||||||
|
if (stream != null) {
|
||||||
|
try {
|
||||||
|
stream.close();
|
||||||
|
} catch (IOException e) {
|
||||||
|
log.error(e, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} catch (Exception e) {
|
||||||
|
log.error(e, e);
|
||||||
|
AbortStartup.abortStartup(ctx);
|
||||||
|
throw new RuntimeException(e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream locatePropertiesFile() {
|
||||||
|
String path = determinePathToProperties();
|
||||||
|
log.debug("Configuration properties path is '" + path + "'");
|
||||||
|
|
||||||
|
if (resourceExists(path)) {
|
||||||
|
log.debug("Found configuration properties as a resource.");
|
||||||
|
return getResourceStream(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (externalFileExists(path)) {
|
||||||
|
log.debug("Found configuration properties as an external file.");
|
||||||
|
return getExternalFileStream(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
throw new IllegalStateException("Can't find the properties file at '"
|
||||||
|
+ path + "'");
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If we can't find it with JNDI, use the default.
|
||||||
|
*/
|
||||||
|
private String determinePathToProperties() {
|
||||||
|
try {
|
||||||
|
Context envCtx = (Context) new InitialContext().lookup(JNDI_BASE);
|
||||||
|
if (envCtx == null) {
|
||||||
|
log.debug("JNDI Lookup on '" + JNDI_BASE + "' failed.");
|
||||||
|
return DEFAULT_CONFIG_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
String configPath = (String) envCtx.lookup(PATH_CONFIGURATION);
|
||||||
|
if (configPath == null) {
|
||||||
|
log.debug("JNDI Lookup on '" + PATH_CONFIGURATION + "' failed.");
|
||||||
|
return DEFAULT_CONFIG_PATH;
|
||||||
|
}
|
||||||
|
|
||||||
|
log.debug("deploy.property as specified by JNDI: " + configPath);
|
||||||
|
return configPath;
|
||||||
|
} catch (NamingException e) {
|
||||||
|
log.warn("JNDI lookup failed. "
|
||||||
|
+ "Using default path for config properties.", e);
|
||||||
|
return DEFAULT_CONFIG_PATH;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean resourceExists(String path) {
|
||||||
|
return getResourceStream(path) != null;
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream getResourceStream(String path) {
|
||||||
|
return getClass().getClassLoader().getResourceAsStream(path);
|
||||||
|
}
|
||||||
|
|
||||||
|
private boolean externalFileExists(String path) {
|
||||||
|
File file = new File(path);
|
||||||
|
return file.isFile();
|
||||||
|
}
|
||||||
|
|
||||||
|
private InputStream getExternalFileStream(String path) {
|
||||||
|
InputStream stream = null;
|
||||||
|
File file = new File(path);
|
||||||
|
if (file.isFile()) {
|
||||||
|
try {
|
||||||
|
stream = new FileInputStream(file);
|
||||||
|
} catch (FileNotFoundException e) {
|
||||||
|
// testing file.isFile() should have prevented this
|
||||||
|
log.error(e, e);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return stream;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public void contextDestroyed(ServletContextEvent sce) {
|
||||||
|
ConfigurationProperties.removeBean(sce.getServletContext());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,41 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package edu.cornell.mannlib.vitro.webapp.config;
|
||||||
|
|
||||||
|
import java.util.Collections;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import org.apache.commons.logging.Log;
|
||||||
|
import org.apache.commons.logging.LogFactory;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* If somebody asks for ConfigurationProperties before it has been initialized,
|
||||||
|
* they get this. It doesn't stop them from proceeding, it just yields no
|
||||||
|
* properties while logging warning messages for each request.
|
||||||
|
*/
|
||||||
|
class DummyConfigurationProperties extends ConfigurationProperties {
|
||||||
|
private static final Log log = LogFactory
|
||||||
|
.getLog(DummyConfigurationProperties.class);
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProperty(String key) {
|
||||||
|
log.warn("ConfigurationProperties has not been initialized: getProperty(\""
|
||||||
|
+ key + "\")");
|
||||||
|
return null;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProperty(String key, String defaultValue) {
|
||||||
|
log.warn("ConfigurationProperties has not been initialized: getProperty(\""
|
||||||
|
+ key + "\", \"" + defaultValue + "\")");
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getPropertyMap() {
|
||||||
|
log.warn("ConfigurationProperties has not been initialized: "
|
||||||
|
+ "getPropertyMap()");
|
||||||
|
return Collections.emptyMap();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
|
@ -0,0 +1,66 @@
|
||||||
|
/* $This file is distributed under the terms of the license in /doc/license.txt$ */
|
||||||
|
|
||||||
|
package stubs.edu.cornell.mannlib.vitro.webapp.config;
|
||||||
|
|
||||||
|
import java.util.HashMap;
|
||||||
|
import java.util.Map;
|
||||||
|
|
||||||
|
import javax.servlet.ServletContext;
|
||||||
|
|
||||||
|
import edu.cornell.mannlib.vitro.webapp.config.ConfigurationProperties;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* A version of ConfigurationProperties that we can use for unit tests. Unlike
|
||||||
|
* the basic implementation, this starts as an empty map, and allows the user to
|
||||||
|
* add properties as desired.
|
||||||
|
*
|
||||||
|
* Call setBean() to store these properties in the ServletContext.
|
||||||
|
*/
|
||||||
|
public class ConfigurationPropertiesStub extends ConfigurationProperties {
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Stub infrastructure
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
private final Map<String, String> propertyMap = new HashMap<String, String>();
|
||||||
|
|
||||||
|
public void setProperty(String key, String value) {
|
||||||
|
propertyMap.put(key, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
public void setBean(ServletContext ctx) {
|
||||||
|
setBean(ctx, this);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String toString() {
|
||||||
|
return "ConfigurationPropertiesStub[map=" + propertyMap + "]";
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Stub methods
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProperty(String key) {
|
||||||
|
return propertyMap.get(key);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public String getProperty(String key, String defaultValue) {
|
||||||
|
if (propertyMap.containsKey(key)) {
|
||||||
|
return propertyMap.get(key);
|
||||||
|
} else {
|
||||||
|
return defaultValue;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public Map<String, String> getPropertyMap() {
|
||||||
|
return new HashMap<String, String>(propertyMap);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
// Un-implemented methods
|
||||||
|
// ----------------------------------------------------------------------
|
||||||
|
|
||||||
|
}
|
Loading…
Add table
Add a link
Reference in a new issue