/**
* 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.core;
import java.io.BufferedReader;
import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.net.MalformedURLException;
import java.net.URL;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import org.apache.log4j.Category;
import org.apache.log4j.Logger;
import org.apache.log4j.helpers.OptionConverter;
/**
* Class for reading the DSpace system configuration. The main configuration is
* read in as properties from a standard properties file. Email templates and
* configuration files for other tools are also be accessed via this class.
* <P>
* The main configuration is by default read from the <em>resource</em>
* <code>/dspace.cfg</code>.
* To specify a different configuration, the system property
* <code>dspace.configuration</code> should be set to the <em>filename</em>
* of the configuration file.
* <P>
* Other configuration files are read from the <code>config</code> directory
* of the DSpace installation directory (specified as the property
* <code>dspace.dir</code> in the main configuration file.)
*
*
* @author Robert Tansley
* @author Larry Stone - Interpolated values.
* @author Mark Diggory - General Improvements to detection, logging and loading.
* @version $Revision$
*/
public class ConfigurationManager
{
/** log4j category */
private static Logger log = Logger.getLogger(ConfigurationManager.class);
/** The configuration properties */
private static Properties properties = null;
/** module configuration properties */
private static Map<String, Properties> moduleProps = null;
/** The default license */
private static String license;
// limit of recursive depth of property variable interpolation in
// configuration; anything greater than this is very likely to be a loop.
private static final int RECURSION_LIMIT = 9;
protected ConfigurationManager()
{
}
/**
* Identify if DSpace is properly configured
* @return boolean true if configured, false otherwise
*/
public static boolean isConfigured()
{
return properties != null;
}
public static boolean isConfigured(String module)
{
return moduleProps.get(module) != null;
}
/**
* REMOVED - Flushing the properties could be dangerous in the current DSpace state
* Need to consider how it will affect in-flight processes
*
* Discard all current properties - will force a reload from disk when
* any properties are requested.
*/
// public static void flush()
// {
// properties = null;
// }
/**
* REMOVED - Flushing the properties could be dangerous in the current DSpace state
* Need to consider how it will affect in-flight processes
*
* 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()
{
Properties props = getMutableProperties();
return props == null ? null : (Properties)props.clone();
}
private static Properties getMutableProperties()
{
if (properties == null)
{
loadConfig(null);
}
return properties;
}
/**
* 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)
{
Properties props = getMutableProperties(module);
return props == null ? null : (Properties)props.clone();
}
private static Properties getMutableProperties(String module)
{
Properties retProps = (module != null) ? moduleProps.get(module) : properties;
if (retProps == null)
{
loadModuleConfig(module);
retProps = moduleProps.get(module);
}
return retProps;
}
/**
* Get a configuration property
*
* @param property
* the name of the property
*
* @return the value of the property, or <code>null</code> if the property
* does not exist.
*/
public static String getProperty(String property)
{
Properties props = getMutableProperties();
String value = props == null ? null : props.getProperty(property);
return (value != null) ? value.trim() : null;
}
/**
* 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 (module == null)
{
return getProperty(property);
}
String value = null;
Properties modProps = getMutableProperties(module);
if (modProps != null)
{
value = modProps.getProperty(property);
}
if (value == null)
{
// look in regular properties with module name prepended
value = getProperty(module + "." + property);
}
return (value != null) ? value.trim() : null;
}
/**
* Get a configuration property as an integer
*
* @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 property)
{
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
*
* @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 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)
{
String stringValue = getProperty(module, property);
int intValue = defaultValue;
if (stringValue != null)
{
try
{
intValue = Integer.parseInt(stringValue.trim());
}
catch (NumberFormatException e)
{
warn("Warning: Number format error in property: " + property);
}
}
return intValue;
}
/**
* Get a configuration property as a long
*
* @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 property)
{
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
*
*
* @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 property, int defaultValue)
{
return getLongProperty(null, property, defaultValue);
}
/**
* Get a configuration property as an long, with default
*
* @param module 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)
{
String stringValue = getProperty(module, property);
long longValue = defaultValue;
if (stringValue != null)
{
try
{
longValue = Long.parseLong(stringValue.trim());
}
catch (NumberFormatException e)
{
warn("Warning: Number format error in property: " + property);
}
}
return longValue;
}
/**
* Get the License
*
* @param
* licenseFile file name
*
* @return
* license text
*
*/
public static String getLicenseText(String licenseFile)
{
// Load in default license
FileReader fr = null;
BufferedReader br = null;
try
{
fr = new FileReader(licenseFile);
br = new BufferedReader(fr);
String lineIn;
license = "";
while ((lineIn = br.readLine()) != null)
{
license = license + lineIn + '\n';
}
}
catch (IOException e)
{
fatal("Can't load configuration", e);
// FIXME: Maybe something more graceful here, but with the
// configuration we can't do anything
throw new IllegalStateException("Failed to read default license.", e);
}
finally
{
if (br != null)
{
try
{
br.close();
}
catch (IOException ioe)
{
}
}
if (fr != null)
{
try
{
fr.close();
}
catch (IOException ioe)
{
}
}
}
return license;
}
/**
* 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
* insensitive.)
*
* @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 property)
{
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 module 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.
* True is indicated if the value
* of the property is <code>TRUE</code> or <code>YES</code> (case
* insensitive.)
*
* @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 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 module 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)
{
String stringValue = getProperty(module, property);
if (stringValue != null)
{
stringValue = stringValue.trim();
return stringValue.equalsIgnoreCase("true") ||
stringValue.equalsIgnoreCase("yes");
}
else
{
return defaultValue;
}
}
/**
* Returns 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()
{
return propertyNames(null);
}
/**
* Returns an enumeration of all the keys in a module configuration
*
* @param module 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)
{
Properties props = getProperties(module);
return props == null ? null : props.propertyNames();
}
/**
* Get the template for an email message. The message is suitable for
* inserting values using <code>java.text.MessageFormat</code>.
*
* @param emailFile
* full name for the email template, for example "/dspace/config/emails/register".
*
* @return the email object, with the content and subject filled out from
* the template
*
* @throws IOException
* if the template couldn't be found, or there was some other
* error reading the template
*/
public static Email getEmail(String emailFile) throws IOException
{
String charset = null;
String subject = "";
StringBuffer contentBuffer = new StringBuffer();
// Read in template
BufferedReader reader = null;
try
{
reader = new BufferedReader(new FileReader(emailFile));
boolean more = true;
while (more)
{
String line = reader.readLine();
if (line == null)
{
more = false;
}
else if (line.toLowerCase().startsWith("subject:"))
{
// Extract the first subject line - everything to the right
// of the colon, trimmed of whitespace
subject = line.substring(8).trim();
}
else if (line.toLowerCase().startsWith("charset:"))
{
// Extract the character set from the email
charset = line.substring(8).trim();
}
else if (!line.startsWith("#"))
{
// Add non-comment lines to the content
contentBuffer.append(line);
contentBuffer.append("\n");
}
}
}
finally
{
if (reader != null)
{
reader.close();
}
}
// Create an email
Email email = new Email();
email.setSubject(subject);
email.setContent(contentBuffer.toString());
if (charset != null)
{
email.setCharset(charset);
}
return email;
}
/**
* Get the site-wide default license that submitters need to grant
*
* @return the default license
*/
public static String getDefaultSubmissionLicense()
{
if (properties == null)
{
loadConfig(null);
}
return license;
}
/**
* Get the path for the news files.
*
*/
public static String getNewsFilePath()
{
String filePath = ConfigurationManager.getProperty("dspace.dir")
+ File.separator + "config" + File.separator;
return filePath;
}
/**
* Reads news from a text file.
*
* @param newsFile
* name of the news file to read in, relative to the news file path.
*/
public static String readNewsFile(String newsFile)
{
String fileName = getNewsFilePath();
fileName += newsFile;
StringBuilder text = new StringBuilder();
try
{
// retrieve existing news from file
FileInputStream fir = new FileInputStream(fileName);
InputStreamReader ir = new InputStreamReader(fir, "UTF-8");
BufferedReader br = new BufferedReader(ir);
String lineIn;
while ((lineIn = br.readLine()) != null)
{
text.append(lineIn);
}
br.close();
}
catch (IOException e)
{
warn("news_read: " + e.getLocalizedMessage());
}
return text.toString();
}
/**
* Writes news to a text file.
*
* @param newsFile
* name of the news file to read in, relative to the news file path.
* @param news
* the text to be written to the file.
*/
public static String writeNewsFile(String newsFile, String news)
{
String fileName = getNewsFilePath();
fileName += newsFile;
try
{
// write the news out to the appropriate file
FileOutputStream fos = new FileOutputStream(fileName);
OutputStreamWriter osr = new OutputStreamWriter(fos, "UTF-8");
PrintWriter out = new PrintWriter(osr);
out.print(news);
out.close();
}
catch (IOException e)
{
warn("news_write: " + e.getLocalizedMessage());
}
return news;
}
/**
* Writes license to a text file.
*
* @param licenseFile
* name for the file int which license will be written,
* relative to the current directory.
*/
public static void writeLicenseFile(String licenseFile, String newLicense)
{
try
{
// write the news out to the appropriate file
FileOutputStream fos = new FileOutputStream(licenseFile);
OutputStreamWriter osr = new OutputStreamWriter(fos, "UTF-8");
PrintWriter out = new PrintWriter(osr);
out.print(newLicense);
out.close();
}
catch (IOException e)
{
warn("license_write: " + e.getLocalizedMessage());
}
license = newLicense;
}
private static File loadedFile = null;
/**
* Return the file that configuration was actually loaded from. Only returns
* a valid File after configuration has been loaded.
*
* @deprecated Please remove all direct usage of the configuration file.
* @return File naming configuration data file, or null if not loaded yet.
*/
protected static File getConfigurationFile()
{
// in case it hasn't been done yet.
if (loadedFile == null)
{
loadConfig(null);
}
return loadedFile;
}
private static synchronized void loadModuleConfig(String module)
{
// 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())
{
Properties modProps = new Properties();
InputStream modIS = null;
try
{
modIS = new FileInputStream(modFile);
modProps.load(modIS);
}
finally
{
if (modIS != null)
{
modIS.close();
}
}
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);
}
else
{
// log invalid request
warn("Requested configuration module: " + module + " not found");
}
}
catch (IOException ioE)
{
fatal("Can't load configuration: " + (modFile == null ? "<unknown>" : modFile.getAbsolutePath()), ioE);
}
return;
}
/**
* Load the DSpace configuration properties. Only does anything if
* properties are not already loaded. Properties are loaded in from the
* specified file, or default locations.
*
* @param configFile
* The <code>dspace.cfg</code> configuration file to use, or
* <code>null</code> to try default locations
*/
public static synchronized void loadConfig(String configFile)
{
if (properties != null)
{
return;
}
URL url = null;
InputStream is = null;
try
{
String configProperty = null;
try
{
configProperty = System.getProperty("dspace.configuration");
}
catch (SecurityException se)
{
// A security manager may stop us from accessing the system properties.
// This isn't really a fatal error though, so catch and ignore
log.warn("Unable to access system properties, ignoring.", se);
}
// 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);
loadedFile = new File(configFile);
url = loadedFile.toURI().toURL();
}
// Has the default configuration location been overridden?
else if (configProperty != null)
{
info("Loading system provided config property (-Ddspace.configuration): " + configProperty);
// Load the overriding configuration
loadedFile = new File(configProperty);
url = loadedFile.toURI().toURL();
}
// Load configuration from default location
else
{
url = ConfigurationManager.class.getResource("/dspace.cfg");
if (url != null)
{
info("Loading from classloader: " + url);
loadedFile = new File(url.getPath());
}
}
if (url == null)
{
fatal("Cannot find dspace.cfg");
throw new IllegalStateException("Cannot find dspace.cfg");
}
else
{
properties = new Properties();
moduleProps = new HashMap<String, Properties>();
is = url.openStream();
properties.load(is);
// walk values, interpolating any embedded references.
for (Enumeration<?> pe = properties.propertyNames(); pe.hasMoreElements(); )
{
String key = (String)pe.nextElement();
String value = interpolate(key, properties.getProperty(key), 1);
if (value != null)
{
properties.setProperty(key, value);
}
}
}
}
catch (IOException e)
{
fatal("Can't load configuration: " + url, e);
// FIXME: Maybe something more graceful here, but with the
// configuration we can't do anything
throw new IllegalStateException("Cannot load configuration: " + url, e);
}
finally
{
if (is != null)
{
try
{
is.close();
}
catch (IOException ioe)
{
}
}
}
// Load in default license
File licenseFile = new File(getProperty("dspace.dir") + File.separator
+ "config" + File.separator + "default.license");
FileInputStream fir = null;
InputStreamReader ir = null;
BufferedReader br = null;
try
{
fir = new FileInputStream(licenseFile);
ir = new InputStreamReader(fir, "UTF-8");
br = new BufferedReader(ir);
String lineIn;
license = "";
while ((lineIn = br.readLine()) != null)
{
license = license + lineIn + '\n';
}
br.close();
}
catch (IOException e)
{
fatal("Can't load license: " + licenseFile.toString() , e);
// FIXME: Maybe something more graceful here, but with the
// configuration we can't do anything
throw new IllegalStateException("Cannot load license: " + licenseFile.toString(),e);
}
finally
{
if (br != null)
{
try
{
br.close();
}
catch (IOException ioe)
{
}
}
if (ir != null)
{
try
{
ir.close();
}
catch (IOException ioe)
{
}
}
if (fir != null)
{
try
{
fir.close();
}
catch (IOException ioe)
{
}
}
}
try
{
/*
* Initialize Logging once ConfigurationManager is initialized.
*
* This is selection from a property in dspace.cfg, if the property
* is absent then nothing will be configured and the application
* will use the defaults provided by log4j.
*
* Property format is:
*
* log.init.config = ${dspace.dir}/config/log4j.properties
* or
* log.init.config = ${dspace.dir}/config/log4j.xml
*
* See default log4j initialization documentation here:
* http://logging.apache.org/log4j/docs/manual.html
*
* If there is a problem with the file referred to in
* "log.configuration" it needs to be sent to System.err
* so do not instantiate another Logging configuration.
*
*/
String dsLogConfiguration = ConfigurationManager.getProperty("log.init.config");
if (dsLogConfiguration == null || System.getProperty("dspace.log.init.disable") != null)
{
/*
* Do nothing if log config not set in dspace.cfg or "dspace.log.init.disable"
* system property set. Leave it upto log4j to properly init its logging
* via classpath or system properties.
*/
info("Using default log4j provided log configuration," +
"if unintended, check your dspace.cfg for (log.init.config)");
}
else
{
info("Using dspace provided log configuration (log.init.config)");
File logConfigFile = new File(dsLogConfiguration);
if(logConfigFile.exists())
{
info("Loading: " + dsLogConfiguration);
OptionConverter.selectAndConfigure(logConfigFile.toURI()
.toURL(), null, org.apache.log4j.LogManager
.getLoggerRepository());
}
else
{
info("File does not exist: " + dsLogConfiguration);
}
}
}
catch (MalformedURLException e)
{
fatal("Can't load dspace provided log4j configuration", e);
throw new IllegalStateException("Cannot load dspace provided log4j configuration",e);
}
}
/**
* Recursively interpolate variable references in value of
* property named "key".
* @return new value if it contains interpolations, or null
* if it had no variable references.
*/
private static String interpolate(String key, String value, int level)
{
if (level > RECURSION_LIMIT)
{
throw new IllegalArgumentException("ConfigurationManager: Too many levels of recursion in configuration property variable interpolation, property=" + key);
}
//String value = (String)properties.get(key);
int from = 0;
StringBuffer result = null;
while (from < value.length())
{
int start = value.indexOf("${", from);
if (start >= 0)
{
int end = value.indexOf('}', start);
if (end < 0)
{
break;
}
String var = value.substring(start+2, end);
if (result == null)
{
result = new StringBuffer(value.substring(from, start));
}
else
{
result.append(value.substring(from, start));
}
if (properties.containsKey(var))
{
String ivalue = interpolate(var, properties.getProperty(var), level+1);
if (ivalue != null)
{
result.append(ivalue);
properties.setProperty(var, ivalue);
}
else
{
result.append(((String)properties.getProperty(var)).trim());
}
}
else
{
log.warn("Interpolation failed in value of property \""+key+
"\", there is no property named \""+var+"\"");
}
from = end+1;
}
else
{
break;
}
}
if (result != null && from < value.length())
{
result.append(value.substring(from));
}
return (result == null) ? null : result.toString();
}
/**
* Command-line interface for running configuration tasks. Possible
* arguments:
* <ul>
* <li><code>-property name</code> prints the value of the property
* <code>name</code> from <code>dspace.cfg</code> to the standard
* output. If the property does not exist, nothing is written.</li>
* </ul>
*
* @param argv
* command-line arguments
*/
public static void main(String[] argv)
{
if ((argv.length == 2) && argv[0].equals("-property"))
{
String val = getProperty(argv[1]);
if (val != null)
{
System.out.println(val);
}
else
{
System.out.println("");
}
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
{
System.err
.println("Usage: ConfigurationManager OPTION\n [-module mod.name] -property prop.name get value of prop.name from module or dspace.cfg");
}
System.exit(1);
}
private static void info(String string)
{
if (!isLog4jConfigured())
{
System.out.println("INFO: " + string);
}
else
{
log.info(string);
}
}
private static void warn(String string)
{
if (!isLog4jConfigured())
{
System.out.println("WARN: " + string);
}
else
{
log.warn(string);
}
}
private static void fatal(String string, Exception e)
{
if (!isLog4jConfigured())
{
System.out.println("FATAL: " + string);
e.printStackTrace();
}
else
{
log.fatal(string, e);
}
}
private static void fatal(String string)
{
if (!isLog4jConfigured())
{
System.out.println("FATAL: " + string);
}
else
{
log.fatal(string);
}
}
/*
* Only current solution available to detect
* if log4j is truly configured.
*/
private static boolean isLog4jConfigured()
{
Enumeration<?> en = org.apache.log4j.LogManager.getRootLogger()
.getAllAppenders();
if (!(en instanceof org.apache.log4j.helpers.NullEnumeration))
{
return true;
}
else
{
Enumeration<?> cats = Category.getCurrentCategories();
while (cats.hasMoreElements())
{
Category c = (Category) cats.nextElement();
if (!(c.getAllAppenders() instanceof org.apache.log4j.helpers.NullEnumeration))
{
return true;
}
}
}
return false;
}
}