X-Git-Url: http://source.jalview.org/gitweb/?a=blobdiff_plain;f=srcjar%2Forg%2Fapache%2Flog4j%2FPropertyConfigurator.java;fp=srcjar%2Forg%2Fapache%2Flog4j%2FPropertyConfigurator.java;h=0000000000000000000000000000000000000000;hb=0e684f72690bd6532272a39ab6c188a27559fd09;hp=3e5cc261470ea58524423719bfa72f3d0aa92674;hpb=91fb50c7dfcda9dcb3399d284f252075e89d54ff;p=jalview.git diff --git a/srcjar/org/apache/log4j/PropertyConfigurator.java b/srcjar/org/apache/log4j/PropertyConfigurator.java deleted file mode 100644 index 3e5cc26..0000000 --- a/srcjar/org/apache/log4j/PropertyConfigurator.java +++ /dev/null @@ -1,1003 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You under the Apache License, Version 2.0 - * (the "License"); you may not use this file except in compliance with - * the License. You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -// Contributors: "Luke Blanshard" -// "Mark DONSZELMANN" -// Anders Kristensen - -package org.apache.log4j; - -import java.io.FileInputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InterruptedIOException; -import java.net.URLConnection; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Properties; -import java.util.StringTokenizer; -import java.util.Vector; -import java.util.Iterator; -import java.util.Map; - -import org.apache.log4j.config.PropertySetter; -import org.apache.log4j.helpers.FileWatchdog; -import org.apache.log4j.helpers.LogLog; -import org.apache.log4j.helpers.OptionConverter; -import org.apache.log4j.or.RendererMap; -import org.apache.log4j.spi.Configurator; -import org.apache.log4j.spi.Filter; -import org.apache.log4j.spi.LoggerFactory; -import org.apache.log4j.spi.LoggerRepository; -import org.apache.log4j.spi.OptionHandler; -import org.apache.log4j.spi.RendererSupport; -import org.apache.log4j.spi.ThrowableRenderer; -import org.apache.log4j.spi.ThrowableRendererSupport; -import org.apache.log4j.spi.ErrorHandler; - -/** - Allows the configuration of log4j from an external file. See - {@link #doConfigure(String, LoggerRepository)} for the - expected format. - -

It is sometimes useful to see how log4j is reading configuration - files. You can enable log4j internal logging by defining the - log4j.debug variable. - -

As of log4j version 0.8.5, at class initialization time class, - the file log4j.properties will be searched from the search - path used to load classes. If the file can be found, then it will - be fed to the {@link PropertyConfigurator#configure(java.net.URL)} - method. - -

The PropertyConfigurator does not handle the - advanced configuration features supported by the {@link - org.apache.log4j.xml.DOMConfigurator DOMConfigurator} such as - support custom {@link org.apache.log4j.spi.ErrorHandler ErrorHandlers}, - nested appenders such as the {@link org.apache.log4j.AsyncAppender - AsyncAppender}, etc. - -

All option values admit variable substitution. The - syntax of variable substitution is similar to that of Unix - shells. The string between an opening "${" and - closing "}" is interpreted as a key. The value of - the substituted variable can be defined as a system property or in - the configuration file itself. The value of the key is first - searched in the system properties, and if not found there, it is - then searched in the configuration file being parsed. The - corresponding value replaces the ${variableName} sequence. For - example, if java.home system property is set to - /home/xyz, then every occurrence of the sequence - ${java.home} will be interpreted as - /home/xyz. - - - @author Ceki Gülcü - @author Anders Kristensen - @since 0.8.1 */ -public class PropertyConfigurator implements Configurator { - - /** - Used internally to keep track of configured appenders. - */ - protected Hashtable registry = new Hashtable(11); - private LoggerRepository repository; - protected LoggerFactory loggerFactory = new DefaultCategoryFactory(); - - static final String CATEGORY_PREFIX = "log4j.category."; - static final String LOGGER_PREFIX = "log4j.logger."; - static final String FACTORY_PREFIX = "log4j.factory"; - static final String ADDITIVITY_PREFIX = "log4j.additivity."; - static final String ROOT_CATEGORY_PREFIX = "log4j.rootCategory"; - static final String ROOT_LOGGER_PREFIX = "log4j.rootLogger"; - static final String APPENDER_PREFIX = "log4j.appender."; - static final String RENDERER_PREFIX = "log4j.renderer."; - static final String THRESHOLD_PREFIX = "log4j.threshold"; - private static final String THROWABLE_RENDERER_PREFIX = "log4j.throwableRenderer"; - private static final String LOGGER_REF = "logger-ref"; - private static final String ROOT_REF = "root-ref"; - private static final String APPENDER_REF_TAG = "appender-ref"; - - - /** Key for specifying the {@link org.apache.log4j.spi.LoggerFactory - LoggerFactory}. Currently set to "log4j.loggerFactory". */ - public static final String LOGGER_FACTORY_KEY = "log4j.loggerFactory"; - - /** - * If property set to true, then hierarchy will be reset before configuration. - */ - private static final String RESET_KEY = "log4j.reset"; - - static final private String INTERNAL_ROOT_NAME = "root"; - - /** - Read configuration from a file. The existing configuration is - not cleared nor reset. If you require a different behavior, - then call {@link LogManager#resetConfiguration - resetConfiguration} method before calling - doConfigure. - -

The configuration file consists of statements in the format - key=value. The syntax of different configuration - elements are discussed below. - -

Repository-wide threshold

- -

The repository-wide threshold filters logging requests by level - regardless of logger. The syntax is: - -

-    log4j.threshold=[level]
-    
- -

The level value can consist of the string values OFF, FATAL, - ERROR, WARN, INFO, DEBUG, ALL or a custom level value. A - custom level value can be specified in the form - level#classname. By default the repository-wide threshold is set - to the lowest possible value, namely the level ALL. -

- - -

Appender configuration

- -

Appender configuration syntax is: -

-    # For appender named appenderName, set its class.
-    # Note: The appender name can contain dots.
-    log4j.appender.appenderName=fully.qualified.name.of.appender.class
-
-    # Set appender specific options.
-    log4j.appender.appenderName.option1=value1
-    ...
-    log4j.appender.appenderName.optionN=valueN
-    
- - For each named appender you can configure its {@link Layout}. The - syntax for configuring an appender's layout is: -
-    log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
-    log4j.appender.appenderName.layout.option1=value1
-    ....
-    log4j.appender.appenderName.layout.optionN=valueN
-    
- - The syntax for adding {@link Filter}s to an appender is: -
-    log4j.appender.appenderName.filter.ID=fully.qualified.name.of.filter.class
-    log4j.appender.appenderName.filter.ID.option1=value1
-    ...
-    log4j.appender.appenderName.filter.ID.optionN=valueN
-    
- The first line defines the class name of the filter identified by ID; - subsequent lines with the same ID specify filter option - value - pairs. Multiple filters are added to the appender in the lexicographic - order of IDs. - - The syntax for adding an {@link ErrorHandler} to an appender is: -
-    log4j.appender.appenderName.errorhandler=fully.qualified.name.of.filter.class
-    log4j.appender.appenderName.errorhandler.root-ref={true|false}
-    log4j.appender.appenderName.errorhandler.logger-ref=loggerName
-    log4j.appender.appenderName.errorhandler.appender-ref=appenderName
-    log4j.appender.appenderName.errorhandler.option1=value1
-    ...
-    log4j.appender.appenderName.errorhandler.optionN=valueN
-    
- -

Configuring loggers

- -

The syntax for configuring the root logger is: -

-      log4j.rootLogger=[level], appenderName, appenderName, ...
-    
- -

This syntax means that an optional level can be - supplied followed by appender names separated by commas. - -

The level value can consist of the string values OFF, FATAL, - ERROR, WARN, INFO, DEBUG, ALL or a custom level value. A - custom level value can be specified in the form - level#classname. - -

If a level value is specified, then the root level is set - to the corresponding level. If no level value is specified, - then the root level remains untouched. - -

The root logger can be assigned multiple appenders. - -

Each appenderName (separated by commas) will be added to - the root logger. The named appender is defined using the - appender syntax defined above. - -

For non-root categories the syntax is almost the same: -

-    log4j.logger.logger_name=[level|INHERITED|NULL], appenderName, appenderName, ...
-    
- -

The meaning of the optional level value is discussed above - in relation to the root logger. In addition however, the value - INHERITED can be specified meaning that the named logger should - inherit its level from the logger hierarchy. - -

If no level value is supplied, then the level of the - named logger remains untouched. - -

By default categories inherit their level from the - hierarchy. However, if you set the level of a logger and later - decide that that logger should inherit its level, then you should - specify INHERITED as the value for the level value. NULL is a - synonym for INHERITED. - -

Similar to the root logger syntax, each appenderName - (separated by commas) will be attached to the named logger. - -

See the appender - additivity rule in the user manual for the meaning of the - additivity flag. - -

ObjectRenderers

- - You can customize the way message objects of a given type are - converted to String before being logged. This is done by - specifying an {@link org.apache.log4j.or.ObjectRenderer ObjectRenderer} - for the object type would like to customize. - -

The syntax is: - -

-    log4j.renderer.fully.qualified.name.of.rendered.class=fully.qualified.name.of.rendering.class
-    
- - As in, -
-    log4j.renderer.my.Fruit=my.FruitRenderer
-    
- -

ThrowableRenderer

- - You can customize the way an instance of Throwable is - converted to String before being logged. This is done by - specifying an {@link org.apache.log4j.spi.ThrowableRenderer ThrowableRenderer}. - -

The syntax is: - -

-   log4j.throwableRenderer=fully.qualified.name.of.rendering.class
-   log4j.throwableRenderer.paramName=paramValue
-   
- - As in, -
-   log4j.throwableRenderer=org.apache.log4j.EnhancedThrowableRenderer
-   
- -

Logger Factories

- - The usage of custom logger factories is discouraged and no longer - documented. - -

Resetting Hierarchy

- - The hierarchy will be reset before configuration when - log4j.reset=true is present in the properties file. - -

Example

- -

An example configuration is given below. Other configuration - file examples are given in the examples folder. - -

-
-    # Set options for appender named "A1".
-    # Appender "A1" will be a SyslogAppender
-    log4j.appender.A1=org.apache.log4j.net.SyslogAppender
-
-    # The syslog daemon resides on www.abc.net
-    log4j.appender.A1.SyslogHost=www.abc.net
-
-    # A1's layout is a PatternLayout, using the conversion pattern
-    # %r %-5p %c{2} %M.%L %x - %m\n. Thus, the log output will
-    # include # the relative time since the start of the application in
-    # milliseconds, followed by the level of the log request,
-    # followed by the two rightmost components of the logger name,
-    # followed by the callers method name, followed by the line number,
-    # the nested diagnostic context and finally the message itself.
-    # Refer to the documentation of {@link PatternLayout} for further information
-    # on the syntax of the ConversionPattern key.
-    log4j.appender.A1.layout=org.apache.log4j.PatternLayout
-    log4j.appender.A1.layout.ConversionPattern=%-4r %-5p %c{2} %M.%L %x - %m\n
-
-    # Set options for appender named "A2"
-    # A2 should be a RollingFileAppender, with maximum file size of 10 MB
-    # using at most one backup file. A2's layout is TTCC, using the
-    # ISO8061 date format with context printing enabled.
-    log4j.appender.A2=org.apache.log4j.RollingFileAppender
-    log4j.appender.A2.MaxFileSize=10MB
-    log4j.appender.A2.MaxBackupIndex=1
-    log4j.appender.A2.layout=org.apache.log4j.TTCCLayout
-    log4j.appender.A2.layout.ContextPrinting=enabled
-    log4j.appender.A2.layout.DateFormat=ISO8601
-
-    # Root logger set to DEBUG using the A2 appender defined above.
-    log4j.rootLogger=DEBUG, A2
-
-    # Logger definitions:
-    # The SECURITY logger inherits is level from root. However, it's output
-    # will go to A1 appender defined above. It's additivity is non-cumulative.
-    log4j.logger.SECURITY=INHERIT, A1
-    log4j.additivity.SECURITY=false
-
-    # Only warnings or above will be logged for the logger "SECURITY.access".
-    # Output will go to A1.
-    log4j.logger.SECURITY.access=WARN
-
-
-    # The logger "class.of.the.day" inherits its level from the
-    # logger hierarchy.  Output will go to the appender's of the root
-    # logger, A2 in this case.
-    log4j.logger.class.of.the.day=INHERIT
-    
- -

Refer to the setOption method in each Appender and - Layout for class specific options. - -

Use the # or ! characters at the - beginning of a line for comments. - -

- @param configFileName The name of the configuration file where the - configuration information is stored. - - */ - public - void doConfigure(String configFileName, LoggerRepository hierarchy) { - Properties props = new Properties(); - FileInputStream istream = null; - try { - istream = new FileInputStream(configFileName); - props.load(istream); - istream.close(); - } - catch (Exception e) { - if (e instanceof InterruptedIOException || e instanceof InterruptedException) { - Thread.currentThread().interrupt(); - } - LogLog.error("Could not read configuration file ["+configFileName+"].", e); - LogLog.error("Ignoring configuration file [" + configFileName+"]."); - return; - } finally { - if(istream != null) { - try { - istream.close(); - } catch(InterruptedIOException ignore) { - Thread.currentThread().interrupt(); - } catch(Throwable ignore) { - } - - } - } - // If we reach here, then the config file is alright. - doConfigure(props, hierarchy); - } - - /** - */ - static - public - void configure(String configFilename) { - new PropertyConfigurator().doConfigure(configFilename, - LogManager.getLoggerRepository()); - } - - /** - Read configuration options from url configURL. - - @since 0.8.2 -*/ -public -static -void configure(java.net.URL configURL) { - new PropertyConfigurator().doConfigure(configURL, - LogManager.getLoggerRepository()); -} - -/** -Reads configuration options from an InputStream. - -@since 1.2.17 -*/ -public -static -void configure(InputStream inputStream) { -new PropertyConfigurator().doConfigure(inputStream, - LogManager.getLoggerRepository()); -} - - - /** - Read configuration options from properties. - - See {@link #doConfigure(String, LoggerRepository)} for the expected format. - */ - static - public - void configure(Properties properties) { - new PropertyConfigurator().doConfigure(properties, - LogManager.getLoggerRepository()); - } - - /** - Like {@link #configureAndWatch(String, long)} except that the - default delay as defined by {@link FileWatchdog#DEFAULT_DELAY} is - used. - - @param configFilename A file in key=value format. - - */ - static - public - void configureAndWatch(String configFilename) { - configureAndWatch(configFilename, FileWatchdog.DEFAULT_DELAY); - } - - - /** - Read the configuration file configFilename if it - exists. Moreover, a thread will be created that will periodically - check if configFilename has been created or - modified. The period is determined by the delay - argument. If a change or file creation is detected, then - configFilename is read to configure log4j. - - @param configFilename A file in key=value format. - @param delay The delay in milliseconds to wait between each check. - */ - static - public - void configureAndWatch(String configFilename, long delay) { - PropertyWatchdog pdog = new PropertyWatchdog(configFilename); - pdog.setDelay(delay); - pdog.start(); - } - - - /** - Read configuration options from properties. - - See {@link #doConfigure(String, LoggerRepository)} for the expected format. - */ - public - void doConfigure(Properties properties, LoggerRepository hierarchy) { - repository = hierarchy; - String value = properties.getProperty(LogLog.DEBUG_KEY); - if(value == null) { - value = properties.getProperty("log4j.configDebug"); - if(value != null) { - LogLog.warn("[log4j.configDebug] is deprecated. Use [log4j.debug] instead."); - } - } - - if(value != null) { - LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true)); - } - - // - // if log4j.reset=true then - // reset hierarchy - String reset = properties.getProperty(RESET_KEY); - if (reset != null && OptionConverter.toBoolean(reset, false)) { - hierarchy.resetConfiguration(); - } - - String thresholdStr = OptionConverter.findAndSubst(THRESHOLD_PREFIX, - properties); - if(thresholdStr != null) { - hierarchy.setThreshold(OptionConverter.toLevel(thresholdStr, - Level.ALL)); - LogLog.debug("Hierarchy threshold set to ["+hierarchy.getThreshold()+"]."); - } - - configureRootCategory(properties, hierarchy); - configureLoggerFactory(properties); - parseCatsAndRenderers(properties, hierarchy); - - LogLog.debug("Finished configuring."); - // We don't want to hold references to appenders preventing their - // garbage collection. - registry.clear(); - } - - /** - * Read configuration options from an InputStream. - * - * @since 1.2.17 - */ - public void doConfigure(InputStream inputStream, LoggerRepository hierarchy) { - Properties props = new Properties(); - try { - props.load(inputStream); - } catch (IOException e) { - if (e instanceof InterruptedIOException) { - Thread.currentThread().interrupt(); - } - LogLog.error("Could not read configuration file from InputStream [" + inputStream - + "].", e); - LogLog.error("Ignoring configuration InputStream [" + inputStream +"]."); - return; - } - this.doConfigure(props, hierarchy); - } - - /** - Read configuration options from url configURL. - */ - public - void doConfigure(java.net.URL configURL, LoggerRepository hierarchy) { - Properties props = new Properties(); - LogLog.debug("Reading configuration from URL " + configURL); - InputStream istream = null; - URLConnection uConn = null; - try { - uConn = configURL.openConnection(); - uConn.setUseCaches(false); - istream = uConn.getInputStream(); - props.load(istream); - } - catch (Exception e) { - if (e instanceof InterruptedIOException || e instanceof InterruptedException) { - Thread.currentThread().interrupt(); - } - LogLog.error("Could not read configuration file from URL [" + configURL - + "].", e); - LogLog.error("Ignoring configuration file [" + configURL +"]."); - return; - } - finally { - if (istream != null) { - try { - istream.close(); - } catch(InterruptedIOException ignore) { - Thread.currentThread().interrupt(); - } catch(IOException ignore) { - } catch(RuntimeException ignore) { - } - } - } - doConfigure(props, hierarchy); - } - - - // -------------------------------------------------------------------------- - // Internal stuff - // -------------------------------------------------------------------------- - - /** - Check the provided Properties object for a - {@link org.apache.log4j.spi.LoggerFactory LoggerFactory} - entry specified by {@link #LOGGER_FACTORY_KEY}. If such an entry - exists, an attempt is made to create an instance using the default - constructor. This instance is used for subsequent Category creations - within this configurator. - - @see #parseCatsAndRenderers - */ - protected void configureLoggerFactory(Properties props) { - String factoryClassName = OptionConverter.findAndSubst(LOGGER_FACTORY_KEY, - props); - if(factoryClassName != null) { - LogLog.debug("Setting category factory to ["+factoryClassName+"]."); - loggerFactory = (LoggerFactory) - OptionConverter.instantiateByClassName(factoryClassName, - LoggerFactory.class, - loggerFactory); - PropertySetter.setProperties(loggerFactory, props, FACTORY_PREFIX + "."); - } - } - - /* - void configureOptionHandler(OptionHandler oh, String prefix, - Properties props) { - String[] options = oh.getOptionStrings(); - if(options == null) - return; - - String value; - for(int i = 0; i < options.length; i++) { - value = OptionConverter.findAndSubst(prefix + options[i], props); - LogLog.debug( - "Option " + options[i] + "=[" + (value == null? "N/A" : value)+"]."); - // Some option handlers assume that null value are not passed to them. - // So don't remove this check - if(value != null) { - oh.setOption(options[i], value); - } - } - oh.activateOptions(); - } - */ - - - void configureRootCategory(Properties props, LoggerRepository hierarchy) { - String effectiveFrefix = ROOT_LOGGER_PREFIX; - String value = OptionConverter.findAndSubst(ROOT_LOGGER_PREFIX, props); - - if(value == null) { - value = OptionConverter.findAndSubst(ROOT_CATEGORY_PREFIX, props); - effectiveFrefix = ROOT_CATEGORY_PREFIX; - } - - if(value == null) { - LogLog.debug("Could not find root logger information. Is this OK?"); - } else { - Logger root = hierarchy.getRootLogger(); - synchronized(root) { - parseCategory(props, root, effectiveFrefix, INTERNAL_ROOT_NAME, value); - } - } - } - - - /** - Parse non-root elements, such non-root categories and renderers. - */ - protected - void parseCatsAndRenderers(Properties props, LoggerRepository hierarchy) { - Enumeration enumeration = props.propertyNames(); - while(enumeration.hasMoreElements()) { - String key = (String) enumeration.nextElement(); - if(key.startsWith(CATEGORY_PREFIX) || key.startsWith(LOGGER_PREFIX)) { - String loggerName = null; - if(key.startsWith(CATEGORY_PREFIX)) { - loggerName = key.substring(CATEGORY_PREFIX.length()); - } else if(key.startsWith(LOGGER_PREFIX)) { - loggerName = key.substring(LOGGER_PREFIX.length()); - } - String value = OptionConverter.findAndSubst(key, props); - Logger logger = hierarchy.getLogger(loggerName, loggerFactory); - synchronized(logger) { - parseCategory(props, logger, key, loggerName, value); - parseAdditivityForLogger(props, logger, loggerName); - } - } else if(key.startsWith(RENDERER_PREFIX)) { - String renderedClass = key.substring(RENDERER_PREFIX.length()); - String renderingClass = OptionConverter.findAndSubst(key, props); - if(hierarchy instanceof RendererSupport) { - RendererMap.addRenderer((RendererSupport) hierarchy, renderedClass, - renderingClass); - } - } else if (key.equals(THROWABLE_RENDERER_PREFIX)) { - if (hierarchy instanceof ThrowableRendererSupport) { - ThrowableRenderer tr = (ThrowableRenderer) - OptionConverter.instantiateByKey(props, - THROWABLE_RENDERER_PREFIX, - org.apache.log4j.spi.ThrowableRenderer.class, - null); - if(tr == null) { - LogLog.error( - "Could not instantiate throwableRenderer."); - } else { - PropertySetter setter = new PropertySetter(tr); - setter.setProperties(props, THROWABLE_RENDERER_PREFIX + "."); - ((ThrowableRendererSupport) hierarchy).setThrowableRenderer(tr); - - } - } - } - } - } - - /** - Parse the additivity option for a non-root category. - */ - void parseAdditivityForLogger(Properties props, Logger cat, - String loggerName) { - String value = OptionConverter.findAndSubst(ADDITIVITY_PREFIX + loggerName, - props); - LogLog.debug("Handling "+ADDITIVITY_PREFIX + loggerName+"=["+value+"]"); - // touch additivity only if necessary - if((value != null) && (!value.equals(""))) { - boolean additivity = OptionConverter.toBoolean(value, true); - LogLog.debug("Setting additivity for \""+loggerName+"\" to "+ - additivity); - cat.setAdditivity(additivity); - } - } - - /** - This method must work for the root category as well. - */ - void parseCategory(Properties props, Logger logger, String optionKey, - String loggerName, String value) { - - LogLog.debug("Parsing for [" +loggerName +"] with value=[" + value+"]."); - // We must skip over ',' but not white space - StringTokenizer st = new StringTokenizer(value, ","); - - // If value is not in the form ", appender.." or "", then we should set - // the level of the loggeregory. - - if(!(value.startsWith(",") || value.equals(""))) { - - // just to be on the safe side... - if(!st.hasMoreTokens()) { - return; - } - - String levelStr = st.nextToken(); - LogLog.debug("Level token is [" + levelStr + "]."); - - // If the level value is inherited, set category level value to - // null. We also check that the user has not specified inherited for the - // root category. - if(INHERITED.equalsIgnoreCase(levelStr) || - NULL.equalsIgnoreCase(levelStr)) { - if(loggerName.equals(INTERNAL_ROOT_NAME)) { - LogLog.warn("The root logger cannot be set to null."); - } else { - logger.setLevel(null); - } - } else { - logger.setLevel(OptionConverter.toLevel(levelStr, Level.DEBUG)); - } - LogLog.debug("Category " + loggerName + " set to " + logger.getLevel()); - } - - // Begin by removing all existing appenders. - logger.removeAllAppenders(); - - Appender appender; - String appenderName; - while(st.hasMoreTokens()) { - appenderName = st.nextToken().trim(); - if(appenderName == null || appenderName.equals(",")) { - continue; - } - LogLog.debug("Parsing appender named \"" + appenderName +"\"."); - appender = parseAppender(props, appenderName); - if(appender != null) { - logger.addAppender(appender); - } - } - } - - Appender parseAppender(Properties props, String appenderName) { - Appender appender = registryGet(appenderName); - if((appender != null)) { - LogLog.debug("Appender \"" + appenderName + "\" was already parsed."); - return appender; - } - // Appender was not previously initialized. - String prefix = APPENDER_PREFIX + appenderName; - String layoutPrefix = prefix + ".layout"; - - appender = (Appender) OptionConverter.instantiateByKey(props, prefix, - org.apache.log4j.Appender.class, - null); - if(appender == null) { - LogLog.error( - "Could not instantiate appender named \"" + appenderName+"\"."); - return null; - } - appender.setName(appenderName); - - if(appender instanceof OptionHandler) { - if(appender.requiresLayout()) { - Layout layout = (Layout) OptionConverter.instantiateByKey(props, - layoutPrefix, - Layout.class, - null); - if(layout != null) { - appender.setLayout(layout); - LogLog.debug("Parsing layout options for \"" + appenderName +"\"."); - //configureOptionHandler(layout, layoutPrefix + ".", props); - PropertySetter.setProperties(layout, props, layoutPrefix + "."); - LogLog.debug("End of parsing for \"" + appenderName +"\"."); - } - } - final String errorHandlerPrefix = prefix + ".errorhandler"; - String errorHandlerClass = OptionConverter.findAndSubst(errorHandlerPrefix, props); - if (errorHandlerClass != null) { - ErrorHandler eh = (ErrorHandler) OptionConverter.instantiateByKey(props, - errorHandlerPrefix, - ErrorHandler.class, - null); - if (eh != null) { - appender.setErrorHandler(eh); - LogLog.debug("Parsing errorhandler options for \"" + appenderName +"\"."); - parseErrorHandler(eh, errorHandlerPrefix, props, repository); - final Properties edited = new Properties(); - final String[] keys = new String[] { - errorHandlerPrefix + "." + ROOT_REF, - errorHandlerPrefix + "." + LOGGER_REF, - errorHandlerPrefix + "." + APPENDER_REF_TAG - }; - for(Iterator iter = props.entrySet().iterator();iter.hasNext();) { - Map.Entry entry = (Map.Entry) iter.next(); - int i = 0; - for(; i < keys.length; i++) { - if(keys[i].equals(entry.getKey())) { - break; - } - } - if (i == keys.length) { - edited.put(entry.getKey(), entry.getValue()); - } - } - PropertySetter.setProperties(eh, edited, errorHandlerPrefix + "."); - LogLog.debug("End of errorhandler parsing for \"" + appenderName +"\"."); - } - - } - //configureOptionHandler((OptionHandler) appender, prefix + ".", props); - PropertySetter.setProperties(appender, props, prefix + "."); - LogLog.debug("Parsed \"" + appenderName +"\" options."); - } - parseAppenderFilters(props, appenderName, appender); - registryPut(appender); - return appender; - } - - private void parseErrorHandler( - final ErrorHandler eh, - final String errorHandlerPrefix, - final Properties props, - final LoggerRepository hierarchy) { - boolean rootRef = OptionConverter.toBoolean( - OptionConverter.findAndSubst(errorHandlerPrefix + ROOT_REF, props), false); - if (rootRef) { - eh.setLogger(hierarchy.getRootLogger()); - } - String loggerName = OptionConverter.findAndSubst(errorHandlerPrefix + LOGGER_REF , props); - if (loggerName != null) { - Logger logger = (loggerFactory == null) ? hierarchy.getLogger(loggerName) - : hierarchy.getLogger(loggerName, loggerFactory); - eh.setLogger(logger); - } - String appenderName = OptionConverter.findAndSubst(errorHandlerPrefix + APPENDER_REF_TAG, props); - if (appenderName != null) { - Appender backup = parseAppender(props, appenderName); - if (backup != null) { - eh.setBackupAppender(backup); - } - } - } - - - void parseAppenderFilters(Properties props, String appenderName, Appender appender) { - // extract filters and filter options from props into a hashtable mapping - // the property name defining the filter class to a list of pre-parsed - // name-value pairs associated to that filter - final String filterPrefix = APPENDER_PREFIX + appenderName + ".filter."; - int fIdx = filterPrefix.length(); - Hashtable filters = new Hashtable(); - Enumeration e = props.keys(); - String name = ""; - while (e.hasMoreElements()) { - String key = (String) e.nextElement(); - if (key.startsWith(filterPrefix)) { - int dotIdx = key.indexOf('.', fIdx); - String filterKey = key; - if (dotIdx != -1) { - filterKey = key.substring(0, dotIdx); - name = key.substring(dotIdx+1); - } - Vector filterOpts = (Vector) filters.get(filterKey); - if (filterOpts == null) { - filterOpts = new Vector(); - filters.put(filterKey, filterOpts); - } - if (dotIdx != -1) { - String value = OptionConverter.findAndSubst(key, props); - filterOpts.add(new NameValue(name, value)); - } - } - } - - // sort filters by IDs, insantiate filters, set filter options, - // add filters to the appender - Enumeration g = new SortedKeyEnumeration(filters); - while (g.hasMoreElements()) { - String key = (String) g.nextElement(); - String clazz = props.getProperty(key); - if (clazz != null) { - LogLog.debug("Filter key: ["+key+"] class: ["+props.getProperty(key) +"] props: "+filters.get(key)); - Filter filter = (Filter) OptionConverter.instantiateByClassName(clazz, Filter.class, null); - if (filter != null) { - PropertySetter propSetter = new PropertySetter(filter); - Vector v = (Vector)filters.get(key); - Enumeration filterProps = v.elements(); - while (filterProps.hasMoreElements()) { - NameValue kv = (NameValue)filterProps.nextElement(); - propSetter.setProperty(kv.key, kv.value); - } - propSetter.activate(); - LogLog.debug("Adding filter of type ["+filter.getClass() - +"] to appender named ["+appender.getName()+"]."); - appender.addFilter(filter); - } - } else { - LogLog.warn("Missing class definition for filter: ["+key+"]"); - } - } - } - - - void registryPut(Appender appender) { - registry.put(appender.getName(), appender); - } - - Appender registryGet(String name) { - return (Appender) registry.get(name); - } -} - -class PropertyWatchdog extends FileWatchdog { - - PropertyWatchdog(String filename) { - super(filename); - } - - /** - Call {@link PropertyConfigurator#configure(String)} with the - filename to reconfigure log4j. */ - public - void doOnChange() { - new PropertyConfigurator().doConfigure(filename, - LogManager.getLoggerRepository()); - } -} - -class NameValue { - String key, value; - public NameValue(String key, String value) { - this.key = key; - this.value = value; - } - public String toString() { - return key + "=" + value; - } -} - -class SortedKeyEnumeration implements Enumeration { - - private Enumeration e; - - public SortedKeyEnumeration(Hashtable ht) { - Enumeration f = ht.keys(); - Vector keys = new Vector(ht.size()); - for (int i, last = 0; f.hasMoreElements(); ++last) { - String key = (String) f.nextElement(); - for (i = 0; i < last; ++i) { - String s = (String) keys.get(i); - if (key.compareTo(s) <= 0) { - break; - } - } - keys.add(i, key); - } - e = keys.elements(); - } - - public boolean hasMoreElements() { - return e.hasMoreElements(); - } - - public Object nextElement() { - return e.nextElement(); - } -}