/*
 * Copyright (C) The Apache Software Foundation. All rights reserved.
 *
 * This software is published under the terms of the Apache Software
 * License version 1.1, a copy of which has been included with this
 * distribution in the LICENSE.txt file.  */


// Contibutors: "Luke Blanshard" <Luke@quiq.com>
//              "Mark DONSZELMANN" <Mark.Donszelmann@cern.ch>
//               Anders Kristensen <akristensen@dynamicsoft.com>

package org.apache.log4j;

import org.apache.log4j.Category;
import org.apache.log4j.Priority;
import org.apache.log4j.DefaultCategoryFactory;
import org.apache.log4j.config.PropertySetter;
//import org.apache.log4j.config.PropertySetterException;
import org.apache.log4j.spi.OptionHandler;
import org.apache.log4j.spi.Configurator;
import org.apache.log4j.spi.CategoryFactory;
import org.apache.log4j.or.ObjectRenderer;
import org.apache.log4j.or.RendererMap;
import org.apache.log4j.helpers.LogLog;
import org.apache.log4j.helpers.OptionConverter;
import org.apache.log4j.helpers.FileWatchdog;

import java.util.NoSuchElementException;
import java.util.Enumeration;
import java.util.Properties;
import java.io.FileInputStream;
import java.io.IOException;
import java.util.StringTokenizer;
import java.util.Hashtable;

/**
   Extends {@link BasicConfigurator} to provide configuration from an
   external file.  See <b>{@link #doConfigure(String, Hierarchy)}</b> for the
   expected format.

   <p>It is sometimes useful to see how log4j is reading configuration
   files. You can enable log4j internal logging by defining the
   <b>log4j.debug</b> variable.

   <P>As of log4j version 0.8.5, at the initialization of the Category
   class, the file <b>log4j.properties</b> 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.

   <p>The <code>PropertyConfigurator</code> does not handle the
   advanced configuration features supported by the {@link
   org.apache.log4j.xml.DOMConfigurator DOMConfigurator} such as
   support for {@link org.apache.log4j.spi.Filter Filters}, custom
   {@link org.apache.log4j.spi.ErrorHandler ErrorHandlers}, nested
   appenders such as the {@link org.apache.log4j.AsyncAppender
   AsyncAppender}, etc.

   <p><em>All option values admit variable substitution.</em> For
   example, if <code>java.home</code> system property is set to
   <code>/home/xyz</code> and the File option is set to the string
   <code>${java.home}/test.log</code>, then File option will be
   interpreted as the string <code>/home/xyz/test.log</code>.

   <p>The value of the substituted variable can be defined as a system
   property or in the configuration file file itself.

   <p>The syntax of variable substitution is similar to that of UNIX
   shells. The string between an opening <b>&quot;${&quot;</b> and
   closing <b>&quot;}&quot;</b> is interpreted as a key. Its value is
   searched in the system properties, and if not founf then in the
   configuration file being parsed.  The corresponding value replaces
   the ${variableName} sequence.



   @author Ceki G&uuml;lc&uuml;
   @author Anders Kristensen
   @since 0.8.1 */
public class PropertyConfigurator extends BasicConfigurator
           implements Configurator {

  /**
     Used internally to keep track of configured appenders.
   */
  protected Hashtable registry = new Hashtable(11);
  protected CategoryFactory categoryFactory = new DefaultCategoryFactory();
  
  static final String      CATEGORY_PREFIX = "log4j.category.";
  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      APPENDER_PREFIX = "log4j.appender.";  
  static final String      RENDERER_PREFIX = "log4j.renderer.";

  /** Key for specifying the {@link org.apache.log4j.spi.CategoryFactory
      CategoryFactory}.  Currently set to 
      "<code>log4j.categoryFactory</code>".  */
  public static final String CATEGORY_FACTORY_KEY = "log4j.categoryFactory";

  static final private String INTERNAL_ROOT_NAME = "root";
  
  /**
    Read configuration from a file. <b>The existing configuration is
    not cleared nor reset.</b> If you require a different behavior,
    then call {@link BasicConfigurator#resetConfiguration
    resetConfiguration} method before calling
    <code>doConfigure</code>.

    <p>The configuration file consists of statements in the format
    <code>key=value</code>. The syntax of different configuration
    elements are discussed below.

    <h3>Appender configuration</h3>

    <p>Appender configuration syntax is:
    <pre>
    # For appender named <i>appenderName</i>, 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
    </pre>
    
    For each named appender you can configure its {@link Layout}. The
    syntax for configuring an appender's layout is:
    <pre>
    log4j.appender.appenderName.layout=fully.qualified.name.of.layout.class
    log4j.appender.appenderName.layout.option1=value1
    ....
    log4j.appender.appenderName.layout.optionN=valueN
    </pre>
    
    <h3>Configuring categories</h3>

    <p>The syntax for configuring the root category is:
    <pre>
      log4j.rootCategory=[priority], appenderName, appenderName, ...
    </pre>

    <p>This syntax means that an optional <em>priority value</em> can
    be supplied followed by appender names separated by commas.

    <p>The priority value can consist of the string values FATAL,
    ERROR, WARN, INFO, DEBUG or a <em>custom priority</em> value. A
    custom priority value can be specified in the form
    <code>priority#classname</code>. 
    
    <p>If a priority value is specified, then the root priority is set
    to the corresponding priority.  If no priority value is specified,
    then the root priority remains untouched.

    <p>The root category can be assigned multiple appenders.
    
    <p>Each <i>appenderName</i> (separated by commas) will be added to
    the root category. The named appender is defined using the
    appender syntax defined above.

    <p>For non-root categories the syntax is almost the same:
    <pre>
    log4j.category.category_name=[priority|INHERITED], appenderName, appenderName, ...
    </pre>

    <p>The meaning of the optional priority value is discussed above
    in relation to the root category. In addition however, the value
    INHERITED can be specified meaning that the named category should
    inherit its priority from the category hierarchy.

    <p>If no priority value is supplied, then the priority of the
    named category remains untouched.

    <p>By default categories inherit their priority from the
    hierarchy. However, if you set the priority of a category and
    later decide that that category should inherit its priority, then
    you should specify INHERITED as the value for the priority value.
    
    <p>Similar to the root category syntax, each <i>appenderName</i>
    (separated by commas) will be attached to the named category.
    
    <p>See the <a href="../../../../manual.html#additivity">appender
    additivity rule</a> in the user manual for the meaning of the
    <code>additivity</code> flag.

    <p>The user can override any of the {@link
    Hierarchy#disable} family of methods by setting the a key
    "log4j.disableOverride" to <code>true</code> or any value other
    than false. As in <pre>log4j.disableOverride=true </pre>

    <h3>ObjectRenderers</h3>
    
    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.

    <p>The syntax is:

    <pre>
    log4j.renderer.fully.qualified.name.of.rendered.class=fully.qualified.name.of.rendering.class
    </pre>

    As in,
    <pre>
    log4j.renderer.my.Fruit=my.FruitRenderer
    </pre>

    <h3>Class Factories</h3>

    In case you are using your own subtypes of the
    <code>Category</code> class and wish to use configuration files,
    then you <em>must</em> set the <code>categoryFactory</code> for
    the subtype that you are using.
    
    <p>The syntax is:

    <pre>
    log4j.categoryFactory=fully.qualified.name.of.categoryFactory.class
    </pre>

    See {@link org.apache.log4j.examples.MyCategory} for an example.
    
    <h3>Example</h3>

    <p>An example configuration is given below. Other configuration
    file examples are given in {@link org.apache.log4j.examples.Sort}
    class documentation.

    <pre>

    # 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 
    # <b>%r %-5p %c{2} %M.%L %x - %m\n</b>. Thus, the log output will
    # include # the relative time since the start of the application in
    # milliseconds, followed by the priority of the log request,
    # followed by the two rightmost components of the category name,
    # followed by the callers method name, followed by the line number,
    # the nested disgnostic 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 category set to DEBUG using the A2 appender defined above.
    log4j.rootCategory=DEBUG, A2

    # Category definitions:
    # The SECURITY category inherits is priority from root. However, it's output
    # will go to A1 appender defined above. It's additivity is non-cumulative.
    log4j.category.SECURITY=INHERIT, A1
    log4j.additivity.SECURITY=false

    # Only warnings or above will be logged for the category "SECURITY.access".
    # Output will go to A1.
    log4j.category.SECURITY.access=WARN

    
    # The category "class.of.the.day" inherits its priority from the
    # category hierarchy.  Output will go to the appender's of the root
    # category, A2 in this case.
    log4j.category.class.of.the.day=INHERIT
    </pre>

    <p>Refer to the <b>setOption</b> method in each Appender and
    Layout for class specific options.
    
    <p>Use the <code>#</code> or <code>!</code> characters at the
    beginning of a line for comments.
   
   <p> 
   @param configFileName The name of the configuration file where the
   configuration information is stored.

  */
  public
  void doConfigure(String configFileName, Hierarchy hierarchy) {
    Properties props = new Properties();
    try {
      FileInputStream istream = new FileInputStream(configFileName);
      props.load(istream);
      istream.close();
    }
    catch (IOException e) {
      LogLog.error("Could not read configuration file ["+configFileName+"].", e);
      LogLog.error("Ignoring configuration file [" + configFileName+"].");
      return;
    }
    // If we reach here, then the config file is alright.
    doConfigure(props, hierarchy);
  }

  /**
   */
  static
  public 
  void configure(String configFilename) {
    new PropertyConfigurator().doConfigure(configFilename, 
					   Category.defaultHierarchy);
  }

  /**
     Read configuration options from url <code>configURL</code>.
     
     @since 0.8.2
   */
  public
  static
  void configure(java.net.URL configURL) {
    new PropertyConfigurator().doConfigure(configURL, Category.defaultHierarchy);
  }


  /**
     Read configuration options from <code>properties</code>.

     See {@link #doConfigure(String, Hierarchy)} for the expected format.
  */
  static
  public
  void configure(Properties properties) {
    new PropertyConfigurator().doConfigure(properties, Category.defaultHierarchy);
  }

  /**
     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 <code>configFilename</code> if it
     exists. Moreover, a thread will be created that will periodically
     check if <code>configFilename</code> has been created or
     modified. The period is determined by the <code>delay</code>
     argument. If a change or file creation is detected, then
     <code>configFilename</code> 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 <code>properties</code>.

     See {@link #doConfigure(String, Hierarchy)} for the expected format.
  */
  public
  void doConfigure(Properties properties, Hierarchy hierarchy) {

    String value = properties.getProperty(LogLog.DEBUG_KEY);
    if(value == null) {
      value = properties.getProperty(LogLog.CONFIG_DEBUG_KEY);
      if(value != null)
	LogLog.warn("[log4j.configDebug] is deprecated. Use [log4j.debug] instead.");
    }
    
    if(value != null) {
      LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true));
    }

    // Check if the config file overides the shipped code flag.
    //String override = properties.getProperty(
    //                              BasicConfigurator.DISABLE_OVERRIDE_KEY);
    //hierarchy.overrideAsNeeded(override);

    //if(override == null) {
    String disableStr = properties.getProperty(BasicConfigurator.DISABLE_KEY);
    if(disableStr != null)
      hierarchy.disable(disableStr);      
    //}
    
    
    configureRootCategory(properties, hierarchy);
    configureCategoryFactory(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 url <code>configURL</code>.
   */
  public
  void doConfigure(java.net.URL configURL, Hierarchy hierarchy) {
    Properties props = new Properties();
    LogLog.debug("Reading configuration from URL " + configURL);
    try {
      props.load(configURL.openStream());
    }
    catch (java.io.IOException e) {
      LogLog.error("Could not read configuration file from URL [" + configURL 
		   + "].", e);
      LogLog.error("Ignoring configuration file [" + configURL +"].");
      return;
    }
    doConfigure(props, hierarchy);
  }


  // --------------------------------------------------------------------------
  // Internal stuff
  // --------------------------------------------------------------------------

  /**
     Check the provided <code>Properties</code> object for a
     {@link org.apache.log4j.spi.CategoryFactory CategoryFactory}
     entry specified by {@link #CATEGORY_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 configureCategoryFactory(Properties props) {
    String factoryClassName = OptionConverter.findAndSubst(CATEGORY_FACTORY_KEY,
							   props);    
    if(factoryClassName != null) {
      LogLog.debug("Setting category factory to ["+factoryClassName+"].");
      categoryFactory = (CategoryFactory) 
                  OptionConverter.instantiateByClassName(factoryClassName,
							 CategoryFactory.class, 
							 categoryFactory);
      PropertySetter.setProperties(categoryFactory, 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, Hierarchy hierarchy) {
    String value = OptionConverter.findAndSubst(ROOT_CATEGORY_PREFIX, props);
    if(value == null) 
      LogLog.debug("Could not find root category information. Is this OK?");
    else {
      Category root = hierarchy.getRoot();
      synchronized(root) {
	parseCategory(props, root, ROOT_CATEGORY_PREFIX, INTERNAL_ROOT_NAME, 
		      value);
      }
    }        
  }


  /**
     Parse non-root elements, such non-root categories and renderers.
  */
  protected
  void parseCatsAndRenderers(Properties props, Hierarchy hierarchy) {
    Enumeration enum = props.propertyNames();
    while(enum.hasMoreElements()) {      
      String key = (String) enum.nextElement();
      if(key.startsWith(CATEGORY_PREFIX)) {
	String categoryName = key.substring(CATEGORY_PREFIX.length());	
	String value =  OptionConverter.findAndSubst(key, props);
	Category cat = hierarchy.getInstance(categoryName, categoryFactory);
	synchronized(cat) {
	  parseCategory(props, cat, key, categoryName, value);
	  parseAdditivityForCategory(props, cat, categoryName);
	}
      } else if(key.startsWith(RENDERER_PREFIX)) {
	String renderedClass = key.substring(RENDERER_PREFIX.length());	
	String renderingClass = OptionConverter.findAndSubst(key, props);
	addRenderer(hierarchy, renderedClass, renderingClass);
      }      
    }
  }  

  /**
     Parse the additivity option for a non-root category.
   */
  void parseAdditivityForCategory(Properties props, Category cat,
				  String categoryName) {
    String value = OptionConverter.findAndSubst(ADDITIVITY_PREFIX + categoryName, 
					     props);
    LogLog.debug("Handling "+ADDITIVITY_PREFIX + categoryName+"=["+value+"]");
    // touch additivity only if necessary	
    if((value != null) && (!value.equals(""))) {
      boolean additivity = OptionConverter.toBoolean(value, true);
      LogLog.debug("Setting additivity for \""+categoryName+"\" to "+
		   additivity); 
      cat.setAdditivity(additivity);
    }
  }
  
  /**
     This method must work for the root category as well.
   */
  void parseCategory(Properties props, Category cat, String optionKey,
		     String catName, String value) {

    LogLog.debug("Parsing for [" +catName +"] 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 priority of the category.
    
    if(!(value.startsWith(",") || value.equals(""))) {

      // just to be on the safe side...
      if(!st.hasMoreTokens())
	return;
    
      String priorityStr = st.nextToken();
      LogLog.debug("Priority token is [" + priorityStr + "].");

      // If the priority value is inherited, set category priority value to
      // null. We also check that the user has not specified inherited for the
      // root category.
      if(priorityStr.equalsIgnoreCase(BasicConfigurator.INHERITED) &&
                                	 !catName.equals(INTERNAL_ROOT_NAME)) {
	cat.setPriority(null);
      } else {
	cat.setLevel(OptionConverter.toLevel(priorityStr, 
					     Priority.DEBUG));
      }
      LogLog.debug("Category " + catName + " set to " + cat.getPriority());
    }

    // Remove all existing appenders. They will be reconstructed below.
    cat.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) {
	cat.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 +"\".");      
	}
      }
      //configureOptionHandler((OptionHandler) appender, prefix + ".", props);
      PropertySetter.setProperties(appender, props, prefix + ".");
      LogLog.debug("Parsed \"" + appenderName +"\" options.");
    }
    registryPut(appender);
    return appender;
  }

  
  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
     <code>filename</code> to reconfigure log4j. */
  public
  void doOnChange() {
    new PropertyConfigurator().doConfigure(filename, Category.defaultHierarchy);
  }
}
