mirror of
https://github.com/DSpace/DSpace.git
synced 2025-10-07 01:54:22 +00:00
Initial refactor commit. Swap out DSpaceConfig/ServiceConfig for Apache Commons Configuration
This commit is contained in:
@@ -94,6 +94,15 @@
|
||||
<groupId>commons-collections</groupId>
|
||||
<artifactId>commons-collections</artifactId>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-configuration</groupId>
|
||||
<artifactId>commons-configuration</artifactId>
|
||||
</dependency>
|
||||
<!-- Required by Commons Configuration -->
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
</dependency>
|
||||
</dependencies>
|
||||
|
||||
<developers>
|
||||
|
@@ -142,6 +142,6 @@ public interface ServiceManager {
|
||||
*
|
||||
* @param settings a map of keys (names) and values
|
||||
*/
|
||||
public void pushConfig(Map<String, String> settings);
|
||||
public void pushConfig(Map<String, Object> settings);
|
||||
|
||||
}
|
||||
|
@@ -17,9 +17,9 @@ import org.dspace.kernel.mixins.InitializedService;
|
||||
import org.dspace.kernel.mixins.ServiceChangeListener;
|
||||
import org.dspace.kernel.mixins.ServiceManagerReadyAware;
|
||||
import org.dspace.kernel.mixins.ShutdownService;
|
||||
import org.dspace.servicemanager.config.DSpaceConfig;
|
||||
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
||||
import org.dspace.servicemanager.spring.SpringServiceManager;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.BeanWrapper;
|
||||
@@ -100,7 +100,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
activators.add(activator);
|
||||
log.info("Started and registered activator: " + activator.getClass().getName());
|
||||
} catch (Exception e1) {
|
||||
log.error("ERROR: Failed to start activator ("+ activator.getClass().getName() +"): " + e1, e1);
|
||||
log.error("ERROR: Failed to start activator ("+ activator.getClass().getName() +"): " + e1.getMessage(), e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -117,7 +117,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
activator.stop(this);
|
||||
log.info("Stopped and unregistered activator: " + activatorClassName);
|
||||
} catch (Exception e1) {
|
||||
log.error("ERROR: Failed to stop activator ("+activatorClassName+"): " + e1,e1);
|
||||
log.error("ERROR: Failed to stop activator ("+activatorClassName+"): " + e1.getMessage(), e1);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -134,7 +134,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
try {
|
||||
serviceManagerReadyAware.serviceManagerReady(this);
|
||||
} catch (Exception e) {
|
||||
System.err.println("ERROR: Failure in service when calling serviceManagerReady: " + e);
|
||||
log.error("ERROR: Failure in service when calling serviceManagerReady: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -168,6 +168,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
/**
|
||||
* Shut down all service managers, including this one.
|
||||
*/
|
||||
@Override
|
||||
public void shutdown() {
|
||||
unregisterActivators();
|
||||
for (ServiceManagerSystem sms : serviceManagers) {
|
||||
@@ -175,7 +176,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
sms.shutdown();
|
||||
} catch (Exception e) {
|
||||
// shutdown failures are not great but should NOT cause an interruption of processing
|
||||
System.err.println("Failure shutting down service manager ("+sms+"): " + e.getMessage());
|
||||
log.error("Failure shutting down service manager ("+sms+"): " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
this.running = false; // wait til the end
|
||||
@@ -184,6 +185,10 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
log.info("Shutdown DSpace core service manager");
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.dspace.servicemanager.ServiceManagerSystem#startup()
|
||||
*/
|
||||
@Override
|
||||
public void startup() {
|
||||
if (!testing) {
|
||||
// try to load up extra config files for spring
|
||||
@@ -220,7 +225,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
} catch (Exception e) {
|
||||
shutdown(); // execute the shutdown
|
||||
String message = "Failed to startup the DSpace Service Manager: " + e.getMessage();
|
||||
System.err.println(message);
|
||||
log.error(message, e);
|
||||
throw new RuntimeException(message, e);
|
||||
}
|
||||
}
|
||||
@@ -358,7 +363,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
}
|
||||
} catch (Exception e) {
|
||||
// keep going if it fails for one
|
||||
System.err.println("Failed to get list of services from service manager ("+sms.getClass()+"): " + e);
|
||||
log.error("Failed to get list of services from service manager ("+sms.getClass()+"): " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
return services;
|
||||
@@ -369,11 +374,11 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
* Every service gets called to notify them of the config change
|
||||
* depending on the the listener they are using.
|
||||
*/
|
||||
public void pushConfig(Map<String, String> properties) {
|
||||
public void pushConfig(Map<String, Object> properties) {
|
||||
checkRunning();
|
||||
if (properties != null && !properties.isEmpty()) {
|
||||
// load in the new settings to the config service
|
||||
String[] changedNames = configurationService.loadConfiguration(properties, false);
|
||||
String[] changedNames = configurationService.loadConfiguration(properties);
|
||||
if (changedNames.length > 0) {
|
||||
// some configs changed so push the changes to the listeners in all known services and providers
|
||||
// make the list of changed setting names and map of changed settings
|
||||
@@ -381,13 +386,12 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
Map<String, String> changedSettings = new LinkedHashMap<String, String>();
|
||||
for (String configName : changedNames) {
|
||||
changedSettingNames.add(configName);
|
||||
changedSettings.put( getSimplerName(configName), configurationService.getProperty(configName) );
|
||||
changedSettings.put( configName, configurationService.getProperty(configName) );
|
||||
}
|
||||
// notify the services that implement the mixin
|
||||
for (ServiceManagerSystem sms : serviceManagers) {
|
||||
List<ConfigChangeListener> configChangeListeners = sms.getServicesByType(ConfigChangeListener.class);
|
||||
for (ConfigChangeListener configChangeListener : configChangeListeners) {
|
||||
String serviceImplName = configChangeListener.getClass().getName();
|
||||
// notify this service
|
||||
try {
|
||||
boolean notify = false;
|
||||
@@ -396,17 +400,9 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
notify = true;
|
||||
} else {
|
||||
for (String notifyName : notifyNames) {
|
||||
// check to see if the change was one of the bean properties for our service
|
||||
String simplerName = getSimplerName(notifyName);
|
||||
String notifyBeanName = DSpaceConfig.getBeanName(notifyName);
|
||||
if (notifyBeanName != null && notifyBeanName.equals(serviceImplName)) {
|
||||
// this is a bean key
|
||||
notify = true;
|
||||
break;
|
||||
}
|
||||
// check to see if the name matches one of those the listener cares about
|
||||
for (String changedName : changedNames) {
|
||||
if (simplerName != null && simplerName.equals(changedName)) {
|
||||
if (notifyName != null && notifyName.equals(changedName)) {
|
||||
notify = true;
|
||||
break;
|
||||
}
|
||||
@@ -418,7 +414,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
configChangeListener.configurationChanged(changedSettingNames, changedSettings);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
System.err.println("Failure occurred while trying to notify service of config change: " + e.getMessage());
|
||||
log.error("Failure occurred while trying to notify service of config change: " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -426,44 +422,43 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* @param key a DSpace config key
|
||||
* @return the simpler name (property name or key without property)
|
||||
*/
|
||||
protected static String getSimplerName(String key) {
|
||||
String simpleName = key;
|
||||
if (key != null) {
|
||||
String propertyName = DSpaceConfig.getBeanProperty(key);
|
||||
if (propertyName != null) {
|
||||
simpleName = propertyName;
|
||||
}
|
||||
}
|
||||
return simpleName;
|
||||
}
|
||||
|
||||
// STATICS
|
||||
|
||||
/**
|
||||
* Adds configuration settings into services if possible.
|
||||
* Skips any that are invalid.
|
||||
* Configures a given service (i.e. bean) based on any DSpace configuration
|
||||
* settings which refer to it by name. .
|
||||
* <P>
|
||||
* NOTE: Any configurations related to a specific service MUST be prefixed
|
||||
* with the given service's name (e.g. [serviceName].setting = value)
|
||||
* <P>
|
||||
* This method logs an error if it encounters configs which refer to a
|
||||
* service by name, but is an invalid setting for that service.
|
||||
*
|
||||
* @param serviceName the name of the service
|
||||
* @param service the service object
|
||||
* @param serviceNameConfigs all known service configuration settings (from the DS config service impl)
|
||||
* @param service the service object (which will be configured)
|
||||
* @param config the running configuration service
|
||||
*/
|
||||
public static void configureService(String serviceName, Object service, Map<String, Map<String, ServiceConfig>> serviceNameConfigs) {
|
||||
// stuff the config settings into the bean if there are any
|
||||
if (serviceNameConfigs.containsKey(serviceName)) {
|
||||
public static void configureService(String serviceName, Object service, ConfigurationService config) {
|
||||
|
||||
// Check if the configuration has any properties whose prefix
|
||||
// corresponds to this service's name
|
||||
List<String> configKeys = config.getPropertyKeys(serviceName);
|
||||
if(configKeys!=null && !configKeys.isEmpty())
|
||||
{
|
||||
BeanWrapper beanWrapper = PropertyAccessorFactory.forBeanPropertyAccess(service);
|
||||
for (String key : configKeys) {
|
||||
// Remove serviceName prefix from key. This is the name of the actual bean's parameter
|
||||
// This removes the first x chars, where x is length of serviceName + 1 char
|
||||
// Format of Key: [serviceName].[param]
|
||||
String param = key.substring(serviceName.length() + 1);
|
||||
|
||||
Map<String, ServiceConfig> configs = serviceNameConfigs.get(serviceName);
|
||||
for (ServiceConfig config : configs.values()) {
|
||||
try {
|
||||
beanWrapper.setPropertyValue(config.getParamName(), config.getValue());
|
||||
|
||||
log.info("Set param ("+config.getParamName()+") on service bean ("+serviceName+") to: " + config.getValue());
|
||||
// Attempt to set this configuration on the given service's bean
|
||||
beanWrapper.setPropertyValue(param, config.getProperty(key));
|
||||
log.info("Set param ("+param+") on service bean ("+serviceName+") to: " + config.getProperty(key));
|
||||
} catch (RuntimeException e) {
|
||||
log.error("Unable to set param ("+config.getParamName()+") on service bean ("+serviceName+"): " + e.getMessage(), e);
|
||||
// If an error occurs, just log it
|
||||
log.error("Unable to set param ("+param+") on service bean ("+serviceName+") to: " + config.getProperty(key), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -479,7 +474,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
try {
|
||||
((InitializedService) service).init();
|
||||
} catch (Exception e) {
|
||||
throw new IllegalStateException("Failure attempting to initialize service (" + service + "): " + e.getMessage());
|
||||
throw new IllegalStateException("Failure attempting to initialize service (" + service + "): " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -493,7 +488,7 @@ public final class DSpaceServiceManager implements ServiceManagerSystem {
|
||||
try {
|
||||
((ShutdownService) service).shutdown();
|
||||
} catch (Exception e) {
|
||||
System.err.println("Failure shutting down service: " + service);
|
||||
log.error("Failure shutting down service: " + service, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -1,58 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.servicemanager;
|
||||
|
||||
import org.dspace.servicemanager.config.DSpaceConfig;
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* This holds the settings for a service config triple.
|
||||
* Create this from a {@link DSpaceConfig} object, or by name and value.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public class ServiceConfig {
|
||||
|
||||
private String paramName;
|
||||
private String serviceName;
|
||||
private Object value;
|
||||
|
||||
/** Construct from scratch. */
|
||||
public ServiceConfig(String paramName, String serviceName, Object value) {
|
||||
if (paramName == null || serviceName == null) {
|
||||
throw new IllegalArgumentException("paramName and serviceName must not be null");
|
||||
}
|
||||
this.paramName = paramName;
|
||||
this.serviceName = serviceName;
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
/** Construct from an existing DSpaceConfig. */
|
||||
public ServiceConfig(DSpaceConfig dspaceConfig) {
|
||||
this.paramName = dspaceConfig.getBeanProperty();
|
||||
this.serviceName = dspaceConfig.getBeanName();
|
||||
if (paramName == null || serviceName == null) {
|
||||
throw new IllegalArgumentException("paramName and serviceName must not be null");
|
||||
}
|
||||
this.value = dspaceConfig.getValue();
|
||||
}
|
||||
|
||||
public String getParamName() {
|
||||
return paramName;
|
||||
}
|
||||
|
||||
public String getServiceName() {
|
||||
return serviceName;
|
||||
}
|
||||
|
||||
public Object getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
}
|
@@ -1,243 +0,0 @@
|
||||
/**
|
||||
* The contents of this file are subject to the license and copyright
|
||||
* detailed in the LICENSE and NOTICE files at the root of the source
|
||||
* tree and available online at
|
||||
*
|
||||
* http://www.dspace.org/license/
|
||||
*/
|
||||
package org.dspace.servicemanager.config;
|
||||
|
||||
/**
|
||||
* This represents a single config setting for a DSpace instance.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
*/
|
||||
public final class DSpaceConfig {
|
||||
|
||||
public static final String ACTIVATOR_PREFIX = "activator.";
|
||||
public static final String ACTIVATOR_CLASS_PREFIX = ACTIVATOR_PREFIX + "class.";
|
||||
|
||||
private String key;
|
||||
private String value;
|
||||
|
||||
private String beanProperty;
|
||||
private String beanName;
|
||||
|
||||
private boolean activator = false;
|
||||
private boolean activatorClass = false;
|
||||
private String activatorClassName;
|
||||
private String activatorName;
|
||||
private String activatorAutowire;
|
||||
|
||||
public DSpaceConfig(String key, String value) {
|
||||
if (key == null || "".equals(key)) {
|
||||
throw new IllegalArgumentException("Failure with config creation, key is empty or null");
|
||||
}
|
||||
this.key = key.trim();
|
||||
this.value = value;
|
||||
// extract the property and class if possible
|
||||
int atLoc = key.indexOf('@');
|
||||
if (atLoc > 0) {
|
||||
try {
|
||||
this.beanProperty = key.substring(0, atLoc);
|
||||
this.beanName = key.substring(atLoc + 1);
|
||||
} catch (RuntimeException e) {
|
||||
throw new IllegalArgumentException("Invalid bean key ("+key+"): could not parse key (should be like param@org.dspace.BeanName): " + e.getMessage(), e);
|
||||
}
|
||||
}
|
||||
// extract the activator info if possible
|
||||
if (this.key.startsWith(ACTIVATOR_CLASS_PREFIX)) {
|
||||
if (this.value == null || this.value.length() <= 2) {
|
||||
throw new IllegalArgumentException("Invalid configuration value for key ("+this.key
|
||||
+"), must not be blank or null and must be set to a class activator string (e.g. org.dspace.MyClass;org.dspace.MyServiceName)");
|
||||
}
|
||||
this.activatorClass = true;
|
||||
if (this.value.indexOf(';') == -1) {
|
||||
this.activatorClassName = this.value.trim();
|
||||
} else {
|
||||
// split it
|
||||
String[] parts = this.value.trim().split(";");
|
||||
this.activatorClassName = parts[0].trim();
|
||||
if (parts.length > 1) {
|
||||
this.activatorName = parts[1].trim();
|
||||
}
|
||||
if (parts.length > 2) {
|
||||
this.activatorAutowire = parts[2].trim().toLowerCase();
|
||||
}
|
||||
}
|
||||
if (this.activatorName == null) {
|
||||
this.activatorName = this.activatorClassName;
|
||||
}
|
||||
if (this.activatorAutowire == null) {
|
||||
this.activatorAutowire = "auto";
|
||||
}
|
||||
} else if (this.key.startsWith(ACTIVATOR_PREFIX)) {
|
||||
if (this.value == null || this.value.length() <= 2) {
|
||||
throw new IllegalArgumentException("Invalid configuration value for key ("+this.key
|
||||
+"), must not be blank or null and must be set to an activator class (e.g. org.dspace.MyActivator)");
|
||||
}
|
||||
this.activator = true;
|
||||
this.activatorClassName = this.value.trim();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets the part before the @ in a config line.
|
||||
* @return the bean property if there is one OR null if this is not a bean config
|
||||
*/
|
||||
public String getBeanProperty() {
|
||||
return beanProperty;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the part after the @ in a config line.
|
||||
* @return the bean name which the property goes with OR null if there is none
|
||||
*/
|
||||
public String getBeanName() {
|
||||
return beanName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates that this configuration is for an activator (a class
|
||||
* that implements Activator).
|
||||
* @return true if this config is for an activator OR false if not
|
||||
*/
|
||||
public boolean isActivator() {
|
||||
return activator;
|
||||
}
|
||||
|
||||
/**
|
||||
* Indicates this is a config for an activator class (a class which
|
||||
* will be started as a service during the service manager startup).
|
||||
* @return true if this is a config for an activator class OR false if not
|
||||
*/
|
||||
public boolean isActivatorClass() {
|
||||
return activatorClass;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the classname of the activator defined by the activator
|
||||
* string if there is one.
|
||||
* This will be the activator class or the class which should be
|
||||
* activated.
|
||||
* Check the {@link #isActivator()} and {@link #isActivatorClass()}
|
||||
* booleans to see which.
|
||||
*
|
||||
* @return the activator class name OR null if this is not an activator config
|
||||
*/
|
||||
public String getActivatorClassName() {
|
||||
return activatorClassName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the name to use for this activator (as defined by the
|
||||
* activator string).
|
||||
* This will always be set if the {@link #activatorClassName} is set.
|
||||
* @return the activator name OR null if this is not an activator config
|
||||
*/
|
||||
public String getActivatorName() {
|
||||
return activatorName;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the activator autowire string. Returns one of:
|
||||
* <dl>
|
||||
* <dt>auto</dt><dd>determine which type of autowiring automatically</dd>
|
||||
* <dt>constructor</dt><dd>autowire the constructor</dd>
|
||||
* <dt>setter</dt><dd>autowire the setters by type</dd>
|
||||
* <dt>none</dt><dd>disable any autowiring (this will only start up
|
||||
* the class using the default constructor)</dd>
|
||||
* </dl>
|
||||
*
|
||||
* @return the autowiring setting (auto/constructor/setter/none) OR
|
||||
* null if this is not an activator config
|
||||
*/
|
||||
public String getActivatorAutowire() {
|
||||
return activatorAutowire;
|
||||
}
|
||||
|
||||
public String getKey() {
|
||||
return key;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
protected void setValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean equals(Object obj) {
|
||||
if (null == obj) {
|
||||
return false;
|
||||
}
|
||||
if (!(obj instanceof DSpaceConfig)) {
|
||||
return false;
|
||||
} else {
|
||||
DSpaceConfig castObj = (DSpaceConfig) obj;
|
||||
if (this.key == null || this.value == null) {
|
||||
return false;
|
||||
} else {
|
||||
return (this.key.equals(castObj.key) &&
|
||||
this.value.equals(castObj.value));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public int hashCode() {
|
||||
if (null == key) {
|
||||
return super.hashCode();
|
||||
}
|
||||
return key.hashCode() + value.hashCode();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return (beanName == null ? key : beanName+"("+beanProperty+")") + " => " + value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bean name from a configuration key if it contains one.
|
||||
* @param key a config key
|
||||
* @return the bean name if there is one OR null if none
|
||||
*/
|
||||
public static String getBeanName(String key) {
|
||||
// extract the property and class if possible
|
||||
String name = null;
|
||||
int atLoc = key.indexOf('@');
|
||||
if (atLoc > 0) {
|
||||
try {
|
||||
//property = key.substring(0, atLoc);
|
||||
name = key.substring(atLoc + 1);
|
||||
} catch (RuntimeException e) {
|
||||
name = null;
|
||||
}
|
||||
}
|
||||
return name;
|
||||
}
|
||||
|
||||
/**
|
||||
* Get the bean property from a configuration key if it contains one.
|
||||
* @param key a config key
|
||||
* @return the bean property if there is one OR null if none
|
||||
*/
|
||||
public static String getBeanProperty(String key) {
|
||||
// extract the property and class if possible
|
||||
String property = null;
|
||||
int atLoc = key.indexOf('@');
|
||||
if (atLoc > 0) {
|
||||
try {
|
||||
property = key.substring(0, atLoc);
|
||||
//name = key.substring(atLoc + 1);
|
||||
} catch (RuntimeException e) {
|
||||
property = null;
|
||||
}
|
||||
}
|
||||
return property;
|
||||
}
|
||||
|
||||
}
|
@@ -7,29 +7,32 @@
|
||||
*/
|
||||
package org.dspace.servicemanager.config;
|
||||
|
||||
import java.io.*;
|
||||
import java.net.InetAddress;
|
||||
import java.net.UnknownHostException;
|
||||
import java.util.*;
|
||||
import java.io.File;
|
||||
import java.math.BigDecimal;
|
||||
import java.math.BigInteger;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Iterator;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Map.Entry;
|
||||
|
||||
import org.dspace.constants.Constants;
|
||||
import org.dspace.servicemanager.ServiceConfig;
|
||||
import java.util.Properties;
|
||||
import org.apache.commons.configuration.Configuration;
|
||||
import org.apache.commons.configuration.ConfigurationConverter;
|
||||
import org.apache.commons.configuration.ConfigurationException;
|
||||
import org.apache.commons.configuration.DefaultConfigurationBuilder;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.slf4j.Logger;
|
||||
import org.slf4j.LoggerFactory;
|
||||
import org.springframework.beans.SimpleTypeConverter;
|
||||
import org.springframework.core.io.ClassPathResource;
|
||||
import org.springframework.core.io.Resource;
|
||||
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
|
||||
|
||||
/**
|
||||
* The central DSpace configuration service.
|
||||
* This is effectively immutable once the config has loaded.
|
||||
* The central DSpace configuration service. Uses Apache Commons Configuration
|
||||
* to provide the ability to reload Property files.
|
||||
*
|
||||
* @author Aaron Zeckoski (azeckoski @ gmail.com)
|
||||
* @author Kevin Van de Velde (kevin at atmire dot com)
|
||||
* @author Mark Diggory (mdiggory at atmire dot com)
|
||||
* @author Tim Donohue (rewrote to use Apache Commons Config
|
||||
* @author Aaron Zeckoski
|
||||
* @author Kevin Van de Velde
|
||||
* @author Mark Diggory
|
||||
*/
|
||||
public final class DSpaceConfigurationService implements ConfigurationService {
|
||||
|
||||
@@ -40,17 +43,18 @@ public final class DSpaceConfigurationService implements ConfigurationService {
|
||||
public static final String EXT_CONFIG = "cfg";
|
||||
public static final String DOT_CONFIG = "." + EXT_CONFIG;
|
||||
|
||||
public static final String DSPACE_PREFIX = "dspace.";
|
||||
public static final String DSPACE_HOME = DSPACE + ".dir";
|
||||
public static final String DEFAULT_CONFIGURATION_FILE_NAME = "dspace-defaults" + DOT_CONFIG;
|
||||
public static final String DEFAULT_DSPACE_CONFIG_PATH = "config/" + DEFAULT_CONFIGURATION_FILE_NAME;
|
||||
public static final String DEFAULT_CONFIG_DIR = "config";
|
||||
public static final String DEFAULT_CONFIG_DEFINITION_FILE = "config-definition.xml";
|
||||
public static final String DSPACE_CONFIG_DEFINITION_PATH = DEFAULT_CONFIG_DIR + File.separatorChar + DEFAULT_CONFIG_DEFINITION_FILE;
|
||||
|
||||
public static final String DSPACE_CONFIG_PATH = "config/" + DSPACE + DOT_CONFIG;
|
||||
public static final String DSPACE_CONFIG_PATH = DEFAULT_CONFIG_DIR + File.separatorChar + DSPACE + DOT_CONFIG;
|
||||
|
||||
public static final String DSPACE_MODULES_CONFIG_PATH = "config" + File.separator + "modules";
|
||||
// Current ConfigurationBuilder
|
||||
DefaultConfigurationBuilder configurationBuilder = null;
|
||||
|
||||
protected transient Map<String, Map<String, ServiceConfig>> serviceNameConfigs;
|
||||
public static final String DSPACE_CONFIG_ADDON = "dspace/config-*";
|
||||
// Current Configuration
|
||||
protected Configuration configuration = null;
|
||||
|
||||
public DSpaceConfigurationService() {
|
||||
// init and load up current config settings
|
||||
@@ -61,32 +65,61 @@ public final class DSpaceConfigurationService implements ConfigurationService {
|
||||
loadInitialConfig(providedHome);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.dspace.services.ConfigurationService#getAllProperties()
|
||||
*/
|
||||
@Override
|
||||
public Map<String, String> getAllProperties() {
|
||||
Map<String, String> props = new LinkedHashMap<String, String>();
|
||||
// for (Entry<String, DSpaceConfig> config : configuration.entrySet()) {
|
||||
// props.put(config.getKey(), config.getValue().getValue());
|
||||
// }
|
||||
|
||||
for (DSpaceConfig config : configuration.values()) {
|
||||
props.put(config.getKey(), config.getValue());
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.dspace.services.ConfigurationService#getProperties()
|
||||
*/
|
||||
@Override
|
||||
public Properties getProperties() {
|
||||
Properties props = new Properties();
|
||||
for (DSpaceConfig config : configuration.values()) {
|
||||
props.put(config.getKey(), config.getValue());
|
||||
// Return our configuration as a set of Properties
|
||||
return ConfigurationConverter.getProperties(configuration);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.dspace.services.ConfigurationService#getPropertyKeys()
|
||||
*/
|
||||
@Override
|
||||
public List<String> getPropertyKeys() {
|
||||
|
||||
Iterator<String> keys = configuration.getKeys();
|
||||
|
||||
List<String> keyList = new ArrayList<>();
|
||||
while(keys.hasNext())
|
||||
{
|
||||
keyList.add(keys.next());
|
||||
}
|
||||
return props;
|
||||
return keyList;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.dspace.services.ConfigurationService#getPropertyKeys(java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public List<String> getPropertyKeys(String prefix) {
|
||||
|
||||
Iterator<String> keys = configuration.getKeys(prefix);
|
||||
|
||||
List<String> keyList = new ArrayList<>();
|
||||
while(keys.hasNext())
|
||||
{
|
||||
keyList.add(keys.next());
|
||||
}
|
||||
return keyList;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.dspace.services.ConfigurationService#getConfiguration()
|
||||
*/
|
||||
@Override
|
||||
public Configuration getConfiguration() {
|
||||
return configuration;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.dspace.services.ConfigurationService#getPropertyValue(java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public Object getPropertyValue(String name) {
|
||||
return configuration.getProperty(name);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -94,12 +127,7 @@ public final class DSpaceConfigurationService implements ConfigurationService {
|
||||
*/
|
||||
@Override
|
||||
public String getProperty(String name) {
|
||||
DSpaceConfig config = configuration.get(name);
|
||||
String value = null;
|
||||
if (config != null) {
|
||||
value = config.getValue();
|
||||
}
|
||||
return value;
|
||||
return configuration.getString(name);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -107,8 +135,7 @@ public final class DSpaceConfigurationService implements ConfigurationService {
|
||||
*/
|
||||
@Override
|
||||
public <T> T getPropertyAsType(String name, Class<T> type) {
|
||||
String value = getProperty(name);
|
||||
return convert(value, type);
|
||||
return convert(name, type);
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
@@ -122,24 +149,26 @@ public final class DSpaceConfigurationService implements ConfigurationService {
|
||||
/* (non-Javadoc)
|
||||
* @see org.dspace.services.ConfigurationService#getPropertyAsType(java.lang.String, java.lang.Object, boolean)
|
||||
*/
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T> T getPropertyAsType(String name, T defaultValue, boolean setDefaultIfNotFound) {
|
||||
String value = getProperty(name);
|
||||
T property = null;
|
||||
if (defaultValue == null) {
|
||||
property = null; // just return null when default value is null
|
||||
} else if (value == null) {
|
||||
property = defaultValue; // just return the default value if nothing is currently set
|
||||
// also set the default value as the current stored value
|
||||
if (setDefaultIfNotFound) {
|
||||
|
||||
// If this key doesn't exist, immediately return a value
|
||||
if(!configuration.containsKey(name))
|
||||
{
|
||||
// if flag is set, save the default value as the new value for this property
|
||||
if(setDefaultIfNotFound)
|
||||
{
|
||||
setProperty(name, defaultValue);
|
||||
}
|
||||
} else {
|
||||
// something is already set so we convert the stored value to match the type
|
||||
property = (T)convert(value, defaultValue.getClass());
|
||||
|
||||
// Either way, return our default value as if it was the setting
|
||||
return defaultValue;
|
||||
}
|
||||
return property;
|
||||
|
||||
// Get the class associated with our default value
|
||||
Class type = defaultValue.getClass();
|
||||
|
||||
return (T) convert(name, type);
|
||||
}
|
||||
|
||||
// config loading methods
|
||||
@@ -148,492 +177,197 @@ public final class DSpaceConfigurationService implements ConfigurationService {
|
||||
* @see org.dspace.services.ConfigurationService#setProperty(java.lang.String, java.lang.Object)
|
||||
*/
|
||||
@Override
|
||||
public boolean setProperty(String name, Object value) {
|
||||
public synchronized boolean setProperty(String name, Object value)
|
||||
{
|
||||
boolean changed = false;
|
||||
if (name == null) {
|
||||
throw new IllegalArgumentException("name cannot be null for setting configuration");
|
||||
}
|
||||
boolean changed = false;
|
||||
if (value == null) {
|
||||
changed = this.configuration.remove(name) != null;
|
||||
log.info("Cleared the configuration setting for name ("+name+")");
|
||||
} else {
|
||||
SimpleTypeConverter converter = new SimpleTypeConverter();
|
||||
String sVal = (String)converter.convertIfNecessary(value, String.class);
|
||||
changed = loadConfig(name, sVal);
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
else
|
||||
{
|
||||
Object oldValue = configuration.getProperty(name);
|
||||
|
||||
// INTERNAL loading methods
|
||||
public List<DSpaceConfig> getConfiguration() {
|
||||
return new ArrayList<DSpaceConfig>( configuration.values() );
|
||||
}
|
||||
|
||||
/**
|
||||
* Get all configs that start with the given value.
|
||||
* @param prefix a string which the configs to return must start with
|
||||
* @return the list of all configs that start with the given string
|
||||
*/
|
||||
public List<DSpaceConfig> getConfigsByPrefix(String prefix) {
|
||||
List<DSpaceConfig> configs = new ArrayList<DSpaceConfig>();
|
||||
if (prefix != null && prefix.length() > 0) {
|
||||
for (DSpaceConfig config : configuration.values()) {
|
||||
if (config.getKey().startsWith(prefix)) {
|
||||
configs.add(config);
|
||||
}
|
||||
if (value == null && oldValue!=null)
|
||||
{
|
||||
changed = true;
|
||||
configuration.clearProperty(name);
|
||||
log.info("Cleared the configuration setting for name ("+name+")");
|
||||
}
|
||||
else if(!value.equals(oldValue))
|
||||
{
|
||||
changed = true;
|
||||
configuration.setProperty(name, value);
|
||||
}
|
||||
}
|
||||
return configs;
|
||||
}
|
||||
|
||||
protected Map<String, DSpaceConfig> configuration = Collections.synchronizedMap(new LinkedHashMap<String, DSpaceConfig>());
|
||||
|
||||
/**
|
||||
* @return a map of the service name configurations that are known for fast resolution
|
||||
*/
|
||||
public Map<String, Map<String, ServiceConfig>> getServiceNameConfigs() {
|
||||
return serviceNameConfigs;
|
||||
}
|
||||
|
||||
public void setConfiguration(Map<String, DSpaceConfig> configuration) {
|
||||
if (configuration == null) {
|
||||
throw new IllegalArgumentException("configuration cannot be null");
|
||||
}
|
||||
this.configuration = configuration;
|
||||
replaceVariables(this.configuration);
|
||||
// refresh the configs
|
||||
serviceNameConfigs = makeServiceNameConfigs();
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Load a series of properties into the configuration.
|
||||
* Checks to see if the settings exist or are changed and only loads
|
||||
* changes. Clears out existing ones depending on the setting.
|
||||
* changes.
|
||||
* <P>
|
||||
* This only adds/updates configurations, if you wish to first clear all
|
||||
* existing configurations, see clear() method.
|
||||
*
|
||||
* @param properties a map of key -> value strings
|
||||
* @param clear if true then clears the existing configuration settings first
|
||||
* @return the list of changed configuration names
|
||||
* @param properties a map of key -> value settings
|
||||
* @return the list of changed configuration keys
|
||||
*/
|
||||
public String[] loadConfiguration(Map<String, String> properties, boolean clear) {
|
||||
public String[] loadConfiguration(Map<String, Object> properties) {
|
||||
if (properties == null) {
|
||||
throw new IllegalArgumentException("properties cannot be null");
|
||||
}
|
||||
// transform to configs and call load
|
||||
ArrayList<DSpaceConfig> dspaceConfigs = new ArrayList<DSpaceConfig>();
|
||||
for (Entry<String, String> entry : properties.entrySet()) {
|
||||
String key = entry.getKey();
|
||||
if (key != null && ! "".equals(key)) {
|
||||
String val = entry.getValue();
|
||||
if (val != null && ! "".equals(val)) {
|
||||
dspaceConfigs.add( new DSpaceConfig(entry.getKey(), entry.getValue()) );
|
||||
}
|
||||
}
|
||||
}
|
||||
return loadConfiguration(dspaceConfigs, clear);
|
||||
}
|
||||
|
||||
/**
|
||||
* Load up a bunch of {@link DSpaceConfig}s into the configuration.
|
||||
* Checks to see if the settings exist or are changed and only
|
||||
* loads changes. Clears out existing ones depending on the setting.
|
||||
*
|
||||
* @param dspaceConfigs a list of {@link DSpaceConfig} objects
|
||||
* @param clear if true then clears the existing configuration settings first
|
||||
* @return the list of changed configuration names
|
||||
*/
|
||||
public String[] loadConfiguration(List<DSpaceConfig> dspaceConfigs, boolean clear) {
|
||||
ArrayList<String> changed = new ArrayList<String>();
|
||||
if (clear) {
|
||||
this.configuration.clear();
|
||||
}
|
||||
for (DSpaceConfig config : dspaceConfigs) {
|
||||
String key = config.getKey();
|
||||
boolean same = true;
|
||||
if (clear) {
|
||||
// all are new
|
||||
same = false;
|
||||
} else {
|
||||
if (this.configuration.containsKey(key)) {
|
||||
if (this.configuration.get(key).equals(config)) {
|
||||
// this one has changed
|
||||
same = false;
|
||||
}
|
||||
} else {
|
||||
// this one is new
|
||||
same = false;
|
||||
}
|
||||
}
|
||||
if (!same) {
|
||||
|
||||
// loop through each new property entry
|
||||
for (Entry<String, Object> entry : properties.entrySet())
|
||||
{
|
||||
String key = entry.getKey();
|
||||
Object value = entry.getValue();
|
||||
|
||||
// Load this new individual key
|
||||
boolean updated = loadConfig(key, value);
|
||||
|
||||
// If it was updated, add to our list of changed settings
|
||||
if(updated)
|
||||
{
|
||||
changed.add(key);
|
||||
this.configuration.put(key, config);
|
||||
}
|
||||
}
|
||||
if (changed.size() > 0) {
|
||||
replaceVariables(this.configuration);
|
||||
// refresh the configs
|
||||
serviceNameConfigs = makeServiceNameConfigs();
|
||||
}
|
||||
|
||||
// Return an array of updated keys
|
||||
return changed.toArray(new String[changed.size()]);
|
||||
}
|
||||
|
||||
/**
|
||||
* Loads an additional config setting into the system.
|
||||
* Loads a single additional config setting into the system.
|
||||
* @param key
|
||||
* @param value
|
||||
* @return true if the config is new or changed
|
||||
*/
|
||||
public boolean loadConfig(String key, String value) {
|
||||
public boolean loadConfig(String key, Object value) {
|
||||
if (key == null) {
|
||||
throw new IllegalArgumentException("key cannot be null");
|
||||
}
|
||||
// update replacements and add
|
||||
boolean changed = replaceAndAddConfig( new DSpaceConfig(key, value) );
|
||||
if (changed) {
|
||||
// refresh the configs
|
||||
serviceNameConfigs = makeServiceNameConfigs();
|
||||
|
||||
// Check if the value has changed
|
||||
if (this.configuration.containsKey(key) &&
|
||||
this.configuration.getProperty(key).equals(value))
|
||||
{
|
||||
// no change to the value
|
||||
return false;
|
||||
}
|
||||
else
|
||||
{
|
||||
// Either this config doesn't exist, or it is not the same value,
|
||||
// so we'll update it.
|
||||
this.configuration.setProperty(key, value);
|
||||
return true;
|
||||
}
|
||||
return changed;
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears the configuration settings.
|
||||
* Clears all the configuration settings.
|
||||
*/
|
||||
public void clear() {
|
||||
this.configuration.clear();
|
||||
this.serviceNameConfigs.clear();
|
||||
log.info("Cleared all configuration settings");
|
||||
}
|
||||
|
||||
/**
|
||||
* Clears a single configuration
|
||||
* @param key key of the configuration
|
||||
*/
|
||||
public void clearConfig(String key) {
|
||||
this.configuration.clearProperty(key);
|
||||
}
|
||||
|
||||
// loading from files code
|
||||
|
||||
/**
|
||||
* Loads up the default initial configuration from the DSpace configuration
|
||||
* files in the file home and on the classpath. Order:
|
||||
* <ol>
|
||||
* <li>Create {@code serverId} from local host name if available.</li>
|
||||
* <li>Create {@code dspace.testing = false}.
|
||||
* <li>Determine the value of {@code dspace.dir} and add to configuration.</li>
|
||||
* <li>Load {@code classpath:config/dspace_defaults.cfg}.</li>
|
||||
* <li>Copy system properties with names beginning "dspace." <em>except</em>
|
||||
* {@code dspace.dir}, removing the "dspace." prefix from the name.</li>
|
||||
* <li>Load all {@code classpath:dspace/config-*.cfg} using whatever
|
||||
* matched "*" as module prefix.</li>
|
||||
* <li>Load all {@code ${dspace.dir}/config/modules/*.cfg} using whatever
|
||||
* matched "*" as module prefix.</li>
|
||||
* <li>Load {@code classpath:dspace.cfg}.</li>
|
||||
* <li>Load from the path in the system property {@code dspace.configuration}
|
||||
* if defined, or {@code ${dspace.dir}/config/dspace.cfg}.</li>
|
||||
* <li>Perform variable substitutions throughout the assembled configuration.</li>
|
||||
* </ol>
|
||||
*
|
||||
* <p>The initial value of {@code dspace.dir} will be:</p>
|
||||
* <ol>
|
||||
* <li>the value of the system property {@code dspace.dir} if defined;</li>
|
||||
* <li>else the value of {@code providedHome} if not null;</li>
|
||||
* <li>else the servlet container's home + "/dspace/" if defined (see {@link getCatalina()});</li>
|
||||
* <li>else the user's home directory if defined;</li>
|
||||
* <li>else "/".
|
||||
* </ol>
|
||||
*
|
||||
* Loads up the configuration from the DSpace configuration files.
|
||||
* <P>
|
||||
* Determines the home directory of DSpace, and then loads the configurations
|
||||
* based on the configuration definition file in that location
|
||||
* (using Apache Commons Configuration).
|
||||
* @param providedHome DSpace home directory, or null.
|
||||
*/
|
||||
public void loadInitialConfig(String providedHome) {
|
||||
Map<String, String> configMap = new LinkedHashMap<String, String>();
|
||||
// load default settings
|
||||
try {
|
||||
String defaultServerId = InetAddress.getLocalHost().getHostName();
|
||||
configMap.put("serverId", defaultServerId);
|
||||
} catch (UnknownHostException e) {
|
||||
// oh well
|
||||
}
|
||||
// default is testing mode off
|
||||
configMap.put(Constants.DSPACE_TESTING_MODE, "false");
|
||||
|
||||
// now we load the settings from properties files
|
||||
public void loadInitialConfig(String providedHome)
|
||||
{
|
||||
// See if homePath is specified as a System Property
|
||||
String homePath = System.getProperty(DSPACE_HOME);
|
||||
|
||||
// now we load from the provided parameter if its not null
|
||||
// If a provided home was passed in & no system property, use provided home
|
||||
if (providedHome != null && homePath == null) {
|
||||
homePath = providedHome;
|
||||
}
|
||||
|
||||
// If still null, check Catalina
|
||||
if (homePath == null) {
|
||||
String catalina = getCatalina();
|
||||
if (catalina != null) {
|
||||
homePath = catalina + File.separatorChar + DSPACE + File.separatorChar;
|
||||
}
|
||||
}
|
||||
// If still null, check "user.home" system property
|
||||
if (homePath == null) {
|
||||
homePath = System.getProperty("user.home");
|
||||
}
|
||||
// Finally, no other option but to assume root path ("/")
|
||||
if (homePath == null) {
|
||||
homePath = "/";
|
||||
}
|
||||
|
||||
// make sure it's set properly
|
||||
//System.setProperty(DSPACE_HOME, homePath);
|
||||
configMap.put(DSPACE_HOME, homePath);
|
||||
// Based on homePath get full path to the configuration definition
|
||||
String configDefinition = homePath + File.separatorChar + DSPACE_CONFIG_DEFINITION_PATH;
|
||||
|
||||
// LOAD the internal defaults
|
||||
Properties defaultProps = readPropertyResource(DEFAULT_DSPACE_CONFIG_PATH);
|
||||
if (defaultProps.size() <= 0) {
|
||||
// failed to load defaults!
|
||||
throw new RuntimeException("Failed to load default dspace config properties: " + DEFAULT_DSPACE_CONFIG_PATH);
|
||||
}
|
||||
pushPropsToMap(configMap, defaultProps);
|
||||
|
||||
// load all properties from the system which begin with the prefix
|
||||
Properties systemProps = System.getProperties();
|
||||
for (Object o : systemProps.keySet()) {
|
||||
String key = (String) o;
|
||||
if (key != null
|
||||
&& ! key.equals(DSPACE_HOME)) {
|
||||
try {
|
||||
if (key.startsWith(DSPACE_PREFIX)) {
|
||||
String propName = key.substring(DSPACE_PREFIX.length());
|
||||
String propVal = systemProps.getProperty(key);
|
||||
log.info("Loading system property as config: "+propName+"=>"+propVal);
|
||||
configMap.put(propName, propVal);
|
||||
}
|
||||
} catch (RuntimeException e) {
|
||||
log.error("Failed to properly get config value from system property: " + o, e);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Collect values from all the properties files: the later ones loaded override settings from prior.
|
||||
|
||||
|
||||
//Find any addon config files found in the config dir in our jars
|
||||
try {
|
||||
PathMatchingResourcePatternResolver patchMatcher = new PathMatchingResourcePatternResolver();
|
||||
Resource[] resources = patchMatcher.getResources("classpath*:" + DSPACE_CONFIG_ADDON + DOT_CONFIG);
|
||||
for (Resource resource : resources) {
|
||||
String prefix = resource.getFilename().substring(0, resource.getFilename().lastIndexOf(".")).replaceFirst("config-", "");
|
||||
pushPropsToMap(configMap, prefix, readPropertyStream(resource.getInputStream()));
|
||||
}
|
||||
}catch (Exception e){
|
||||
log.error("Failed to retrieve properties from classpath: " + e.getMessage(), e);
|
||||
|
||||
}
|
||||
//Attempt to load up all the config files in the modules directory
|
||||
try{
|
||||
File modulesDirectory = new File(homePath + File.separator + DSPACE_MODULES_CONFIG_PATH + File.separator);
|
||||
if(modulesDirectory.exists()){
|
||||
try{
|
||||
Resource[] resources = new PathMatchingResourcePatternResolver().getResources(modulesDirectory.toURI().toURL().toString() + "*" + DOT_CONFIG);
|
||||
if(resources != null){
|
||||
for(Resource resource : resources){
|
||||
String prefix = resource.getFilename().substring(0, resource.getFilename().lastIndexOf("."));
|
||||
pushPropsToMap(configMap, prefix, readPropertyStream(resource.getInputStream()));
|
||||
}
|
||||
}
|
||||
}catch (IOException e){
|
||||
log.error("Error while loading the modules properties from:" + modulesDirectory.getAbsolutePath());
|
||||
}
|
||||
}else{
|
||||
log.info("Failed to load the modules properties since (" + homePath + File.separator + DSPACE_MODULES_CONFIG_PATH + "): Does not exist");
|
||||
}
|
||||
|
||||
}catch (IllegalArgumentException e){
|
||||
//This happens if we don't have a modules directory
|
||||
log.error("Error while loading the module properties since (" + homePath + File.separator + DSPACE_MODULES_CONFIG_PATH + "): is not a valid directory", e);
|
||||
}
|
||||
|
||||
// attempt to load from the current classloader also (works for commandline config sitting on classpath
|
||||
pushPropsToMap(configMap, readPropertyResource(DSPACE + DOT_CONFIG));
|
||||
|
||||
// read all the known files from the home path that are properties files
|
||||
String configPath = System.getProperty("dspace.configuration");
|
||||
if (null == configPath)
|
||||
try
|
||||
{
|
||||
configPath = homePath + File.separatorChar + DSPACE_CONFIG_PATH;
|
||||
// Load our configuration definition, which in turn loads all our config files/settings
|
||||
// See: http://commons.apache.org/proper/commons-configuration/userguide_v1.10/howto_configurationbuilder.html
|
||||
configurationBuilder = new DefaultConfigurationBuilder(configDefinition);
|
||||
|
||||
// Actually parser our configuration definition & return the resulting Configuration
|
||||
configuration = configurationBuilder.getConfiguration();
|
||||
}
|
||||
pushPropsToMap(configMap, readPropertyFile(configPath));
|
||||
|
||||
// TODO: still use this local file loading?
|
||||
// pushPropsToMap(configMap, readPropertyFile(homePath + File.separatorChar + "local" + DOT_PROPERTIES));
|
||||
|
||||
|
||||
// pushPropsToMap(configMap, readPropertyResource(DSPACE + DOT_PROPERTIES));
|
||||
// pushPropsToMap(configMap, readPropertyResource("local" + DOT_PROPERTIES));
|
||||
// pushPropsToMap(configMap, readPropertyResource("webapp" + DOT_PROPERTIES));
|
||||
|
||||
|
||||
|
||||
|
||||
// now push all of these into the config service store
|
||||
loadConfiguration(configMap, true);
|
||||
log.info("Started up configuration service and loaded "+configMap.size()+" settings");
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Adds in this DSConfig and then updates the config by checking for
|
||||
* replacements everywhere else.
|
||||
* @param dsConfig a DSConfig to update the value of and then add in to the main config
|
||||
* @return true if the config changed or is new
|
||||
*/
|
||||
protected boolean replaceAndAddConfig(DSpaceConfig dsConfig) {
|
||||
DSpaceConfig newConfig = null;
|
||||
String key = dsConfig.getKey();
|
||||
if (dsConfig.getValue().contains("${")) {
|
||||
String value = dsConfig.getValue();
|
||||
int start = -1;
|
||||
while ((start = value.indexOf("${")) > -1) {
|
||||
int end = value.indexOf('}', start);
|
||||
if (end > -1) {
|
||||
String newKey = value.substring(start+2, end);
|
||||
if (newKey.equals(key)) {
|
||||
log.warn("Found circular reference for key ("+newKey+") in config value: " + value);
|
||||
break;
|
||||
}
|
||||
DSpaceConfig dsc = this.configuration.get(newKey);
|
||||
if (dsc == null) {
|
||||
log.warn("Could not find key ("+newKey+") for replacement in value: " + value);
|
||||
break;
|
||||
}
|
||||
String newVal = dsc.getValue();
|
||||
value = value.replace("${"+newKey+"}", newVal);
|
||||
newConfig = new DSpaceConfig(key, value);
|
||||
} else {
|
||||
log.warn("Found '${' but could not find a closing '}' in the value: " + value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
catch(ConfigurationException ce)
|
||||
{
|
||||
log.error("Unable to load configurations based on definition at " + configDefinition);
|
||||
System.err.println("Unable to load configurations based on definition at " + configDefinition);
|
||||
throw new RuntimeException(ce);
|
||||
}
|
||||
|
||||
// add the config
|
||||
if (this.configuration.containsKey(key) && this.configuration.get(key).equals(dsConfig)) {
|
||||
return false; // SHORT CIRCUIT
|
||||
}
|
||||
|
||||
// config changed or new
|
||||
this.configuration.put(key, newConfig != null ? newConfig : dsConfig);
|
||||
// update replacements
|
||||
replaceVariables(this.configuration);
|
||||
return true;
|
||||
log.info("Started up configuration service and loaded settings: " + toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* This will replace the ${key} with the value from the matching key
|
||||
* if it exists. Logs a warning if the key does not exist.
|
||||
* Goes through and updates the replacements for the the entire
|
||||
* configuration and updates any replaced values.
|
||||
* Reload the configuration from the DSpace configuration files.
|
||||
* <P>
|
||||
* Uses the initialized ConfigurationBuilder to reload all configurations.
|
||||
*/
|
||||
protected void replaceVariables(Map<String, DSpaceConfig> dsConfiguration) {
|
||||
for (Entry<String, DSpaceConfig> entry : dsConfiguration.entrySet()) {
|
||||
if (entry.getValue().getValue().contains("${")) {
|
||||
String value = entry.getValue().getValue();
|
||||
int start = -1;
|
||||
while ((start = value.indexOf("${")) > -1) {
|
||||
int end = value.indexOf('}', start);
|
||||
if (end > -1) {
|
||||
String newKey = value.substring(start+2, end);
|
||||
DSpaceConfig dsc = dsConfiguration.get(newKey);
|
||||
if (dsc == null) {
|
||||
log.warn("Could not find key ("+newKey+") for replacement in value: " + value);
|
||||
break;
|
||||
}
|
||||
String newVal = dsc.getValue();
|
||||
String oldValue = value;
|
||||
value = value.replace("${"+newKey+"}", newVal);
|
||||
if (value.equals(oldValue)) {
|
||||
log.warn("No change after variable replacement -- is "
|
||||
+ newKey + " = " + newVal +
|
||||
" a circular reference?");
|
||||
break;
|
||||
}
|
||||
entry.setValue( new DSpaceConfig(entry.getValue().getKey(), value) );
|
||||
} else {
|
||||
log.warn("Found '${' but could not find a closing '}' in the value: " + value);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
@Override
|
||||
public void reloadConfig()
|
||||
{
|
||||
try
|
||||
{
|
||||
configurationBuilder.reload();
|
||||
this.configuration = configurationBuilder.getConfiguration();
|
||||
}
|
||||
catch(ConfigurationException ce)
|
||||
{
|
||||
log.error("Unable to reload configurations based on definition at " + configurationBuilder.getFile().getAbsolutePath(), ce);
|
||||
}
|
||||
log.info("Reloaded configuration service: " + toString());
|
||||
}
|
||||
|
||||
protected Properties readPropertyFile(String filePathName) {
|
||||
Properties props = new Properties();
|
||||
InputStream is = null;
|
||||
try {
|
||||
File f = new File(filePathName);
|
||||
if (f.exists()) {
|
||||
is = new FileInputStream(f);
|
||||
props.load(is);
|
||||
log.info("Loaded "+props.size()+" config properties from file: " + f);
|
||||
}
|
||||
else
|
||||
{
|
||||
log.info("Failed to load config properties from file ("+filePathName+"): Does not exist");
|
||||
@Override
|
||||
public String toString() {
|
||||
// Get the size of the generated Properties
|
||||
Properties props = getProperties();
|
||||
int size = props!=null ? props.size() : 0;
|
||||
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to load config properties from file ("+filePathName+"): " + e.getMessage(), e);
|
||||
} finally {
|
||||
if (is != null) {
|
||||
try {
|
||||
is.close();
|
||||
} catch (IOException ioe) {
|
||||
// Ignore exception on close
|
||||
}
|
||||
}
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
protected Properties readPropertyResource(String resourcePathName) {
|
||||
Properties props = new Properties();
|
||||
try {
|
||||
ClassPathResource resource = new ClassPathResource(resourcePathName);
|
||||
if (resource.exists()) {
|
||||
props.load(resource.getInputStream());
|
||||
log.info("Loaded "+props.size()+" config properties from resource: " + resource);
|
||||
}
|
||||
} catch (Exception e) {
|
||||
log.warn("Failed to load config properties from resource ("+resourcePathName+"): " + e.getMessage(), e);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
protected Properties readPropertyFile(File propertyFile) {
|
||||
Properties props = new Properties();
|
||||
try{
|
||||
if(propertyFile.exists()){
|
||||
props.load(new FileInputStream(propertyFile));
|
||||
log.info("Loaded"+props.size() + " config properties from file: " + propertyFile.getName());
|
||||
}
|
||||
|
||||
} catch (Exception e){
|
||||
log.warn("Failed to load config properties from file (" + propertyFile.getName() + ": "+ e.getMessage(), e);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
protected Properties readPropertyStream(InputStream propertyStream){
|
||||
Properties props = new Properties();
|
||||
try{
|
||||
props.load(propertyStream);
|
||||
log.info("Loaded"+props.size() + " config properties from stream");
|
||||
} catch (Exception e){
|
||||
log.warn("Failed to load config properties from stream: " + e.getMessage(), e);
|
||||
}
|
||||
return props;
|
||||
}
|
||||
|
||||
protected void pushPropsToMap(Map<String, String> map, Properties props) {
|
||||
pushPropsToMap(map, null, props);
|
||||
|
||||
}
|
||||
protected void pushPropsToMap(Map<String, String> map, String prefix, Properties props) {
|
||||
for (Entry<Object, Object> entry : props.entrySet()) {
|
||||
String key = entry.getKey().toString();
|
||||
if(prefix != null){
|
||||
key = prefix + "." + key;
|
||||
}
|
||||
map.put(key, entry.getValue() == null ? "" : entry.getValue().toString());
|
||||
}
|
||||
// Return the configuration directory and number of configs loaded
|
||||
return "ConfigDir=" + configuration.getString(DSPACE_HOME) + File.separatorChar + DEFAULT_CONFIG_DIR + ", Size=" + size;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -648,55 +382,58 @@ public final class DSpaceConfigurationService implements ConfigurationService {
|
||||
return catalina;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "Config:" + DSPACE_HOME + ":size=" + configuration.size();
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* Constructs service name configs map for fast lookup of service
|
||||
* configurations.
|
||||
* @return the map of config service settings
|
||||
* Convert the value of a given property to a specific object type.
|
||||
* <P>
|
||||
* Note: in most cases we can just use Configuration get*() methods.
|
||||
*
|
||||
* @param name Key of the property to convert
|
||||
* @param <T> object type
|
||||
* @return converted value
|
||||
*/
|
||||
public Map<String, Map<String, ServiceConfig>> makeServiceNameConfigs() {
|
||||
Map<String, Map<String, ServiceConfig>> serviceNameConfigs = new HashMap<String, Map<String,ServiceConfig>>();
|
||||
for (DSpaceConfig dsConfig : getConfiguration()) {
|
||||
String beanName = dsConfig.getBeanName();
|
||||
if (beanName != null) {
|
||||
Map<String, ServiceConfig> map = null;
|
||||
if (serviceNameConfigs.containsKey(beanName)) {
|
||||
map = serviceNameConfigs.get(beanName);
|
||||
} else {
|
||||
map = new HashMap<String, ServiceConfig>();
|
||||
serviceNameConfigs.put(beanName, map);
|
||||
}
|
||||
map.put(beanName, new ServiceConfig(dsConfig));
|
||||
}
|
||||
}
|
||||
return serviceNameConfigs;
|
||||
}
|
||||
private <T> T convert(String name, Class<T> type) {
|
||||
|
||||
private <T> T convert(String value, Class<T> type) {
|
||||
SimpleTypeConverter converter = new SimpleTypeConverter();
|
||||
|
||||
if (value != null) {
|
||||
if (type.isArray()) {
|
||||
String[] values = value.split(",");
|
||||
return (T)converter.convertIfNecessary(values, type);
|
||||
}
|
||||
|
||||
if (type.isAssignableFrom(String.class)) {
|
||||
return (T)value;
|
||||
}
|
||||
} else {
|
||||
if (boolean.class.equals(type)) {
|
||||
return (T)Boolean.FALSE;
|
||||
} else if (int.class.equals(type) || long.class.equals(type)) {
|
||||
return (T)converter.convertIfNecessary(0, type);
|
||||
}
|
||||
// If this key doesn't exist, just return null
|
||||
if(!configuration.containsKey(name))
|
||||
{
|
||||
// Special case. For booleans, return false if key doesn't exist
|
||||
if(Boolean.class.equals(type) || boolean.class.equals(type))
|
||||
return (T) Boolean.FALSE;
|
||||
else
|
||||
return null;
|
||||
}
|
||||
|
||||
return (T)converter.convertIfNecessary(value, type);
|
||||
// Based on the type of class, call the appropriate
|
||||
// method of the Configuration object
|
||||
if(type.isArray())
|
||||
return (T) configuration.getStringArray(name);
|
||||
else if(String.class.equals(type) || type.isAssignableFrom(String.class))
|
||||
return (T) configuration.getString(name);
|
||||
else if(BigDecimal.class.equals(type))
|
||||
return (T) configuration.getBigDecimal(name);
|
||||
else if(BigInteger.class.equals(type))
|
||||
return (T) configuration.getBigInteger(name);
|
||||
else if(Boolean.class.equals(type) || boolean.class.equals(type))
|
||||
return (T) Boolean.valueOf(configuration.getBoolean(name));
|
||||
else if(Byte.class.equals(type) || byte.class.equals(type))
|
||||
return (T) Byte.valueOf(configuration.getByte(name));
|
||||
else if(Double.class.equals(type) || double.class.equals(type))
|
||||
return (T) Double.valueOf(configuration.getDouble(name));
|
||||
else if(Float.class.equals(type) || float.class.equals(type))
|
||||
return (T) Float.valueOf(configuration.getFloat(name));
|
||||
else if(Integer.class.equals(type) || int.class.equals(type))
|
||||
return (T) Integer.valueOf(configuration.getInt(name));
|
||||
else if(List.class.equals(type))
|
||||
return (T) configuration.getList(name);
|
||||
else if(Long.class.equals(type) || long.class.equals(type))
|
||||
return (T) Long.valueOf(configuration.getLong(name));
|
||||
else if(Short.class.equals(type) || short.class.equals(type))
|
||||
return (T) Short.valueOf(configuration.getShort(name));
|
||||
else
|
||||
{
|
||||
// If none of the above works, try to convert the value to the required type
|
||||
SimpleTypeConverter converter = new SimpleTypeConverter();
|
||||
return (T) converter.convertIfNecessary(configuration.getProperty(name), type);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -34,15 +34,19 @@ public final class DSpaceBeanPostProcessor implements BeanPostProcessor, Destruc
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessBeforeInitialization(java.lang.Object, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object postProcessBeforeInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
DSpaceServiceManager.configureService(beanName, bean, configurationService.getServiceNameConfigs());
|
||||
// Before initializing the service, first configure it based on any related settings in the configurationService
|
||||
// NOTE: configs related to this bean MUST be prefixed with the bean's name (e.g. [beanName].setting = value)
|
||||
DSpaceServiceManager.configureService(beanName, bean, configurationService);
|
||||
return bean;
|
||||
}
|
||||
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.config.BeanPostProcessor#postProcessAfterInitialization(java.lang.Object, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public Object postProcessAfterInitialization(Object bean, String beanName)
|
||||
throws BeansException {
|
||||
DSpaceServiceManager.initService(bean);
|
||||
@@ -52,6 +56,7 @@ public final class DSpaceBeanPostProcessor implements BeanPostProcessor, Destruc
|
||||
/* (non-Javadoc)
|
||||
* @see org.springframework.beans.factory.config.DestructionAwareBeanPostProcessor#postProcessBeforeDestruction(java.lang.Object, java.lang.String)
|
||||
*/
|
||||
@Override
|
||||
public void postProcessBeforeDestruction(Object bean, String beanName) throws BeansException {
|
||||
DSpaceServiceManager.shutdownService(bean);
|
||||
}
|
||||
|
@@ -319,7 +319,7 @@ public final class SpringServiceManager implements ServiceManagerSystem {
|
||||
return services;
|
||||
}
|
||||
|
||||
public void pushConfig(Map<String, String> settings) {
|
||||
public void pushConfig(Map<String, Object> settings) {
|
||||
throw new UnsupportedOperationException("Not implemented for individual service manager systems");
|
||||
}
|
||||
|
||||
|
@@ -7,8 +7,9 @@
|
||||
*/
|
||||
package org.dspace.services;
|
||||
|
||||
import java.util.Map;
|
||||
import java.util.List;
|
||||
import java.util.Properties;
|
||||
import org.apache.commons.configuration.Configuration;
|
||||
|
||||
|
||||
/**
|
||||
@@ -90,29 +91,57 @@ public interface ConfigurationService {
|
||||
public <T> T getPropertyAsType(String name, T defaultValue, boolean setDefaultIfNotFound);
|
||||
|
||||
/**
|
||||
* Get all currently known configuration settings
|
||||
* Get keys all currently known configuration settings
|
||||
*
|
||||
* @return all the configuration properties as a map of name -> value
|
||||
* @return all the configuration keys as a List
|
||||
*/
|
||||
public Map<String, String> getAllProperties();
|
||||
public List<String> getPropertyKeys();
|
||||
|
||||
/**
|
||||
* Get keys all currently known configuration settings, which
|
||||
* begin with a given prefix.
|
||||
* <P>
|
||||
* For example, passing in "db" would return the keys "db.url", "db.username", etc.
|
||||
*
|
||||
* @param prefix prefix of key
|
||||
* @return all the configuration keys as a List
|
||||
*/
|
||||
public List<String> getPropertyKeys(String prefix);
|
||||
|
||||
/**
|
||||
* Convenience method - get a configuration property (setting) from
|
||||
* the system.
|
||||
* the system as a String.
|
||||
*
|
||||
* @param name the property name
|
||||
* @return the property value OR null if none is found
|
||||
*/
|
||||
public String getProperty(String name);
|
||||
|
||||
/**
|
||||
* Convenience method - get a configuration property (setting) from
|
||||
* the system as its stored object
|
||||
*
|
||||
* @param name the property name
|
||||
* @return the property value OR null if none is found
|
||||
*/
|
||||
public Object getPropertyValue(String name);
|
||||
|
||||
/**
|
||||
* Convenience method - get all configuration properties (settings)
|
||||
* from the system.
|
||||
*
|
||||
*
|
||||
* @return all the configuration properties in a properties object (name -> value)
|
||||
*/
|
||||
public Properties getProperties();
|
||||
|
||||
/**
|
||||
* Convenience method - get entire configuration (settings)
|
||||
* from the system.
|
||||
*
|
||||
* @return Configuration object representing the system configuration
|
||||
*/
|
||||
public Configuration getConfiguration();
|
||||
|
||||
/**
|
||||
* Set a configuration property (setting) in the system.
|
||||
* Type is not important here since conversion happens automatically
|
||||
@@ -126,4 +155,11 @@ public interface ConfigurationService {
|
||||
*/
|
||||
public boolean setProperty(String name, Object value);
|
||||
|
||||
/**
|
||||
* Reload the configuration from the DSpace configuration files.
|
||||
* <P>
|
||||
* Uses the initialized ConfigurationService to reload all configurations.
|
||||
*/
|
||||
public void reloadConfig();
|
||||
|
||||
}
|
||||
|
@@ -141,11 +141,12 @@ public final class CachingServiceImpl implements CachingService, InitializedServ
|
||||
* Reloads the config settings from the configuration service.
|
||||
*/
|
||||
protected void reloadConfig() {
|
||||
useClustering = configurationService.getPropertyAsType(knownConfigNames[0], boolean.class);
|
||||
useDiskStore = configurationService.getPropertyAsType(knownConfigNames[1], boolean.class);
|
||||
maxElementsInMemory = configurationService.getPropertyAsType(knownConfigNames[2], int.class);
|
||||
timeToLiveSecs = configurationService.getPropertyAsType(knownConfigNames[3], int.class);
|
||||
timeToIdleSecs = configurationService.getPropertyAsType(knownConfigNames[4], int.class);
|
||||
// Reload caching configurations, but have sane default values if unspecified in configs
|
||||
useClustering = configurationService.getPropertyAsType(knownConfigNames[0], false);
|
||||
useDiskStore = configurationService.getPropertyAsType(knownConfigNames[1], true);
|
||||
maxElementsInMemory = configurationService.getPropertyAsType(knownConfigNames[2], 2000);
|
||||
timeToLiveSecs = configurationService.getPropertyAsType(knownConfigNames[3], 3600);
|
||||
timeToIdleSecs = configurationService.getPropertyAsType(knownConfigNames[4], 600);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -18,10 +18,6 @@
|
||||
default-autowire-candidates="*Service,*DAO,javax.sql.DataSource">
|
||||
|
||||
<context:annotation-config /> <!-- allows us to use spring annotations in beans -->
|
||||
<!-- NOTE: I am not convinced this is a good idea, it is really slow and I think possibly dangerous -AZ -->
|
||||
<!--
|
||||
<context:component-scan base-package="org.dspace" name-generator="org.dspace.servicemanager.spring.FullPathBeanNameGenerator" />
|
||||
-->
|
||||
|
||||
<!-- the bean processor interceptor -->
|
||||
<bean class="org.dspace.servicemanager.spring.DSpaceBeanPostProcessor" />
|
||||
|
@@ -38,8 +38,10 @@ public class DSpaceServiceManagerTest {
|
||||
@Before
|
||||
public void init() {
|
||||
configurationService = new DSpaceConfigurationService();
|
||||
configurationService.loadConfig("testName@" + SampleAnnotationBean.class.getName(), "beckyz");
|
||||
configurationService.loadConfig("fakeParam@fakeBean", "beckyz");
|
||||
|
||||
// Set some sample configurations relating to services/beans
|
||||
configurationService.loadConfig(SampleAnnotationBean.class.getName() + ".sampleValue", "beckyz");
|
||||
configurationService.loadConfig("fakeBean.fakeParam", "beckyz");
|
||||
|
||||
dsm = new DSpaceServiceManager(configurationService, TestSpringServiceManager.SPRING_TEST_CONFIG_FILE);
|
||||
}
|
||||
@@ -168,8 +170,11 @@ public class DSpaceServiceManagerTest {
|
||||
assertEquals("azeckoski", concrete.getName());
|
||||
concrete = null;
|
||||
|
||||
// initialize a SampleAnnotationBean
|
||||
SampleAnnotationBean sab = dsm.getServiceByName(SampleAnnotationBean.class.getName(), SampleAnnotationBean.class);
|
||||
assertNotNull(sab);
|
||||
// Based on the configuration for "sampleValue" in the init() method above,
|
||||
// a value should be pre-set!
|
||||
assertEquals("beckyz", sab.getSampleValue());
|
||||
sab = null;
|
||||
}
|
||||
@@ -193,11 +198,6 @@ public class DSpaceServiceManagerTest {
|
||||
assertNotNull(l2);
|
||||
assertTrue(l2.size() >= 1);
|
||||
l2 = null;
|
||||
|
||||
List<ServiceConfig> l3 = dsm.getServicesByType(ServiceConfig.class);
|
||||
assertNotNull(l3);
|
||||
assertEquals(0, l3.size());
|
||||
l3 = null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -248,7 +248,7 @@ public class DSpaceServiceManagerTest {
|
||||
public void testPushConfig() {
|
||||
dsm.startup();
|
||||
|
||||
Map<String, String> properties = new HashMap<String, String>();
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
properties.put("some.test.thing", "A value");
|
||||
dsm.pushConfig(properties);
|
||||
|
||||
@@ -289,7 +289,7 @@ public class DSpaceServiceManagerTest {
|
||||
assertEquals(1, service.getTriggers());
|
||||
|
||||
// now we do a config change
|
||||
Map<String, String> properties = new HashMap<String, String>();
|
||||
Map<String, Object> properties = new HashMap<String, Object>();
|
||||
properties.put("azeckoski.FakeService1.something", "THING");
|
||||
dsm.pushConfig(properties);
|
||||
assertEquals("config:THING", service.getSomething());
|
||||
|
@@ -83,7 +83,7 @@ public class MockServiceManagerSystem implements ServiceManagerSystem {
|
||||
/* (non-Javadoc)
|
||||
* @see org.dspace.kernel.ServiceManager#pushConfig(java.util.Map)
|
||||
*/
|
||||
public void pushConfig(Map<String, String> settings) {
|
||||
public void pushConfig(Map<String, Object> settings) {
|
||||
this.sms.pushConfig(settings);
|
||||
}
|
||||
|
||||
|
@@ -58,7 +58,7 @@ public class SampleAnnotationBean implements InitializedService, ShutdownService
|
||||
}
|
||||
|
||||
private String value = null;
|
||||
public void setTestName(String value) {
|
||||
public void setSampleValue(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
|
@@ -9,9 +9,7 @@ package org.dspace.servicemanager.config;
|
||||
|
||||
import static org.junit.Assert.*;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Properties;
|
||||
|
||||
@@ -31,19 +29,26 @@ public class DSpaceConfigurationServiceTest {
|
||||
|
||||
@Before
|
||||
public void init() {
|
||||
// Give a default setting to DSPACE_HOME
|
||||
System.setProperty(DSpaceConfigurationService.DSPACE_HOME, "src/test/resources");
|
||||
|
||||
configurationService = new DSpaceConfigurationService();
|
||||
|
||||
List<DSpaceConfig> l = new ArrayList<DSpaceConfig>();
|
||||
l.add( new DSpaceConfig("service.name", "DSpace") );
|
||||
l.add( new DSpaceConfig("sample.array", "itemA,itemB,itemC") );
|
||||
l.add( new DSpaceConfig("sample.number", "123") );
|
||||
l.add( new DSpaceConfig("sample.boolean", "true") );
|
||||
l.add( new DSpaceConfig("aaronz", "Aaron Zeckoski") );
|
||||
l.add( new DSpaceConfig("current.user", "${aaronz}") );
|
||||
l.add( new DSpaceConfig("test.key1", "This is a value") );
|
||||
l.add( new DSpaceConfig("test.key2", "This is key1=${test.key1}") );
|
||||
// clear out default configs
|
||||
configurationService.clear();
|
||||
|
||||
configurationService.loadConfiguration(l, true);
|
||||
// Start fresh with out own set of 8 configs
|
||||
Map<String,Object> l = new HashMap<String,Object>();
|
||||
l.put("service.name", "DSpace");
|
||||
l.put("sample.array", "itemA,itemB,itemC");
|
||||
l.put("sample.number", "123");
|
||||
l.put("sample.boolean", "true");
|
||||
l.put("aaronz", "Aaron Zeckoski");
|
||||
l.put("current.user", "${aaronz}");
|
||||
l.put("test.key1", "This is a value");
|
||||
l.put("test.key2", "This is key1=${test.key1}");
|
||||
|
||||
configurationService.loadConfiguration(l);
|
||||
l = null;
|
||||
}
|
||||
|
||||
@@ -53,60 +58,51 @@ public class DSpaceConfigurationServiceTest {
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.dspace.servicemanager.config.DSpaceConfigurationService#replaceVariables(java.util.Map)}.
|
||||
* A generic method to test that variable replacement is happening properly.
|
||||
*/
|
||||
@Test(timeout=10000)
|
||||
public void testReplaceVariables() {
|
||||
public void testVariableReplacement() {
|
||||
|
||||
List<DSpaceConfig> l = new ArrayList<DSpaceConfig>();
|
||||
l.add( new DSpaceConfig("service.name", "DSpace") );
|
||||
l.add( new DSpaceConfig("aaronz", "Aaron Zeckoski") );
|
||||
l.add( new DSpaceConfig("current.user", "${aaronz}") );
|
||||
l.add( new DSpaceConfig("test.key1", "This is a value") );
|
||||
l.add( new DSpaceConfig("test.key2", "This is key1=${test.key1}") );
|
||||
l.add( new DSpaceConfig("test.key3", "This is key2=${test.key2}") );
|
||||
int dirIdx = l.size();
|
||||
l.add( new DSpaceConfig("circular", "${circular}"));
|
||||
int indirIdx = l.size();
|
||||
l.add( new DSpaceConfig("indirect.circular", "${circular} square"));
|
||||
Map<String,Object> l = new HashMap<String,Object>();
|
||||
l.put("service.name", "DSpace");
|
||||
l.put("aaronz", "Aaron Zeckoski");
|
||||
l.put("current.user", "${aaronz}");
|
||||
l.put("test.key1", "This is a value");
|
||||
l.put("test.key2", "This is key1=${test.key1}");
|
||||
l.put("test.key3", "This is key2=${test.key2}");
|
||||
|
||||
Map<String, DSpaceConfig> configMap = new HashMap<String, DSpaceConfig>();
|
||||
for (DSpaceConfig config : l) {
|
||||
configMap.put(config.getKey(), config);
|
||||
}
|
||||
configurationService.replaceVariables(configMap);
|
||||
configurationService.loadConfiguration(l);
|
||||
|
||||
assertEquals("DSpace", configurationService.getProperty("service.name"));
|
||||
assertEquals("Aaron Zeckoski", configurationService.getProperty("aaronz"));
|
||||
assertEquals("Aaron Zeckoski", configurationService.getProperty("current.user"));
|
||||
assertEquals("This is a value", configurationService.getProperty("test.key1"));
|
||||
assertEquals("This is key1=This is a value", configurationService.getProperty("test.key2"));
|
||||
assertEquals("This is key2=This is key1=This is a value", configurationService.getProperty("test.key3"));
|
||||
|
||||
assertEquals("all configuration list members should be map members",
|
||||
l.size(), configMap.size());
|
||||
assertEquals("DSpace", configMap.get("service.name").getValue());
|
||||
assertEquals("Aaron Zeckoski", configMap.get("aaronz").getValue());
|
||||
assertEquals("Aaron Zeckoski", configMap.get("current.user").getValue());
|
||||
assertEquals("This is a value", configMap.get("test.key1").getValue());
|
||||
assertEquals("This is key1=This is a value", configMap.get("test.key2").getValue());
|
||||
assertEquals("This is key2=This is key1=This is a value", configMap.get("test.key3").getValue());
|
||||
assertEquals("Direct circular reference should not be replaced",
|
||||
configMap.get("circular").getValue(), l.get(dirIdx).getValue());
|
||||
assertEquals("Indirect circular reference should not be replaced",
|
||||
configMap.get("indirect.circular").getValue(), l.get(indirIdx).getValue());
|
||||
|
||||
//trash the references
|
||||
l = null;
|
||||
configMap = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Test method for {@link org.dspace.servicemanager.config.DSpaceConfigurationService#getAllProperties()}.
|
||||
*/
|
||||
@Test
|
||||
public void testGetAllProperties() {
|
||||
Map<String, String> props = configurationService.getAllProperties();
|
||||
assertNotNull(props);
|
||||
assertEquals(8, props.size());
|
||||
assertNotNull(props.get("service.name"));
|
||||
assertEquals("DSpace", props.get("service.name"));
|
||||
|
||||
//trash the references
|
||||
props = null;
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testVariableReplacementCircular()
|
||||
{
|
||||
// add a circular reference
|
||||
configurationService.loadConfig("circular", "${circular}");
|
||||
|
||||
// try to get the value (should throw an error)
|
||||
configurationService.getProperty("circular");
|
||||
}
|
||||
|
||||
@Test(expected=IllegalStateException.class)
|
||||
public void testVariableReplacementIndirectCircular()
|
||||
{
|
||||
// add a circular reference
|
||||
configurationService.loadConfig("circular", "${circular}");
|
||||
// add an indirect reference to that circular reference
|
||||
configurationService.loadConfig("indirect.circular", "$indirect ${circular}");
|
||||
|
||||
// try to get the value (should throw an error)
|
||||
configurationService.getProperty("indirect.circular");
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -155,9 +151,19 @@ public class DSpaceConfigurationServiceTest {
|
||||
Integer number = configurationService.getPropertyAsType("sample.number", Integer.class);
|
||||
assertNotNull(number);
|
||||
assertEquals(new Integer(123), number);
|
||||
|
||||
Boolean bool = configurationService.getPropertyAsType("sample.boolean", Boolean.class);
|
||||
assertNotNull(bool);
|
||||
assertEquals(Boolean.TRUE, bool);
|
||||
|
||||
Boolean bool2 = configurationService.getPropertyAsType("INVALID.PROPERTY", Boolean.class);
|
||||
assertNotNull(bool2);
|
||||
assertEquals(Boolean.FALSE, bool2);
|
||||
|
||||
boolean bool3 = configurationService.getPropertyAsType("INVALID.PROPERTY", boolean.class);
|
||||
assertNotNull(bool3);
|
||||
assertEquals(false, bool3);
|
||||
|
||||
assertEquals(123, (int) configurationService.getPropertyAsType("sample.number", int.class) );
|
||||
assertEquals(true, (boolean) configurationService.getPropertyAsType("sample.boolean", boolean.class) );
|
||||
|
||||
@@ -199,21 +205,21 @@ public class DSpaceConfigurationServiceTest {
|
||||
|
||||
@Test
|
||||
public void testGetPropertyAsTypeStringTBoolean() {
|
||||
String prop = configurationService.getProperty("service.fake.thing");
|
||||
Object prop = configurationService.getPropertyValue("service.fake.thing");
|
||||
assertNull(prop);
|
||||
|
||||
prop = configurationService.getPropertyAsType("service.fake.thing", "Fakey", false);
|
||||
assertNotNull(prop);
|
||||
assertEquals("Fakey", prop);
|
||||
|
||||
prop = configurationService.getProperty("service.fake.thing");
|
||||
prop = configurationService.getPropertyValue("service.fake.thing");
|
||||
assertNull(prop);
|
||||
|
||||
prop = configurationService.getPropertyAsType("service.fake.thing", "Fakey", true);
|
||||
assertNotNull(prop);
|
||||
assertEquals("Fakey", prop);
|
||||
|
||||
prop = configurationService.getProperty("service.fake.thing");
|
||||
prop = configurationService.getPropertyValue("service.fake.thing");
|
||||
assertNotNull(prop);
|
||||
assertEquals("Fakey", prop);
|
||||
prop = null;
|
||||
@@ -221,25 +227,25 @@ public class DSpaceConfigurationServiceTest {
|
||||
|
||||
@Test
|
||||
public void testSetProperty() {
|
||||
String prop = configurationService.getProperty("newOne");
|
||||
Object prop = configurationService.getPropertyValue("newOne");
|
||||
assertNull(prop);
|
||||
|
||||
boolean changed = configurationService.setProperty("newOne", "1111111");
|
||||
assertTrue(changed);
|
||||
|
||||
prop = configurationService.getProperty("newOne");
|
||||
prop = configurationService.getPropertyValue("newOne");
|
||||
assertNotNull(prop);
|
||||
assertEquals("1111111", prop);
|
||||
|
||||
prop = configurationService.getProperty("newBool");
|
||||
prop = configurationService.getPropertyValue("newBool");
|
||||
assertNull(prop);
|
||||
|
||||
changed = configurationService.setProperty("newBool", true);
|
||||
assertTrue(changed);
|
||||
|
||||
prop = configurationService.getProperty("newBool");
|
||||
prop = configurationService.getPropertyValue("newBool");
|
||||
assertNotNull(prop);
|
||||
assertEquals("true", prop);
|
||||
assertEquals(Boolean.TRUE, prop);
|
||||
|
||||
changed = configurationService.setProperty("newBool", true);
|
||||
assertFalse(changed);
|
||||
@@ -247,7 +253,7 @@ public class DSpaceConfigurationServiceTest {
|
||||
changed = configurationService.setProperty("newBool", null);
|
||||
assertTrue(changed);
|
||||
|
||||
prop = configurationService.getProperty("newBool");
|
||||
prop = configurationService.getPropertyValue("newBool");
|
||||
assertNull(prop);
|
||||
prop = null;
|
||||
}
|
||||
@@ -258,7 +264,7 @@ public class DSpaceConfigurationServiceTest {
|
||||
@Test
|
||||
public void testGetConfiguration() {
|
||||
assertNotNull( configurationService.getConfiguration() );
|
||||
assertEquals(8, configurationService.getConfiguration().size() );
|
||||
assertEquals(8, configurationService.getProperties().size() );
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -266,16 +272,16 @@ public class DSpaceConfigurationServiceTest {
|
||||
*/
|
||||
@Test
|
||||
public void testLoadConfig() {
|
||||
assertEquals(8, configurationService.getConfiguration().size());
|
||||
assertEquals(8, configurationService.getProperties().size());
|
||||
configurationService.loadConfig("newA", "A");
|
||||
assertEquals(9, configurationService.getConfiguration().size());
|
||||
assertEquals(9, configurationService.getProperties().size());
|
||||
assertEquals("A", configurationService.getProperty("newA"));
|
||||
configurationService.loadConfig("newB", "service is ${service.name}");
|
||||
assertEquals(10, configurationService.getConfiguration().size());
|
||||
assertEquals(10, configurationService.getProperties().size());
|
||||
assertEquals("service is DSpace", configurationService.getProperty("newB"));
|
||||
|
||||
configurationService.loadConfig("newA", "aaronz");
|
||||
assertEquals(10, configurationService.getConfiguration().size());
|
||||
assertEquals(10, configurationService.getProperties().size());
|
||||
assertEquals("aaronz", configurationService.getProperty("newA"));
|
||||
|
||||
}
|
||||
@@ -286,24 +292,77 @@ public class DSpaceConfigurationServiceTest {
|
||||
@Test
|
||||
public void testClear() {
|
||||
configurationService.clear();
|
||||
assertEquals(0, configurationService.getAllProperties().size());
|
||||
assertEquals(0, configurationService.getProperties().size());
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the ability of the system to properly extract system properties into the configuration
|
||||
* Test method for {@link org.dspace.servicemanager.config.DSpaceConfigurationService#reloadConfig()}.
|
||||
*/
|
||||
@Test
|
||||
public void testReloadConfig() {
|
||||
// Initialize new config service
|
||||
DSpaceConfigurationService dscs = new DSpaceConfigurationService();
|
||||
int size = dscs.getProperties().size();
|
||||
|
||||
// Add two new Sytem properties
|
||||
System.setProperty("Hello","World");
|
||||
System.setProperty("Tim", "Donohue");
|
||||
|
||||
// Assert the new properties are not yet loaded
|
||||
assertEquals(size, dscs.getProperties().size());
|
||||
|
||||
dscs.reloadConfig();
|
||||
|
||||
// Assert the new properties now exist
|
||||
assertEquals(size + 2, dscs.getProperties().size());
|
||||
|
||||
// Set a new value
|
||||
System.setProperty("Hello", "There");
|
||||
|
||||
// Assert old value still in Configuration
|
||||
assertEquals("World", dscs.getProperty("Hello"));
|
||||
|
||||
dscs.reloadConfig();
|
||||
|
||||
// Now, should be new value
|
||||
assertEquals("There", dscs.getProperty("Hello"));
|
||||
|
||||
// Clear set properties
|
||||
System.clearProperty("Hello");
|
||||
System.clearProperty("Tim");
|
||||
|
||||
// Assert value not yet cleared from Configuration
|
||||
assertEquals("There", dscs.getProperty("Hello"));
|
||||
|
||||
dscs.reloadConfig();
|
||||
|
||||
// Now, should be null
|
||||
assertNull(dscs.getProperty("Hello"));
|
||||
|
||||
dscs.clear();
|
||||
dscs = null;
|
||||
}
|
||||
|
||||
/**
|
||||
* Tests the ability of the system to properly extract system properties into the configuration.
|
||||
* (NOTE: This ability to load system properties is specified in the test "config-definition.xml")
|
||||
*/
|
||||
@Test
|
||||
public void testGetPropertiesFromSystem() {
|
||||
DSpaceConfigurationService dscs = new DSpaceConfigurationService();
|
||||
int size = dscs.getConfiguration().size();
|
||||
int size = dscs.getProperties().size();
|
||||
|
||||
System.setProperty("dspace.az.system.config", "Hello");
|
||||
System.setProperty("not.dspace", "Adios");
|
||||
System.setProperty("dspace.system.config", "Hello");
|
||||
System.setProperty("another.property", "Adios");
|
||||
|
||||
dscs = new DSpaceConfigurationService();
|
||||
assertEquals(size + 1, dscs.getConfiguration().size());
|
||||
assertEquals("Hello", dscs.getProperty("az.system.config"));
|
||||
dscs.reloadConfig();
|
||||
|
||||
assertEquals(size + 2, dscs.getProperties().size());
|
||||
assertEquals("Hello", dscs.getProperty("dspace.system.config"));
|
||||
assertEquals("Adios", dscs.getProperty("another.property"));
|
||||
|
||||
System.clearProperty("dspace.system.config");
|
||||
System.clearProperty("another.property");
|
||||
dscs.clear();
|
||||
dscs = null;
|
||||
}
|
||||
|
@@ -17,10 +17,8 @@ import java.util.List;
|
||||
|
||||
import org.dspace.servicemanager.MockServiceManagerSystem;
|
||||
import org.dspace.servicemanager.SampleAnnotationBean;
|
||||
import org.dspace.servicemanager.ServiceConfig;
|
||||
import org.dspace.servicemanager.config.DSpaceConfigurationService;
|
||||
import org.dspace.servicemanager.example.ConcreteExample;
|
||||
import org.dspace.services.ConfigurationService;
|
||||
import org.junit.After;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
@@ -41,8 +39,8 @@ public class TestSpringServiceManager {
|
||||
@Before
|
||||
public void init() {
|
||||
configurationService = new DSpaceConfigurationService();
|
||||
configurationService.loadConfig("testName@" + SampleAnnotationBean.class.getName(), "beckyz");
|
||||
configurationService.loadConfig("fakeParam@fakeBean", "beckyz");
|
||||
configurationService.loadConfig(SampleAnnotationBean.class.getName() + ".sampleValue", "beckyz");
|
||||
configurationService.loadConfig("fakeBean.fakeParam", "beckyz");
|
||||
|
||||
ssm = new SpringServiceManager(new MockServiceManagerSystem(ssm), configurationService, true, true, SPRING_TEST_CONFIG_FILE);
|
||||
}
|
||||
@@ -139,11 +137,6 @@ public class TestSpringServiceManager {
|
||||
assertNotNull(l2);
|
||||
assertEquals(1, l2.size());
|
||||
l2 = null;
|
||||
|
||||
List<ServiceConfig> l3 = ssm.getServicesByType(ServiceConfig.class);
|
||||
assertNotNull(l3);
|
||||
assertEquals(0, l3.size());
|
||||
l3 = null;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@@ -69,7 +69,7 @@ public class ProviderStackTest {
|
||||
public boolean isServiceExists(String name) {
|
||||
return false;
|
||||
}
|
||||
public void pushConfig(Map<String, String> settings) {
|
||||
public void pushConfig(Map<String, Object> settings) {
|
||||
}
|
||||
public void registerService(String name, Object service) {
|
||||
}
|
||||
|
@@ -0,0 +1,33 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!--
|
||||
|
||||
The contents of this file are subject to the license and copyright
|
||||
detailed in the LICENSE and NOTICE files at the root of the source
|
||||
tree and available online at
|
||||
|
||||
http://www.dspace.org/license/
|
||||
|
||||
-->
|
||||
<!--
|
||||
Test Configuration Definition
|
||||
This file defines the ordering of configuration files loaded by the ConfigurationService
|
||||
|
||||
For more information and examples of valid configuration definition files, see:
|
||||
http://commons.apache.org/proper/commons-configuration/userguide_v1.10/howto_configurationbuilder.html
|
||||
-->
|
||||
<configuration>
|
||||
<!-- Configurations in this section override one another.
|
||||
Earlier values take precedence, and override any values in later config files -->
|
||||
<override>
|
||||
<!-- NOTE: Optionally, you could just use Variable Interpolation instead
|
||||
of directly loading these System/Env properties:
|
||||
http://commons.apache.org/proper/commons-configuration/userguide_v1.10/howto_basicfeatures.html#Variable_Interpolation -->
|
||||
<!-- Load System properties -->
|
||||
<system/>
|
||||
<!-- Load Environment variables -->
|
||||
<env/>
|
||||
|
||||
<!-- Load test local.properties (for unit testing)-->
|
||||
<properties fileName="local.properties" throwExceptionOnMissing="true"/>
|
||||
</override>
|
||||
</configuration>
|
37
dspace/config/config-definition.xml
Normal file
37
dspace/config/config-definition.xml
Normal file
@@ -0,0 +1,37 @@
|
||||
<?xml version="1.0"?>
|
||||
<!--
|
||||
DSpace Configuration Definition
|
||||
This file defines the ordering of configuration files loaded by DSpace.
|
||||
|
||||
For more information and examples of valid configuration definition files, see:
|
||||
http://commons.apache.org/proper/commons-configuration/userguide_v1.10/howto_configurationbuilder.html
|
||||
-->
|
||||
<configuration>
|
||||
<header>
|
||||
<!-- Necessary for CombinedConfiguration to detect & reload individual config files.
|
||||
See JavaDocs for org.apache.commons.configuration.CombinedConfiguration setForceReloadCheck() method -->
|
||||
<result forceReloadCheck="true"/>
|
||||
</header>
|
||||
<!-- Configurations in this section override one another.
|
||||
Earlier values take precedence, and override any values in later config files -->
|
||||
<override>
|
||||
<!-- NOTE: Optionally, you could just use Variable Interpolation instead
|
||||
of directly loading these System/Env properties:
|
||||
http://commons.apache.org/proper/commons-configuration/userguide_v1.10/howto_basicfeatures.html#Variable_Interpolation -->
|
||||
<!-- Load System properties -->
|
||||
<system/>
|
||||
<!-- Load Environment variables -->
|
||||
<env/>
|
||||
|
||||
<!-- Load our dspace.cfg-->
|
||||
<properties fileName="dspace.cfg" throwExceptionOnMissing="true">
|
||||
<!-- Reload this file if it has changed, and at least 1 minute (60,000 ms) has passed -->
|
||||
<reloadingStrategy refreshDelay="60000"
|
||||
config-class="org.apache.commons.configuration.reloading.FileChangedReloadingStrategy"/>
|
||||
</properties>
|
||||
|
||||
<!-- Load dspace-defaults.cfg (defines default settings for dspace-services) -->
|
||||
<properties fileName="dspace-defaults.cfg" config-optional="true"/>
|
||||
</override>
|
||||
|
||||
</configuration>
|
11
pom.xml
11
pom.xml
@@ -1007,6 +1007,12 @@
|
||||
<artifactId>dspace-tm-extractors</artifactId>
|
||||
<version>1.0.1</version>
|
||||
</dependency>
|
||||
<!-- Required by Commons Configuration -->
|
||||
<dependency>
|
||||
<groupId>commons-beanutils</groupId>
|
||||
<artifactId>commons-beanutils</artifactId>
|
||||
<version>1.9.2</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-cli</groupId>
|
||||
<artifactId>commons-cli</artifactId>
|
||||
@@ -1023,6 +1029,11 @@
|
||||
<version>3.2</version>
|
||||
<!-- <version>3.1</version> xmlui - wing -->
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>commons-configuration</groupId>
|
||||
<artifactId>commons-configuration</artifactId>
|
||||
<version>1.10</version>
|
||||
</dependency>
|
||||
<dependency>
|
||||
<groupId>org.apache.commons</groupId>
|
||||
<artifactId>commons-dbcp2</artifactId>
|
||||
|
Reference in New Issue
Block a user