[DS-726] Add modular configuration

git-svn-id: http://scm.dspace.org/svn/repo/dspace/trunk@5665 9c30dcfa-912a-0410-8fc2-9e0234be79fd
This commit is contained in:
Richard Rodgers
2010-10-26 21:59:50 +00:00
parent cb80f0cad4
commit 1b1cc00a34
2 changed files with 455 additions and 114 deletions

View File

@@ -50,6 +50,8 @@ import java.io.PrintWriter;
import java.net.MalformedURLException; import java.net.MalformedURLException;
import java.net.URL; import java.net.URL;
import java.util.Enumeration; import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties; import java.util.Properties;
import org.apache.log4j.Category; import org.apache.log4j.Category;
@@ -85,6 +87,9 @@ public class ConfigurationManager
/** The configuration properties */ /** The configuration properties */
private static Properties properties = null; private static Properties properties = null;
/** module configuration properties */
private static Map<String, Properties> moduleProps = null;
/** The default license */ /** The default license */
private static String license; private static String license;
@@ -102,16 +107,50 @@ public class ConfigurationManager
} }
/** /**
* Discard all current properties - will force a reload from disk when
* any properties are requested.
*/
public static void flush()
{
properties = null;
}
/**
* Discard properties for a module - will force a reload from disk
* when any of module's properties are requested
* *
* @param module the module name
*/
public static void flush(String module)
{
moduleProps.remove(module);
}
/**
* Returns all properties in main configuration
*
* @return properties - all non-modular properties
*/ */
public static Properties getProperties() public static Properties getProperties()
{
return getProperties(null);
}
/**
* Returns all properties for a given module
*
* @param module
* the name of the module
* @return properties - all module's properties
*/
public static Properties getProperties(String module)
{ {
if (properties == null) if (properties == null)
{ {
loadConfig(null); loadConfig(null);
} }
Properties retProps =
return (Properties)properties.clone(); (module != null) ? moduleProps.get(module) : properties;
return (Properties)retProps.clone();
} }
/** /**
@@ -124,18 +163,83 @@ public class ConfigurationManager
* does not exist. * does not exist.
*/ */
public static String getProperty(String property) public static String getProperty(String property)
{
return getProperty(null, property);
}
/**
* Get a module configuration property value.
*
* @param module
* the name of the module, or <code>null</code> for regular configuration
* property
* @param property
* the name (key) of the property
* @return
* the value of the property, or <code>null</code> if the
* property does not exist
*/
public static String getProperty(String module, String property)
{ {
if (properties == null) if (properties == null)
{ {
loadConfig(null); loadConfig(null);
} }
String propertyValue = properties.getProperty(property); String value = null;
if (module == null)
if (propertyValue != null)
{ {
propertyValue = propertyValue.trim(); value = properties.getProperty(property);
} }
return propertyValue; else
{
Properties modProps = moduleProps.get(module);
if (modProps != null)
{
value = modProps.getProperty(property);
}
else
{
// look in regular properties with module name prepended
value = properties.getProperty(module + "." + property);
if (value == null) {
// try to find it in modules
File modFile = null;
try
{
modFile = new File(getProperty("dspace.dir") +
File.separator + "config" +
File.separator + "modules" +
File.separator + module + ".cfg");
if (modFile.exists())
{
modProps = new Properties();
modProps.load(new FileInputStream(modFile));
for (Enumeration pe = modProps.propertyNames(); pe.hasMoreElements(); )
{
String key = (String)pe.nextElement();
String ival = interpolate(key, modProps.getProperty(key), 1);
if (ival != null)
modProps.setProperty(key, ival);
}
moduleProps.put(module, modProps);
value = modProps.getProperty(property);
}
else
{
// log invalid request
warn("Requested configuration module: " + module + " not found");
}
}
catch (IOException ioE)
{
fatal("Can't load configuration: " + modFile.getAbsolutePath(), ioE);
}
}
}
}
return (value != null) ? value.trim() : null;
} }
/** /**
@@ -153,6 +257,24 @@ public class ConfigurationManager
return getIntProperty(property, 0); return getIntProperty(property, 0);
} }
/**
* Get a module configuration property as an integer
*
* @param module
* the name of the module
*
* @param property
* the name of the property
*
* @return the value of the property. <code>0</code> is returned if the
* property does not exist. To differentiate between this case and
* when the property actually is zero, use <code>getProperty</code>.
*/
public static int getIntProperty(String module, String property)
{
return getIntProperty(module, property, 0);
}
/** /**
* Get a configuration property as an integer, with default * Get a configuration property as an integer, with default
* *
@@ -168,13 +290,35 @@ public class ConfigurationManager
* <code>getProperty</code>. * <code>getProperty</code>.
*/ */
public static int getIntProperty(String property, int defaultValue) public static int getIntProperty(String property, int defaultValue)
{
return getIntProperty(null, property, defaultValue);
}
/**
* Get a module configuration property as an integer, with default
*
* @param module
* the name of the module
*
* @param property
* the name of the property
*
* @param defaultValue
* value to return if property is not found or is not an Integer.
*
* @return the value of the property. <code>default</code> is returned if
* the property does not exist or is not an Integer. To differentiate between this case
* and when the property actually is false, use
* <code>getProperty</code>.
*/
public static int getIntProperty(String module, String property, int defaultValue)
{ {
if (properties == null) if (properties == null)
{ {
loadConfig(null); loadConfig(null);
} }
String stringValue = properties.getProperty(property); String stringValue = getProperty(module, property);
int intValue = defaultValue; int intValue = defaultValue;
if (stringValue != null) if (stringValue != null)
@@ -192,33 +336,6 @@ public class ConfigurationManager
return intValue; return intValue;
} }
/**
* Get a configuration property and specify the fallback default
*
* @param property
* the name of the property
*
* @param defaultValue
* the default value of the property
*
* @return the value of the property or the default value if the property
* does not exist.
*/
public static String getProperty(String property, String defaultValue)
{
if (properties == null) {
loadConfig(null);
}
String propertyValue = properties.getProperty(property);
if (propertyValue != null) {
propertyValue = propertyValue.trim();
} else {
propertyValue = defaultValue;
}
return propertyValue;
}
/** /**
* Get a configuration property as a long * Get a configuration property as a long
* *
@@ -234,9 +351,27 @@ public class ConfigurationManager
return getLongProperty(property, 0); return getLongProperty(property, 0);
} }
/**
* Get a module configuration property as a long
*
* @param module
* the name of the module
* @param property
* the name of the property
*
* @return the value of the property. <code>0</code> is returned if the
* property does not exist. To differentiate between this case and
* when the property actually is zero, use <code>getProperty</code>.
*/
public static long getLongProperty(String module, String property)
{
return getLongProperty(module, property, 0);
}
/** /**
* Get a configuration property as an long, with default * Get a configuration property as an long, with default
* *
*
* @param property * @param property
* the name of the property * the name of the property
* *
@@ -249,13 +384,34 @@ public class ConfigurationManager
* <code>getProperty</code>. * <code>getProperty</code>.
*/ */
public static long getLongProperty(String property, int defaultValue) public static long getLongProperty(String property, int defaultValue)
{
return getLongProperty(null, property, defaultValue);
}
/**
* Get a configuration property as an long, with default
*
* @param the module, or <code>null</code> for regular property
*
* @param property
* the name of the property
*
* @param defaultValue
* value to return if property is not found or is not a Long.
*
* @return the value of the property. <code>default</code> is returned if
* the property does not exist or is not an Integer. To differentiate between this case
* and when the property actually is false, use
* <code>getProperty</code>.
*/
public static long getLongProperty(String module, String property, int defaultValue)
{ {
if (properties == null) if (properties == null)
{ {
loadConfig(null); loadConfig(null);
} }
String stringValue = properties.getProperty(property); String stringValue = properties.getProperty(module, property);
long longValue = defaultValue; long longValue = defaultValue;
if (stringValue != null) if (stringValue != null)
@@ -277,7 +433,7 @@ public class ConfigurationManager
* Get the License * Get the License
* *
* @param * @param
* licenseFile file name * license file name
* *
* @return * @return
* license text * license text
@@ -329,6 +485,7 @@ public class ConfigurationManager
} }
catch (IOException ioe) catch (IOException ioe)
{ {
} }
} }
} }
@@ -336,7 +493,6 @@ public class ConfigurationManager
return license; return license;
} }
/** /**
* Get a configuration property as a boolean. True is indicated if the value * Get a configuration property as a boolean. True is indicated if the value
* of the property is <code>TRUE</code> or <code>YES</code> (case * of the property is <code>TRUE</code> or <code>YES</code> (case
@@ -355,6 +511,26 @@ public class ConfigurationManager
return getBooleanProperty(property, false); return getBooleanProperty(property, false);
} }
/**
* Get a module configuration property as a boolean. True is indicated if
* the value of the property is <code>TRUE</code> or <code>YES</code> (case
* insensitive.)
*
* @param the module, or <code>null</code> for regular property
*
* @param property
* the name of the property
*
* @return the value of the property. <code>false</code> is returned if
* the property does not exist. To differentiate between this case
* and when the property actually is false, use
* <code>getProperty</code>.
*/
public static boolean getBooleanProperty(String module, String property)
{
return getBooleanProperty(module, property, false);
}
/** /**
* Get a configuration property as a boolean, with default. * Get a configuration property as a boolean, with default.
* True is indicated if the value * True is indicated if the value
@@ -373,13 +549,37 @@ public class ConfigurationManager
* <code>getProperty</code>. * <code>getProperty</code>.
*/ */
public static boolean getBooleanProperty(String property, boolean defaultValue) public static boolean getBooleanProperty(String property, boolean defaultValue)
{
return getBooleanProperty(null, property, defaultValue);
}
/**
* Get a module configuration property as a boolean, with default.
* True is indicated if the value
* of the property is <code>TRUE</code> or <code>YES</code> (case
* insensitive.)
*
* @param the module, or <code>null</code> for regular property
*
* @param property
* the name of the property
*
* @param defaultValue
* value to return if property is not found.
*
* @return the value of the property. <code>default</code> is returned if
* the property does not exist. To differentiate between this case
* and when the property actually is false, use
* <code>getProperty</code>.
*/
public static boolean getBooleanProperty(String module, String property, boolean defaultValue)
{ {
if (properties == null) if (properties == null)
{ {
loadConfig(null); loadConfig(null);
} }
String stringValue = properties.getProperty(property); String stringValue = getProperty(module, property);
if (stringValue != null) if (stringValue != null)
{ {
@@ -399,14 +599,34 @@ public class ConfigurationManager
* @return an enumeration of all the keys in the DSpace configuration * @return an enumeration of all the keys in the DSpace configuration
*/ */
public static Enumeration<?> propertyNames() public static Enumeration<?> propertyNames()
{
return propertyNames(null);
}
/**
* Returns an enumeration of all the keys in a module configuration
*
* @param the module, or <code>null</code> for regular property
*
* @return an enumeration of all the keys in the module configuration,
* or <code>null</code> if the module does not exist.
*/
public static Enumeration<?> propertyNames(String module)
{ {
if (properties == null) if (properties == null)
{ {
loadConfig(null); loadConfig(null);
} }
if (module == null)
{
return properties.propertyNames(); return properties.propertyNames();
} }
if (moduleProps.containsKey(module))
{
return moduleProps.get(module).propertyNames();
}
return null;
}
/** /**
* Get the template for an email message. The message is suitable for * Get the template for an email message. The message is suitable for
@@ -476,9 +696,7 @@ public class ConfigurationManager
email.setContent(contentBuffer.toString()); email.setContent(contentBuffer.toString());
if (charset != null) if (charset != null)
{
email.setCharset(charset); email.setCharset(charset);
}
return email; return email;
} }
@@ -552,8 +770,7 @@ public class ConfigurationManager
* Writes news to a text file. * Writes news to a text file.
* *
* @param newsFile * @param newsFile
* name of the news file to write, relative to the news file path. * name of the news file to read in, relative to the news file path.
*
* @param news * @param news
* the text to be written to the file. * the text to be written to the file.
*/ */
@@ -584,10 +801,8 @@ public class ConfigurationManager
* Writes license to a text file. * Writes license to a text file.
* *
* @param licenseFile * @param licenseFile
* name for the file into which the license will be written, * name for the file int which license will be written,
* relative to the current directory. * relative to the current directory.
* @param newLicense
* the text to be written to the file.
*/ */
public static void writeLicenseFile(String licenseFile, String newLicense) public static void writeLicenseFile(String licenseFile, String newLicense)
{ {
@@ -663,7 +878,14 @@ public class ConfigurationManager
log.warn("Unable to access system properties, ignoring.", se); log.warn("Unable to access system properties, ignoring.", se);
} }
if (configFile != null) // should only occur after a flush()
if (loadedFile != null)
{
info("Reloading current config file: " + loadedFile.getAbsolutePath());
url = loadedFile.toURI().toURL();
}
else if (configFile != null)
{ {
info("Loading provided config file: " + configFile); info("Loading provided config file: " + configFile);
@@ -700,6 +922,7 @@ public class ConfigurationManager
else else
{ {
properties = new Properties(); properties = new Properties();
moduleProps = new HashMap<String, Properties>();
is = url.openStream(); is = url.openStream();
properties.load(is); properties.load(is);
@@ -707,7 +930,7 @@ public class ConfigurationManager
for (Enumeration<?> pe = properties.propertyNames(); pe.hasMoreElements(); ) for (Enumeration<?> pe = properties.propertyNames(); pe.hasMoreElements(); )
{ {
String key = (String)pe.nextElement(); String key = (String)pe.nextElement();
String value = interpolate(key, 1); String value = interpolate(key, properties.getProperty(key), 1);
if (value != null) if (value != null)
{ {
properties.setProperty(key, value); properties.setProperty(key, value);
@@ -806,6 +1029,8 @@ public class ConfigurationManager
} }
} }
try try
{ {
/* /*
@@ -877,13 +1102,13 @@ public class ConfigurationManager
* @return new value if it contains interpolations, or null * @return new value if it contains interpolations, or null
* if it had no variable references. * if it had no variable references.
*/ */
private static String interpolate(String key, int level) private static String interpolate(String key, String value, int level)
{ {
if (level > RECURSION_LIMIT) if (level > RECURSION_LIMIT)
{ {
throw new IllegalArgumentException("ConfigurationManager: Too many levels of recursion in configuration property variable interpolation, property=" + key); throw new IllegalArgumentException("ConfigurationManager: Too many levels of recursion in configuration property variable interpolation, property=" + key);
} }
String value = (String)properties.get(key); //String value = (String)properties.get(key);
int from = 0; int from = 0;
StringBuffer result = null; StringBuffer result = null;
while (from < value.length()) while (from < value.length())
@@ -907,7 +1132,7 @@ public class ConfigurationManager
} }
if (properties.containsKey(var)) if (properties.containsKey(var))
{ {
String ivalue = interpolate(var, level+1); String ivalue = interpolate(var, properties.getProperty(var), level+1);
if (ivalue != null) if (ivalue != null)
{ {
result.append(ivalue); result.append(ivalue);
@@ -915,7 +1140,7 @@ public class ConfigurationManager
} }
else else
{ {
result.append((String) properties.getProperty(var)); result.append((String)properties.getProperty(var));
} }
} }
else else
@@ -966,10 +1191,26 @@ public class ConfigurationManager
System.exit(0); System.exit(0);
} }
else if ((argv.length == 4) && argv[0].equals("-module") &&
argv[2].equals("-property"))
{
String val = getProperty(argv[1], argv[3]);
if (val != null)
{
System.out.println(val);
}
else
{
System.out.println("");
}
System.exit(0);
}
else else
{ {
System.err System.err
.println("Usage: ConfigurationManager OPTION\n -property prop.name get value of prop.name from dspace.cfg"); .println("Usage: ConfigurationManager OPTION\n [-module mod.name] -property prop.name get value of prop.name from module or dspace.cfg");
} }
System.exit(1); System.exit(1);

View File

@@ -55,7 +55,6 @@ import java.io.File;
import java.io.IOException; import java.io.IOException;
import org.apache.log4j.Logger; import org.apache.log4j.Logger;
import org.dspace.content.crosswalk.DisseminationCrosswalk;
/** /**
* The Plugin Manager is a very simple component container. It creates and * The Plugin Manager is a very simple component container. It creates and
@@ -116,7 +115,7 @@ public class PluginManager
// Predicate -- whether or not to cache this class. Ironically, // Predicate -- whether or not to cache this class. Ironically,
// the cacheability information is itself cached. // the cacheability information is itself cached.
private static boolean cacheMe(Class implClass) private static boolean cacheMe(String module, Class implClass)
{ {
if (cacheMeCache.containsKey(implClass)) if (cacheMeCache.containsKey(implClass))
{ {
@@ -125,7 +124,9 @@ public class PluginManager
else else
{ {
String key = REUSABLE_PREFIX+implClass.getName(); String key = REUSABLE_PREFIX+implClass.getName();
boolean reusable = ConfigurationManager.getBooleanProperty(key, true); boolean reusable = (module != null) ?
ConfigurationManager.getBooleanProperty(module, key, true) :
ConfigurationManager.getBooleanProperty(key, true);
cacheMeCache.put(implClass, Boolean.valueOf(reusable)); cacheMeCache.put(implClass, Boolean.valueOf(reusable));
return reusable; return reusable;
} }
@@ -147,21 +148,38 @@ public class PluginManager
*/ */
public static Object getSinglePlugin(Class interfaceClass) public static Object getSinglePlugin(Class interfaceClass)
throws PluginConfigurationError, PluginInstantiationException throws PluginConfigurationError, PluginInstantiationException
{
return getSinglePlugin(null, interfaceClass);
}
/**
* Returns an instance of the singleton (single) plugin implementing
* the given interface. There must be exactly one single plugin
* configured for this interface, otherwise the
* <code>PluginConfigurationError</code> is thrown.
* <p>
* Note that this is the only "get plugin" method which throws an
* exception. It is typically used at initialization time to set up
* a permanent part of the system so any failure is fatal.
*
* @param name of config module, or <code>null</code> for standard location
* @param interfaceClass interface Class object
* @return instance of plugin
* @throws PluginConfigurationError
*/
public static Object getSinglePlugin(String module, Class interfaceClass)
throws PluginConfigurationError, PluginInstantiationException
{ {
String iname = interfaceClass.getName(); String iname = interfaceClass.getName();
// configuration format is prefix.<interface> = <classname> // configuration format is prefix.<interface> = <classname>
String classname = ConfigurationManager.getProperty(SINGLE_PREFIX+iname); String classname = getConfigProperty(module, SINGLE_PREFIX+iname);
if (classname != null)
{
return getAnonymousPlugin(classname.trim());
}
else
{
throw new PluginConfigurationError("No Single Plugin configured for interface \"" + iname + "\"");
}
}
if (classname != null)
return getAnonymousPlugin(module, classname.trim());
else
throw new PluginConfigurationError("No Single Plugin configured for interface \""+iname+"\"");
}
// cache of config data for Sequence Plugins; format its // cache of config data for Sequence Plugins; format its
// <interface-name> -> [ <classname>.. ] (value is Array) // <interface-name> -> [ <classname>.. ] (value is Array)
@@ -181,6 +199,25 @@ public class PluginManager
*/ */
public static Object[] getPluginSequence(Class intfc) public static Object[] getPluginSequence(Class intfc)
throws PluginInstantiationException throws PluginInstantiationException
{
return getPluginSequence(null, intfc);
}
/**
* Returns instances of all plugins that implement the interface
* intface, in an Array. Returns an empty array if no there are no
* matching plugins.
* <p>
* The order of the plugins in the array is the same as their class
* names in the configuration's value field.
*
* @param module name of config module, or <code>null</code> for standard
* @param intfc interface for which to find plugins.
* @return an array of plugin instances; if none are
* available an empty array is returned.
*/
public static Object[] getPluginSequence(String module, Class intfc)
throws PluginInstantiationException
{ {
// cache the configuration for this interface after grovelling it once: // cache the configuration for this interface after grovelling it once:
// format is prefix.<interface> = <classname> // format is prefix.<interface> = <classname>
@@ -188,7 +225,7 @@ public class PluginManager
String classname[] = null; String classname[] = null;
if (!sequenceConfig.containsKey(iname)) if (!sequenceConfig.containsKey(iname))
{ {
String val = ConfigurationManager.getProperty(SEQUENCE_PREFIX+iname); String val = getConfigProperty(module, SEQUENCE_PREFIX+iname);
if (val == null) if (val == null)
{ {
log.warn("No Configuration entry found for Sequence Plugin interface="+iname); log.warn("No Configuration entry found for Sequence Plugin interface="+iname);
@@ -206,23 +243,24 @@ public class PluginManager
for (int i = 0; i < classname.length; ++i) for (int i = 0; i < classname.length; ++i)
{ {
log.debug("Adding Sequence plugin for interface= "+iname+", class="+classname[i]); log.debug("Adding Sequence plugin for interface= "+iname+", class="+classname[i]);
result[i] = getAnonymousPlugin(classname[i]); result[i] = getAnonymousPlugin(module, classname[i]);
} }
return result; return result;
} }
// Map of cached (reusable) single plugin instances - class -> instance. // Map of cached (reusable) single plugin instances - class -> instance.
private static Map<Serializable, Object> anonymousInstanceCache = new HashMap<Serializable, Object>(); private static Map<Serializable, Object> anonymousInstanceCache = new HashMap<Serializable, Object>();
// Get possibly-cached plugin instance for un-named plugin, // Get possibly-cached plugin instance for un-named plugin,
// this is shared by Single and Sequence plugins. // this is shared by Single and Sequence plugins.
private static Object getAnonymousPlugin(String classname) private static Object getAnonymousPlugin(String module, String classname)
throws PluginInstantiationException throws PluginInstantiationException
{ {
try try
{ {
Class pluginClass = Class.forName(classname); Class pluginClass = Class.forName(classname);
if (cacheMe(pluginClass)) if (cacheMe(module, pluginClass))
{ {
Object cached = anonymousInstanceCache.get(pluginClass); Object cached = anonymousInstanceCache.get(pluginClass);
if (cached == null) if (cached == null)
@@ -260,7 +298,7 @@ public class PluginManager
private static Map<Serializable, Object> namedInstanceCache = new HashMap<Serializable, Object>(); private static Map<Serializable, Object> namedInstanceCache = new HashMap<Serializable, Object>();
// load and cache configuration data for the given interface. // load and cache configuration data for the given interface.
private static void configureNamedPlugin(String iname) private static void configureNamedPlugin(String module, String iname)
throws ClassNotFoundException throws ClassNotFoundException
{ {
int found = 0; int found = 0;
@@ -276,7 +314,7 @@ public class PluginManager
// 1. Get classes named by the configuration. format is: // 1. Get classes named by the configuration. format is:
// plugin.named.<INTF> = <CLASS> = <name>, <name> [,] \ // plugin.named.<INTF> = <CLASS> = <name>, <name> [,] \
// <CLASS> = <name>, <name> [ ... ] // <CLASS> = <name>, <name> [ ... ]
String namedVal = ConfigurationManager.getProperty(NAMED_PREFIX+iname); String namedVal = getConfigProperty(module, NAMED_PREFIX+iname);
if (namedVal != null) if (namedVal != null)
{ {
namedVal = namedVal.trim(); namedVal = namedVal.trim();
@@ -307,7 +345,7 @@ public class PluginManager
// 2. Get Self-named config entries: // 2. Get Self-named config entries:
// format is plugin.selfnamed.<INTF> = <CLASS> , <CLASS> .. // format is plugin.selfnamed.<INTF> = <CLASS> , <CLASS> ..
String selfNamedVal = ConfigurationManager.getProperty(SELFNAMED_PREFIX+iname); String selfNamedVal = getConfigProperty(module, SELFNAMED_PREFIX+iname);
if (selfNamedVal != null) if (selfNamedVal != null)
{ {
String classnames[] = selfNamedVal.trim().split("\\s*,\\s*"); String classnames[] = selfNamedVal.trim().split("\\s*,\\s*");
@@ -380,11 +418,28 @@ public class PluginManager
*/ */
public static Object getNamedPlugin(Class intfc, String name) public static Object getNamedPlugin(Class intfc, String name)
throws PluginInstantiationException throws PluginInstantiationException
{
return getNamedPlugin(null, intfc, name);
}
/**
* Returns an instance of a plugin that implements the interface
* intface and is bound to a name matching name. If there is no
* matching plugin, it returns null. The names are matched by
* String.equals().
*
* @param module config module, or <code>null</code> for standard location
* @param intfc the interface class of the plugin
* @param name under which the plugin implementation is configured.
* @return instance of plugin implementation, or null if there is no match or an error.
*/
public static Object getNamedPlugin(String module, Class intfc, String name)
throws PluginInstantiationException
{ {
try try
{ {
String iname = intfc.getName(); String iname = intfc.getName();
configureNamedPlugin(iname); configureNamedPlugin(module, iname);
String key = iname + SEP + name; String key = iname + SEP + name;
String cname = namedPluginClasses.get(key); String cname = namedPluginClasses.get(key);
if (cname == null) if (cname == null)
@@ -394,7 +449,7 @@ public class PluginManager
else else
{ {
Class pluginClass = Class.forName(cname); Class pluginClass = Class.forName(cname);
if (cacheMe(pluginClass)) if (cacheMe(module, pluginClass))
{ {
String nkey = pluginClass.getName() + SEP + name; String nkey = pluginClass.getName() + SEP + name;
Object cached = namedInstanceCache.get(nkey); Object cached = namedInstanceCache.get(nkey);
@@ -454,11 +509,27 @@ public class PluginManager
*/ */
public static boolean hasNamedPlugin(Class intfc, String name) public static boolean hasNamedPlugin(Class intfc, String name)
throws PluginInstantiationException throws PluginInstantiationException
{
return hasNamedPlugin(null, intfc, name);
}
/**
* Returns whether a plugin exists which implements the specified interface
* and has a specified name. If a matching plugin is found to be configured,
* return true. If there is no matching plugin, return false.
*
* @param module the config module or <code>null</code> for regular location
* @param intfc the interface class of the plugin
* @param name under which the plugin implementation is configured.
* @return true if plugin was found to be configured, false otherwise
*/
public static boolean hasNamedPlugin(String module, Class intfc, String name)
throws PluginInstantiationException
{ {
try try
{ {
String iname = intfc.getName(); String iname = intfc.getName();
configureNamedPlugin(iname); configureNamedPlugin(module, iname);
String key = iname + SEP + name; String key = iname + SEP + name;
return namedPluginClasses.get(key) != null; return namedPluginClasses.get(key) != null;
} }
@@ -468,6 +539,7 @@ public class PluginManager
e.toString(), e); e.toString(), e);
} }
} }
/** /**
* Returns all of the names under which a named plugin implementing * Returns all of the names under which a named plugin implementing
* the interface intface can be requested (with getNamedPlugin()). * the interface intface can be requested (with getNamedPlugin()).
@@ -482,11 +554,30 @@ public class PluginManager
* available an empty array is returned. * available an empty array is returned.
*/ */
public static String[] getAllPluginNames(Class intfc) public static String[] getAllPluginNames(Class intfc)
{
return getAllPluginNames(null, intfc);
}
/**
* Returns all of the names under which a named plugin implementing
* the interface intface can be requested (with getNamedPlugin()).
* The array is empty if there are no matches. Use this to populate
* a menu of plugins for interactive selection, or to document what
* the possible choices are.
* <p>
* NOTE: The names are NOT returned in any deterministic order.
*
* @param module the module name
* @param intfc plugin interface for which to return names.
* @return an array of strings with every name; if none are
* available an empty array is returned.
*/
public static String[] getAllPluginNames(String module, Class intfc)
{ {
try try
{ {
String iname = intfc.getName(); String iname = intfc.getName();
configureNamedPlugin(iname); configureNamedPlugin(module, iname);
String prefix = iname + SEP; String prefix = iname + SEP;
ArrayList<String> result = new ArrayList<String>(); ArrayList<String> result = new ArrayList<String>();
@@ -603,7 +694,7 @@ public class PluginManager
{ {
try try
{ {
configureNamedPlugin(iname); configureNamedPlugin(null, iname);
} }
catch (ClassNotFoundException ce) catch (ClassNotFoundException ce)
{ {
@@ -611,6 +702,15 @@ public class PluginManager
} }
} }
// get module-specific, or generic configuration property
private static String getConfigProperty(String module, String property)
{
if (module != null) {
return ConfigurationManager.getProperty(module, property);
}
return ConfigurationManager.getProperty(property);
}
/** /**
* Validate the entries in the DSpace Configuration relevant to * Validate the entries in the DSpace Configuration relevant to
* PluginManager. Look for inconsistencies, illegal syntax, etc. * PluginManager. Look for inconsistencies, illegal syntax, etc.