You are viewing a plain text version of this content. The canonical link for it is here.
Posted to log4j-dev@logging.apache.org by ce...@apache.org on 2003/01/09 11:57:11 UTC

cvs commit: jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness confParsing.1 hello min.1 min.2 shallow.1

ceki        2003/01/09 02:57:11

  Added:       log4jMini build.xml
               log4jMini/docs .cvsignore index.html overview.html
               log4jMini/src/java/org/apache/log4j Appender.java
                        AppenderSkeleton.java Category.java
                        CategoryKey.java FileAppender.java Hierarchy.java
                        Layout.java NDC.java PatternLayout.java
                        Priority.java PropertyConfigurator.java
                        ProvisionNode.java StressCategory.java
                        WriterAppender.java package.html
               log4jMini/src/java/org/apache/log4j/examples .cvsignore
                        Makefile Sort.java SortAlgo.java Trivial.java
                        sort1.lcf sort2.lcf sort3.lcf
               log4jMini/src/java/org/apache/log4j/helpers
                        FormattingInfo.java LogLog.java
                        OptionConverter.java PatternConverter.java
                        PatternParser.java
               log4jMini/src/java/org/apache/log4j/spi LoggingEvent.java
                        OptionHandler.java RootCategory.java
               log4jMini/src/java/org/apache/log4j/test .cvsignore
                        .functions ConfigurationFileParsing.java Hello.java
                        Min.java Shallow.java confParsing hello min shallow
               log4jMini/src/java/org/apache/log4j/test/witness
                        confParsing.1 hello min.1 min.2 shallow.1
  Log:
  Added log4jMini to CVS repository as requested on the developers list.
  
  Revision  Changes    Path
  1.1                  jakarta-log4j/log4jMini/build.xml
  
  Index: build.xml
  ===================================================================
  
  <project name="log4jMini" default="build" basedir="." >
  
    <property name="version" value="1.2alpha"/>
  
    <!-- The base directory relative to which most targets are built -->
    <property name="base" value="."/>
   
    <!-- The directory where source files are stored. -->
    <property name="java.source.dir" value="src/java/"/>
  
    <!-- The directory where the package-list file is found, ./ or -->
    <!-- build/ -->
    <property name="packaging.dir" value="build"/>
  
    <!-- Destination for compiled files -->
    <property name="javac.dest" value="dist/classes"/>
  
    <!-- Destination for generated jar files -->
    <property name="jar.dest" value="${basedir}"/>
  
    <!-- The jar file that the jar task will generate -->
    <property name="log4jMini.jar" value="log4jMini-${version}.jar"/>
  
    <!-- Destination for documentation files generated or not -->
    <property name="docs" value="docs"/>
  
    <!-- Destination for javadoc generated files -->
    <property name="javadoc.dest" value="docs/api"/>
  
    <!-- The stem where most log4j source code is located. -->
    <property name="stem" value="org/apache/log4j"/>
  
    <!-- Some targets needs a more precise stem. -->
    <property name="BSTEM" value="${java.source.dir}/${stem}"/>
  
    <!-- Original manifest.mf file before filtering. -->
    <property name="manifest.src" value="build/manifest.mf"/>
  
    <!-- Directory where release images go. -->
    <property name="dist.images"  value="dist/images"/>
  
    <!-- Directory for temporary files. -->
    <property name="dist.tmp" value="dist/tmp"/>
  
    
    <!-- Construct compile classpath -->
    <path id="compile.classpath">
      <pathelement location="${build.home}/classes"/>
    </path>
  
    <target name="junitCheck">
      <available classname="junit.framework.TestCase" property="junit-present"/>
    </target>   
    <target name="junit" depends="junitCheck" if="junit-present">
      <echo message="JUnit is present."/>
    </target>
  
    <!-- ================================================================= -->
    <!-- Initialize variables                                              -->
    <!-- NOTE: all directories are relative to jakarta-log4j/              -->
    <!-- ================================================================= -->
    <target name="init">
      <tstamp />
    </target>
  
    <target name="build" depends="init">
      <mkdir dir="${javac.dest}" />
      <javac srcdir="${java.source.dir}"
             destdir="${javac.dest}"
             includes="${stem}/**/*.java, ${stem}/xml/XMLLayout.java,"
             excludes="**/examples/**, ${stem}/StressCategory.java"
             deprecation="${deprecation}"
             debug="on">
       <classpath refid="compile.classpath"/>
      </javac>
    </target>
  
    <!-- ================================================================= -->
    <!-- Remove all generated (compiled) class files.                      -->
    <!-- ================================================================= -->
    <target name="clean" depends="init">
      <delete dir="${javac.dest}/" />
    </target>
  
    <!-- ================================================================= -->
    <!-- Create log4jMini.jar, excluding tests and other odds and ends.        -->
    <!-- ================================================================= -->
    <target name="jar" depends="build">
      <delete>
        <fileset dir="${jar.dest}">
          <include name="${log4j.jar}"/>
        </fileset>
      </delete>
  
      <jar jarfile="${jar.dest}/${log4j.jar}" basedir="${javac.dest}"
          includes="${stem}/*.class, 
  	          ${stem}/helpers/*.class,
                    ${stem}/spi/*.class, 
  		  ${stem}/or/*.class,
  		  ${stem}/config/PropertySetter.class
  		  ${stem}/config/PropertySetterException.class"
        excludes="**/UnitTest**,
                  **/examples/**,
                  **/selectors/*.class,
                  **/servlet/*.class">
  
        <manifest>
          <attribute name="Manifest-version" value="1.0"/>
          <section name="org/apache/log4j/">
            <attribute name="Implementation-Title" value="log4jMini"/>
            <attribute name="Implementation-Version" value="${version}"/>
            <attribute name="Implementation-Vendor" value="Apache Software Foundation"/>
          </section>
        </manifest>
      </jar>
    </target>
  
    <!-- ================================================================= -->
    <!-- This target builds the javadoc files.                             -->
    <!-- ================================================================= -->
    <target name="javadoc" depends="init">
  
      <mkdir dir="${javadoc.dest}" />
  
      <javadoc sourcepath="${java.source.dir}" 
             destdir="${javadoc.dest}" 
  	   packagenames="org.apache.log4j,
                           org.apache.log4j.helpers,
  		         org.apache.log4j.spi"
  	   version="true"
  	   protected="true"
  	   author="true"
  	   use="true"		   
  	   overview="${docs}/overview.html"
  	   doctitle="log4j MicroEdition version ${version}&lt;br&gt;API Specification"
  	   windowtitle="Log4jME Version ${version}" 
             header="&lt;b&gt;Log4jME ${version}&lt;/b&gt;"
  	   bottom="Please &lt;a href=http://lists.sourceforge.net/mailman/listinfo/log4j-announce&gt;&lt;b&gt;notify me&lt;/b&gt;&lt;/a&gt; about new log4j releases. &lt;hr&gt;"> 
  		   
             <link offline="true" 
                   href="http://java.sun.com/products/jdk/1.2/docs/api"
                   packageListLoc="${packaging.dir}"/>
      </javadoc>		
    </target>
  
   <!-- ================================================================= -->
   <!-- Build a complete distribution. Results go to ${dist.images}       -->
   <!-- ================================================================= -->
    <target name="dist" depends="init, clean, jar">
  
      <delete verbose="true">
        <fileset dir="."> 
          <patternset>
  	   <include name="**/*.bak"/>
  	   <include name="dist/velocity.log"/>
  	   <include name="${BSTEM}/**/temp*"/>
  	   <include name="${BSTEM}/performance/test"/>
  	   <include name="${BSTEM}/test/current.*"/>
  	   <include name="${BSTEM}/test/current.*"/>
  	   <include name="${BSTEM}/examples/test"/>
  	   <include name="${BSTEM}/test/logging.*"/>
  	   <include name="${BSTEM}/test/log4j.properties"/>
  	   <include name="{$BSTEM}/test/socket.lcf"/>
  	   <include name="${BSTEM}/test/file"/>
  	   <include name="${BSTEM}/test/output.*"/>
  	   <include name="${jar.dest}/manifest.mf"/>
  	   <include name="${javac.dest}/*.class"/>
          </patternset>
       </fileset>         
      </delete>
  
      <mkdir  dir="${dist.images}" />
  
      <mkdir  dir="${dist.tmp}/log4jME-${version}" />
  
      <copy todir="${dist.tmp}/log4jME-${version}">
         <fileset dir="${base}"
                  includes="make/**,
  		          src/**, 
  			  docs/**, 
  			  Makefile, 
  			  build/*, build.bat, build.sh,
  			  build/lib/*.jar,
                            manifest.mf, 
  			  INSTALL, 
  			  LICENSE.txt, 
  			  dist/lib/*.jar, 
  		          org/**,  
  			  dist/classes/**"
                  excludes="make/make.loc, 
  		          **/*.bak, **/goEnv.bat,
  			  **/.#*"/>
      </copy>
  
      
      <fixcrlf srcdir="${dist.tmp}/log4jME-${version}"  
               includes="build.sh" cr="remove"/>
      <fixcrlf srcdir="${dist.tmp}/log4jME-${version}"   
               includes="build.bat" cr="add"/>
      <chmod   dir="${dist.tmp}/log4jME-${version}"   
               includes="build.sh" perm="+x"/>
  
      <tar tarfile="${dist.images}/log4jME-${version}.tar" 
           basedir="${dist.tmp}"
           includes="log4jME-${version}/**" />
  
      <gzip src="${dist.images}/log4jME-${version}.tar" 
            zipfile="${dist.images}/log4jME-${version}.tar.gz" />
  
      <zip zipfile="${dist.images}/log4jME-${version}.zip" 
           basedir="${dist.tmp}"
           includes="log4jME-${version}/**" />
  
      	 
      <delete dir="${dist.tmp}" />
  
    </target>
  
  </project>
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/docs/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  api
  
  
  1.1                  jakarta-log4j/log4jMini/docs/index.html
  
  Index: index.html
  ===================================================================
  
  <HTML>
  
  <BODY>
  
  <p>Log4jME, or log4j MicroEdition is based on nearly the same code as
  <a href="http://jakarta.apache.org/log4j">log4j</a>. However, as the
  name indicates the micro-edition is much smaller. It offers the same
  client interface such that code compiled for log4jME is 100%
  compatible with log4j standard edition. You can choose to upgrade to
  log4j standard edition at any time by replacing
  <code>log4jME.jar</code> with <code>log4j.jar</code> in your
  classpath.
  
  <p>Download log4jME version 1.0beta1 including full source code, class
  files and documentation in <a
  href="../log4jME-1.0b1.tar.gz"><b>TAR.GZ</b></a> format or in <a
  href="../log4jME-1.0b1.zip"><b>ZIP</b></a> format. 
  
  <p>You may also browse log4jME <a
  href="api/index.html">documentation</a>.
  
  </BODY>
  
  </HTML>
  
  
  1.1                  jakarta-log4j/log4jMini/docs/overview.html
  
  Index: overview.html
  ===================================================================
  <html>
  <head>
  
  <title>Log4jME</title>
  </head>
  <body>
  
  <p>Log4jME, or log4j MicroEdition is based on nearly the same code as
  <a href="http://jakarta.apache.org/log4j">log4j</a>. However, as the
  name indicates the micro-edition is much smaller. It offers the same
  client interface such that code compiled for log4jME is 100%
  compatible with log4j standard edition. You can choose to upgrade to
  log4j standard edition at any time by replacing
  <code>log4jME.jar</code> with <code>log4j.jar</code> in your
  classpath.
  
  <p>The features of log4jME are
  
  <ul>
  
  <li><b>Same client interface</b>
  
  <p>The <code>org.apache.log4j.Category</code> shipped with log4jME has
  the same interface except support for <code>ResourceBundles</code>,
  custom category factories and object renderers.
  
  <p><li><b>Smaller org.apache.log4j.FileAppender</b>
  
  <p>Log4jME contains a modified
  <code>org.apache.log4jFileAppender</code> which supports logging to
  files and output streams including <code>Systemout</code> and
  <code>System.err</code>. 
  
  <p><li><b>Smaller org.apache.log4j.PatternLayout</b>
  
  <p>Log4jME contains a modified
  <code>org.apache.log4j.PatternLayout</code> which supports the a
  limited set of conversion characters namely,
  <code>%p</code>,
  <code>%t</code>, 
  <code>%r</code>, 
  <code>%c</code>, 
  <code>%m</code>, 
  <code>%n</code>
  as well as literals. In particular, the <code>%d</code> ans
  <code>%x</code> conversion characters are not supported.
  
  <p><li><b>Smaller org.apache.log4j.PropertyConfigurator</b>
  
  <p>Log4jME contains a modified
  <code>org.apache.log4j.PropertyConfigurator</code> which supports the
  same configuration syntax as the <code>PropertyConfigurator</code> in
  the standard edition except support for category factories and
  renderers.
  </ul>
  
  <p>The micro edition does nor offer the same number of appenders and
  layouts as in the standard edition. The <code>DOMConfigurator</code>
  is also not supported.
  
  </body> </html>
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/Appender.java
  
  Index: Appender.java
  ===================================================================
  
  package org.apache.log4j;
  
  import org.apache.log4j.spi.LoggingEvent;
  
  /**
     Implement this interface for your own strategies for printing log
     statements. 
  
     @author Ceki G&uuml;lc&uuml;
  */
  public interface Appender {
  
  
    /**
       Release any resources allocated within the appender such as file
       handles, network connections, etc.
  
       <p>It is a programming error to append to a closed appender.
  
       @since 0.8.4
    */
    public
    void close();
    
    /**
       Log in Appender specific way.  */
    public
    void doAppend(LoggingEvent event);
  
  
    /**
       Get the name of this appender. The name uniquely identifies the
       appender.  */
    public
    String getName();
  
  
    /**
       Set the {@link Layout} for this appender.
  
       @since 0.8.1
    */
    public
    void setLayout(Layout layout);
  
    /**
       Returns this appenders layout.
       
       @since 1.1
    */
    public
    Layout getLayout();
    
  
    /**
       Set the name of this appender. The name is used by other
       components to identify this appender.
  
       @since 0.8.1
    */
    public
    void setName(String name);
  
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/AppenderSkeleton.java
  
  Index: AppenderSkeleton.java
  ===================================================================
  package org.apache.log4j;
  
  import org.apache.log4j.Layout;
  import org.apache.log4j.spi.LoggingEvent;
  import org.apache.log4j.spi.OptionHandler;
  import org.apache.log4j.helpers.LogLog;
  
  
  /** 
     Abstract superclass of the other appenders in the package.
     
     This class provides the code for common functionality, such as
     support for threshold filtering and support for general filters.
  
     @since 0.8.1
     @author Ceki G&uuml;lc&uuml; */
  public abstract class AppenderSkeleton implements Appender, OptionHandler {
  
    /** The layout variable does not need to be set if the appender
        implementation has its own layout. */
    protected Layout layout;
  
    /** Appenders are named. */
    protected String name;
  
    /**
       There is no priority threshold filtering by default.  */
    protected Priority threshold;
  
    /**
       Is this appender closed? 
     */
    protected boolean closed = false;
  
    boolean firstTime = true;
  
    /**
       A string constant used in naming the option for setting the
       threshold for the appender. See also {@link #setThreshold
       setThreshold} method. Current value of this string constant is
       <b>Threshold</b>.
  
       <p>Note that all option keys are case sensitive.
       
    */
    public static final String THRESHOLD_OPTION = "Threshold";
    
  
    /**
       Derived appenders should override this method if option structure
       requires it.  */
    public
    void activateOptions() {
    }
  
  
    /**
       Subclasses of <code>AppenderSkeleton</code> should implement this
       method to perform actual logging. See also {@link #doAppend
       AppenderSkeleton.doAppend} method.
  
       @since 0.9.0
    */
    abstract
    protected
    void append(LoggingEvent event);
  
  
    /**
       Finalize this appender by calling the imlenentation's
       <code>close</code> method.
  
       @since 0.8.4
    */
    public
    void finalize() {
      // An appender might be closed then garbage collected. There is no
      // point in closing twice.
      if(this.closed) 
        return;
      close();
    }
  
    /**
       Prints the message and the stack trace of the exception on
       <code>System.err</code>.  */
    public
    void error(String message, Exception e) { 
      if(firstTime) {
        LogLog.error(message, e);
        firstTime = false;
      }
    }
  
    /**
       Print a the error message passed as parameter on
       <code>System.err</code>.  
    */
    public
    void error(String message) {
      error(message, null);
    }
  
    /**
       Returns the layout of this appender. The value may be null.
    */
    public
    Layout getLayout() {
      return layout;
    }
  
  
    /**
       Returns the name of this FileAppender.
     */
    public
    final
    String getName() {
      return this.name;
    }
  
    /**
       Returns the string array {{@link #THRESHOLD_OPTION}}.
  
       <p>Configurable Appenders must override this method to return the
       additional options they accept.  */
    public
    String[] getOptionStrings() {
      return new String[] {THRESHOLD_OPTION};
    }
  
    /**
       Returns this appenders threshold priority. See the {@link
       #setThreshold} method for the meaning of this option.
       
       @since 1.1 */
    public
    Priority getThreshold() {
      return threshold;
    }
  
  
    /**
       Check whether the message priority is below the appender's
       threshold. If there is no threshold set, then the return value is
       always <code>true</code>.
  
    */
    public
    boolean isAsSevereAsThreshold(Priority priority) {
      return ((threshold == null) || priority.isGreaterOrEqual(threshold));
    }
  
  
    /**
       This method performs threshold checks and invokes filters before
       delegating actual logging to the subclasses specific {@link
       AppenderSkeleton#append} method.
  
     */
    public
    synchronized 
    void doAppend(LoggingEvent event) {
      if(closed) {
        LogLog.warn("Appender ["+name+"] is closed.");
      }
  
      if(!isAsSevereAsThreshold(event.priority)) {
        return;
      }
      
      this.append(event);    
    }
  
    /**
       Set the layout for this appender. Note that some appenders have
       their own (fixed) layouts or do not use one. 
    */
    public
    void setLayout(Layout layout) {
      this.layout = layout;
    }
  
    
    /**
       Set the name of this Appender.
     */
    public
    void setName(String name) {
      this.name = name;
    }
  
    /**
       Configurable Appenders should override this method if they admit
       additional options.
  
       All classes derived from {@link AppenderSkeleton} admit the
       <b>Threshold</b> option, that is the value of the string constant
       {@link #THRESHOLD_OPTION}.
  
       See {@link #setThreshold} method for the meaning of this option.
    */
    public
    void setOption(String key, String value) {
      if(key.equalsIgnoreCase(THRESHOLD_OPTION)) {
        threshold = Priority.toPriority(value);
      }
    }
  
    /**
       Set the threshold priority. All log events with lower priority
       than the threshold priority are ignored by the appender.
       
       <p>In configuration files this option is specified by setting the
       value of the <b>Threshold</b> option to a priority
       string, such as "DEBUG", "INFO" and so on.
       
       @since 0.8.3 */
    public
    void setThreshold(Priority threshold) {
      this.threshold = threshold;
    }  
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/Category.java
  
  Index: Category.java
  ===================================================================
  /*
   * 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: Alex Blewitt <Al...@ioshq.com>
  //              Markus Oestreicher <oe...@zurich.ibm.com>
  //              Frank Hoering <fh...@zurich.ibm.com>
  //              Nelson Minar <ne...@media.mit.edu>
  //              Jim Cakalic <ji...@na.biomerieux.com>
  //              Avy Sharell <as...@club-internet.fr>
  //              Ciaran Treanor <ci...@xelector.com>
  //              Jeff Turner <je...@socialchange.net.au>
  //              Michael Horwitz <MH...@siemens.co.za>
  //              Calvin Chan <ca...@hic.gov.au>
  //              Aaron Greenhouse <aa...@cs.cmu.edu>
  //              Beat Meier <bm...@infovia.com.ar>
  
  package org.apache.log4j;
  
  import org.apache.log4j.Priority;
  import org.apache.log4j.spi.RootCategory;
  import org.apache.log4j.spi.LoggingEvent;
  import org.apache.log4j.helpers.LogLog;
  
  import java.util.Enumeration;
  import java.util.Vector;
  import java.util.MissingResourceException;
  import java.text.MessageFormat;
  import java.util.ResourceBundle;
  import java.net.URL;
  import java.net.MalformedURLException;
  
  
  /**
    This is the central class in the log4j package. One of the
    distintive features of log4j are hierarchical categories and their
    evaluation.
  
    <p>See the <a href="../../../../manual.html">user manual</a> for an
    introduction on this class. 
  
    @author Ceki G&uuml;lc&uuml;
    @author Anders Kristensen */
  public class Category {
  
    /**
       The hierarchy where categories are attached to by default.
    */
    static 
    public 
    final Hierarchy defaultHierarchy = new Hierarchy(new 
  						   RootCategory(Priority.DEBUG));
  
    /**
       The name of this category.
    */
    protected String   name;  
  
    /**
       The assigned priority of this category.  The
       <code>priority</code> variable need not be assined a value in
       which case it is inherited form the hierarchy.  */
    volatile protected Priority priority;
  
    /**
       The parent of this category. All categories have at least one
       ancestor which is the root category. */
    volatile protected Category parent;
  
    // Categories need to know what Hierarchy they are in
    protected Hierarchy hierarchy;
    
    /** Array of appenders. */
    protected Vector  appenderList;
  
    /** Additivity is set to true by default, that is children inherit
        the appenders of their ancestors by default. If this variable is
        set to <code>false</code> then the appenders found in the
        ancestors of this category are not used. However, the children
        of this category will inherit its appenders, unless the children
        have their additivity flag set to <code>false</code> too. See
        the user manual for more details. */
    protected boolean additive = true;
    
    /**
       This constructor created a new <code>Category</code> instance and
       sets its name.
  
       <p>It is intended to be used by sub-classes only. You should not
       create categories directly.
  
       @param name The name of the category.  
    */
    protected 
    Category(String name) {
      this.name = name;
    }
  
    /**
       Add <code>newAppender</code> to the list of appenders of this
       Category instance.
  
       <p>If <code>newAppender</code> is already in the list of
       appenders, then it won't be added again.
    */
    synchronized  
    public 
    void addAppender(Appender newAppender) {
      // Null values for newAppender parameter are strictly forbidden.
      if(newAppender == null)
        return;
      
      if(appenderList == null) {
        appenderList = new Vector(1);
      }
      if(!appenderList.contains(newAppender))
        appenderList.addElement(newAppender);
    }
  
    public
    int appendLoopOnAppenders(LoggingEvent event) {
      int size = 0;
      Appender appender;
  
      if(appenderList != null) {
        size = appenderList.size();
        for(int i = 0; i < size; i++) {
  	appender = (Appender) appenderList.elementAt(i);
  	appender.doAppend(event);
        }
      }    
      return size;
    }
  
    /**
       Call the appenders in the hierrachy starting at
       <code>this</code>.  If no appenders could be found, emit a
       warning.
  
       <p>This method calls all the appenders inherited from the
       hierarchy circumventing any evaluation of whether to log or not
       to log the particular log request.
       
       @param LoggingEvent the event to log.  */
    public
    void callAppenders(LoggingEvent event) {
      int writes = 0;
  
      for(Category c = this; c != null; c=c.parent) {
        // Protected against simultaneous call to addAppender, removeAppender,...
        synchronized(c) {
  	if(c.appenderList != null) {
  	  writes += c.appendLoopOnAppenders(event);
  	}
  	if(!c.additive) {
  	  break;
  	}
        }
      }
      // No appenders in hierarchy, warn user only once.
      if(!hierarchy.emittedNoAppenderWarning && writes == 0) {
        LogLog.error("No appenders could be found for category (" +
  		    this.getName() + ").");
        LogLog.error("Please initialize the log4j system properly.");
        hierarchy.emittedNoAppenderWarning = true;
      }
    }
  
    /** 
      Log a message object with the {@link Priority#DEBUG DEBUG} priority.
  
      <p>This method first checks if this category is <code>DEBUG</code>
      enabled by comparing the priority of this category with the {@link
      Priority#DEBUG DEBUG} priority. If this category is
      <code>DEBUG</code> enabled, then it invokes all the registered
      appenders in this category and also higher in the hierarchy
      depending on the value of the additivity flag.
  
      <p><b>WARNING</b> Note that passing a {@link Throwable} to this
      method will print the name of the <code>Throwable</code> but no
      stack trace. To print a stack trace use the {@link #debug(Object,
      Throwable)} form instead.
      
      @param message the message object to log. */
    public
    void debug(Object message) {
      if(hierarchy.enableInt >  Priority.DEBUG_INT) 
        return;    
      if(Priority.DEBUG.isGreaterOrEqual(this.getChainedPriority())) {
        forcedLog(Priority.DEBUG, message, null);
      }
    }
    
  
    /**  
     Log a message object with the <code>DEBUG</code> priority including
     the stack trace of the {@link Throwable} <code>t</code> passed as
     parameter.
     
     <p>See {@link #debug(Object)} form for more detailed information.
     
     @param message the message object to log.
     @param t the exception to log, including its stack trace.  */  
    public
    void debug(Object message, Throwable t) {
      if(hierarchy.enableInt >  Priority.DEBUG_INT) 
        return;
      if(Priority.DEBUG.isGreaterOrEqual(this.getChainedPriority()))
        forcedLog(Priority.DEBUG, message, t);    
    }
  
    /** 
      Log a message object with the {@link Priority#ERROR ERROR} priority.
  
      <p>This method first checks if this category is <code>ERROR</code>
      enabled by comparing the priority of this category with {@link
      Priority#ERROR ERROR} priority.  If this category is
      <code>DEBUG</code> enabled, then it invokes all the registered
      appenders in this category and also higher in the hierarchy
      depending on the value of the additivity flag.
  
      <p><b>WARNING</b> Note that passing a {@link Throwable} to this
      method will print the name of the <code>Throwable</code> but no
      stack trace. To print a stack trace use the {@link #error(Object,
      Throwable)} form instead.
      
      @param message the message object to log */
    public
    void error(Object message) {
      if(hierarchy.enableInt >  Priority.ERROR_INT) 
        return;
      if(Priority.ERROR.isGreaterOrEqual(this.getChainedPriority()))
        forcedLog(Priority.ERROR, message, null);
    }
  
    /** 
     Log a message object with the <code>ERROR</code> priority including
     the stack trace of the {@link Throwable} <code>t</code> passed as
     parameter.
     
     <p>See {@link #error(Object)} form for more detailed information.
     
     @param message the message object to log.
     @param t the exception to log, including its stack trace.  */  
    public
    void error(Object message, Throwable t) {
      if(hierarchy.enableInt >  Priority.ERROR_INT) 
        return;
      if(Priority.ERROR.isGreaterOrEqual(this.getChainedPriority()))
        forcedLog(Priority.ERROR, message, t);
      
    }
  
    /** 
      Log a message object with the {@link Priority#FATAL FATAL} priority.
  
      <p>This method first checks if this category is <code>FATAL</code>
      enabled by comparing the priority of this category with {@link
      Priority#FATAL FATAL} priority.  If this category is
      <code>DEBUG</code> enabled, then it invokes all the registered
      appenders in this category and also higher in the hierarchy
      depending on the value of the additivity flag.
  
      <p><b>WARNING</b> Note that passing a {@link Throwable} to this
      method will print the name of the Throwable but no stack trace. To
      print a stack trace use the {@link #fatal(Object, Throwable)} form
      instead. 
      
      @param message the message object to log */
    public
    void fatal(Object message) {
      if(hierarchy.enableInt >  Priority.FATAL_INT) 
        return;    
      if(Priority.FATAL.isGreaterOrEqual(this.getChainedPriority()))
        forcedLog(Priority.FATAL, message, null);
    }
    
    /** 
     Log a message object with the <code>FATAL</code> priority including
     the stack trace of the {@link Throwable} <code>t</code> passed as
     parameter.
     
     <p>See {@link #fatal(Object)} for more detailed information.
     
     @param message the message object to log.
     @param t the exception to log, including its stack trace.  */
    public
    void fatal(Object message, Throwable t) {
      if(hierarchy.enableInt >  Priority.FATAL_INT) 
        return;   
      if(Priority.FATAL.isGreaterOrEqual(this.getChainedPriority()))
        forcedLog(Priority.FATAL, message, t);
    }
  
  
    /**
       This method creates a new logging event and logs the event
       without further checks.  */
    protected
    void forcedLog(Priority priority, Object message, Throwable t) {
      callAppenders(new LoggingEvent(this, priority, message, t));
    }
  
  
    /**
       Get the additivity flag for this Category instance.  
    */
    public
    boolean getAdditivity() {
      return additive;
    }
  
  
    /**
       Starting from this category, search the category hierarchy for a
       non-null priority and return it. Otherwise, return the priority of the
       root category.
       
       <p>The Category class is designed so that this method executes as
       quickly as possible.
     */
    public 
    Priority getChainedPriority() {
      for(Category c = this; c != null; c=c.parent) {
        if(c.priority != null) 
  	return c.priority;
      }
      return null; // If reached will cause an NullPointerException.
    }
  
   /**
       Return the the {@link Hierarchy} where this <code>Category</code> instance is
       attached.
  
       @since 1.1 */
    public  
    Hierarchy getHierarchy() {
      return hierarchy;
    }
  
    
   /**
       Retrieve a category with named as the <code>name</code>
       parameter. If the named category already exists, then the
       existing instance will be reutrned. Otherwise, a new instance is
       created. 
  
       By default, categories do not have a set priority but inherit
       it from the hierarchy. This is one of the central features of
       log4j.
  
       @param name The name of the category to retrieve.  */
    public
    static
    Category getInstance(String name) {
      return defaultHierarchy.getInstance(name);
    }	
  
   /**
      Shorthand for <code>getInstance(clazz.getName())</code>.
  
      @param clazz The name of <code>clazz</code> will be used as the
      name of the category to retrieve.  See {@link
      #getInstance(String)} for more detailed information.
  
      @since 1.0 */
    public
    static
    Category getInstance(Class clazz) {
      return getInstance(clazz.getName());
    }	
  
    /**
       Return the category name.  */
    public
    final
    String getName() {
      return name;
    }
      
    /**
       Returns the assigned {@link Priority}, if any, for this Category.  
       
       @return Priority - the assigned Priority, can be <code>null</code>.
    */
    final
    public
    Priority getPriority() {
      return this.priority;
    }
  
    /**
       Return the root of the default category hierrachy.
  
       <p>The root category is always instantiated and available. It's
       name is "root".
  
       <p>Nevertheless, calling {@link #getInstance
       Category.getInstance("root")} does not retrieve the root category 
       but a category just under root named "root".
       
     */
    final
    public
    static
    Category getRoot() {
      return defaultHierarchy.getRoot();
    }
  
  
    /** 
      Log a message object with the {@link Priority#INFO INFO} priority.
  
      <p>This method first checks if this category is <code>INFO</code>
      enabled by comparing the priority of this category with {@link
      Priority#INFO INFO} priority.  If this category is
      <code>DEBUG</code> enabled, then it invokes all the registered
      appenders in this category and also higher in the hierarchy
      depending on the value of the additivity flag.
  
      <p><b>WARNING</b> Note that passing a {@link Throwable} to this
      method will print the name of the Throwable but no stack trace. To
      print a stack trace use the {@link #info(Object, Throwable)} form
      instead. 
      
      @param message the message object to log */
    public
    void info(Object message) {
      if(hierarchy.enableInt >  Priority.INFO_INT) 
        return;    
      if(Priority.INFO.isGreaterOrEqual(this.getChainedPriority()))
        forcedLog(Priority.INFO, message, null);
    }
    
    /** 
     Log a message object with the <code>INFO</code> priority including
     the stack trace of the {@link Throwable} <code>t</code> passed as
     parameter.
     
     <p>See {@link #info(Object)} for more detailed information.
     
     @param message the message object to log.
     @param t the exception to log, including its stack trace.  */
    public
    void info(Object message, Throwable t) {
      if(hierarchy.enableInt >  Priority.INFO_INT) 
        return;   
      if(Priority.INFO.isGreaterOrEqual(this.getChainedPriority()))
        forcedLog(Priority.INFO, message, t);
    }
  
    /**
      *  Check whether this category is enabled for the <code>DEBUG</code>
      *  priority.
      *  
      *  <p> This function is intended to lessen the computational cost of
      *  disabled log debug statements.
      * 
      *  <p> For some <code>cat</code> Category object, when you write,
      *  <pre>
      *      cat.debug("This is entry number: " + i );
      *  </pre>
      *  
      *  <p>You incur the cost constructing the message, concatenatiion in
      *  this case, regardless of whether the message is logged or not.
      * 
      *  <p>If you are worried about speed, then you should write
      *  <pre>
      * 	 if(cat.isDebugEnabled()) { 
      * 	   cat.debug("This is entry number: " + i );
      * 	 }
      *  </pre>
      * 
      *  <p>This way you will not incur the cost of parameter
      *  construction if debugging is disabled for <code>cat</code>. On
      *  the other hand, if the <code>cat</code> is debug enabled, you
      *  will incur the cost of evaluating whether the category is debug
      *  enabled twice. Once in <code>isDebugEnabled</code> and once in
      *  the <code>debug</code>.  This is an insignificant overhead
      *  since evaluating a category takes about 1%% of the time it
      *  takes to actually log.
      * 
      *  @return boolean - <code>true</code> if this category is debug
      *  enabled, <code>false</code> otherwise.
      *   */
    public
    boolean isDebugEnabled() {
      if(hierarchy.enableInt >  Priority.DEBUG_INT)
        return false;   
      return Priority.DEBUG.isGreaterOrEqual(this.getChainedPriority());
    }
    
    /**
       Check whether this category is enabled for a given {@link
       Priority} passed as parameter.
  
       See also {@link #isDebugEnabled}.
         
       @return boolean True if this category is enabled for <code>priority</code>.
    */
    public
    boolean isEnabledFor(Priority priority) {
      if(hierarchy.enableInt >  priority.level) 
        return false;
      return priority.isGreaterOrEqual(this.getChainedPriority());
    }
  
    /**
      Check whether this category is enabled for the info priority.
      See also {@link #isDebugEnabled}.
  
      @return boolean - <code>true</code> if this category is enabled
      for priority info, <code>false</code> otherwise.
    */
    public
    boolean isInfoEnabled() {
      if(hierarchy.enableInt > Priority.INFO_INT)
        return false;   
      return Priority.INFO.isGreaterOrEqual(this.getChainedPriority());
    }
  
  
    
    /**
       Remove all previously added appenders from this Category
       instance.
  
       <p>This is useful when re-reading configuration information.
    */
    synchronized
    public
    void removeAllAppenders() {
      if(appenderList != null) {
        int len = appenderList.size();      
        for(int i = 0; i < len; i++) {
  	Appender a = (Appender) appenderList.elementAt(i);
  	a.close();
        }
        appenderList.removeAllElements();
        appenderList = null;      
      }
    }
  
    /**
       Remove the appender passed as parameter form the list of appenders.
  
       @since 0.8.2
    */
    synchronized
    public
    void removeAppender(Appender appender) {
      if(appender == null || appenderList == null) 
        return;
      appenderList.removeElement(appender);    
    }
  
    /**
       Remove the appender with the name passed as parameter form the
       list of appenders.
  
       @since 0.8.2 */
    synchronized
    public
    void removeAppender(String name) {
      if(name == null || appenderList == null) return;
      int size = appenderList.size();
      for(int i = 0; i < size; i++) {
        if(name.equals(((Appender)appenderList.elementAt(i)).getName())) {
  	appenderList.removeElementAt(i);
  	break;
        }
      }
    }
    
    /**
       Set the additivity flag for this Category instance.
       @since 0.8.1
     */
    public
    void setAdditivity(boolean additive) {
      this.additive = additive;
    }
  
    /**
       Only the Hiearchy class can set the hiearchy of a
       category. Default package access is MANDATORY here.  */
    final
    void setHierarchy(Hierarchy hierarchy) {
      this.hierarchy = hierarchy;
    }
    
    /**
       Set the priority of this Category.
  
       <p>Null values are admitted.
    */
    public
    void setPriority(Priority priority) {
      this.priority = priority;
    }
  
    /** 
      Log a message object with the {@link Priority#WARN WARN} priority.
  
      <p>This method first checks if this category is <code>WARN</code>
      enabled by comparing the priority of this category with {@link
      Priority#WARN WARN} priority.  If this category is
      <code>DEBUG</code> enabled, then it invokes all the registered
      appenders in this category and also higher in the hierarchy
      depending on the value of the additivity flag.
  
      <p><b>WARNING</b> Note that passing a {@link Throwable} to this
      method will print the name of the Throwable but no stack trace. To
      print a stack trace use the {@link #warn(Object, Throwable)} form
      instead.  <p>
      
      @param message the message object to log.  */
    public
    void warn(Object message) {
      if(hierarchy.enableInt >  Priority.WARN_INT) 
        return;   
  
      if(Priority.WARN.isGreaterOrEqual(this.getChainedPriority()))
        forcedLog(Priority.WARN, message, null);    
    }
    
    /** 
     Log a message with the <code>WARN</code> priority including the
     stack trace of the {@link Throwable} <code>t</code> passed as
     parameter.
     
     <p>See {@link #warn(Object)} for more detailed information.
     
     @param message the message object to log.
     @param t the exception to log, including its stack trace.  */
    public
    void warn(Object message, Throwable t) {
      if(hierarchy.enableInt >  Priority.WARN_INT) 
        return;   
      if(Priority.WARN.isGreaterOrEqual(this.getChainedPriority()))
        forcedLog(Priority.WARN, message, t);
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/CategoryKey.java
  
  Index: CategoryKey.java
  ===================================================================
  /*
   * 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.  */
  
  package org.apache.log4j;
  
  /**
     CategoryKey is heavily used internally to accelerate hash table searches.
     @author Ceki G&uuml;lc&uuml; 
  */
  class CategoryKey {
  
    String   name;  
    int hashCache;
  
    CategoryKey(String name) {
      this.name = name.intern();
      hashCache = name.hashCode();
    }
  
    final
    public  
    int hashCode() {
      return hashCache;
    }
  
    final
    public
    boolean equals(Object rArg) {
      if(this == rArg)
        return true;
      
      if(rArg != null && CategoryKey.class == rArg.getClass()) 
        return  name == ((CategoryKey)rArg ).name;
      else 
        return false;
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/FileAppender.java
  
  Index: FileAppender.java
  ===================================================================
  /*
   * 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.APL file.  */
  
  package org.apache.log4j;
  
  import java.io.IOException;
  import java.io.Writer;
  import java.io.FileWriter;
  import java.io.OutputStream;
  import java.io.OutputStreamWriter;
  
  import org.apache.log4j.spi.LoggingEvent;
  import org.apache.log4j.helpers.OptionConverter;
  import org.apache.log4j.helpers.LogLog;
  
  // Contibutors: Jens Uwe Pipka <je...@gmx.de>
  
  /**
     FileAppender appends log events to the console, to a file, to a
     {@link java.io.Writer} or an {@link java.io.OutputStream} depending
     on the user's choice.
  
     @author Ceki G&uuml;lc&uuml;
     */
  public class FileAppender extends AppenderSkeleton {
  
    /**
       A string constant used in naming the option for setting the
       output file. Current value of this string constant is
       <b>File</b>.
  
       <p>Note that all option keys are case sensitive.
       
    */
    public static final String FILE_OPTION = "File";
  
    /**
       A string constant used in naming the option that determines whether 
       the output file will be truncated or appended to. Current value
       of this string constant is <b>Append</b>.
  
       <p>Note that all option keys are case sensitive.
       
    */
    public static final String APPEND_OPTION = "Append";
  
    
    /** Append to or truncate the file? The default value for this
        variable is <code>true</code>, meaning that by default a
        <code>FileAppender</code> will append to an existing file and
        not truncate it.
  
        <p>This option is meaningful only if the FileAppender opens the
        file.      
    */
    protected boolean fileAppend = true;
  
    /**
       The name of the log file. */
    protected String fileName = null;
  
    protected Writer w;
  
    /**
       Is the QuietWriter ours or was it created and passed by the user?
    */
    protected boolean wIsOurs = false;
    
    /**
       The default constructor does no longer set a default layout nor a
       default output target.  */
    public
    FileAppender() {
    }
  
    /**
       Instantiate a FileAppender and set the output destination to
       <code>writer</code>.
  
       <p>The <code>writer</code> must have been opened by the user.  */
    public
    FileAppender(Layout layout, OutputStream os) {
      this(layout, new OutputStreamWriter(os));
    }                    
  
  
  
    /**
       Instantiate a FileAppender and set the output destination to
       <code>writer</code>.
  
       <p>The <code>writer</code> must have been opened by the user.  */
    public
    FileAppender(Layout layout, Writer writer) {
      this.layout = layout;
      this.setWriter(writer);
    }                    
  
  
    /**
      Instantiate a FileAppender and open the file designated by
      <code>filename</code>. The opened filename will become the ouput
      destination for this appender.
  
      <p>If the <code>append</code> parameter is true, the file will be
      appended to. Otherwise, the file desginated by
      <code>filename</code> will be truncated before being opened.
    */
    public
    FileAppender(Layout layout, String filename, boolean append)
                                        throws IOException {
      this.layout = layout;
      this.setFile(filename, append);
    }
  
    /**
       Instantiate a FileAppender and open the file designated by
      <code>filename</code>. The opened filename will become the output
      destination for this appender.
  
      <p>The file will be appended to.  */
    public
    FileAppender(Layout layout, String filename) throws IOException {
      this(layout, filename, true);
    }
  
    /**
       If the a value for {@link #FILE_OPTION} is non-null, then {@link
       #setFile} is called with the values of {@link #FILE_OPTION} and
       {@link #APPEND_OPTION}.
  
       @since 0.8.1 */
    public
    void activateOptions() {    
      if(fileName != null) {
        try {
  	setFile(fileName, fileAppend);
        }
        catch(java.io.IOException e) {
  	error("setFile("+fileName+","+fileAppend+") call failed.", e);
        }
      }
    }
  
  
    /**
       This method called by {@link AppenderSkeleton#doAppend}
       method. 
  
       <p>If the output stream exists an is writable then write a log
       statement to the output stream. Otherwise, write a single warning
       message to <code>System.err</code>.
  
       <p>The format of the output will depend on this appender's
       layout.
       
    */
    public
    void append(LoggingEvent event) {
  
      // Reminder: the nesting of calls is:
      //
      //    doAppend()
      //      - check threshold
      //      - filter
      //      - append();
      //        - checkEntryConditions();
      //        - subAppend();
  
      if(!checkEntryConditions()) {
        return;
      }
      subAppend(event);
     } 
  
    /**
       This method determines if there is a sense in attempting to append.
       
       <p>It checks whether there is a set output target and also if
       there is a set layout. If these checks fail, then the boolean
       value <code>false</code> is returned. */
    protected
    boolean checkEntryConditions() {
      if(this.w == null) {
        error("No output target set for \""+ name+"\".");
        return false;
      }
      
      if(this.layout == null) {
        error("No layout set for \""+ name+"\".");
        return false;
      }
      return true;
    }
  
  
    /**
       Will close the stream opened by a previos {@link #setFile}
       call. If the writer is owned by the user it remains untouched.
  
       @see #setFile
       @see #setWriter
       @since 0.8.4
    */
    public
    void close() {
      this.closed = true;
      reset();
    }
  
  
    
    /**
       Close this.writer if opened by setFile or FileAppend(filename..)
    */
    protected
    void closeWriterIfOurs() {
      if(this.wIsOurs && this.w != null) {
        try {
  	this.w.close();
        }
        catch(java.io.IOException e) {
  	LogLog.error("Could not close output stream " + w, e);
        }
      }      
    }
  
    /**
       Retuns the option names for this component, namely the string
       array {{@link #FILE_OPTION}, {@link #APPEND_OPTION}} in addition
       to the options of its super class {@link AppenderSkeleton}.  */
    public
    String[] getOptionStrings() {
      return new String[] {THRESHOLD_OPTION, FILE_OPTION, APPEND_OPTION};
    }
  
   
    /**
      <p>Sets and <i>opens</i> the file where the log output will
      go. The specified file must be writable. 
  
      <p>If there was already an opened stream opened through this
      method, then the previous stream is closed first. If the stream
      was opened by the user and passed to {@link #setWriter
      setWriter}, then the previous stream remains
      untouched. It is the users responsability to close it.
  
      @param fileName The path to the log file.
      @param boolean If true will append to fileName. Otherwise will
      truncate fileName.  */
    public
    synchronized
    void setFile(String fileName, boolean append) throws IOException {
      reset();
      this.w = new FileWriter(fileName, append);
      this.fileName = fileName;
      this.wIsOurs = true;
    }
  
    /**
      <p>Sets and <i>opens</i> the file where the log output will
      go. The specified file must be writable.
  
      <p>The open mode (append/truncate) will depend on the value of
      FileAppend option. If undefined, append mode is used.
  
      @param fileName The name of the log file.
    */
    public
    void setFile(String fileName) throws IOException {    
      this.setFile(fileName, fileAppend);
    }
    
    /**
       Set FileAppender specific options.
            
       The recognized options are <b>File</b> and <b>Append</b>,
       i.e. the values of the string constants {@link #FILE_OPTION} and
       respectively {@link #APPEND_OPTION}. The options of the super
       class {@link AppenderSkeleton} are also recognized.
  
       <p>The <b>File</b> option takes a string value which should be
       one of the strings "System.out" or "System.err" or the name of a
       file.
  
       <p>If the option is set to "System.out" or "System.err" the
       output will go to the corresponding stream. Otherwise, if the
       option is set to the name of a file, then the file will be opened
       and output will go there.
       
       <p>The <b>Append</b> option takes a boolean value. It is set to
       <code>true</code> by default. If true, then <code>File</code>
       will be opened in append mode by {@link #setFile setFile} (see
       above). Otherwise, {@link #setFile setFile} will open
       <code>File</code> in truncate mode.
  
       <p>Note: Actual opening of the file is made when {@link
       #activateOptions} is called, not when the options are set.
       
       @since 0.8.1 */
    public
    void setOption(String key, String value) {
      if(value == null) return;
      super.setOption(key, value);
      
      if(key.equalsIgnoreCase(FILE_OPTION)) {
        // Trim spaces from both ends. The users probably does not want 
        // trailing spaces in file names.
        value = value.trim();
        if(value.equalsIgnoreCase("System.out"))
  	setWriter(new OutputStreamWriter(System.out));
        else if(value.equalsIgnoreCase("System.err"))
  	setWriter(new OutputStreamWriter(System.err));
        else {
  	fileName = value;
        } 
      } else if (key.equalsIgnoreCase(APPEND_OPTION)) {
        fileAppend = OptionConverter.toBoolean(value, fileAppend);
      }
   
    }
    
    /**
      <p>Sets the Writer where the log output will go. The
      specified Writer must be opened by the user and be
      writable.
  
  
      <p>If there was already an opened stream opened through the {@link
      #setFile setFile} method, then the previous stream is closed
      first. If the stream was opened by the user and passed to this
      method, then the previous stream remains untouched. It is the
      user's responsability to close it.
  
      <p><b>WARNING:</b> Logging to an unopened Writer will fail.
      <p>  
      @param Writer An already opened Writer.
      @return Writer The previously attached Writer.
    */
    public
    synchronized
    void setWriter(Writer writer) {
      reset();
      this.w = writer;
      this.wIsOurs = false;    
    }
  
    /**
       Actual writing occurs here.
  
       <p>Most sub-classes of <code>FileAppender</code> will need to
       override this method.
  
       @since 0.9.0 */
    protected
    void subAppend(LoggingEvent event) {
      this.write(this.layout.format(event));
  
  
      if(layout.ignoresThrowable()) {
        String s = event.getThrowableStr();
        if (s != null) {
  	write(s);
        }
      }
  
      try {
        w.flush();
      } catch(IOException e) {
        error("Failed to flush", e);
      }    
    }
  
    /**
       The FileAppender requires a layout. Hence, this method returns
       <code>true</code>.
  
       @since 0.8.4 */
    public
    boolean requiresLayout() {
      return true;
    }
  
    protected
    void reset() {
       closeWriterIfOurs();
       this.fileName = null;
       this.w = null;
    }
  
    public
    void write(String string) {
      try {
        w.write(string);
      } catch(IOException e) {
        error("Failed to writing", e);
      }
    }
    
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/Hierarchy.java
  
  Index: Hierarchy.java
  ===================================================================
  /*
   * 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.  */
  
  // WARNING This class MUST not have references to the Category or
  // WARNING RootCategory classes in its static initiliazation neither 
  // WARNING directly nor indirectly.
  
  // Contributors:
  //                Luke Blanshard <lu...@quiq.com>
  //                Mario Schomburg - IBM Global Services/Germany
  //                Anders Kristensen
  //                Igor Poteryaev
   
  package org.apache.log4j;
  
  
  import java.util.Hashtable;
  import java.util.Enumeration;
  import java.util.Vector;
  
  import org.apache.log4j.spi.RootCategory;
  import org.apache.log4j.Appender;
  import org.apache.log4j.helpers.LogLog;
  
  /**
     This class is specialized in retrieving categories by name and
     also maintaining the category hierarchy.
  
     <p><em>The casual user should not have to deal with this class
     directly.</em> In fact, up until version 0.9.0, this class had
     default package access. 
  
     <p>The structure of the category hierarchy is maintained by the
     {@link #getInstance} method. The hierarchy is such that children
     link to their parent but parents do not have any pointers to their
     children. Moreover, categories can be instantiated in any order, in
     particular descendant before ancestor.
  
     <p>In case a descendant is created before a particular ancestor,
     then it creates a provision node for the ancestor and adds itself
     to the provision node. Other descendants of the same ancestor add
     themselves to the previously created provision node.
  
     @author Ceki G&uuml;lc&uuml; 
  
  */
  public class Hierarchy {
  
    Hashtable ht;
    Category root;
    
    int enableInt;
    Priority enable;
  
    boolean emittedNoAppenderWarning = false;
    boolean emittedNoResourceBundleWarning = false;  
  
    /**
       Create a new Category hierarchy.
  
       @param root The root of the new hierarchy.
  
     */
    public
    Hierarchy(Category root) {
      ht = new Hashtable();
      this.root = root;
      // Enable all priority levels by default.
      enable(Priority.ALL);
      this.root.setHierarchy(this);
    }
  
    /**
       Enable all logging priorities for this hierarchy. This is the
       default.
       
     */
    public
    void enableAll() {
      enable(Priority.ALL);
    }
  
    public 
    void enable(Priority p) {
      if(p != null) {
        enableInt = p.level;
        enable = p;
      }
    }
  
    /**
       Returns the string representation of the internal
       <code>enable</code> state.  
  
       @since 1.2
    */
    public
    Priority getEnable() {
      return enable;
    }
  
   /**
       Return a new category instance named as the first parameter using
       <code>factory</code>.
       
       <p>If a category of that name already exists, then it will be
       returned.  Otherwise, a new category will be instantiated by the
       <code>factory</code> parameter and linked with its existing
       ancestors as well as children.
       
       @param name The name of the category to retrieve.
       @param factory The factory that will make the new category instance.
  
   */
    public
    Category getInstance(String name) {
      //System.out.println("getInstance("+name+") called.");
      CategoryKey key = new CategoryKey(name);    
      // Synchronize to prevent write conflicts. Read conflicts (in
      // getChainedPriority method) are possible only if variable
      // assignments are non-atomic.
      Category category;
      
      synchronized(ht) {
        Object o = ht.get(key);
        if(o == null) {
  	category = new Category(name);
  	category.setHierarchy(this);
  	ht.put(key, category);      
  	updateParents(category);
  	return category;
        } else if(o instanceof Category) {
  	return (Category) o;
        } else if (o instanceof ProvisionNode) {
  	category = new Category(name);
  	category.setHierarchy(this); 
  	ht.put(key, category);
  	updateChildren((ProvisionNode) o, category);
  	updateParents(category);	
  	return category;
        }
        else {
  	// It should be impossible to arrive here
  	return null;  // but let's keep the compiler happy.
        }
      }
    }
  
    /**
       Get the root of this hierarchy.
       
       @since 0.9.0
     */
    public
    Category getRoot() {
      return root;
    }
  
  
    /**
       This method loops through all the *potential* parents of
       'cat'. There 3 possible cases:
  
       1) No entry for the potential parent of 'cat' exists
  
          We create a ProvisionNode for this potential parent and insert
          'cat' in that provision node.
  
       2) There entry is of type Category for the potential parent.
  
          The entry is 'cat's nearest existing parent. We update cat's
          parent field with this entry. We also break from the loop
          because updating our parent's parent is our parent's
          responsibility.
  	 
       3) There entry is of type ProvisionNode for this potential parent.
  
          We add 'cat' to the list of children for this potential parent.
     */
    final
    private
    void updateParents(Category cat) {
      String name = cat.name;
      int length = name.length();
      boolean parentFound = false;
      
      //System.out.println("UpdateParents called for " + name);
      
      // if name = "w.x.y.z", loop thourgh "w.x.y", "w.x" and "w", but not "w.x.y.z" 
      for(int i = name.lastIndexOf('.', length-1); i >= 0; 
  	                                 i = name.lastIndexOf('.', i-1))  {
        String substr = name.substring(0, i);
  
        //System.out.println("Updating parent : " + substr);
        CategoryKey key = new CategoryKey(substr); // simple constructor
        Object o = ht.get(key);
        // Create a provision node for a future parent.
        if(o == null) {
  	//System.out.println("No parent "+substr+" found. Creating ProvisionNode.");
  	ProvisionNode pn = new ProvisionNode(cat);
  	ht.put(key, pn);
        } else if(o instanceof Category) {
  	parentFound = true;
  	cat.parent = (Category) o;
  	//System.out.println("Linking " + cat.name + " -> " + ((Category) o).name);
  	break; // no need to update the ancestors of the closest ancestor
        } else if(o instanceof ProvisionNode) {
  	((ProvisionNode) o).addElement(cat);
        } else {
  	Exception e = new IllegalStateException("unexpected object type " + 
  					o.getClass() + " in ht.");
  	e.printStackTrace();			   
        }
      }
      // If we could not find any existing parents, then link with root.
      if(!parentFound) 
        cat.parent = root;
    }
  
    /** 
        We update the links for all the children that placed themselves
        in the provision node 'pn'. The second argument 'cat' is a
        reference for the newly created Category, parent of all the
        children in 'pn'
  
        We loop on all the children 'c' in 'pn':
  
           If the child 'c' has been already linked to a child of
           'cat' then there is no need to update 'c'.
  
  	 Otherwise, we set cat's parent field to c's parent and set
  	 c's parent field to cat.
  
    */
    final
    private
    void updateChildren(ProvisionNode pn, Category cat) {
      //System.out.println("updateChildren called for " + cat.name);
      final int last = pn.size();
  
      for(int i = 0; i < last; i++) {
        Category c = (Category) pn.elementAt(i);
        //System.out.println("Updating child " +p.name);
  
        // Unless this child already points to a correct (lower) parent,
        // make cat.parent point to c.parent and c.parent to cat.
        if(!c.parent.name.startsWith(cat.name)) {
  	cat.parent = c.parent;
  	c.parent = cat;      
        }
      }
    }    
  
  }
  
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/Layout.java
  
  Index: Layout.java
  ===================================================================
  /*
   * 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.  */
  
  package org.apache.log4j;
  
  import org.apache.log4j.spi.OptionHandler;
  import org.apache.log4j.spi.LoggingEvent;
  
  /**
     Extend this abstract class to create your own log layout format.
     
     @author Ceki G&uuml;lc&uuml;
  
  */
    
  public abstract class Layout implements OptionHandler {
  
    // Note that the line.separator property can be looked up even by
    // applets.
    public final static String LINE_SEP = System.getProperty("line.separator");
    public final static int LINE_SEP_LEN  = LINE_SEP.length();
  
  
    /**
       Implement this method to create your own layout format.
    */
    abstract
    public
    String format(LoggingEvent event);
  
    /**
       If the layout handles the throwable object contained within
       {@link LoggingEvent}, then the layout should return
       <code>false</code>. Otherwise, if the layout ignores throwable
       object, then the layout should return <code>true</code>.
  
       @since 1.0 */
    abstract
    public
    boolean ignoresThrowable();
  
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/NDC.java
  
  Index: NDC.java
  ===================================================================
  /*
   * 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.
   */
  
  //      Contributors:      Dan Milstein 
  //                         Ray Millard
  
  package org.apache.log4j;
  
  import java.util.Hashtable;
  import java.util.Stack;
  import java.util.Enumeration;
  import java.util.Vector;
  
  import org.apache.log4j.helpers.LogLog;
  
  /**
     The NDC class implements <i>nested diagnostic contexts</i> as
     defined by Neil Harrison in the article "Patterns for Logging
     Diagnostic Messages" part of the book "<i>Pattern Languages of
     Program Design 3</i>" edited by Martin et al.
  
     <p>A Nested Diagnostic Context, or NDC in short, is an instrument
     to distinguish interleaved log output from different sources. Log
     output is typically interleaved when a server handles multiple
     clients near-simultaneously.
  
     <p>Interleaved log output can still be meaningful if each log entry
     from different contexts had a distinctive stamp. This is where NDCs
     come into play.
  
     <p><em><b>Note that NDCs are managed on a per thread
     basis</b></em>. NDC operations such as {@link #push push}, {@link
     #pop}, {@link #clear}, {@link #getDepth} and {@link #setMaxDepth}
     affect the NDC of the <em>current</em> thread only. NDCs of other
     threads remain unaffected.
  
     <p>For example, a servlet can build a per client request NDC
     consisting the clients host name and other information contained in
     the the request. <em>Cookies</em> are another source of distinctive
     information. To build an NDC one uses the {@link #push push}
     operation. Simply put,
  
     <p><ul>
       <li>Contexts can be nested.
  
       <p><li>When entering a context, call <code>NDC.push</code>. As a
       side effect, if there is no nested diagnostic context for the
       current thread, this method will create it.
  
       <p><li>When leaving a context, call <code>NDC.pop</code>.
  
       <p><li><b>When exiting a thread make sure to call {@link #remove
       NDC.remove()}</b>.  
     </ul>
     
     <p>There is no penalty for forgetting to match each
     <code>push</code> operation with a corresponding <code>pop</code>,
     except the obvious mismatch between the real application context
     and the context set in the NDC.
  
     <p>If configured to do so, {@link PatternLayout} and {@link
     TTCCLayout} instances automatically retrieve the nested diagnostic
     context for the current thread without any user intervention.
     Hence, even if a servlet is serving multiple clients
     simultaneously, the logs emanating from the same code (belonging to
     the same category) can still be distinguished because each client
     request will have a different NDC tag.
  
     <p>Heavy duty systems should call the {@link #remove} method when
     leaving the run method of a thread. This ensures that the memory
     used by the thread can be freed by the Java garbage
     collector. There is a mechanism to lazily remove references to dead
     threads. In practice, this means that you can be a little sloppy
     and sometimes forget to call {@link #remove} before exiting a
     thread.
     
     <p>A thread may inherit the nested diagnostic context of another
     (possibly parent) thread using the {@link #inherit inherit}
     method. A thread may obtain a copy of its NDC with the {@link
     #cloneStack cloneStack} method and pass the reference to any other
     thread, in particular to a child.
     
     @author Ceki G&uuml;lc&uuml;
     @since 0.7.0
    
  */
   
  public class NDC {
  
    // The synchronized keyword is not used in this class. This may seem
    // dangerous, especially since the class will be used by
    // multiple-threads. In particular, all threads share the same
    // hashtable (the "ht" variable). This is OK since java hashtables
    // are thread safe. Same goes for Stacks.
  
    // More importantly, when inheriting diagnostic contexts the child
    // thread is handed a clone of the parent's NDC.  It follows that
    // each thread has its own NDC (i.e. stack).
  
    static Hashtable ht = new Hashtable();
  
    static int pushCounter = 0; // the number of times push has been called
                                // after the latest call to lazyRemove
  
    // The number of times we allow push to be called before we call lazyRemove
    // 5 is a relatively small number. As such, lazyRemove is not called too
    // frequently. We thus avoid the cost of creating an Enumeration too often.
    // The higher this number, the longer is the avarage period for which all
    // logging calls in all threads are blocked.
    static final int REAP_THRESHOLD = 5;
    
    // No instances allowed.
    private NDC() {}
  
  
    /**
       Clear any nested diagnostic information if any. This method is
       useful in cases where the same thread can be potentially used
       over and over in different unrelated contexts.
  
       <p>This method is equivalent to calling the {@link #setMaxDepth}
       method with a zero <code>maxDepth</code> argument.
       
       @since 0.8.4c */
    public
    static
    void clear() {
      Stack stack = (Stack) ht.get(Thread.currentThread());    
      if(stack != null) 
        stack.setSize(0);    
    }
  
    
    /**
       Clone the diagnostic context for the current thread.
  
       <p>Internally a diagnostic context is represented as a stack.  A
       given thread can supply the stack (i.e. diagnostic context) to a
       child thread so that the child can inherit the parent thread's
       diagnostic context.
  
       <p>The child thread uses the {@link #inherit inherit} method to
       inherit the parent's diagnostic context.
       
       @return Stack A clone of the current thread's  diagnostic context.
  
    */
    public
    static
    Stack cloneStack() {
      Object o = ht.get(Thread.currentThread());
      if(o == null)
        return null;
      else {
        Stack stack = (Stack) o;
        return (Stack) stack.clone();
      }
    }
  
    
    /**
       Inherit the diagnostic context of another thread.
  
       <p>The parent thread can obtain a reference to its diagnostic
       context using the {@link #cloneStack} method.  It should
       communicate this information to its child so that it may inherit
       the parent's diagnostic context.
  
       <p>The parent's diagnostic context is cloned before being
       inherited. In other words, once inherited, the two diagnostic
       contexts can be managed independently.
       
       <p>In java, a child thread cannot obtain a reference to its
       parent, unless it is directly handed the reference. Consequently,
       there is no client-transparent way of inheriting diagnostic
       contexts. Do you know any solution to this problem?
  
       @param stack The diagnostic context of the parent thread.
  
    */
    public
    static
    void inherit(Stack stack) {
      if(stack != null)
        ht.put(Thread.currentThread(), stack);
    }
  
  
    /**
       <font color="#FF4040"><b>Never use this method directly, use the {@link
       org.apache.log4j.spi.LoggingEvent#getNDC} method instead.</b></font>
    */
    static
    public
    String get() {
      Stack s = (Stack) ht.get(Thread.currentThread());
      if(s != null && !s.isEmpty()) 
        return ((DiagnosticContext) s.peek()).fullMessage;
      else
        return null;
    }
    
    /**
       Get the current nesting depth of this diagnostic context.
  
       @see #setMaxDepth
       @since 0.7.5
     */
    public
    static
    int getDepth() {
      Stack stack = (Stack) ht.get(Thread.currentThread());          
      if(stack == null)
        return 0;
      else
        return stack.size();      
    }
  
    private
    static
    void lazyRemove() {
       
      // The synchronization on ht is necessary to prevent JDK 1.2.x from
      // throwing ConcurrentModificationExceptions at us. This sucks BIG-TIME.
      // One solution is to write our own hashtable implementation.
      Vector v;
      
      synchronized(ht) {
        // Avoid calling clean-up too often.
        if(++pushCounter <= REAP_THRESHOLD) {
  	return; // We release the lock ASAP.
        } else {
  	pushCounter = 0; // OK let's do some work.
        }
  
        int misses = 0;
        v = new Vector(); 
        Enumeration enum = ht.keys();
        // We give up after 4 straigt missses. That is 4 consecutive
        // inspected threads in 'ht' that turn out to be alive.
        // The higher the proportion on dead threads in ht, the higher the
        // chances of removal.
        while(enum.hasMoreElements() && (misses <= 4)) {
  	Thread t = (Thread) enum.nextElement();
  	if(t.isAlive()) {
  	  misses++;
  	} else {
  	  misses = 0;
  	  v.addElement(t);
  	}
        }
      } // synchronized
  
      int size = v.size();
      for(int i = 0; i < size; i++) {
        Thread t = (Thread) v.elementAt(i);
        LogLog.debug("Lazy NDC removal for thread [" + t.getName() + "] ("+ 
  		   ht.size() + ").");
        ht.remove(t);
      }
    }
  
    /**
       Clients should call this method before leaving a diagnostic
       context.
  
       <p>The returned value is the value that was pushed last. If no
       context is available, then the empty string "" is returned.
       
       @return String The innermost diagnostic context.
       
       */
    public
    static
    String pop() {
      Thread key = Thread.currentThread();
      Stack stack = (Stack) ht.get(key);
      if(stack != null && !stack.isEmpty()) 
        return ((DiagnosticContext) stack.pop()).message;
      else
        return "";
    }
  
    /**
       Looks at the last diagnostic context at the top of this NDC
       without removing it.
  
       <p>The returned value is the value that was pushed last. If no
       context is available, then the empty string "" is returned.
       
       @return String The innermost diagnostic context.
       
       */
    public
    static
    String peek() {
      Thread key = Thread.currentThread();
      Stack stack = (Stack) ht.get(key);
      if(stack != null && !stack.isEmpty())
        return ((DiagnosticContext) stack.peek()).message;
      else
        return "";
    }
    
    /**
       Push new diagnostic context information for the current thread.
  
       <p>The contents of the <code>message</code> parameter is
       determined solely by the client.  
       
       @param message The new diagnostic context information.  */
    public
    static
    void push(String message) {
      Thread key = Thread.currentThread();
      Stack stack = (Stack) ht.get(key);
        
      if(stack == null) {
        DiagnosticContext dc = new DiagnosticContext(message, null);      
        stack = new Stack();
        ht.put(key, stack);
        stack.push(dc);
      } else if (stack.isEmpty()) {
        DiagnosticContext dc = new DiagnosticContext(message, null);            
        stack.push(dc);
      } else {
        DiagnosticContext parent = (DiagnosticContext) stack.peek();
        stack.push(new DiagnosticContext(message, parent));
      }    
    }
  
    /**
       Remove the diagnostic context for this thread.
  
       <p>Each thread that created a diagnostic context by calling
       {@link #push} should call this method before exiting. Otherwise,
       the memory used by the <b>thread</b> cannot be reclaimed by the
       VM.
  
       <p>As this is such an important problem in heavy duty systems and
       because it is difficult to always guarantee that the remove
       method is called before exiting a thread, this method has been
       augmented to lazily remove references to dead threads. In
       practice, this means that you can be a little sloppy and
       occasionally forget to call {@link #remove} before exiting a
       thread. However, you must call <code>remove</code> sometime. If
       you never call it, then your application is sure to run out of
       memory.
       
    */
    static
    public
    void remove() {
      ht.remove(Thread.currentThread());
      
      // Lazily remove dead-thread references in ht.
      lazyRemove();    
    }
  
    /**
       Set maximum depth of this diagnostic context. If the current
       depth is smaller or equal to <code>maxDepth</code>, then no
       action is taken.
  
       <p>This method is a convenient alternative to multiple {@link
       #pop} calls. Moreover, it is often the case that at the end of
       complex call sequences, the depth of the NDC is
       unpredictable. The <code>setMaxDepth</code> method circumvents
       this problem.
  
       <p>For example, the combination
       <pre>
         void foo() {
         &nbsp;  int depth = NDC.getDepth();
  
         &nbsp;  ... complex sequence of calls
  
         &nbsp;  NDC.setMaxDepth(depth);
         }
       </pre>
  
       ensures that between the entry and exit of foo the depth of the
       diagnostic stack is conserved.
       
       @see #getDepth
       @since 0.7.5 */
    static
    public
    void setMaxDepth(int maxDepth) {
      Stack stack = (Stack) ht.get(Thread.currentThread());    
      if(stack != null && maxDepth < stack.size()) 
        stack.setSize(maxDepth);
    }
    
    // =====================================================================
     private static class DiagnosticContext {
  
      String fullMessage;
      String message;
      
      DiagnosticContext(String message, DiagnosticContext parent) {
        this.message = message;
        if(parent != null) {
  	fullMessage = parent.fullMessage + ' ' + message;
        } else {
  	fullMessage = message;
        }
      }
    }
  }
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/PatternLayout.java
  
  Index: PatternLayout.java
  ===================================================================
  /*
   * 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 file.
   */
  
  package org.apache.log4j;
  
  import org.apache.log4j.Category;
  import org.apache.log4j.Priority;
  import org.apache.log4j.Layout;
  import org.apache.log4j.spi.LoggingEvent;
  import org.apache.log4j.NDC;
  import org.apache.log4j.helpers.PatternParser;
  import org.apache.log4j.helpers.PatternConverter;
  
  import java.io.PrintWriter;
  import java.io.StringWriter;
  import java.text.DateFormat;
  import java.text.SimpleDateFormat;
  import java.util.Date;
  import java.util.TimeZone;
  import java.util.Vector;
  import java.text.FieldPosition;
  
  // Contributors:   Nelson Minar <ne...@monkey.org>
  //                 Anders Kristensen <ak...@dynamicsoft.com>
  
  /**
     
     A flexible layout configurable with pattern string.
  
     <p>The goal of this class is to {@link #format format} a {@link
     LoggingEvent} and return the results as a String. The results
     depend on the <em>conversion pattern</em>.
  
     <p>The conversion pattern is closely related to the conversion
     pattern of the printf function in C. A conversion pattern is
     composed of literal text and format control expressions called
     <em>conversion specifiers</em>.
  
     <p><i>You are free to insert any literal text within the conversion
     pattern.</i>
     
     <p>Each conversion specifier starts with a percent sign (%) and is
     followed by optional <em>format modifiers</em> and a <em>conversion
     character</em>. The conversion character specifies the type of
     data, e.g. category, priority, date, thread name. The format
     modifiers control such things as field width, padding, left and
     right justification. The following is a simple example.
  
     <p>Let the conversion pattern be <b>"%-5p [%t]: %m%n"</b> and assume
     that the log4j environment was set to use a PatternLayout. Then the
     statements
     <pre>
     Category root = Category.getRoot();
     root.debug("Message 1");
     root.warn("Message 2");   
     </pre>
     would yield the output
     <pre>
     DEBUG [main]: Message 1
     WARN  [main]: Message 2  
     </pre>
  
     <p>Note that there is no explicit separator between text and
     conversion specifiers. The pattern parser knows when it has reached
     the end of a conversion specifier when it reads a conversion
     character. In the example above the conversion specifier
     <b>%-5p</b> means the priority of the logging event should be left
     justified to a width of five characters.
     
     The recognized conversion characters are
     
     <p>
     <table border="1" CELLPADDING="8">
     <th>Conversion Character</th>
     <th>Effect</th>
  
     <tr>
       <td align=center><b>c</b></td>
  
       <td>Used to output the category of the logging event. The
       category conversion specifier can be optionally followed by
       <em>precision specifier</em>, that is a decimal constant in
       brackets.
  
       <p>If a precision specifier is given, then only the corresponding
       number of right most components of the category name will be
       printed. By default the category name is printed in full.
  
       <p>For example, for the category name "a.b.c" the pattern
       <b>%c{2}</b> will output "b.c".
  
       </td>
     </tr>
  
     <tr>
       <td align=center><b>C</b></td>
  
       <td>Used to output the fully qualified class name of the caller
       issuing the logging request. This conversion specifier
       can be optionally followed by <em>precision specifier</em>, that
       is a decimal constant in brackets.
  
       <p>If a precision specifier is given, then only the corresponding
       number of right most components of the class name will be
       printed. By default the class name is output in fully qualified form.
       
       <p>For example, for the class name "org.apache.xyz.SomeClass", the
       pattern <b>%C{1}</b> will output "SomeClass".
  
       <p><b>WARNING</b> Generating the caller class information is
       slow. Thus, it's use should be avoided unless execution speed is
       not an issue.
  
       </td>
       </tr>
     
     <tr>
     <td align=center><b>F</b></td>
  
     <td>Used to output the file name where the logging request was
     issued.
  
     <p><b>WARNING</b> Generating caller location information is
     extremely slow. It's use should be avoided unless execution speed
     is not an issue.
  
     </tr>
     
     <tr>
     <td align=center><b>l</b></td>
  
       <td>Used to output location information of the caller which generated
       the logging event. 
  
       <p>The location information depends on the JVM implementation but
       usually consists of the fully qualified name of the calling
       method followed by the callers source the file name and line
       number between parentheses.
  
       <p>The location information can be very useful. However, it's
       generation is <em>extremely</em> slow. It's use should be avoided
       unless execution speed is not an issue.
     
       </td>
     </tr>
  
     <tr>
     <td align=center><b>L</b></td>
  
     <td>Used to output the line number from where the logging request
     was issued.
  
     <p><b>WARNING</b> Generating caller location information is
     extremely slow. It's use should be avoided unless execution speed
     is not an issue.
  
     </tr>
  
     
     <tr>
       <td align=center><b>m</b></td>
       <td>Used to output the application supplied message associated with 
       the logging event.</td>   
     </tr>
  
     <tr>
     <td align=center><b>M</b></td>
  
     <td>Used to output the method name where the logging request was
     issued.
  
     <p><b>WARNING</b> Generating caller location information is
     extremely slow. It's use should be avoided unless execution speed
     is not an issue.
  
     </tr>
  
     <tr>
       <td align=center><b>n</b></td>
       
       <td>Outputs the platform dependent line separator character or
       characters. 
  
       <p>This conversion character offers practically the same
       performance as using non-portable line separator strings such as
       "\n", or "\r\n". Thus, it is the preferred way of specifying a
       line separator.
  
       
     </tr>
     
     <tr>
       <td align=center><b>p</b></td>
       <td>Used to output the priority of the logging event.</td>
     </tr>
     
     <tr>
  
       <td align=center><b>r</b></td>
  
       <td>Used to output the number of milliseconds elapsed since the start
       of the application until the creation of the logging event.</td>
     </tr>  
     
  
     <tr>
       <td align=center><b>t</b></td>
  
       <td>Used to output the name of the thread that generated the
       logging event.</td>
       
     </tr>
      
     <tr>
  
       <td align=center><b>x</b></td>
  
       <td>Used to output the NDC (nested diagnostic context) associated
       with the thread that generated the logging event.
       </td>     
     </tr>
  
     <tr>
  
       <td align=center><b>%</b></td>
  
       <td>The sequence %% outputs a single percent sign.
       </td>     
     </tr>
     
     </table>
  
     <p>By default the relevant information is output as is. However,
     with the aid of format modifiers it is possible to change the
     minimum field width, the maximum field width and justification.
  
     <p>The optional format modifier is placed between the percent sign
     and the conversion character.
  
     <p>The first optional format modifier is the <em>left justification
     flag</em> which is just the minus (-) character. Then comes the
     optional <em>minimum field width</em> modifier. This is a decimal
     constant that represents the minimum number of characters to
     output. If the data item requires fewer characters, it is padded on
     either the left or the right until the minimum width is
     reached. The default is to pad on the left (right justify) but you
     can specify right padding with the left justification flag. The
     padding character is space. If the data item is larger than the
     minimum field width, the field is expanded to accommodate the
     data. The value is never truncated.
  
     <p>This behavior can be changed using the <em>maximum field
     width</em> modifier which is designated by a period followed by a
     decimal constant. If the data item is longer than the maximum
     field, then the extra characters are removed from the
     <em>beginning</em> of the data item and not from the end. For
     example, it the maximum field width is eight and the data item is
     ten characters long, then the first two characters of the data item
     are dropped. This behavior deviates from the printf function in C
     where truncation is done from the end.
  
     <p>Below are various format modifier examples for the category
     conversion specifier.
  
     <p>
     <TABLE BORDER=1 CELLPADDING=8>
     <th>Format modifier
     <th>left justify
     <th>minimum width
     <th>maximum width
     <th>comment
  
     <tr>
     <td align=center>%20c</td>
     <td align=center>false</td>
     <td align=center>20</td>
     <td align=center>none</td>
  
     <td>Left pad with spaces if the category name is less than 20
     characters long.
  
     <tr> <td align=center>%-20c</td> <td align=center>true</td> <td
     align=center>20</td> <td align=center>none</td> <td>Right pad with
     spaces if the category name is less than 20 characters long.
     
     <tr>
     <td align=center>%.30c</td>
     <td align=center>NA</td>
     <td align=center>none</td>
     <td align=center>30</td>
  
     <td>Truncate from the beginning if the category name is longer than 30
     characters.
  
     <tr>
     <td align=center>%20.30c</td>
     <td align=center>false</td>
     <td align=center>20</td>
     <td align=center>30</td>
  
     <td>Left pad with spaces if the category name is shorter than 20
     characters. However, if category name is longer than 30 characters,
     then truncate from the beginning.   
  
     <tr>
     <td align=center>%-20.30c</td>
     <td align=center>true</td>
     <td align=center>20</td>
     <td align=center>30</td>
  
     <td>Right pad with spaces if the category name is shorter than 20
     characters. However, if category name is longer than 30 characters,
     then truncate from the beginning.   
     
     </table>
  
     <p>Below are some examples of conversion patterns.
  
     <dl>
  
     <p><dt><b>%r [%t] %-5p %c %x - %m\n</b> 
     <p><dd>This is essentially the TTCC layout.
  
     <p><dt><b>%-6r [%15.15t] %-5p %30.30c %x - %m\n</b>
  
     <p><dd>Similar to the TTCC layout except that the relative time is
     right padded if less than 6 digits, thread name is right padded if
     less than 15 characters and truncated if longer and the category
     name is left padded if shorter than 30 characters and truncated if
     longer.
     
    </dl>
     
     <p>The above text is largely inspired from Peter A. Darnell and
     Philip E. Margolis' highly recommended book "C -- a Software
     Engineering Approach", ISBN 0-387-97389-3.
     
     @author <a href="mailto:cakalijp@Maritz.com">James P. Cakalic</a>
     @author Ceki G&uuml;lc&uuml;
  
  
     @since 0.8.2 */
  public class PatternLayout extends Layout {
  
    /**
       A string constant used in naming the option for setting the
       layout pattern. Current value of this string constant is
       <b>ConversionPattern</b>.
  
       <p>Note that the search for all option keys is case sensitive.
       
    */
    final static public String CONVERSION_PATTERN_OPTION = "ConversionPattern";
  
  
    /** Default pattern string for log output. Currently set to the
        string <b>"%m%n"</b> which just prints the application supplied
        message. */
    public final static String DEFAULT_CONVERSION_PATTERN ="%m%n";
    
    protected final int BUF_SIZE = 256;
    protected final int MAX_CAPACITY = 1024;
  
    // output buffer appended to when format() is invoked
    private StringBuffer sbuf = new StringBuffer(BUF_SIZE);
    
    private String pattern;
    
    private PatternConverter head;
  
    private String timezone;
    
    /**
       Constructs a PatternLayout using the DEFAULT_LAYOUT_PATTERN.
        
       The default pattern just produces the application supplied message.
    */
    public PatternLayout() {
      this(DEFAULT_CONVERSION_PATTERN);
    }
  
    /**
       Constructs a PatternLayout using the supplied conversion pattern.
    */
    public PatternLayout(String pattern) {
      this.pattern = pattern;
      head = new PatternParser((pattern == null) ? DEFAULT_CONVERSION_PATTERN : 
  			     pattern).parse();
    }
    
   
    /**
       Set the <b>ConversionPattern</b> option. This is the string which
       controls formatting and consists of a mix of literal content and
       conversion specifiers.
     */
    public
    void setConversionPattern(String conversionPattern) {
      pattern = conversionPattern;
      head = new PatternParser(conversionPattern).parse();
    }
    
    /**
       Returns the value of the <b>ConversionPattern</b> option.
     */
    public
    String getConversionPattern() {
      return pattern;
    }
    
    /**
       Does not do anything as options become effective immediately. See
       {@link #setOption} method. */
    public
    void activateOptions() {
      // nothing to do.
    }
  
    /**
       Returns the the array of option strings that {@link
       PatternLayout} recognizes. The only recognized option string is
       the value of {@link #CONVERSION_PATTERN_OPTION}.
    */
    public
    String[] getOptionStrings() {
      return new String[] {CONVERSION_PATTERN_OPTION};
    }	
    
   /**
       The PatternLayout does not handle the throwable contained within
       {@link LoggingEvent LoggingEvents}. Thus, it returns
       <code>true</code>.
  
       @since 0.8.4 */
    public
    boolean ignoresThrowable() {
      return true;
    }
  
    /**
      Returns PatternParser used to parse the conversion string. Subclasses
      may override this to return a subclass of PatternParser which recognize
      custom conversion characters.
  
      @since 0.9.0
    */
    //protected PatternParser createPatternParser(String pattern) {
    //return new PatternParser(pattern);
    //}
  
  
    /**
       Produces a formatted string as specified by the conversion pattern.
    */
    public String format(LoggingEvent event) {
      // Reset working stringbuffer
      if(sbuf.capacity() > MAX_CAPACITY) {
        sbuf = new StringBuffer(BUF_SIZE);
      } else {
        sbuf.setLength(0);
      }
      
      PatternConverter c = head;
  
      while(c != null) {
        c.format(sbuf, event);
        c = c.next;
      }
      return sbuf.toString();
    }
  
    /**
       The PatternLayout specific options are:
  
       <p>
       <dl>
       <dt><b>ConversionPattern</b>
  
       <p><dd>The value determines the conversion pattern used.
       
       </dl>
     */
    public
    void setOption(String option, String value) {
      if(value == null)
        return;
      if(option.equalsIgnoreCase(CONVERSION_PATTERN_OPTION)) {
        head = new PatternParser(value).parse();
      }
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/Priority.java
  
  Index: Priority.java
  ===================================================================
  
  package org.apache.log4j;
  
  /**
     Defines the minimum set of priorities recognized by the system,
     that is {@link #FATAL}, {@link #ERROR}, {@link #WARN}, {@link
     #INFO} and {@link #DEBUG}.
  
     <p>The <code>Priority</code> class may be subclassed to define a larger
     priority set.
  
     @author Ceki G&uuml;lc&uuml;
   */
  public class Priority {
  
    int level;
    String levelStr;
  
    public final static int OFF_INT = Integer.MAX_VALUE;
    public final static int FATAL_INT = 50000;
    public final static int ERROR_INT = 40000;
    public final static int WARN_INT  = 30000;
    public final static int INFO_INT  = 20000;
    public final static int DEBUG_INT = 10000;
    public final static int ALL_INT = Integer.MIN_VALUE;
  
  
    /**
       The <code>OFF</code> is used to turn off logging.
     */
    final static public Priority OFF = new Priority(OFF_INT, "OFF");
  
  
    /**
       The <code>FATAL</code> priority designates very severe error
       events that will presumably lead the application to abort.
     */
    final static public Priority FATAL = new Priority(FATAL_INT, "FATAL");
  
    /**
       The <code>ERROR</code> priority designates error events that
       might still allow the application to continue running.  */
    final static public Priority ERROR = new Priority(ERROR_INT, "ERROR");
  
    /**
       The <code>WARN</code> priority designates potentially harmful situations.
    */
    final static public Priority WARN  = new Priority(WARN_INT, "WARN");
  
    /**
       The <code>INFO</code> priority designates informational messages
       that highlight the progress of the application at coarse-grained
       level.  */
    final static public Priority INFO  = new Priority(INFO_INT, "INFO");
  
    /**
       The <code>DEBUG</code> priority designates fine-grained
       informational events that are most useful to debug an
       application.  */
    final static public Priority DEBUG = new Priority(DEBUG_INT, "DEBUG");
  
    /**
       The <code>ALL</code> is used to turn on all logging.
    */
    final static public Priority ALL = new Priority(ALL_INT, "ALL");
  
    
    /**
       Instantiate a priority object.
     */
    protected
    Priority(int level, String levelStr) {
      this.level = level;
      this.levelStr = levelStr;
    }
  
  
    /**
       Returns the string representation of this priority.
     */
    final
    public
    String toString() {
      return levelStr;
    }
  
    /**
       Returns the integer representation of this priority.
     */
    public
    final
    int toInt() {
      return level;
    }
  
      
    /**
       Returns <code>true</code> if this priority has a higher or equal
       priority than the priority passed as argument, <code>false</code>
       otherwise.  
       
       <p>You should think twice before overriding the default
       implementation of <code>isGreaterOrEqual</code> method.
  
    */
    public
    boolean isGreaterOrEqual(Priority r) {
      return level >= r.level;
    }
  
  
    /**
       Convert the string passed as argument to a priority. If the
       conversion fails, then this method returns {@link #DEBUG}. 
    */
    public
    static
    Priority toPriority(String sArg) {
      return toPriority(sArg, Priority.DEBUG);
    }
  
    /**
      Convert an integer passed as argument to a priority. If the
      conversion fails, then this method returns {@link #DEBUG}.
  
    */
    public
    static
    Priority toPriority(int val) {
      return toPriority(val, Priority.DEBUG);
    }
  
    /**
      Convert an integer passed as argument to a priority. If the
      conversion fails, then this method returns the specified default.
    */
    public
    static
    Priority toPriority(int val, Priority defaultPriority) {
      switch(val) {
      case ALL_INT: return ALL;
      case DEBUG_INT: return DEBUG;
      case INFO_INT: return INFO;
      case WARN_INT: return WARN;
      case ERROR_INT: return ERROR;
      case FATAL_INT: return FATAL;
      case OFF_INT: return OFF;
      default: return defaultPriority;
      }
    }
  
    /**
       Convert the string passed as argument to a priority. If the
       conversion fails, then this method returns the value of
       <code>defaultPriority</code>.  
    */
    public
    static
    Priority toPriority(String sArg, Priority defaultPriority) {                  
      if(sArg == null)
         return defaultPriority;
      
      String s = sArg.toUpperCase();
  
      if(s.equals("ALL")) return Priority.ALL; 
      if(s.equals("DEBUG")) return Priority.DEBUG; 
      if(s.equals("INFO"))  return Priority.INFO;
      if(s.equals("WARN"))  return Priority.WARN;  
      if(s.equals("ERROR")) return Priority.ERROR;
      if(s.equals("FATAL")) return Priority.FATAL;
      if(s.equals("OFF")) return Priority.OFF;
      return defaultPriority;
    }
  
  
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/PropertyConfigurator.java
  
  Index: PropertyConfigurator.java
  ===================================================================
  /*
   * 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.APL file.  */
  
  
  // Contibutors: "Luke Blanshard" <Lu...@quiq.com>
  //              "Mark DONSZELMANN" <Ma...@cern.ch>
  //              Anders Kristensen <ak...@dynamicsoft.com>
  
  package org.apache.log4j;
  
  import org.apache.log4j.Category;
  import org.apache.log4j.Priority;
  import org.apache.log4j.spi.OptionHandler;
  import org.apache.log4j.helpers.LogLog;
  import org.apache.log4j.helpers.OptionConverter;
  
  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;
  
  /**
     Allows the log4j 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>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.
  
  
     @author Ceki G&uuml;lc&uuml;
     @since log4jME 1.0
  */
  public class PropertyConfigurator {
  
    /**
       Used internally to keep track of configured appenders.
     */
    protected Hashtable registry = new Hashtable(11);
    
    static final String CATEGORY_PREFIX = "log4j.category.";
    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 CATEGORY_FACTORY_KEY = "log4j.categoryFactory";
  
    static final private String INHERITED = "inherited";
    static final private String INTERNAL_ROOT_NAME = "root";
    
    /**
      Read configuration from a file. The existing configuration is not
      cleared nor reset. 
  
      <p>The configuration file consists of staments in the format
      <code>key=value</code>.
  
      <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>
      log.appender.appenderName.layout=fully.qualified.name.of.layout.class
      log.appender.appenderName.layout.option1=value1
      ....
      log.appender.appenderName.layout.optionN=valueN
      </pre>
      
      <h3>Configuring categories</h3>
  
      <p>The syntax for configuring the root category is:
      <pre>
        log4j.rootCategory=[FATAL|ERROR|WARN|INFO|DEBUG], appenderName, appenderName, ...
      </pre>
  
      <p>This syntax means that one of the strings values ERROR, WARN,
      INFO or DEBUG can be supplied followed by appender names separated
      by commas.
      
      <p>If one of the optional priority values ERROR, WARN, INFO or
      DEBUG is given, 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> (seperated 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=[INHERITED|FATAL|ERROR|WARN|INFO|DEBUG], appenderName, appenderName, ...
      </pre>
  
      <p>Thus, one of the usual priority values FATAL, ERROR, WARN,
      INFO, or DEBUG can be optionally specified. For any any of these
      values the named category is assigned the corresponding
      priority. In addition however, the value INHERITED can be
      optionally specified which means that 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>
      (seperated 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.
  
      <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 FileAppender
      log4j.appender.A1=org.apache.log4j.FileAppender
  
      # It will send its output to System.out
      log4j.appender.A1.File=System.out
  
      # A1's layout is a PatternLayout, using the conversion pattern 
      # <b>%-4r %-5p %c{2} - %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
      # 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%n
  
      # Set options for appender named "A2"
      # A2 should be a <code>FileAppender</code> printing to the
      # file <code>temp</code>.
      log4j.appender.A2=org.apache.log4j.FileAppender
      log4j.appender.A2.File=temp
  
      log4j.appender.A2.layout=org.apache.log4j.PatternLayout
      log4j.appender.A2.layout.ConversionPattern=%-4r %-5p %c - %m%n
  
      # Root category set to DEBUG using the A2 appender defined above.
      log4j.rootCategory=DEBUG, A2
  
      # Category definions:
      # 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 hierrarchy.  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 config file [" + configFileName+
  			 "].", e);
        LogLog.error("Ignoring config 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);
    }
  
    /**
       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) {
        LogLog.setInternalDebugging(OptionConverter.toBoolean(value, true));
      }
      
      configureRootCategory(properties, hierarchy);
      parseCats(properties, hierarchy);
  
      // 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 URL " + configURL);
      try {
        props.load(configURL.openStream());
      }
      catch (java.io.IOException e) {
        LogLog.error("Could not read config file [" + configURL 
  		   + "].", e);
        LogLog.error("Ignoring config file [" + configURL +"].");
        return;
      }
      doConfigure(props, hierarchy);
    }
  
  
    // -------------------------------------------------------------------------------
    // Internal stuff
    // -------------------------------------------------------------------------------
  
  
    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 =  props.getProperty(prefix + options[i]);
        LogLog.debug(
           "Option " + options[i] + "=[" + (value == null? "null" : 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 = props.getProperty(ROOT_CATEGORY_PREFIX);
      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 parseCats(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 =  props.getProperty(key);
  	Category cat = hierarchy.getInstance(categoryName);
  	synchronized(cat) {
  	  parseCategory(props, cat, key, categoryName, value);
  	  parseAdditivityForCategory(props, cat, categoryName);
  	}
        }      
      }
    }  
  
    /**
       Parse the additivity option for a non-root category.
     */
    void parseAdditivityForCategory(Properties props, Category cat,
  				  String categoryName) {
      String value = props.getProperty(ADDITIVITY_PREFIX + categoryName);
      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(INHERITED) && !catName.equals(INTERNAL_ROOT_NAME)) 
  	cat.setPriority(null);
        else 
  	cat.setPriority(Priority.toPriority(priorityStr));
        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) {
        configureOptionHandler((OptionHandler) appender, prefix + ".", props);
        LogLog.debug("Parsed \"" + appenderName +"\" options.");
        
        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);
  	LogLog.debug("End of parsing for \"" + appenderName +"\".");      
        }
      }
      registryPut(appender);
      return appender;
    }
  
    
    void  registryPut(Appender appender) {
      registry.put(appender.getName(), appender);
    }
    
    Appender registryGet(String name) {
      return (Appender) registry.get(name);
    }
  }
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/ProvisionNode.java
  
  Index: ProvisionNode.java
  ===================================================================
  /*
   * 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.  */
  
  package org.apache.log4j;
  
  import java.util.Vector;
  
  class ProvisionNode extends Vector {
      
    ProvisionNode(Category cat) {
      super();
      this.addElement(cat);
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/StressCategory.java
  
  Index: StressCategory.java
  ===================================================================
  /*
   * 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.  */
  
  package org.apache.log4j;
  
  
  import org.apache.log4j.Priority;
  import org.apache.log4j.Category;
  import java.util.Random;
  
  /*
    Stress test the Category class.
  
  */
  
  class StressCategory {
  
    static Priority[] priority = new Priority[] {Priority.DEBUG, 
  					       Priority.INFO, 
  					       Priority.WARN,
  					       Priority.ERROR,
  					       Priority.FATAL};
  
    static Priority defaultPriority = Category.getRoot().getPriority();
    
    static int LENGTH;
    static String[] names;
    static Category[] cat;
    static CT[] ct;
  
    static Random random = new Random(10);
  
    public static void main(String[] args) {
      
      LENGTH = args.length;
  
      if(LENGTH == 0) {
        System.err.println( "Usage: java " + StressCategory.class.getName() +
  			  " name1 ... nameN\n.");      
        System.exit(1);
      }
      if(LENGTH >= 7) {
        System.err.println(
          "This stress test suffers from combinatorial explosion.\n"+
          "Invoking with seven arguments takes about 90 minutes even on fast machines");
      }
  
      names = new String[LENGTH];
      for(int i=0; i < LENGTH; i++) {
        names[i] = args[i];
      }    
      cat = new Category[LENGTH];
      ct = new CT[LENGTH]; 
  
  
      permute(0); 
  
      // If did not exit, then passed all tests.
    }
  
    // Loop through all permutations of names[].
    // On each possible permutation call createLoop
    static
    void permute(int n) {
      if(n == LENGTH)
        createLoop(0);
      else
        for(int i = n; i < LENGTH; i++) {
  	swap(names, n, i);
  	permute(n+1);
  	swap(names, n, i);	
        }
    }
  
    static
    void swap(String[] names, int i, int j) {
      String t = names[i];
      names[i] = names[j];
      names[j] = t;
    }
    
    public
    static
    void permutationDump() {
      System.out.print("Current permutation is - ");
      for(int i = 0; i < LENGTH; i++) {
        System.out.print(names[i] + " ");
      }
      System.out.println();
    }
  
  
    // Loop through all possible 3^n combinations of not instantiating, 
    // instantiating and setting/not setting a priority.
  
    static
    void createLoop(int n) {
      if(n == LENGTH) {  
        //System.out.println("..............Creating cat[]...........");
        for(int i = 0; i < LENGTH; i++) {
  	if(ct[i] == null)
  	  cat[i] = null;
  	else {
  	  cat[i] = Category.getInstance(ct[i].catstr);
  	  cat[i].setPriority(ct[i].priority);
  	}
        }
        test();
        // Clear hash table for next round
        Category.defaultHierarchy.clear();
      }
      else {      
        ct[n]  = null;
        createLoop(n+1);  
  
        ct[n]  = new CT(names[n], null);
        createLoop(n+1);  
        
        int r = random.nextInt(); if(r < 0) r = -r;
        ct[n]  = new CT(names[n], priority[r%5]);
        createLoop(n+1);
      }
    }
  
  
    static
    void test() {    
      //System.out.println("++++++++++++TEST called+++++++++++++");
      //permutationDump();
      //catDump();
  
      for(int i = 0; i < LENGTH; i++) {
        if(!checkCorrectness(i)) {
  	System.out.println("Failed stress test.");
  	permutationDump();
  	
  	//Hierarchy._default.fullDump();
  	ctDump();
  	catDump();
  	System.exit(1);
        }
      }
    }
    
    static
    void ctDump() {
      for(int j = 0; j < LENGTH; j++) {
         if(ct[j] != null) 
  	    System.out.println("ct [" + j + "] = ("+ct[j].catstr+"," + 
  			       ct[j].priority + ")");
         else 
  	 System.out.println("ct [" + j + "] = undefined");
      }
    }
    
    static
    void catDump() {
      for(int j = 0; j < LENGTH; j++) {
        if(cat[j] != null)
  	System.out.println("cat[" + j + "] = (" + cat[j].name + "," +
  			   cat[j].getPriority() + ")");
        else
  	System.out.println("cat[" + j + "] = undefined"); 
      }
    }
  
    //  static
    //void provisionNodesDump() {
    //for (Enumeration e = CategoryFactory.ht.keys(); e.hasMoreElements() ;) {
    //  CategoryKey key = (CategoryKey) e.nextElement();
    //  Object c = CategoryFactory.ht.get(key);
    //  if(c instanceof  ProvisionNode) 
    //((ProvisionNode) c).dump(key.name);
    //}
    //}
    
    static
    boolean checkCorrectness(int i) {
      CT localCT = ct[i];
  
      // Can't perform test if category is not instantiated
      if(localCT == null) 
        return true;
      
      // find expected priority
      Priority expected = getExpectedPrioriy(localCT);
  
  			    
      Priority purported = cat[i].getChainedPriority();
  
      if(expected != purported) {
        System.out.println("Expected priority for " + localCT.catstr + " is " +
  		       expected);
        System.out.println("Purported priority for "+ cat[i].name + " is "+purported);
        return false;
      }
      return true;
        
    }
  
    static
    Priority getExpectedPrioriy(CT ctParam) {
      Priority priority = ctParam.priority;
      if(priority != null) 
        return priority;
  
      
      String catstr = ctParam.catstr;    
      
      for(int i = catstr.lastIndexOf('.', catstr.length()-1); i >= 0; 
  	                              i = catstr.lastIndexOf('.', i-1))  {
        String substr = catstr.substring(0, i);
  
        // find the priority of ct corresponding to substr
        for(int j = 0; j < LENGTH; j++) {	
  	if(ct[j] != null && substr.equals(ct[j].catstr)) {
  	  Priority p = ct[j].priority;
  	  if(p != null) 
  	    return p;	  
  	}
        }
      }
      return defaultPriority;
    }
  
    
  
    static class CT {
      public String   catstr;
      public Priority priority;
  
      CT(String catstr,  Priority priority) {
        this.catstr = catstr;
        this.priority = priority;
      }
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/WriterAppender.java
  
  Index: WriterAppender.java
  ===================================================================
  /*
   * 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.  */
  
  package org.apache.log4j;
  
  import java.io.IOException;
  import java.io.Writer;
  import java.io.FileWriter;
  import java.io.OutputStream;
  import java.io.OutputStreamWriter;
  
  import org.apache.log4j.spi.LoggingEvent;
  import org.apache.log4j.helpers.LogLog;
  
  // Contibutors: Jens Uwe Pipka <je...@gmx.de>
  
  /**
     WriterAppender appends log events to a {@link java.io.Writer} or an
     {@link java.io.OutputStream} depending on the user's choice.
  
     @author Ceki G&uuml;lc&uuml;
     @since 1.1 */
  public class WriterAppender extends AppenderSkeleton {
  
    /**
       This is the {@link QuietWriter quietWriter} where we will write
       to. 
    */
    protected Writer w;
  
    
    /**
       This default constructor does nothing.  */
    public
    WriterAppender() {
    }
  
    /**
       Instantiate a WriterAppender and set the output destination to a
       new {@link OutputStreamWriter} initialized with <code>os</code>
       as its {@link OutputStream}.  */
    //public
    //WriterAppender(Layout layout, OutputStream os) {
    //this(layout, new OutputStreamWriter(os));
    //}
    
    /**
       Instantiate a WriterAppender and set the output destination to
       <code>writer</code>.
  
       <p>The <code>writer</code> must have been previously opened by
       the user.  */
    public
    WriterAppender(Layout layout, Writer writer) {
      this.layout = layout;
      this.setWriter(writer);
    }
  
    public
    void write(String string) {
      try {
        w.write(string);
      } catch(IOException e) {
        error("Failed to writing", e);
      }
    }
  
    /**
       Does nothing.
    */
    public
    void activateOptions() {    
    }
  
  
    /**
       This method is called by the {@link AppenderSkeleton#doAppend}
       method. 
  
       <p>If the output stream exists and is writable then write a log
       statement to the output stream. Otherwise, write a single warning
       message to <code>System.err</code>.
  
       <p>The format of the output will depend on this appender's
       layout.
       
    */
    public
    void append(LoggingEvent event) {
  
      // Reminder: the nesting of calls is:
      //
      //    doAppend()
      //      - check threshold
      //      - filter
      //      - append();
      //        - checkEntryConditions();
      //        - subAppend();
  
      if(!checkEntryConditions()) {
        return;
      }
      write(this.layout.format(event));
  
      if(layout.ignoresThrowable()) {
        String s = event.getThrowableStr();
        if (s != null) {
  	write(s);
        }
      }
  
      try {
        w.flush();
      } catch(IOException e) {
        error("Failed to flush", e);
      }
     } 
  
    /**
       This method determines if there is a sense in attempting to append.
       
       <p>It checks whether there is a set output target and also if
       there is a set layout. If these checks fail, then the boolean
       value <code>false</code> is returned. */
    protected
    boolean checkEntryConditions() {
      if(this.closed) {
        return false;
      }
  
      if(this.w == null) {
        error("No Writer for ["+name+"]");
        return false;
      }
      
      if(this.layout == null) {
        error("No layout for ["+ name+"]");
        return false;
      }
      return true;
    }
  
  
    /**
       Close this appender instance. The underlying stream or writer is
       also closed.
       
       <p>Closed appenders cannot be reused.
  
       @see #setWriter
       @since 0.8.4 */
    public
    synchronized
    void close() {
      if(this.closed)
        return;
      this.closed = true;
      closeWriter();
      this.w = null;
    }
  
    /**
       Close the underlying {@link java.io.Writer}.
    */
    protected 
    void closeWriter() {
      if(w != null) {
        try {
  	w.close();
        } catch(IOException e) {
  	LogLog.error("Failed closing", e); 
        }
      }
    }
  
   
    /**
      <p>Sets the Writer where the log output will go. The
      specified Writer must be opened by the user and be
      writable.
      
      <p>The <code>java.io.Writer</code> will be closed when the
      appender instance is closed.
  
      
      <p><b>WARNING:</b> Logging to an unopened Writer will fail.
      <p>  
      @param Writer An already opened Writer.  */
    public
    synchronized
    void setWriter(Writer writer) {
      closeWriter();
      this.w = null;
      this.w = writer;
    }
  
    /**
       Clear internal references to the writer and other variables.
  
       Subclasses can override this method for an alternate closing
       behavior.  */
    //protected
    //void reset() {
    //closeWriter();
    //this.w = null;
    //}
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/package.html
  
  Index: package.html
  ===================================================================
  <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN">
  <html> <head>
  <title></title>
  </head>
  
  <body>
  
  <p>The main package of log4j.
  
  <hr>
  </body> </html>
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  doc-files
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/Makefile
  
  Index: Makefile
  ===================================================================
  
  PKG_DIR :=org/apache/log4j/examples
  DEPTH   :=../../../../../..
  JSOURCES:=SortAlgo.java Sort.java 
  
  # include master-rule file
  include $(DEPTH)/make/make.inc
  
  
  
  
  
  
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/Sort.java
  
  Index: Sort.java
  ===================================================================
  
  package org.apache.log4j.examples;
  
  import org.apache.log4j.PropertyConfigurator;
  import org.apache.log4j.Category;
  import org.apache.log4j.Priority;  
  
  /**
     Example code for log4j to viewed in conjunction with the {@link
     org.apache.log4j.examples.SortAlgo SortAlgo} class.
     
     <p>This program expects a configuration file name as its first
     argument, and the size of the array to sort as the second and last
     argument. See its <b><a href="doc-files/Sort.java">source
     code</a></b> for more details.
  
     <p>Play around with different values in the configuration file and
     watch the changing behavior.
  
     <p>Example configuration files <a
     href="doc-files/sort1.lcf">sort1.lcf</a>, 
     <a href="doc-files/sort2.lcf">sort2.lcf</a>, 
     <a href="doc-files/sort3.lcf">sort3.lcf</a> and 
     <a href="doc-files/sort4.lcf">sort4.lcf</a> are supplied with the
     package.
     
     <p>If you are interested in logging performance, then have look at
     the {@link org.apache.log4j.performance.Logging} class.
  
     @author Ceki G&uuml;lc&uuml; */
  
  public class Sort {
  
    static Category CAT = Category.getInstance(Sort.class.getName());
    
    public static void main(String[] args) {
      if(args.length != 2) {
        usage("Incorrect number of parameters.");
      }
      int arraySize = -1;
      try {
        arraySize = Integer.valueOf(args[1]).intValue();
        if(arraySize <= 0) 
  	usage("Negative array size.");
      }
      catch(java.lang.NumberFormatException e) {
        usage("Could not number format ["+args[1]+"].");
      }
  
      Sort.init(args[0]);
  
      int[] intArray = new int[arraySize];
  
      CAT.info("Populating an array of " + arraySize + " elements in" +
  	     " reverse order.");
      for(int i = arraySize -1 ; i >= 0; i--) {
        intArray[i] = arraySize - i - 1;
      }
  
      SortAlgo sa1 = new SortAlgo(intArray);
      sa1.bubbleSort();
      sa1.dump();
  
      // We intentionally initilize sa2 with null.
      SortAlgo sa2 = new SortAlgo(null);
      CAT.info("The next log statement should be an error message.");
      sa2.dump();  
      CAT.info("Exiting main method.");    
    }
    
    static
    void usage(String errMsg) {
      System.err.println(errMsg);
      System.err.println("\nUsage: java org.apache.log4j.examples.Sort " +
  		       "configFile ARRAY_SIZE\n"+
        "where  configFile is a configuration file\n"+
        "      ARRAY_SIZE is a positive integer.\n");
      System.exit(1);
    }
  
    static
    void init(String configFile) {
      PropertyConfigurator.configure(configFile);
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/SortAlgo.java
  
  Index: SortAlgo.java
  ===================================================================
  
  package org.apache.log4j.examples;
  
  import org.apache.log4j.Category;
  import org.apache.log4j.NDC;
  
  /**
     Example code for log4j to viewed in conjunction with the {@link
     org.apache.log4j.examples.Sort Sort} class.
        
     <p>SortAlgo uses the bubble sort algorithm to sort an integer
     array. See also its <b><a href="doc-files/SortAlgo.java">source
     code</a></b>.
  
     @author Ceki G&uuml;lc&uuml;
  */
  public class SortAlgo {
  
    final static String className = SortAlgo.class.getName();
    final static Category CAT = Category.getInstance(className);
    final static Category OUTER = Category.getInstance(className + ".OUTER");
    final static Category INNER = Category.getInstance(className + ".INNER");
    final static Category DUMP = Category.getInstance(className + ".DUMP");
    final static Category SWAP = Category.getInstance(className + ".SWAP");
  
    int[] intArray;
  
    SortAlgo(int[] intArray) {
      this.intArray = intArray;
    }
      
    void bubbleSort() {
      CAT.info( "Entered the sort method.");
  
      for(int i = intArray.length -1; i >= 0  ; i--) {
        NDC.push("i=" + i);
        OUTER.debug("in outer loop.");
        for(int j = 0; j < i; j++) {
  	NDC.push("j=" + j);
  	// It is poor practice to ship code with log staments in tight loops.
  	// We do it anyway in this example.
  	INNER.debug( "in inner loop.");
           if(intArray[j] > intArray[j+1])
  	   swap(j, j+1);
  	NDC.pop();
        }
        NDC.pop();
      }
    }  
  
    void dump() {    
      if(! (this.intArray instanceof int[])) {
        DUMP.error( "Tried to dump an uninitialized array.");
        return;
      }
      DUMP.info( "Dump of integer array:");
      for(int i = 0; i < this.intArray.length; i++) {
        DUMP.info( "Element [" + i + "]=" + this.intArray[i]);
      }    
    }
  
    void swap(int l, int r) {
      // It is poor practice to ship code with log staments in tight
      // loops or code called potentially millions of times.
      SWAP.debug( "Swapping intArray["+l+"]=" + intArray[l] +
  	                     " and intArray["+r+"]=" + intArray[r]);
      int temp = this.intArray[l];
      this.intArray[l] = this.intArray[r];
      this.intArray[r] = temp;
    }
  }
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/Trivial.java
  
  Index: Trivial.java
  ===================================================================
  
  package org.apache.log4j.examples;
  
  
  import org.apache.log4j.Category;
  import org.apache.log4j.BasicConfigurator;
  import org.apache.log4j.NDC;
  
  /**
     View the <a href="doc-files/Trivial.java">source code</a> of this a
     trivial usage example. Running <code>java
     org.apache.log4j.examples.Trivial</code> should output something
     similar to:
  
     <pre>
        0    INFO  [main] org.apache.log4j.examples.Trivial (Client #45890) - Awake awake. Put on thy strength.
        15   DEBUG [main] org.apache.log4j.examples.Trivial (Client #45890 DB) - Now king David was old.
        278  INFO  [main] org.apache.log4j.examples.Trivial$InnerTrivial (Client #45890) - Entered foo.
        293  INFO  [main] org.apache.log4j.examples.Trivial (Client #45890) - Exiting Trivial.   
     </pre>
     
     <p> The increasing numbers at the beginning of each line are the
     times elapsed since the start of the program. The string between
     the parentheses is the nested diagnostic context.
  
     <p>See {@link Sort} and {@link SortAlgo} for sligtly more elaborate
     examples.
  
     <p>Note thent class files for the example code is not included in
     any of the distributed log4j jar files. You will have to add the
     directory <code>/dir-where-you-unpacked-log4j/classes</code> to
     your classpath before trying out the examples.
  
   */
  public class Trivial {
  
    static Category cat = Category.getInstance(Trivial.class.getName());
  
    public static void main(String[] args) {
      BasicConfigurator.configure();
      NDC.push("Client #45890"); 
  
      cat.info("Awake awake. Put on thy strength.");
      Trivial.foo();
      InnerTrivial.foo();
      cat.info("Exiting Trivial.");    
    }
  
    static
    void foo() {
      NDC.push("DB"); 
      cat.debug("Now king David was old.");    
      NDC.pop(); 
    }
  
    static class InnerTrivial {
      static  Category cat = Category.getInstance(InnerTrivial.class.getName());
  
      static    
      void foo() {
        cat.info("Entered foo."); 
      }
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/sort1.lcf
  
  Index: sort1.lcf
  ===================================================================
  # An example log4j configuration file that outputs to System.out.
  # The output info consists of relative time, priority, thread name,
  # category name, nested diagnostic context, the and the message in
  # that order.
  
  # For the general syntax of property based configuration files see the
  # documenation of org.apache.log4j.PropertyConfigurator.
  
  # The root category uses the appender called A1. Since no priority is
  # specified, the root category assumes the default priority for root
  # which is DEBUG in log4j. The root category is the only category that
  # has a default priority. All other categories do not have a default
  # priority. in which case the priority is inherited from the
  # hierarchy.
  
  log4j.rootCategory=, A1
  
  # A1 is set to be a ConsoleAppender which outputs to System.out. 
  log4j.appender.A1=org.apache.log4j.FileAppender
  log4j.appender.A1.File=System.out
  
  # A1 uses PatternLayout.
  log4j.appender.A1.layout=org.apache.log4j.PatternLayout
  
  # The conversion pattern uses format specifiers. You might want to
  # change the pattern an watch the output layout change.
  log4j.appender.A1.layout.ConversionPattern=%-4r %-5p [%t] %37c %3x - %m%n
  
  # In this example, we are not really interested in INNER loop or SWAP
  # messages. Try changing the priorities of these categories.
  # log4j.category.org.apache.log4j.examples.SortAlgo.INNER=WARN
  # log4j.category.org.apache.log4j.examples.SortAlgo.SWAP=WARN
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/sort2.lcf
  
  Index: sort2.lcf
  ===================================================================
  # An example log4j configuration file that outputs both to System.out
  # and a file named 'test'.
  
  log4j.rootCategory=, A1, A2
  
  # A1 is set to be FileAppender sending its output to System.out
  log4j.appender.A1=org.apache.log4j.FileAppender
  log4j.appender.A1.File=System.out
  
  
  # A1 uses PatternLayout.
  log4j.appender.A1.layout=org.apache.log4j.PatternLayout
  
  # The conversion pattern consists of date in ISO8601 format, priority,
  # thread name, category name truncated to its rightmost two components
  # and left justified to 17 characters, location information consisting
  # of file name (padded to 13 characters) and line number, nested
  # diagnostic context, the and the application supplied message
  
  log4j.appender.A1.layout.ConversionPattern=%d %-5p [%t] %-17c{2} (%13F:%L) %3x - %m%n
  
  # Appender A2 writes to the file "test".
  log4j.appender.A2=org.apache.log4j.FileAppender
  log4j.appender.A2.File=test
  
  # Truncate 'test' if it aleady exists.
  log4j.appender.A2.Append=false
  
  # Appender A2 uses the PatternLayout.
  log4j.appender.A2.layout=org.apache.log4j.PatternLayout
  log4j.appender.A2.layout.ConversionPattern=%-5r %-5p [%t] %c{2} - %m%n
  
  
  # In this example, we are not interested in INNER loop or SWAP
  # messages.  You might try to set INNER and SWAP to DEBUG for more
  # verbose output.
  
  log4j.category.org.apache.log4j.examples.SortAlgo.INNER=INFO
  log4j.category.org.apache.log4j.examples.SortAlgo.SWAP=INFO
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/examples/sort3.lcf
  
  Index: sort3.lcf
  ===================================================================
  # Attach appender A1 to root. Set root priority to Prority.DEBUG.
  log4j.rootCategory=DEBUG, A1
  
  
  
  # A1 is set to be a FileAppender sending its output to
  # System.out. However, only error messages and above will be printed
  # since the threshold is set to Priority.ERROR.
  
  # The fact that the root priority is set to Prority.DEBUG only
  # influences log requests made to the root category. It has no
  # influence on the appenders attached to root.
  
  log4j.appender.A1=org.apache.log4j.ConsoleAppender
  log4j.appender.A1.Threshold=ERROR
  
  
  log4j.appender.A1.layout=org.apache.log4j.PatternLayout
  log4j.appender.A1.layout.ConversionPattern=%p [%t] %c{2} (%M:%L) - %m%n
  
  # Set the priority of the category named "org.apache.log4j.examples" to 
  # Priority.INFO, attach appender A2.
  log4j.category.org.apache.log4j.examples=INFO, A2
  
  # Appender A2 writes to the file "test" in user's home.
  log4j.appender.A2=org.apache.log4j.FileAppender
  log4j.appender.A2.File=${user.home}/test
  
  # Truncate 'test' if it aleady exists.
  log4j.appender.A2.Append=false
  
  # Appender A2 uses the PatternLayout.
  log4j.appender.A2.layout=org.apache.log4j.PatternLayout
  log4j.appender.A2.layout.ConversionPattern=%5r %-5p [%t] %c{2} - %m%n
  
  
  
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/helpers/FormattingInfo.java
  
  Index: FormattingInfo.java
  ===================================================================
  /*
   * 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.APL file.
   */
  
  package org.apache.log4j.helpers;
  
  
  /**
     FormattingInfo instances contain the information obtained when parsing
     formatting modifiers in conversion modifiers.
  
     @author <a href=mailto:jim_cakalic@na.biomerieux.com>Jim Cakalic</a>
     @author Ceki G&uuml;lc&uuml;
  
     @since 0.8.2   
   */
  public class FormattingInfo {
    int min = -1;
    int max = 0x7FFFFFFF;
    boolean leftAlign = false;
  
    void reset() {
      min = -1;
      max = 0x7FFFFFFF;
      leftAlign = false;      
    }
  }
   
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/helpers/LogLog.java
  
  Index: LogLog.java
  ===================================================================
  /*
   * 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.
   */
  
  package org.apache.log4j.helpers;
  
  /**
     This class used to output log statements from within the log4j package.
  
     <p>Log4j components cannot make log4j logging calls. However, it is
     sometimes useful for the user to learn about what log4j is
     doing. You can enable log4j internal logging by defining the
     <b>log4j.configDebug</b> variable.
  
     <p>All log4j internal debug calls go to <code>System.out</code>
     where as internal error messages are sent to
     <code>System.err</code>. All internal messages are prepended with
     the string "log4j: ".
     
     @since 0.8.2
     @author Ceki G&uuml;lc&uuml;
  */
  public class LogLog {
  
    /**
       Defining this value makes log4j print log4j-internal debug
       statements to <code>System.out</code>.
       
      <p> The value of this string is <b>log4j.debug</b>.
      
      <p>Note that the search for all option names is case sensitive.  */
    public static final String DEBUG_KEY="log4j.debug";
  
     protected static boolean debugEnabled = false;  
  
    /**
       In quietMode not even errors generate any output.
     */
    private static boolean quietMode = false;
  
    private static final String PREFIX = "log4j: ";
    private static final String ERR_PREFIX = "log4j:ERROR ";
    private static final String WARN_PREFIX = "log4j:WARN ";
  
    static {
      String key = getSystemProperty(DEBUG_KEY, null);
      if(key != null) { 
        debugEnabled = OptionConverter.toBoolean(key, true);
      }
    }
  
    /**
       Allows to enable/disable log4j internal logging.
     */
    static
    public
    void setInternalDebugging(boolean enabled) {
      debugEnabled = enabled;
    }
  
    /**
       This method is used to output log4j internal debug
       statements. Output goes to <code>System.out</code>.
    */
    public
    static
    void debug(String msg) {
      debug(msg, null);
    }
  
    /**
       This method is used to output log4j internal debug
       statements. Output goes to <code>System.out</code>.
    */
    public
    static
    void debug(String msg, Throwable t) {
      if(debugEnabled && !quietMode) {
        System.out.println(PREFIX+msg);
        if(t != null)
  	t.printStackTrace(System.out);
      }
    }
  
    /**
       This method is used to output log4j internal error
       statements. There is no way to disable error statements.
       Output goes to <code>System.err</code>.
    */
    public
    static
    void error(String msg) {
      error(msg, null);
    }  
  
    /**
       This method is used to output log4j internal error
       statements. There is no way to disable error statements.
       Output goes to <code>System.err</code>.  
    */
    public
    static
    void error(String msg, Throwable t) {
      if(quietMode)
        return;
  
      System.err.println(ERR_PREFIX+msg);
      if(t != null) {
        t.printStackTrace();
      }
    }  
  
    public
    static
    String getSystemProperty(String key, String def) {
      try {
        return System.getProperty(key, def);
      } catch(Throwable e) { 
        return def;
      }
    }
  
    /**
       In quite mode no LogLog generates strictly no output, not even
       for errors. 
  
       @param quietMode A true for not
    */
    public
    static
    void setQuietMode(boolean quietMode) {
      LogLog.quietMode = quietMode;
    }
  
    /**
       This method is used to output log4j internal warning
       statements. There is no way to disable warning statements.
       Output goes to <code>System.err</code>.  */
    public
    static
    void warn(String msg) {
      warn(msg, null);
    }  
  
    /**
       This method is used to output log4j internal warnings. There is
       no way to disable warning statements.  Output goes to
       <code>System.err</code>.  */
    public
    static
    void warn(String msg, Throwable t) {
      if(quietMode)
        return;
  
      System.err.println(WARN_PREFIX+msg);
      if(t != null) {
        t.printStackTrace();
      }
    }  
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/helpers/OptionConverter.java
  
  Index: OptionConverter.java
  ===================================================================
  /*
   * 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.  */
  
  package org.apache.log4j.helpers;
  
  import java.util.Properties;
  
  public class OptionConverter {
  
    public
    static
    boolean toBoolean(String value, boolean defaultVal) {
      if(value == null)
        return defaultVal;
      String trimmedVal = value.trim();
      if("true".equalsIgnoreCase(trimmedVal)) 
    	return true;
      if("false".equalsIgnoreCase(trimmedVal))
        return false;
      return defaultVal;
    }
  
  
    public
    static
    Object instantiateByKey(Properties props, String key, Class superClass,
  				Object defaultValue) {
  
      // Get the value of the property in string form
      String className = props.getProperty(key);
      if(className == null) {
        LogLog.error("Could not find value for " + key);
        return defaultValue;
      }
      // Trim className to avoid trailing spaces that cause problems.
      return OptionConverter.instantiateByClassName(className.trim(), superClass,
  						  defaultValue);
    }
  
  
      /**
       Instantiate an object given a class name. Check that the
       <code>className</code> is a subclass of <code>superClass</code>.
  
     */
    public
    static
    Object instantiateByClassName(String className, Class superClass,
  				Object defaultValue) {
      if(className != null) {
        try {
  	Class classObj = Class.forName(className);
  	if(!superClass.isAssignableFrom(classObj)) 
  	  LogLog.error("A \""+className+"\" object is not assignable to a \""+
  		       superClass.getName() + "\" object.");
  	return classObj.newInstance();
        }
        catch (Exception e) {
  	LogLog.error("Could not instantiate class [" + className + "].", e);
        }
      }
      return defaultValue;    
    }
  
  
  
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/helpers/PatternConverter.java
  
  Index: PatternConverter.java
  ===================================================================
  /*
   * 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.APL file.
   */
  
  package org.apache.log4j.helpers;
  
  import org.apache.log4j.spi.LoggingEvent;
  
  /**
  
     <p>PatternConverter is an abtract class that provides the
     formatting functionality that derived classes need.
  
     <p>Conversion specifiers in a conversion patterns are parsed to
     individual PatternConverters. Each of which is responsible for
     converting a logging event in a converter specific manner.
  
     @author <a href="mailto:cakalijp@Maritz.com">James P. Cakalic</a>
     @author Ceki G&uuml;lc&uuml;
  
     @since 0.8.2
   */
  public abstract class PatternConverter {
    public PatternConverter next;
    int min = -1;
    int max = 0x7FFFFFFF;
    boolean leftAlign = false;
  
    protected
    PatternConverter() {  }
    
    protected
    PatternConverter(FormattingInfo fi) {
      min = fi.min;
      max = fi.max;
      leftAlign = fi.leftAlign;
    }
  
    /**
       Derived pattern converters must override this method in order to
       convert conversion specifiers in the correct way.
    */
    abstract
    protected
    String convert(LoggingEvent event);
  
    /**
       A template method for formatting in a converter specific way.
     */
    public
    void format(StringBuffer sbuf, LoggingEvent e) {
      String s = convert(e);
  
      if(s == null) {
        if(0 < min)
  	spacePad(sbuf, min);
        return;
      }
  
      int len = s.length();
  
      if(len > max)
        sbuf.append(s.substring(len-max));
      else if(len < min) {
        if(leftAlign) {	
  	sbuf.append(s);
  	spacePad(sbuf, min-len);
        }
        else {
  	spacePad(sbuf, min-len);
  	sbuf.append(s);
        }
      }
      else
        sbuf.append(s);
    }	
  
    static String[] SPACES = {" ", "  ", "    ", "        " };  //1,2,4,8 spaces
  
  
    /**
       Fast space padding method.
    */
    public
    void spacePad(StringBuffer sbuf, int length) {
      while(length >= 8) {
        sbuf.append(SPACES[3]);
        length -= 8;
      }
      
      for(int i = 2; i >= 0; i--) {	
        if((length & (1<<i)) != 0) {
  	sbuf.append(SPACES[i]);
        }
      }
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/helpers/PatternParser.java
  
  Index: PatternParser.java
  ===================================================================
  package org.apache.log4j.helpers;
  
  import org.apache.log4j.helpers.LogLog;
  import org.apache.log4j.Layout;
  import org.apache.log4j.NDC;
  import org.apache.log4j.spi.LoggingEvent;
  import java.text.DateFormat;
  import java.util.Date;
  
  // Contributors:   Nelson Minar <(n...@monkey.org>
  //                 Igor E. Poteryaev <ja...@mail.ru>  
  //                 Reinhard Deschler <re...@web.de> 
  
  /**
     Most of the work of the {@link org.apache.log4j.PatternLayout} class
     is delegated to the PatternParser class.
  
     @author <a href=mailto:"cakalijp@Maritz.com">James P. Cakalic</a>
     @author Ceki G&uuml;lc&uuml;
     @author Anders Kristensen       
  
     @since 0.8.2
  */
  public class PatternParser {
  
    private static final char ESCAPE_CHAR = '%';
    
    private static final int LITERAL_STATE = 0;
    private static final int CONVERTER_STATE = 1;
    private static final int MINUS_STATE = 2;
    private static final int DOT_STATE = 3;
    private static final int MIN_STATE = 4;
    private static final int MAX_STATE = 5;
  
  
    static final int RELATIVE_TIME_CONVERTER = 2000;
    static final int THREAD_CONVERTER = 2001;
    static final int PRIORITY_CONVERTER = 2002;
    //static final int NDC_CONVERTER = 2003;
    static final int MESSAGE_CONVERTER = 2004;
  
    int state;
    protected StringBuffer currentLiteral = new StringBuffer(32);
    protected int patternLength;
    protected int i;
    PatternConverter head;
    PatternConverter tail;
    protected FormattingInfo formattingInfo = new FormattingInfo();
    protected String pattern;
  
    public
    PatternParser(String pattern) {
      this.pattern = pattern;
      patternLength =  pattern.length();    
      state = LITERAL_STATE;
    }
  
    private
    void  addToList(PatternConverter pc) {
      if(head == null) {
        head = tail = pc;
      } else {
        tail.next = pc;
        tail = pc;    
      }
    }
  
    private
    String extractOption() {
      if((i < patternLength) && (pattern.charAt(i) == '{')) {
        int end = pattern.indexOf('}', i);	
        if (end > i) {
  	String r = pattern.substring(i + 1, end);
  	i = end+1;
  	return r;
        }
      }
      return null;
    }
  
  
    /**
       The option is expected to be in decimal and positive. In case of
       error, zero is returned.  */
    private
    int extractPrecisionOption() {
      String opt = extractOption();
      int r = 0;
      if(opt != null) {
        try {
  	r = Integer.parseInt(opt);
  	if(r <= 0) {
  	    LogLog.error(opt + " <= 0");
  	    r = 0;
  	}
        }      
        catch (NumberFormatException e) {
  	LogLog.error(opt+" invalid", e);
        }      
      }
      return r;    
    }
        
    public 
    PatternConverter parse() {
      char c;
      i = 0;
      while(i < patternLength) {
        c = pattern.charAt(i++);
        switch(state) {
        case LITERAL_STATE: 
          // In literal state, the last char is always a literal.
          if(i == patternLength) {
            currentLiteral.append(c);
            continue;
          }
          if(c == ESCAPE_CHAR) {      
            // peek at the next char. 
            switch(pattern.charAt(i)) {
            case ESCAPE_CHAR:
              currentLiteral.append(c);
              i++; // move pointer
              break;
            case 'n':
              currentLiteral.append(Layout.LINE_SEP);
              i++; // move pointer
              break;
            default:
              if(currentLiteral.length() != 0) {
                addToList(new LiteralPatternConverter(
                                                    currentLiteral.toString()));
                //LogLog.debug("Parsed LITERAL converter: \"" 
                //           +currentLiteral+"\".");
              }
              currentLiteral.setLength(0); 
              currentLiteral.append(c); // append %
              state = CONVERTER_STATE;
              formattingInfo.reset();
            }
          }
          else {
            currentLiteral.append(c);
          }
          break;
        case CONVERTER_STATE:
  	currentLiteral.append(c);
  	switch(c) {
  	case '-':
  	  formattingInfo.leftAlign = true;
  	  break;
  	case '.':
  	  state = DOT_STATE;
  	  break;
  	default:
  	  if(c >= '0' && c <= '9') {
  	    formattingInfo.min = c - '0';
  	    state = MIN_STATE;
  	  }
  	  else 
  	    finalizeConverter(c);	    
  	} // switch
  	break;
        case MIN_STATE:
  	currentLiteral.append(c);
  	if(c >= '0' && c <= '9') 
  	  formattingInfo.min = formattingInfo.min*10 + (c - '0');
  	else if(c == '.')
  	  state = DOT_STATE;
  	else {
  	  finalizeConverter(c);
  	}
  	break;
        case DOT_STATE:
  	currentLiteral.append(c);
  	if(c >= '0' && c <= '9') {
  	  formattingInfo.max = c - '0';
  	   state = MAX_STATE;
  	}
  	else {
  	  LogLog.error("["+c+"] at pos "+i+" not a digit");
  	  state = LITERAL_STATE;
  	}
  	break;
        case MAX_STATE:
  	currentLiteral.append(c);
  	if(c >= '0' && c <= '9') 
  	  formattingInfo.max = formattingInfo.max*10 + (c - '0');
  	else {
  	  finalizeConverter(c);
  	  state = LITERAL_STATE;
  	}
  	break;
        } // switch
      } // while
      if(currentLiteral.length() != 0) {
        addToList(new LiteralPatternConverter(currentLiteral.toString()));
        //LogLog.debug("Parsed LITERAL converter: \""+currentLiteral+"\".");
      }
      return head;
    }
  
    protected
    void finalizeConverter(char c) {
      PatternConverter pc = null;
      switch(c) {
      case 'c':
        pc = new CategoryPatternConverter(formattingInfo,
  					extractPrecisionOption());	
        //LogLog.debug("CATEGORY converter.");
        //formattingInfo.dump();      
        currentLiteral.setLength(0);
        break;
      case 'm':
        pc = new BasicPatternConverter(formattingInfo, MESSAGE_CONVERTER);
        //LogLog.debug("MESSAGE converter.");
        //formattingInfo.dump();      
        currentLiteral.setLength(0);
        break;
      case 'p':
        pc = new BasicPatternConverter(formattingInfo, PRIORITY_CONVERTER);
        //LogLog.debug("PRIORITY converter.");
        //formattingInfo.dump();
        currentLiteral.setLength(0);
        break;
      case 'r':
        pc = new BasicPatternConverter(formattingInfo, 
  					 RELATIVE_TIME_CONVERTER);
        //LogLog.debug("RELATIVE time converter.");
        //formattingInfo.dump();
        currentLiteral.setLength(0);
        break;
      case 't':
        pc = new BasicPatternConverter(formattingInfo, THREAD_CONVERTER);
        //LogLog.debug("THREAD converter.");
        //formattingInfo.dump();      
        currentLiteral.setLength(0);
        break;
        /*case 'u':
        if(i < patternLength) {
  	char cNext = pattern.charAt(i);
  	if(cNext >= '0' && cNext <= '9') {
  	  pc = new UserFieldPatternConverter(formattingInfo, cNext - '0');
  	  LogLog.debug("USER converter ["+cNext+"].");
  	  formattingInfo.dump();      
  	  currentLiteral.setLength(0);
  	  i++;
  	}
  	else 
  	  LogLog.error("Unexpected char" +cNext+" at position "+i);
        }
        break;*/
        //case 'x':
        //pc = new BasicPatternConverter(formattingInfo, NDC_CONVERTER);
        //currentLiteral.setLength(0);
        //break;
      default:
        LogLog.error("Unexpected ["+c+"] at "+i+" in ConvPattern");
        pc = new LiteralPatternConverter(currentLiteral.toString());
        currentLiteral.setLength(0);
      }
      
      addConverter(pc);
    }
  
    protected
    void addConverter(PatternConverter pc) {
      currentLiteral.setLength(0);
      // Add the pattern converter to the list.
      addToList(pc);
      // Next pattern is assumed to be a literal.
      state = LITERAL_STATE;
      // Reset formatting info
      formattingInfo.reset();
    }
  
    // ---------------------------------------------------------------------
    //                      PatternConverters
    // ---------------------------------------------------------------------
      
    private static class BasicPatternConverter extends PatternConverter {
      int type;
      
      BasicPatternConverter(FormattingInfo formattingInfo, int type) {
        super(formattingInfo);     
        this.type = type;
      }
  
      public
      String convert(LoggingEvent event) {
        switch(type) {
        case RELATIVE_TIME_CONVERTER: 
  	return (Long.toString(event.timeStamp - LoggingEvent.getStartTime()));
        case THREAD_CONVERTER:
  	return event.getThreadName();
        case PRIORITY_CONVERTER:
  	return event.priority.toString();
  	//case NDC_CONVERTER:  
  	//return event.getNDC();
        case MESSAGE_CONVERTER: {
  	return event.message;
        }
        default: return null;
        }
      }
    }
    
    private static class LiteralPatternConverter extends PatternConverter {
      private String literal;
    
      LiteralPatternConverter(String value) {
        literal = value;
      }
  
      public
      final
      void format(StringBuffer sbuf, LoggingEvent event) {
        sbuf.append(literal);
      }
      
      public    
      String convert(LoggingEvent event) {
        return literal;
      }
    }
  
    private static  class CategoryPatternConverter extends PatternConverter {
      int precision;
      
      CategoryPatternConverter(FormattingInfo formattingInfo, int precision) {
        super(formattingInfo);
        this.precision =  precision;      
      }
  
      //String getFullyQualifiedName(LoggingEvent event) {
      //return 
      //}
      
      public
      String convert(LoggingEvent event) {
        String n = event.categoryName;
        if(precision <= 0)
  	return n;
        else {
  	int len = n.length();
  
  	// We substract 1 from 'len' when assigning to 'end' to avoid out of
  	// bounds exception in return r.substring(end+1, len). This can happen if
  	// precision is 1 and the category name ends with a dot. 
  	int end = len -1 ;
  	for(int i = precision; i > 0; i--) {	  
  	  end = n.lastIndexOf('.', end-1);
  	  if(end == -1)
  	    return n;
  	}
  	return n.substring(end+1, len);
        }      
      }
    }
  }
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/spi/LoggingEvent.java
  
  Index: LoggingEvent.java
  ===================================================================
  /*
   * 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.  */
  
  package org.apache.log4j.spi;
  
  import org.apache.log4j.Category;
  import org.apache.log4j.Priority;
  import org.apache.log4j.NDC;
  
  import org.apache.log4j.helpers.LogLog;
  
  import java.io.StringWriter;
  import java.io.PrintWriter;
  import java.lang.reflect.Method;
  import java.io.ObjectOutputStream;
  import java.io.ObjectInputStream;
  import java.util.Hashtable;
  
  // Contributors:   Nelson Minar <ne...@monkey.org>
  //                 Wolf Siberski
  //                 Anders Kristensen <ak...@dynamicsoft.com>
  
  /**
     The internal representation of logging events. When an affirmative
     decision is made to log then a <code>LoggingEvent</code> instance
     is created. This instance is passed around to the different log4j
     components.
  
     <p>This class is of concern to those wishing to extend log4j. 
  
     @author Ceki G&uuml;lc&uuml;
     @author James P. Cakalic
     
     @since 0.8.2 */
  public class LoggingEvent {
  
    private static long startTime = System.currentTimeMillis();
  
    /** The category of the logging event. The category field is not
    serialized for performance reasons. 
  
    <p>It is set by the LoggingEvent constructor or set by a remote
    entity after deserialization. */
    transient public Category category;
  
    /** The category name. */
    public final String categoryName;
    
    /** Priority of logging event. Priority cannot be serializable
        because it is a flyweight.  Due to its special seralization it
        cannot be declared final either. */
    transient public Priority priority;
  
    /** The nested diagnostic context (NDC) of logging event. */
    //private String ndc;
  
    /** Have we tried to do an NDC lookup? If we did, there is no need
        to do it again.  Note that its value is always false when
        serialized. Thus, a receiving SocketNode will never use it's own
        (incorrect) NDC. See also writeObject method. */
    private boolean ndcLookupRequired = true;
  
  
    /** The application supplied message of logging event. */
    transient public String message;
    
    /** The name of thread in which this logging event was generated. */
    private String threadName;
  
    /** The throwable associated with this logging event.
  
        This is field is transient because not all exception are
        serializable. More importantly, the stack information does not
        survive serialization.
    */
    transient public Throwable throwable;
  
    /** This variable collects the info on a throwable. This variable
        will be shipped to       
     */
    public String throwableStr;
  
    /** The number of milliseconds elapsed from 1/1/1970 until logging event
        was created. */
    public final long timeStamp;
  
    /**
       Instantiate a LoggingEvent from the supplied parameters.
       
       <p>Except {@link #timeStamp} all the other fields of
       <code>LoggingEvent</code> are filled when actually needed.
       <p>
       @param category The category of this event.
       @param priority The priority of this event.
       @param message  The message of this event.
       @param throwable The throwable of this event.  */
    public LoggingEvent(Category category, Priority priority, Object message, 
  		      Throwable throwable) {
      this.category = category;
      this.categoryName = category.getName();
      this.priority = priority;
      this.message = message.toString();
      this.throwable = throwable;
      timeStamp = System.currentTimeMillis();
    }  
  
    /**
       Return the message for this logging event. 
  
       <p>Before serialization, the returned object is the message
       passed by the user to generate the logging event. After
       serialization, the returned value equals the String form of the
       message possibly after object rendering. 
  
       @since 1.1 */
    public
    Object getMessage() {
      return message;
    }
  
    //public
    //String getMessageStr() {
    //return message.toString();
    //}
  
  
    //public
    //String getNDC() {
    //  if(ndcLookupRequired) {
    //	ndcLookupRequired = false;
    //	ndc = NDC.get();
    //  }
    //  return ndc; 
    //}
  
    /**
       Returns the time when the application started, in milliseconds
       elapsed since 01.01.1970.  */
    public
    static 
    long getStartTime() {
      return startTime;
    }
  
    public
    String getThreadName() {
      if(threadName == null)
        threadName = (Thread.currentThread()).getName();
      return threadName;
    }
  
    /**
       Returns the throwable information contained within this
       event. May be <code>null</code> if there is no such information.
    */
    public
    String getThrowableStr() {
      if(throwable == null) {
        return null;
      }
      
      if(throwableStr == null ) {
        StringWriter sw = new StringWriter();
        PrintWriter pw = new PrintWriter(sw);
        
        throwable.printStackTrace(pw);
        throwableStr = sw.toString();
      }    
      return throwableStr;
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/spi/OptionHandler.java
  
  Index: OptionHandler.java
  ===================================================================
  
  package org.apache.log4j.spi;
  
  import org.apache.log4j.FileAppender;
  
  /**
     A string based interface to configure package components.
  
     @author Ceki G&uuml;lc&uuml;
   */
  public interface OptionHandler {
  
    /**
       Activate the options that were previously set with calls to option
       setters.
  
       <p>This allows to defer activiation of the options until all
       options have been set. This is required for components which have
       related options that remain ambigous until all are set.
  
     */
    public
    void activateOptions();
    
    public
    String[] getOptionStrings();
    
    public
    void setOption(String key, String value);
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/spi/RootCategory.java
  
  Index: RootCategory.java
  ===================================================================
  
  package org.apache.log4j.spi;
  
  import  org.apache.log4j.Category;
  import  org.apache.log4j.Priority;
  import  org.apache.log4j.helpers.LogLog;
  
  
  /**
     RootCategory sits at the top of the category hierachy. It is a
     regular category except that it provides several guarantees.
  
     <p>First, it cannot be assigned a <code>null</code>
     priority. Second, since root category cannot have a parent, the
     {@link #getChainedPriority} method always returns the value of the
     priority field without walking the hierarchy.
  
     @author Ceki G&uuml;lc&uuml;
  
   */
  final public class RootCategory extends Category {
  
    /**
       The root category names itself as "root". However, the root
       category cannot be retrieved by name.  
    */
    public
    RootCategory(Priority priority) {
      super("root");
      setPriority(priority);
    }
  
    
    /**
       Return the assigned priority value without walking the category
       hierarchy.
    */
    final
    public 
    Priority getChainedPriority() {
      return priority;
    }
  
    /**
       Setting a null value to the priority of the root category may have catastrophic
       results. We prevent this here.
  
       @since 0.8.3 */
    final  
    public
    void setPriority(Priority priority) {
      if(priority == null) {
        LogLog.error("null priority disallowed", new Throwable());
      }
      else {
        this.priority = priority;
      }
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/.cvsignore
  
  Index: .cvsignore
  ===================================================================
  test*
  current.reg*
  logging.lcf
  socket.lcf
  temp*
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/.functions
  
  Index: .functions
  ===================================================================
  
  # Constants
  TEMP=temp
  OUTPUT=current.reg
  LCF=logging.lcf
  
  # +=============================================+
  # Strip the filename, retain the directory only.|
  # +=============================================+
  function getShellScriptDirectory {
    local dir
    
    dir=${0%/*}
  
    if [ "$dir" = "." ]
    then
      dir=$(pwd)
    elif [ "${dir#/}" = "$dir" ]  # dir does not start with a /
    then
      dir=$(pwd)/$dir
    fi
   echo $dir
  }
  # +=============================================
  # Compensate for ZRL idiosyncrasy
  # +=============================================
  function setPERL {
    if [ -z "$PERL" ]
    then
     PERL=perl
    fi
  }
  # +============================================
  # Print a message and exit.
  # +============================================
  function die {
    echo $1
    exit 1
  }
  # ==============================================
  # Delete the file if exists
  # ==============================================
  function deleteFile {
    if [ -e $1 ]; then
      echo "Deleting file [$1]."
      rm $1
    fi
  }
  # ----------------------------------------------------------------------
  function check() {
    if ! cmp -s $1 $2
    then
      echo "The output of current code DIFFERS from witness."
      exit 1;
    fi
  }
  # =============================================
  # Echo to $LCF
  # =============================================
  function lecho {
   # The quotes ensure that spaces in arguments are preserved.
   echo "$*" >> $LCF
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/ConfigurationFileParsing.java
  
  Index: ConfigurationFileParsing.java
  ===================================================================
  /*
   * 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.  */
  
  package org.apache.log4j.test; 
  
  import org.apache.log4j.PropertyConfigurator;
  import org.apache.log4j.Category;
  
  public class ConfigurationFileParsing {
    
    static Category log = Category.getInstance(ConfigurationFileParsing.class);
  
    public 
    static 
    void main(String argv[]) {
  
      if(argv.length == 1) {
        PropertyConfigurator.configure(argv[0]);
        Category root = Category.getRoot();
        root.debug("Message 1");
        log.info("Message 2");      
  
        root.warn("Message 3");
        log.error("Message 4");      
  
      }
      else {
        Usage("Wrong number of arguments.");
      }
      
    }
  
    static
    void Usage(String msg) {
      System.err.println(msg);
      System.err.println("Usage: java "+ConfigurationFileParsing.class.getName()
  		       + " fileName");
      System.exit(1);
    }
  
    
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/Hello.java
  
  Index: Hello.java
  ===================================================================
  /*
   * 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.  */
  
  package org.apache.log4j.test; 
  
  import org.apache.log4j.*;
  import org.apache.log4j.helpers.LogLog;
  
  /**
     Very simple log4j usage example.
  
     @author  Ceki G&uuml;lc&uuml;   
   */
  public class Hello {
  
    static Category log = Category.getInstance(Hello.class);
  
    public 
    static 
    void main(String argv[]) {
      Category root = Category.getRoot();
      Layout layout = new PatternLayout("%p [%t] %c - %m%n");
      try {
        root.addAppender(new FileAppender(layout, System.out));
      } catch(Exception e) {
        LogLog.warn("Could not open file appender.");
      }
  
      log.debug("Hello world.");
      log.info("What a beatiful day.");
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/Min.java
  
  Index: Min.java
  ===================================================================
  
  package org.apache.log4j.test; 
  
  import org.apache.log4j.*;
  import org.apache.log4j.helpers.LogLog;
  import java.io.IOException;
  
  /**
     This class tests the functionality of the Category class and the
     different layouts.
  
     @author  Ceki G&uuml;lc&uuml;
  */
  public class Min {
  
    public 
    static 
    void main(String argv[]) {
  
        if(argv.length == 1) {
  	ProgramInit(argv[0]);
        }
        else {
  	Usage("Wrong number of arguments.");
        }
        test1();
    }
  
  
    static
    void Usage(String msg) {
      System.err.println(msg);
      System.err.println( "Usage: java org.apache.log4j.test.Min format");
      System.exit(1);
    }
  
  
    /**
      Program wide initialization method.
      */
  
    static
    void ProgramInit(String format) {
      try {
        Layout layout = new PatternLayout(format);        
        Appender appender = new FileAppender(layout, System.out);
        Category.getRoot().addAppender(appender);
      } catch(Exception e) {
        LogLog.error("Could not initialize log4j.");
      }
    }
  
    
    static
    void test1() {
  
      int i = 0;
  
      // In the lines below, the category names are chosen as an aid in
      // remembering their priority values. In general, the category
      // names should have no bearing to priority values.
      
      Category ERR = Category.getInstance("ERR");
      ERR.setPriority(Priority.ERROR);
      Category INF = Category.getInstance("INF");
      INF.setPriority(Priority.INFO);
      Category INF_ERR = Category.getInstance("INF.ERR");
      INF_ERR.setPriority(Priority.ERROR);
      Category DEB = Category.getInstance("DEB");
      DEB.setPriority(Priority.DEBUG);
      
      // Note: categories with undefined priority 
      Category INF_UNDEF = Category.getInstance("INF.UNDEF");
      Category INF_ERR_UNDEF = Category.getInstance("INF.ERR.UNDEF");    
      Category UNDEF = Category.getInstance("UNDEF");   
  
  
      // These should all log.----------------------------
      ERR.fatal("Message " + i); i++;  //0
      ERR.error("Message " + i); i++;          
      ERR.info("Message " + i); 
      ERR.debug("Message " + i); 
  
      INF.fatal("Message " + i); i++; // 2
      INF.error( "Message " + i); i++;         
      INF.warn ( "Message " + i); i++; 
      INF.info ( "Message " + i); i++;
  
      INF_UNDEF.fatal( "Message " + i); i++;  //6
      INF_UNDEF.error( "Message " + i); i++;         
      INF_UNDEF.warn ( "Message " + i); i++; 
      INF_UNDEF.info ( "Message " + i); i++; 
      INF_UNDEF.debug ( "Message " + i);
      
      
      INF_ERR.fatal( "Message " + i); i++;  // 10
      INF_ERR.error( "Message " + i); i++;  
  
      INF_ERR_UNDEF.fatal( "Message " + i); i++; 
      INF_ERR_UNDEF.error( "Message " + i); i++;             
  
      DEB.fatal( "Message " + i); i++;  //14
      DEB.error( "Message " + i); i++;         
      DEB.warn ( "Message " + i); i++; 
      DEB.info ( "Message " + i); i++; 
      DEB.debug( "Message " + i); i++; 
  
      
      // defaultPriority=DEBUG
      UNDEF.error("Message " + i); i++;         
      UNDEF.warn ("Message " + i); i++; 
      UNDEF.info ("Message " + i); i++; 
      UNDEF.debug("Message " + i, new Exception("Just testing")); i++;    
  
      // -------------------------------------------------
      // The following should not log
      ERR.warn("Message " + i);  i++; 
      ERR.info("Message " + i);  i++; 
      ERR.debug("Message " + i);  i++; 
        
      INF.debug("Message " + i);  i++; 
      INF_UNDEF.debug("Message " + i); i++; 
  
  
      INF_ERR.warn("Message " + i);  i++; 
      INF_ERR.info("Message " + i);  i++; 
      INF_ERR.debug("Message " + i); i++; 
      INF_ERR_UNDEF.warn("Message " + i);  i++; 
      INF_ERR_UNDEF.info("Message " + i);  i++; 
      INF_ERR_UNDEF.debug("Message " + i); i++; 
      // -------------------------------------------------
        
      INF.info("Messages should bear numbers 0 through 22.");
    }     
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/Shallow.java
  
  Index: Shallow.java
  ===================================================================
  
  package org.apache.log4j.test; 
  
  import org.apache.log4j.*;
  import org.apache.log4j.helpers.LogLog;
  import java.io.IOException;
  import java.util.Enumeration;
  /** 
     This class is a shallow test of the various appenders and
     layouts. It also tests their reading of the configuration file.
     @author  Ceki G&uuml;lc&uuml;
  */
  public class Shallow {
    
    static Category cat = Category.getInstance(Shallow.class);
    
    public 
    static 
    void main(String argv[]) {
      if(argv.length == 2) 
        init(argv[0], argv[1]);
      else 
        usage("Wrong number of arguments.");
      test();
    }
  
    static
    void usage(String msg) {
      System.err.println(msg);
      System.err.println( "Usage: java "+ Shallow.class.getName()+" file format");
      System.exit(1);
    }
  
    static 
    void init(String file, String format) {
      Category root = Category.getRoot();
      Layout layout = new PatternLayout(format);
      try {
        root.addAppender(new FileAppender(layout, file));
      } catch(Exception e) {
        LogLog.warn("Could not open file ["+file+"].");
      }
    }
  
    static 
    void test() {
      int i = -1; 
  
      Category root = Category.getRoot();
      cat.debug("Message " + ++i);
      root.debug("Message " + i);
      cat.info ("Message " + ++i);
      cat.warn ("Message " + ++i);
      cat.error("Message " + ++i);
      
      Exception e = new Exception("Just testing");
      cat.debug("Message " + ++i, e);    
      root.info("Message " + ++i, e);
      cat.warn("Message " + ++i, e);
      root.error("Message " + ++i, e);
    }
  }
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/confParsing
  
  Index: confParsing
  ===================================================================
  #!/bin/bash
  	
  # Read the .functions file
  . .functions
  
  declare -i start=$1
  
  setPERL
  
  # =========================================================================
  
  # This script runs ConfigurationFileParsing java program with args1 and 2.
  # It has the side effect of aggregating the following arguments to one
  # file called $TEMP.
  
  # It runs a perl filter to remove date, line and other variable
  # information from the output.
  
  # =========================================================================
  function testConfigurationParsing {
   configFile=$1; 
   options=$2; shift; shift;
   
   echo -n " ConfigurationParsing test $TEST - "
   java $D_FLAG org.apache.log4j.test.ConfigurationFileParsing $configFile
  
   if [ -n "$*" ]; then
     cat $* $TEMP >> $TEMP.x
     mv $TEMP.x $TEMP
   fi
   
   $PERL filter.pl $TEMP $OUTPUT ConfigurationFileParsing $options
   if [ $? != 0 ]; then
     echo "The output is not in expected format. See the file [$OUTPUT]."
     exit 1   
   fi
  
   check witness/confParsing.$TEST $OUTPUT; echo " OK"
  }
  
  
  # =========================================================================
  # Just run ConfigurationFileParsing and direct the output to STDOUT or
  # STDERR.
  # =========================================================================
  function testConfigurationParsingII {
   conf=$1; 
   target=$2
  
   case $target in
   OUT )
     java $D_FLAG org.apache.log4j.test.ConfigurationFileParsing $conf>$TEMP
     ;;
   ERR )
     java $D_FLAG org.apache.log4j.test.ConfigurationFileParsing $conf>& $TEMP
     ;;
   esac
     
   check witness/confParsing.$TEST $TEMP; echo " OK"
  }
  # ======================================================
  
  declare -i TEST
  
  
  TEST=1;
  if [ $TEST -ge $start ]; then
    D_FLAG=""
    echo  "log4j.rootCategory=  , testAppender" > $LCF
    lecho "log4j.debug="
    lecho "log4j.appender.testAppender=org.apache.log4j.FileAppender"
    lecho "log4j.appender.testAppender.File=$TEMP"
    lecho "log4j.appender.testAppender.Append=   false  "
    lecho "log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout"
    lecho "log4j.appender.testAppender.layout.ConversionPattern=%-5p [%t] %c{2} - %m%n"
    
    testConfigurationParsing $LCF NONE
  fi
  
  
  TEST=2;
  if [ $TEST -ge $start ]; then
    D_FLAG=""
    echo  "log4j.rootCategory= DEBUG , testAppender" > $LCF
    lecho "log4j.debug=false"
    lecho "log4j.appender.testAppender=org.apache.log4j.FileAppender"
    # Note the spaces
    lecho "log4j.appender.testAppender.File=System.out  "
    lecho "log4j.appender.testAppender.layout=org.apache.log4j.PatternLayout "
    lecho "log4j.appender.testAppender.layout.ConversionPattern=[%t] %p - %m%n"
    echo -n " ConfigurationParsing test $TEST - "
    testConfigurationParsingII $LCF OUT
  fi
  
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/hello
  
  Index: hello
  ===================================================================
  #!/bin/bash
  
  # A regression test to check the option reading code and print formats.
   
  # Read the .functions file
  
  . .functions
  
  
  deleteFile $OUTPUT
  
  echo -n "Hello test $TEST - "
  java org.apache.log4j.test.Hello > $OUTPUT
  check witness/hello $OUTPUT; echo "OK"
  
  
  
  
  
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/min
  
  Index: min
  ===================================================================
  #!/bin/bash
  
  # A regression test to check the option reading code and print formats.
   
  # Read the .functions file
  
  . .functions
  
  
  # If set, allows to skip tests 
  declare -i start=$1
  
  # ----------------------------------------------------------------------
  function testMin {
  
   filter="$1"
   format="$2"   
  
   echo -n "Min test $TEST - "
   runMin "$format" 
   $PERL filter.pl $TEMP $OUTPUT Min $filter
  
   if [ $? != 0 ]; then
    echo "The output is not in expected format. See the file [$OUTPUT]."
    exit 1   
   fi
  
   check witness/min.$TEST $OUTPUT; echo "OK" 
  }
  # ----------------------------------------------------------------------
  function runMin {
   format="$1"
   file="$2" 
   #java -Dlog4j.configDebug org.apache.log4j.test.Shallow $confFile
   java org.apache.log4j.test.Min "$format" > $TEMP
  }
  # ===============================================================
  
  setPERL
  
  declare -i TEST
  
  deleteFile $TEMP 
  
  TEST=1
  if [ $TEST -ge $start ]; then
    testMin NONE "%5p %c [%t] - %m%n"
  fi
  
  
  TEST=2
  if [ $TEST -ge $start ]; then
    testMin RELATIVE "%r [%t] %p - %m%n"
  fi
  
  
  
  
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/shallow
  
  Index: shallow
  ===================================================================
  #!/bin/bash
  
  # A regression test to check the option reading code and print formats.
   
  # Read the .functions file
  
  . .functions
  
  
  # If set, allows to skip tests 
  declare -i start=$1
  
  # ----------------------------------------------------------------------
  function testShallow {
  
   file="$1"
   filter="$2"
   format="$3"   
  
   echo -n "Shallow test $TEST - "
   runShallow "$format" $file 
   $PERL filter.pl $TEMP $OUTPUT Shallow $filter
  
   if [ $? != 0 ]; then
    echo "The output is not in expected format. See the file [$OUTPUT]."
    exit 1   
   fi
  
   check witness/shallow.$TEST $OUTPUT; echo "OK" 
  }
  # ----------------------------------------------------------------------
  function runShallow {
   format="$1"
   file="$2" 
   #java -Dlog4j.configDebug org.apache.log4j.test.Shallow $confFile
   java org.apache.log4j.test.Shallow "$file" "$format"
  }
  # ===============================================================
  
  setPERL
  
  declare -i TEST
  
  deleteFile $TEMP 
  
  TEST=1
  if [ $TEST -ge $start ]; then
    testShallow $TEMP NONE "%p %c - %m%n"
  fi
  
  
  
  
  
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness/confParsing.1
  
  Index: confParsing.1
  ===================================================================
  DEBUG [main] root - Message 1
  INFO  [main] test.ConfigurationFileParsing - Message 2
  WARN  [main] root - Message 3
  ERROR [main] test.ConfigurationFileParsing - Message 4
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness/hello
  
  Index: hello
  ===================================================================
  DEBUG [main] org.apache.log4j.test.Hello - Hello world.
  INFO [main] org.apache.log4j.test.Hello - What a beatiful day.
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness/min.1
  
  Index: min.1
  ===================================================================
  FATAL ERR [main] - Message 0
  ERROR ERR [main] - Message 1
  FATAL INF [main] - Message 2
  ERROR INF [main] - Message 3
   WARN INF [main] - Message 4
   INFO INF [main] - Message 5
  FATAL INF.UNDEF [main] - Message 6
  ERROR INF.UNDEF [main] - Message 7
   WARN INF.UNDEF [main] - Message 8
   INFO INF.UNDEF [main] - Message 9
  FATAL INF.ERR [main] - Message 10
  ERROR INF.ERR [main] - Message 11
  FATAL INF.ERR.UNDEF [main] - Message 12
  ERROR INF.ERR.UNDEF [main] - Message 13
  FATAL DEB [main] - Message 14
  ERROR DEB [main] - Message 15
   WARN DEB [main] - Message 16
   INFO DEB [main] - Message 17
  DEBUG DEB [main] - Message 18
  ERROR UNDEF [main] - Message 19
   WARN UNDEF [main] - Message 20
   INFO UNDEF [main] - Message 21
  DEBUG UNDEF [main] - Message 22
  java.lang.Exception: Just testing
  	at org.apache.log4j.test.Min.test1(Min.java)
  	at org.apache.log4j.test.Min.main(Min.java)
   INFO INF [main] - Messages should bear numbers 0 through 22.
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness/min.2
  
  Index: min.2
  ===================================================================
  [main] FATAL - Message 0
  [main] ERROR - Message 1
  [main] FATAL - Message 2
  [main] ERROR - Message 3
  [main] WARN - Message 4
  [main] INFO - Message 5
  [main] FATAL - Message 6
  [main] ERROR - Message 7
  [main] WARN - Message 8
  [main] INFO - Message 9
  [main] FATAL - Message 10
  [main] ERROR - Message 11
  [main] FATAL - Message 12
  [main] ERROR - Message 13
  [main] FATAL - Message 14
  [main] ERROR - Message 15
  [main] WARN - Message 16
  [main] INFO - Message 17
  [main] DEBUG - Message 18
  [main] ERROR - Message 19
  [main] WARN - Message 20
  [main] INFO - Message 21
  [main] DEBUG - Message 22
  java.lang.Exception: Just testing
  	at org.apache.log4j.test.Min.test1(Min.java)
  	at org.apache.log4j.test.Min.main(Min.java)
  [main] INFO - Messages should bear numbers 0 through 22.
  
  
  
  1.1                  jakarta-log4j/log4jMini/src/java/org/apache/log4j/test/witness/shallow.1
  
  Index: shallow.1
  ===================================================================
  DEBUG org.apache.log4j.test.Shallow - Message 0
  DEBUG root - Message 0
  INFO org.apache.log4j.test.Shallow - Message 1
  WARN org.apache.log4j.test.Shallow - Message 2
  ERROR org.apache.log4j.test.Shallow - Message 3
  DEBUG org.apache.log4j.test.Shallow - Message 4
  java.lang.Exception: Just testing
  	at org.apache.log4j.test.Shallow.test(Shallow.java)
  	at org.apache.log4j.test.Shallow.main(Shallow.java)
  INFO root - Message 5
  java.lang.Exception: Just testing
  	at org.apache.log4j.test.Shallow.test(Shallow.java)
  	at org.apache.log4j.test.Shallow.main(Shallow.java)
  WARN org.apache.log4j.test.Shallow - Message 6
  java.lang.Exception: Just testing
  	at org.apache.log4j.test.Shallow.test(Shallow.java)
  	at org.apache.log4j.test.Shallow.main(Shallow.java)
  ERROR root - Message 7
  java.lang.Exception: Just testing
  	at org.apache.log4j.test.Shallow.test(Shallow.java)
  	at org.apache.log4j.test.Shallow.main(Shallow.java)
  
  
  

--
To unsubscribe, e-mail:   <ma...@jakarta.apache.org>
For additional commands, e-mail: <ma...@jakarta.apache.org>