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 ho...@apache.org on 2003/02/18 16:50:20 UTC

cvs commit: jakarta-log4j-sandbox/src/java/org/apache/log4j/servlet InitContextListener.java InitServlet.java

hoju        2003/02/18 07:50:20

  Modified:    .        build.xml sunCodingConvention.xml
               src/java/org/apache/log4j/selector
                        ContextClassLoaderSelector.java
               src/java/org/apache/log4j/servlet InitContextListener.java
                        InitServlet.java
  Log:
  1.  Updating selector and servlet initializers based on suggestions by Ceki.  Also made them comply with checkstyle....except for InitServlet.java which has an init() method that is over the length limit recommended by the Sun coding standards.  However, this is somewhat unavoidable so I left it that way.
  
  2.  Updating build.xml to create log4j-sandbox-selector-[versions].jar and log4j-sandbox-servlet-[version].jar.  Also moved a path, which both of the jalopy targets require, outside the single target so both targets can use it.  Also updated the jalopy targets to depend on the "init" target like all the other targets in the build.
  
  3.  Updating sunCodingConvention.xml with additions agreed upon by Mark Womack.
  
  Jake
  
  Revision  Changes    Path
  1.3       +45 -11    jakarta-log4j-sandbox/build.xml
  
  Index: build.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j-sandbox/build.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- build.xml	8 Feb 2003 07:55:35 -0000	1.2
  +++ build.xml	18 Feb 2003 15:50:19 -0000	1.3
  @@ -22,7 +22,7 @@
     <property name="java.source.dir" value="./src/java/"/>
   
     <property name="build.home" value="./build"/>
  -  
  +
     <!-- Destination for compiled files -->
     <property name="javac.dest" value="${build.home}/classes"/>
   
  @@ -37,6 +37,8 @@
   
     <!-- The jar file that the jar task will generate -->
     <property name="log4j-sandbox.jar" value="log4j-sandbox-${version}.jar"/>
  +  <property name="log4j-sandbox-selector.jar" value="log4j-sandbox-selector-${version}.jar"/>
  +  <property name="log4j-sandbox-servlet.jar" value="log4j-sandbox-servlet-${version}.jar"/>
   
     <!-- Construct compile classpath -->
     <path id="compile.classpath">
  @@ -61,7 +63,7 @@
       javadoc - build project javadoc files
   
       jar     - build log4j-core and log4j jar files
  -    
  +
       </echo>
     </target>
   
  @@ -72,7 +74,7 @@
   			</classpath>
   		</available>
   	</target>
  -  
  +
     <target name="servlet" depends="servlet23Check" if="servlet23-present">
       <echo message="Servlet 2.3 is present."/>
     </target>
  @@ -116,17 +118,23 @@
     <!-- ================================================================= -->
     <fileset dir="${java.source.dir}" id="styled_files">
     	<include name="**/filter/*.java"/>
  +  	<include name="**/selector/*.java"/>
  +  	<include name="**/servlet/*.java"/>
     </fileset>
   
     <!-- ================================================================= -->
  +  <!-- Construct Jalopy classpath                                        -->
  +  <!-- ================================================================= -->
  +  <path id="jalopy.path">
  +    <fileset dir="${jalopy.lib}">
  +      <include name="*.jar" />
  +    </fileset>
  +  </path>
  +
  +  <!-- ================================================================= -->
     <!-- Runs jalopy.  Available from http://jalopy.sourceforge.net        -->
     <!-- ================================================================= -->
  -  <target name="runJalopy">
  -    <path id="jalopy.path">
  -      <fileset dir="${jalopy.lib}">
  -        <include name="*.jar" />
  -      </fileset>
  -    </path>
  +  <target name="runJalopy" depends="init">
       <taskdef name="jalopy"
                classname="de.hunsicker.jalopy.plugin.ant.AntPlugin"
                classpathref="jalopy.path" />
  @@ -140,7 +148,7 @@
     <!-- ================================================================= -->
     <!-- Runs jalopy preferences editor.                                   -->
     <!-- ================================================================= -->
  -  <target name="editJalopyPreferences">
  +  <target name="editJalopyPreferences" depends="init">
       <java classname="de.hunsicker.jalopy.swing.SettingsDialog"
             classpathref="jalopy.path"
             fork="true" />
  @@ -190,7 +198,33 @@
   				<attribute name="Manifest-version" value="1.0"/>
   					<section name="org/apache/log4j/">
   					  <attribute name="Implementation-Title" value="log4j-sandbox"/>
  -					  <attribute name="Implementation-Version" value="${version}"/> 
  +					  <attribute name="Implementation-Version" value="${version}"/>
  +					  <attribute name="Implementation-Vendor" value="Apache Software Foundation"/>
  +					</section>
  +      </manifest>
  +    </jar>
  +
  +    <jar jarfile="${jar.dest}/${log4j-sandbox-selector.jar}"
  +         basedir="${javac.dest}"
  +         includes="**/selector/*.class">
  +			<manifest>
  +				<attribute name="Manifest-version" value="1.0"/>
  +					<section name="org/apache/log4j/">
  +					  <attribute name="Implementation-Title" value="log4j-sandbox-selector"/>
  +					  <attribute name="Implementation-Version" value="${version}"/>
  +					  <attribute name="Implementation-Vendor" value="Apache Software Foundation"/>
  +					</section>
  +      </manifest>
  +    </jar>
  +
  +    <jar jarfile="${jar.dest}/${log4j-sandbox-servlet.jar}"
  +         basedir="${javac.dest}"
  +         includes="**/servlet/*.class">
  +			<manifest>
  +				<attribute name="Manifest-version" value="1.0"/>
  +					<section name="org/apache/log4j/">
  +					  <attribute name="Implementation-Title" value="log4j-sandbox-servlet"/>
  +					  <attribute name="Implementation-Version" value="${version}"/>
   					  <attribute name="Implementation-Vendor" value="Apache Software Foundation"/>
   					</section>
         </manifest>
  
  
  
  1.3       +2 -1      jakarta-log4j-sandbox/sunCodingConvention.xml
  
  Index: sunCodingConvention.xml
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j-sandbox/sunCodingConvention.xml,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- sunCodingConvention.xml	15 Feb 2003 19:13:09 -0000	1.2
  +++ sunCodingConvention.xml	18 Feb 2003 15:50:19 -0000	1.3
  @@ -92,6 +92,7 @@
                   <order>static|field|initializer|constructor|method|interface|class</order>
               </declaration>
               <modifier>
  +                <enable>true</enable>
                   <order>public|protected|private|abstract|static|final|synchronized|transient|volatile|native|strictfp</order>
               </modifier>
           </sorting>
  @@ -158,7 +159,7 @@
                   </parameter>
               </always>
               <general>
  -                <beforeOperator>false</beforeOperator>
  +                <beforeOperator>true</beforeOperator>
                   <enable>true</enable>
                   <lineLength>79</lineLength>
               </general>
  
  
  
  1.3       +28 -62    jakarta-log4j-sandbox/src/java/org/apache/log4j/selector/ContextClassLoaderSelector.java
  
  Index: ContextClassLoaderSelector.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j-sandbox/src/java/org/apache/log4j/selector/ContextClassLoaderSelector.java,v
  retrieving revision 1.2
  retrieving revision 1.3
  diff -u -r1.2 -r1.3
  --- ContextClassLoaderSelector.java	14 Feb 2003 05:58:56 -0000	1.2
  +++ ContextClassLoaderSelector.java	18 Feb 2003 15:50:20 -0000	1.3
  @@ -8,7 +8,6 @@
   
   import org.apache.log4j.Hierarchy;
   import org.apache.log4j.Level;
  -import org.apache.log4j.LogManager;
   import org.apache.log4j.spi.LoggerRepository;
   import org.apache.log4j.spi.RepositorySelector;
   import org.apache.log4j.spi.RootCategory;
  @@ -23,7 +22,7 @@
    *
    * <p>based primarily on Ceki G�lc�'s article <h3>Supporting the Log4j
    * <code>RepositorySelector</code> in Servlet Containers</h3> at:
  - * http://qos.ch/containers/sc.html</p>
  + * http://qos.ch/logging/sc.html</p>
    *
    * <p>By default, the class static <code>RepositorySelector</code> variable
    * of the <code>LogManager</code> class is set to a trivial
  @@ -51,66 +50,33 @@
    * @since 1.3
    */
   public class ContextClassLoaderSelector implements RepositorySelector {
  -    /**
  -     * key: current thread's ContextClassLoader,
  -     * value: Hierarchy instance
  -     */
  -    private static final Map HIER_MAP =
  -        Collections.synchronizedMap(new WeakHashMap());
  -
  -    /**
  -     * singleton instance for this class
  -     */
  -    private static final ContextClassLoaderSelector SINGLETON =
  -        new ContextClassLoaderSelector();
  -
  -    /**
  -     * remember idempotent initialization status
  -     */
  -    private static boolean initialized = false;
  -
  -    /**
  -     * private no-args constructor to guarantee no outside code can create an
  -     * instance
  -     */
  -    private ContextClassLoaderSelector() {
  +  /**
  +   * key: current thread's ContextClassLoader,
  +   * value: Hierarchy instance
  +   */
  +  private static final Map HIER_MAP =
  +    Collections.synchronizedMap(new WeakHashMap());
  +
  +  /**
  +   * public no-args constructor
  +   */
  +  public ContextClassLoaderSelector() {
  +  }
  +
  +  /**
  +   * implemented RepositorySelector interface method.
  +   *
  +   * @return the appropriate classloader-keyed Hierarchy/LoggerRepository
  +   */
  +  public LoggerRepository getLoggerRepository() {
  +    ClassLoader cl = Thread.currentThread().getContextClassLoader();
  +    Hierarchy hierarchy = (Hierarchy) HIER_MAP.get(cl);
  +
  +    if (hierarchy == null) {
  +      hierarchy = new Hierarchy(new RootCategory((Level) Level.DEBUG));
  +      HIER_MAP.put(cl, hierarchy);
       }
   
  -    /**
  -     * implemented RepositorySelector interface method.
  -     *
  -     * @return the appropriate classloader-keyed Hierarchy/LoggerRepository
  -     */
  -    public LoggerRepository getLoggerRepository() {
  -        ClassLoader cl = Thread.currentThread().getContextClassLoader();
  -        Hierarchy hierarchy = (Hierarchy) HIER_MAP.get(cl);
  -
  -        if (hierarchy == null) {
  -            hierarchy = new Hierarchy(new RootCategory((Level) Level.DEBUG));
  -            HIER_MAP.put(cl, hierarchy);
  -        }
  -
  -        return hierarchy;
  -    }
  -
  -    /**
  -     * The Container should initialize the logger repository for each
  -     * webapp upon startup or reload.  In this case, it is controllable
  -     * via each webapp.
  -     */
  -    public static void doIdempotentInitialization() {
  -        if (!initialized) {
  -            try {
  -                Object guard = new Object();
  -                LogManager.setRepositorySelector(SINGLETON, guard);
  -                initialized = true;
  -            } catch (IllegalArgumentException iae) {
  -                // either ignore the exception or log the fact that the
  -                // setting of this custom repository selector failed because
  -                // another had been set previously and maybe we should set
  -                // "initialized" to "true" in here so this exception doesn't
  -                // occur again in this class
  -            }
  -        }
  -    }
  +    return hierarchy;
  +  }
   }
  
  
  
  1.2       +325 -226  jakarta-log4j-sandbox/src/java/org/apache/log4j/servlet/InitContextListener.java
  
  Index: InitContextListener.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j-sandbox/src/java/org/apache/log4j/servlet/InitContextListener.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- InitContextListener.java	4 Feb 2003 06:28:16 -0000	1.1
  +++ InitContextListener.java	18 Feb 2003 15:50:20 -0000	1.2
  @@ -4,28 +4,30 @@
    * 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.servlet;
   
  -import javax.servlet.ServletContext;
  -import javax.servlet.ServletContextListener;
  -import javax.servlet.ServletContextEvent;
  +import org.apache.log4j.LogManager;
  +import org.apache.log4j.PropertyConfigurator;
  +import org.apache.log4j.helpers.LogLog;
  +import org.apache.log4j.selector.ContextClassLoaderSelector;
  +import org.apache.log4j.xml.DOMConfigurator;
   
   import java.io.File;
  +
   import java.net.MalformedURLException;
   import java.net.URL;
  +
   import java.util.Properties;
   
  -import org.apache.log4j.helpers.LogLog;
  -import org.apache.log4j.PropertyConfigurator;
  -import org.apache.log4j.xml.DOMConfigurator;
  +import javax.servlet.ServletContext;
  +import javax.servlet.ServletContextEvent;
  +import javax.servlet.ServletContextListener;
   
  -import org.apache.log4j.selector.ContextClassLoaderSelector;
   
   /**
    * A servlet context listener for initializing and shutting down Log4j. See
  - * <a href="http://jakarta.apache.org/log4j/docs/documentation.html">Log4j documentation</a>
  - * for how to use Log4j.
  + * <a href="http://jakarta.apache.org/log4j/docs/documentation.html">Log4j
  + * documentation</a> for how to use Log4j.
    * <p>
    * This is a <code>ServletContextListener</code> as defined by the servlet 2.3
    * specification.  It gets called immediately before full application startup
  @@ -36,19 +38,19 @@
    * use it to initialize things once at application startup and clean things
    * up at application shutdown.</p>
    * <p>
  - * Initialization is described below in the discussion of the various parameters
  - * available for configuring this context listener.  In the case of shutdown we are
  - * concerned with cleaning up loggers and appenders within the
  - * <code>Hierarchy</code> that the current application is using for
  - * logging.  If we didn't do this, there is a chance that, for instance, file
  - * appenders won't have given up handles to files they are logging to which
  - * would leave them in a locked state until the current JVM is shut down.  This
  - * would entail a full shutdown of the application server in order to release
  - * locks on log files.  Using this servlet context listener ensures that locks
  - * will be released without requiring a full server shutdown.</p>
  - * </p>
  + * Initialization is described below in the discussion of the various
  + * parameters available for configuring this context listener.  In the case of
  + * shutdown we are concerned with cleaning up loggers and appenders within the
  + * <code>Hierarchy</code> that the current application is using for logging.
  + * If we didn't do this, there is a chance that, for instance, file appenders
  + * won't have given up handles to files they are logging to which would leave
  + * them in a locked state until the current JVM is shut down.  This would
  + * entail a full shutdown of the application server in order to release locks
  + * on log files.  Using this servlet context listener ensures that locks will
  + * be released without requiring a full server shutdown.</p>
    * <p>
  - * The following needs to be added to the webapp's web.xml file to configure this listener:
  + * The following needs to be added to the webapp's web.xml file to configure
  + * this listener:
    * <blockquote>
    * <pre>
    * &lt;context-param&gt;
  @@ -73,10 +75,14 @@
    *              [webapp name].log.home
    *          If the app has a path of &quot;/Barracuda&quot;, the system
    *          variable name would be &quot;Barracuda.log.home&quot;.  So,
  - *          the FileAppender in log4j.xml would contain a param which looks like:
  - *              &lt;param name=&quot;File&quot; value=&quot;${Barracuda.log.home}/arbitraryLogFileName.log&quot; /&gt;
  - *          If the &quot;log4j-log-home&quot; context param is not specified, the
  - *          path associated with the generated system variable defaults to
  + *          the FileAppender in log4j.xml would contain a param which looks
  + *          like:
  + *              &lt;param
  + *                name=&quot;File&quot;
  + *                value=&quot;
  + *                  ${Barracuda.log.home}/arbitraryLogFileName.log&quot; /&gt;
  + *          If the &quot;log4j-log-home&quot; context param is not specified,
  + *          the path associated with the generated system variable defaults to
    *          the WEB-INF/logs directory of the current webapp which is created
    *          if it doesn't exist... unless the webapp is running directly
    *          from a .war file.  In the latter case, this context param
  @@ -96,7 +102,8 @@
    * </pre>
    * </blockquote>
    * </p>
  - * <h4>Below is some more information on each of the configuration properties</h4>
  + * <h4>Below is some more information on each of the configuration properties
  + * </h4>
    * <p>
    * <dl>
    * <dt><code>log4j-config</code></dt>
  @@ -105,42 +112,49 @@
    * Log4j configuration file relative to the current webapp.
    * If the <code>log4j-config</code> init parameter is omitted, this class
    * will just let Log4j configure itself since, upon first use of Log4j, if it
  - * has not yet been configured, it will search for a config file named log4j.xml
  - * or log4j.properties in the classpath. If it can't find one, it falls back to using the
  - * <code>BasicConfigurator.configure()</code> to initialize Log4j.
  + * has not yet been configured, it will search for a config file named
  + * log4j.xml or log4j.properties in the classpath. If it can't find one, it
  + * falls back to using the <code>BasicConfigurator.configure()</code> to
  + * initialize Log4j.
    * </dd>
    * <dt><code>log4j-cron</code></dt>
    * <dd>
  - * The <code>log4j-cron</code> init parameter specifies the number of milliseconds
  - * to wait in between reads of the config file using <code>configureAndWatch()</code>.
  - * If omitted, given a value of 0, or given a value that is other than something that
  - * which can be converted to a Java long value a normal <code>configure()</code> is used.
  + * The <code>log4j-cron</code> init parameter specifies the number of
  + * milliseconds to wait in between reads of the config file using
  + * <code>configureAndWatch()</code>. If omitted, given a value of 0, or given
  + * a value that is other than something that which can be converted to a Java
  + * long value a normal <code>configure()</code> is used.
    * </dd>
    * <dt><code>log4j-log-home</code></dt>
    * <dd>
    * The <code>log4j-log-home</code> init parameter is optional. It specifies a
  - * custom path to a directory meant to contain log files for the current webapp
  - * when using a <code>FileAppender</code>. If not specified, it will default to
  - * using the location WEB-INF/logs to contain log files. If the directory doesn't
  - * exist, it is created. A system parameter is then created in the following format:
  + * custom path to a directory meant to contain log files for the current
  + * webapp when using a <code>FileAppender</code>. If not specified, it will
  + * default to using the location WEB-INF/logs to contain log files. If the
  + * directory doesn't exist, it is created. A system parameter is then created
  + * in the following format:
    * <blockquote>
    *     <code>[webapp name].log.home</code>
    * </blockquote>
  - * This can be referenced in an xml config file (not sure if it works for a properties
  - * config file?) in the following fashion for a webapp with the context path &quot;/Barracuda&quot;:
  + * This can be referenced in an xml config file (not sure if it works for a
  + * properties config file?) in the following fashion for a webapp with the
  + * context path &quot;/Barracuda&quot;:
    * <blockquote>
  - *     <code>&lt;param name=&quot;File&quot; value=&quot;${Barracuda.log.home}/main.log&quot; /&gt;</code>
  + *   <code>&lt;param
  + *           name=&quot;File&quot;
  + *           value=&quot;${Barracuda.log.home}/main.log&quot; /&gt;</code>
    * </blockquote>
  - * In this case, we are running in the &quot;Barracuda&quot; context and the &quot;main.log&quot; file
  - * will get created in whatever directory path is specified by the system property
  - * &quot;Barracuda.log.home&quot;.
  + * In this case, we are running in the &quot;Barracuda&quot; context and the
  + * &quot;main.log&quot; file will get created in whatever directory path is
  + * specified by the system property &quot;Barracuda.log.home&quot;.
    * <p>
  - * <strong>Note</strong> that if the webapp is being run directly from a .war file, the automatic creation
  - * of the WEB-INF/logs directory and [webapp name].log.home system property will *not* be
  - * performed. In this case, you would have to provide a custom directory path for the
  - * this to work. Also note that <code>configureAndWatch()</code> will not be used in the case
  - * that the webapp is running directly from a .war file. <code>configure()</code> will be used
  - * instead.
  + * <strong>Note</strong> that if the webapp is being run directly from a .war
  + * file, the automatic creation of the WEB-INF/logs directory and
  + * [webapp name].log.home system property will *not* be performed. In this
  + * case, you would have to provide a custom directory path for the this to
  + * work. Also note that <code>configureAndWatch()</code> will not be used in
  + * the case that the webapp is running directly from a .war file.
  + * <code>configure()</code> will be used instead.
    * </p>
    * </dd>
    * </dl>
  @@ -149,192 +163,277 @@
    * @since   1.3
    */
   public class InitContextListener implements ServletContextListener {
  +  /**
  +   * relative path to config file within current webapp
  +   */
  +  private static final String PARAM_LOG4J_CONFIG_PATH = "log4j-config";
  +
  +  /**
  +   * config file re-reading specified in milliseconds
  +   */
  +  private static final String PARAM_LOG4J_WATCH_INTERVAL = "log4j-cron";
  +
  +  /**
  +   * path to be read from a log4j xml config file as a system property
  +   */
  +  private static final String PARAM_LOG4J_LOG_HOME = "log4j-log-home";
  +
  +  /**
  +   * default path to write log files if using a file appender
  +   */
  +  private static final String DEFAULT_LOG_HOME =
  +    "WEB-INF" + File.separator + "logs";
  +
  +  /**
  +   * Application Startup Event
  +   *
  +   * @param sce the context event provided by the container
  +   */
  +  public void contextInitialized(ServletContextEvent sce) {
  +    ServletContext context = sce.getServletContext();
  +
  +    initializeLog4j(context);
  +  }
  +
  +  /**
  +   * Application Shutdown Event
  +   *
  +   * @param sce the context event provided by the container
  +   */
  +  public void contextDestroyed(ServletContextEvent sce) {
  +    ServletContext context = sce.getServletContext();
  +
  +    cleanupLog4j(context);
  +  }
  +
  +  /**
  +   * Log4j specific cleanup.  Shuts down all loggers and appenders and
  +   * removes the hierarchy associated with the current classloader.
  +   *
  +   * @param context the current servlet context
  +   */
  +  private void cleanupLog4j(ServletContext context) {
  +    //shutdown this webapp's logger repository
  +    context.log(
  +      "Cleaning up Log4j resources for context: "
  +      + context.getServletContextName() + "...");
  +    context.log("Shutting down all loggers and appenders...");
  +    org.apache.log4j.LogManager.shutdown();
  +    context.log("Log4j cleaned up.");
  +  }
  +
  +  /**
  +   * Log4j specific initialization.  Sets up log4j for the current
  +   * servlet context. Installs a custom repository selector if one hasn't
  +   * already been installed.
  +   *
  +   * @param context the current servlet context
  +   */
  +  private void initializeLog4j(ServletContext context) {
  +    String configPath = context.getInitParameter(PARAM_LOG4J_CONFIG_PATH);
  +
  +    // if the log4j-config parameter is not set, then no point in trying
  +    if (configPath != null) {
  +      if (configPath.startsWith("/")) {
  +        configPath = (configPath.length() > 1) ? configPath.substring(1) : "";
  +      }
  +
  +      // if the configPath is an empty string, then no point in trying
  +      if (configPath.length() >= 1) {
  +        // set up log path System property
  +        String logHome = context.getInitParameter(PARAM_LOG4J_LOG_HOME);
  +
  +        if (logHome != null) {
  +          // set up custom log path system property
  +          setFileAppenderSystemProperty(logHome, context);
  +        }
   
  -    // store the time at which the current application became fully initialized
  -    public static long applicationInitialized = 0L;
  -
  -    private final static String PARAM_LOG4J_CONFIG_PATH = "log4j-config";
  -    private final static String PARAM_LOG4J_WATCH_INTERVAL = "log4j-cron";
  -    private final static String PARAM_LOG4J_LOG_HOME = "log4j-log-home";
  -    private final static String DEFAULT_LOG_HOME = "WEB-INF" + File.separator + "logs";
  -
  -
  -    /**
  -     * Application Startup Event
  -     */
  -    public void contextInitialized(ServletContextEvent sce) {
  -        applicationInitialized = System.currentTimeMillis();
  -
  -        ServletContext context = sce.getServletContext();
  -
  -        initializeLog4j(context);
  -    }
  -
  -    /**
  -     * Application Shutdown Event
  -     */
  -    public void contextDestroyed(ServletContextEvent sce) {
  -        ServletContext context = sce.getServletContext();
  -
  -        cleanupLog4j(context);
  -    }
  -
  +        boolean isXMLConfigFile = (configPath.endsWith(".xml")) ? true : false;
  +        String contextPath = context.getRealPath("/");
   
  +        if (contextPath != null) {
  +          // The webapp is deployed directly off the filesystem,
  +          // not from a .war file so we *can* do File IO.
  +          // This means we can use configureAndWatch() to re-read
  +          // the the config file at defined intervals.
  +          // Now let's check if the given configPath actually exists.
  +          if (logHome == null) {
  +            // no log path specified in web.xml. Setting to default
  +            logHome = contextPath + DEFAULT_LOG_HOME;
  +            setFileAppenderSystemProperty(logHome, context);
  +          }
  +
  +          String systemConfigPath =
  +            configPath.replace('/', File.separatorChar);
  +          File log4jFile = new File(contextPath + systemConfigPath);
  +
  +          if (log4jFile.canRead()) {
  +            log4jFile = null;
  +
  +            String timerInterval =
  +              context.getInitParameter(PARAM_LOG4J_WATCH_INTERVAL);
  +            long timerIntervalVal = 0L;
  +
  +            if (timerInterval != null) {
  +              try {
  +                timerIntervalVal = Integer.valueOf(timerInterval).longValue();
  +              } catch (NumberFormatException nfe) {
  +                //ignore...we just won't use configureAndWatch if there is no
  +                //valid int
  +              }
  +            }
   
  -    /**
  -     * Log4j specific cleanup.  Shuts down all loggers and appenders and
  -     * removes the hierarchy associated with the current classloader.
  -     */
  -    private void cleanupLog4j(ServletContext context) {
  -        //shutdown this webapp's logger repository
  -        context.log("Cleaning up Log4j resources for context: " + context.getServletContextName() + "...");
  -        context.log("Shutting down all loggers and appenders...");
  -        org.apache.log4j.LogManager.shutdown();
  -        context.log("Log4j cleaned up.");
  -    }
  +            setSelector();
  +            context.log(
  +              "Configuring Log4j from File: " + contextPath + systemConfigPath);
  +
  +            if (timerIntervalVal > 0) {
  +              context.log(
  +                "Configuring Log4j with watch interval: " + timerIntervalVal
  +                + "ms");
  +
  +              if (isXMLConfigFile) {
  +                DOMConfigurator.configureAndWatch(
  +                  contextPath + systemConfigPath, timerIntervalVal);
  +              } else {
  +                PropertyConfigurator.configureAndWatch(
  +                  contextPath + systemConfigPath, timerIntervalVal);
  +              }
  +            } else {
  +              if (isXMLConfigFile) {
  +                DOMConfigurator.configure(contextPath + systemConfigPath);
  +              } else {
  +                PropertyConfigurator.configure(contextPath + systemConfigPath);
  +              }
  +            }
  +          } else {
  +            //The given configPath does not exist.  So, let's just let Log4j
  +            //look for the default files (log4j.properties or log4j.xml) on
  +            //its own.
  +            displayConfigNotFoundMessage();
  +          }
   
  -    /**
  -     * Log4j specific initialization.  Shuts down all loggers and appenders and
  -     * removes the hierarchy associated with the current classloader.
  -     */
  -    private void initializeLog4j(ServletContext context) {
  -
  -        String configPath = context.getInitParameter(PARAM_LOG4J_CONFIG_PATH);
  -        // if the log4j-config parameter is not set, then no point in trying
  -        if (configPath!=null) {
  -            if (configPath.startsWith("/")) configPath = (configPath.length() > 1) ? configPath.substring(1) : "";
  -            // if the configPath is an empty string, then no point in trying
  -            if (configPath.length() >= 1) {
  -                // set up log path System property
  -                String logHome = context.getInitParameter(PARAM_LOG4J_LOG_HOME);
  -                if (logHome!=null) {
  -                    // set up custom log path system property
  -                    setFileAppenderSystemProperty(logHome, context);
  -                }
  -                boolean isXMLConfigFile = (configPath.endsWith(".xml")) ? true : false;
  -                String contextPath = context.getRealPath("/");
  -                if (contextPath!=null) {
  -                    // The webapp is deployed directly off the filesystem,
  -                    // not from a .war file so we *can* do File IO.
  -                    // This means we can use configureAndWatch() to re-read
  -                    // the the config file at defined intervals.
  -                    // Now let's check if the given configPath actually exists.
  -                    if (logHome==null) {
  -                        // no log path specified in web.xml. Setting to default
  -                        logHome = contextPath+DEFAULT_LOG_HOME;
  -                        setFileAppenderSystemProperty(logHome, context);
  -                    }
  -                    String systemConfigPath = configPath.replace('/', File.separatorChar);
  -                    File log4jFile = new File(contextPath+systemConfigPath);
  -                    if (log4jFile.canRead()) {
  -                        log4jFile = null;
  -                        String timerInterval = context.getInitParameter(PARAM_LOG4J_WATCH_INTERVAL);
  -                        long timerIntervalVal = 0L;
  -                        if (timerInterval!=null) {
  -                            try {
  -                                timerIntervalVal = Integer.valueOf(timerInterval).longValue();
  -                            }
  -                            catch (NumberFormatException nfe) {}
  -                        }
  -                        initLoggerRepository();
  -                        context.log("Configuring Log4j from File: "+contextPath+systemConfigPath);
  -                        if (timerIntervalVal > 0) {
  -                            context.log("Configuring Log4j with watch interval: "+timerIntervalVal+"ms");
  -                            if (isXMLConfigFile) {
  -                                DOMConfigurator.configureAndWatch(contextPath+systemConfigPath, timerIntervalVal);
  -                            }
  -                            else {
  -                                PropertyConfigurator.configureAndWatch(contextPath+systemConfigPath, timerIntervalVal);
  -                            }
  -                        }
  -                        else {
  -                            if (isXMLConfigFile) {
  -                                DOMConfigurator.configure(contextPath+systemConfigPath);
  -                            }
  -                            else {
  -                                PropertyConfigurator.configure(contextPath+systemConfigPath);
  -                            }
  -                        }
  -                    }
  -                    else {
  -                        // The given configPath does not exist.  So, let's just let Log4j look for the
  -                        // default files (log4j.properties or log4j.xml) on its own.
  -                        displayConfigNotFoundMessage();
  -                    } //end log4jFile.canRead() check
  -                }
  -                else {
  -                    // The webapp is deployed from a .war file, not directly
  -                    // off the file system so we *cannot* do File IO.
  -                    // Note that we *won't* be able to use configureAndWatch() here
  -                    // because that requires an absolute system file path.
  -                    // Now let's check if the given configPath actually exists.
  -                    URL log4jURL = null;
  -                    try {
  -                        log4jURL = context.getResource("/"+configPath);
  -                    }
  -                    catch (MalformedURLException murle) {}
  -                    if (log4jURL!=null) {
  -                        initLoggerRepository();
  -                        context.log("Configuring Log4j from URL at path: /"+configPath);
  -                        if (isXMLConfigFile) {
  -                            try {
  -                                DOMConfigurator.configure(log4jURL);
  -                            }
  -                            //catch (javax.xml.parsers.FactoryConfigurationError fce) {}
  -                            catch (Exception e) {
  -                                //report errors to server logs
  -                                LogLog.error(e.getMessage());
  -                            }
  -                        }
  -                        else {
  -                            Properties log4jProps = new Properties();
  -                            try {
  -                                log4jProps.load(log4jURL.openStream());
  -                                PropertyConfigurator.configure(log4jProps);
  -                            }
  -                            //catch (java.io.IOException ioe) {}
  -                            catch (Exception e) {
  -                                //report errors to server logs
  -                                LogLog.error(e.getMessage());
  -                            }
  -                        }
  -                    }
  -                    else {
  -                        // The given configPath does not exist.  So, let's just let Log4j look for the
  -                        // default files (log4j.properties or log4j.xml) on its own.
  -                        displayConfigNotFoundMessage();
  -                    } //end log4jURL null check
  -                } //end contextPath null check
  +          //end log4jFile.canRead() check
  +        } else {
  +          //The webapp is deployed from a .war file, not directly
  +          //off the file system so we *cannot* do File IO.
  +          //Note that we *won't* be able to use configureAndWatch() here
  +          //because that requires an absolute system file path.
  +          //Now let's check if the given configPath actually exists.
  +          URL log4jURL = null;
  +
  +          try {
  +            log4jURL = context.getResource("/" + configPath);
  +          } catch (MalformedURLException murle) {
  +            //ignore...we check for null later
  +          }
  +
  +          if (log4jURL != null) {
  +            setSelector();
  +            context.log("Configuring Log4j from URL at path: /" + configPath);
  +
  +            if (isXMLConfigFile) {
  +              try {
  +                DOMConfigurator.configure(log4jURL);
  +
  +                //catch (javax.xml.parsers.FactoryConfigurationError fce) {}
  +              } catch (Exception e) {
  +                //report errors to server logs
  +                LogLog.error(e.getMessage());
  +              }
  +            } else {
  +              Properties log4jProps = new Properties();
  +
  +              try {
  +                log4jProps.load(log4jURL.openStream());
  +                PropertyConfigurator.configure(log4jProps);
  +
  +                //catch (java.io.IOException ioe) {}
  +              } catch (Exception e) {
  +                //report errors to server logs
  +                LogLog.error(e.getMessage());
  +              }
               }
  -            else {
  -                LogLog.error("Zero length Log4j config file path given.");
  -                displayConfigNotFoundMessage();
  -            } //end configPath length check
  -        }
  -        else {
  -            LogLog.error("Missing log4j-config servlet parameter missing.");
  +          } else {
  +            //The given configPath does not exist.  So, let's just let Log4j
  +            //look for the default files (log4j.properties or log4j.xml) on
  +            //its own.
               displayConfigNotFoundMessage();
  -        } //end configPath null check
  -    }
  +          }
   
  -    private void displayConfigNotFoundMessage() {
  -        LogLog.warn("No Log4j configuration file found at given path. Falling back to Log4j auto-configuration.");
  +          //end log4jURL null check
  +        }
  +
  +        //end contextPath null check
  +      } else {
  +        LogLog.error("Zero length Log4j config file path given.");
  +        displayConfigNotFoundMessage();
  +      }
  +
  +      //end configPath length check
  +    } else {
  +      LogLog.error("Missing log4j-config servlet parameter missing.");
  +      displayConfigNotFoundMessage();
       }
   
  -    private void setFileAppenderSystemProperty(String logHome, ServletContext context) {
  -        File logHomeDir = new File(logHome);
  -        if (logHomeDir.exists() || logHomeDir.mkdirs()) {
  -            String tempdir = ""+context.getAttribute("javax.servlet.context.tempdir");
  -            int lastSlash = tempdir.lastIndexOf(File.separator);
  -            if ((tempdir.length()-1) > lastSlash) {
  -                String logHomePropertyName = tempdir.substring(lastSlash+1) + ".log.home";
  -                context.log("Setting system property [ " + logHomePropertyName + " ] to [ " + logHome + " ]");
  -                System.setProperty(logHomePropertyName, logHome);
  -            }
  -        }
  +    //end configPath null check
  +  }
  +
  +  /**
  +   * standard configuration not found message
  +   */
  +  private void displayConfigNotFoundMessage() {
  +    LogLog.warn(
  +      "No Log4j configuration file found at given path. "
  +      + "Falling back to Log4j auto-configuration.");
  +  }
  +
  +  /**
  +   * sets the [webapp].log.home system property for use with a file appender.
  +   *
  +   * @param logHome the path to a logging directory
  +   * @param context the current servlet context
  +   */
  +  private void setFileAppenderSystemProperty(
  +    String logHome, ServletContext context) {
  +    File logHomeDir = new File(logHome);
  +
  +    if (logHomeDir.exists() || logHomeDir.mkdirs()) {
  +      String tempdir =
  +        "" + context.getAttribute("javax.servlet.context.tempdir");
  +      int lastSlash = tempdir.lastIndexOf(File.separator);
  +
  +      if ((tempdir.length() - 1) > lastSlash) {
  +        String logHomePropertyName =
  +          tempdir.substring(lastSlash + 1) + ".log.home";
  +        context.log(
  +          "Setting system property [ " + logHomePropertyName + " ] to [ "
  +          + logHome + " ]");
  +        System.setProperty(logHomePropertyName, logHome);
  +      }
       }
  +  }
   
  -    private void initLoggerRepository() {
  -        ContextClassLoaderSelector.doIdempotentInitialization();
  +  /**
  +   * Do idempotent initialization of the the logger repository.  Only one
  +   * repository selector may be set during runtime of log4j.  Therefore, this
  +   * method is only a guarantee that a repository selector will have been set.
  +   * It does not guarantee that your preferred selector will be used.  If
  +   * some other code sets the selector first, that is the selector that all
  +   * applications using Log4j will use, assuming log4j is running in a shared
  +   * class loader.
  +   */
  +  private void setSelector() {
  +    try {
  +      Object guard = new Object();
  +      ContextClassLoaderSelector crs = new ContextClassLoaderSelector();
  +      LogManager.setRepositorySelector(crs, guard);
  +    } catch (IllegalArgumentException iae) {
  +      //either ignore the exception or log the fact that the
  +      //setting of this custom repository selector failed because
  +      //another had been set previously and maybe we should set
  +      //"initialized" to "true" in here so this exception doesn't
  +      //occur again in this class
       }
  +  }
   }
  
  
  
  1.2       +312 -178  jakarta-log4j-sandbox/src/java/org/apache/log4j/servlet/InitServlet.java
  
  Index: InitServlet.java
  ===================================================================
  RCS file: /home/cvs/jakarta-log4j-sandbox/src/java/org/apache/log4j/servlet/InitServlet.java,v
  retrieving revision 1.1
  retrieving revision 1.2
  diff -u -r1.1 -r1.2
  --- InitServlet.java	4 Feb 2003 06:28:16 -0000	1.1
  +++ InitServlet.java	18 Feb 2003 15:50:20 -0000	1.2
  @@ -4,37 +4,40 @@
    * 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.servlet;
   
  -import javax.servlet.ServletConfig;
  -import javax.servlet.ServletContext;
  -import javax.servlet.ServletException;
  -import javax.servlet.http.HttpServlet;
  -import javax.servlet.http.HttpServletRequest;
  -import javax.servlet.http.HttpServletResponse;
  +import org.apache.log4j.LogManager;
  +import org.apache.log4j.PropertyConfigurator;
  +import org.apache.log4j.helpers.LogLog;
  +import org.apache.log4j.selector.ContextClassLoaderSelector;
  +import org.apache.log4j.xml.DOMConfigurator;
   
   import java.io.File;
   import java.io.IOException;
  +
   import java.net.MalformedURLException;
   import java.net.URL;
  +
   import java.util.Properties;
   
  -import org.apache.log4j.helpers.LogLog;
  -import org.apache.log4j.PropertyConfigurator;
  -import org.apache.log4j.xml.DOMConfigurator;
  +import javax.servlet.ServletConfig;
  +import javax.servlet.ServletContext;
  +import javax.servlet.ServletException;
  +import javax.servlet.http.HttpServlet;
  +import javax.servlet.http.HttpServletRequest;
  +import javax.servlet.http.HttpServletResponse;
   
  -import org.apache.log4j.selector.ContextClassLoaderSelector;
   
   /**
    * A servlet for initializing Log4j. See
  - * <a href="http://jakarta.apache.org/log4j/docs/documentation.html">Log4j documentation</a>
  - * for how to use Log4j.
  + * <a href="http://jakarta.apache.org/log4j/docs/documentation.html">Log4j
  + * documentation</a> for how to use Log4j.
    * <p>
  - * <strong>Note:</strong> This log4j initialization servlet should be used *only* when
  - * running under a container which doesn't support servlet-2.3. A far better choice for
  - * servlet-2.3 configuration exists in {@link Log4jApplicationWatch}. Use it instead of
  - * this class for initialization.  If you really need to use this class, read on...</p>
  + * <strong>Note:</strong> This log4j initialization servlet should be used
  + * *only* when running under a container which doesn't support servlet-2.3.
  + * A far better choice for servlet-2.3 configuration exists in
  + * {@link Log4jApplicationWatch}. Use it instead of this class for
  + * initialization.  If you really need to use this class, read on...</p>
    * <p>
    * This servlet is never called by a client, but should be called during
    * web application initialization, i.e. when the servlet engine starts. The
  @@ -44,7 +47,9 @@
    * <pre>
    *  &lt;servlet&gt;
    *      &lt;servlet-name&gt;log4j-init&lt;/servlet-name&gt;
  - *      &lt;servlet-class&gt;org.apache.log4j.servlet.InitServlet&lt;/servlet-class&gt;
  + *      &lt;servlet-class&gt;
  + *        org.apache.log4j.servlet.InitServlet
  + *      &lt;/servlet-class&gt;
    *      &lt;init-param&gt;
    *           &lt;param-name&gt;log4j-config&lt;/param-name&gt;
    *           &lt;param-value&gt;WEB-INF/log4j.xml&lt;/param-value&gt;
  @@ -62,185 +67,314 @@
    * </pre>
    * </p>
    * <p>
  - * See {@link Log4jApplicationWatch} for detailed information about these parameters.
  + * See {@link Log4jApplicationWatch} for detailed information about these
  + * parameters.
    * </p>
    *
    * @author  Jacob Kjome <ho...@visi.com>
    * @since   1.3
    */
   public class InitServlet extends HttpServlet {
  +  /**
  +   * relative path to config file within current webapp
  +   */
  +  private static final String PARAM_LOG4J_CONFIG_PATH = "log4j-config";
  +
  +  /**
  +   * config file re-reading specified in milliseconds
  +   */
  +  private static final String PARAM_LOG4J_WATCH_INTERVAL = "log4j-cron";
  +
  +  /**
  +   * path to be read from a log4j xml config file as a system property
  +   */
  +  private static final String PARAM_LOG4J_LOG_HOME = "log4j-log-home";
  +
  +  /**
  +   * default path to write log files if using a file appender
  +   */
  +  private static final String DEFAULT_LOG_HOME =
  +    "WEB-INF" + File.separator + "logs";
  +
  +  /**
  +   * variable used to syncronize upon
  +   */
  +  private static Boolean configured = Boolean.FALSE;
  +
  +  /**
  +   * Log4j specific initialization.  Sets up log4j for the current
  +   * servlet context. Installs a custom repository selector if one hasn't
  +   * already been installed.
  +   *
  +   * @throws ServletException indicates problem running servlet
  +   */
  +  public void init() throws ServletException {
  +    if (configured.equals(Boolean.FALSE)) {
  +      String configPath = getInitParameter(PARAM_LOG4J_CONFIG_PATH);
  +
  +      // if the log4j-config parameter is not set, then no point in trying
  +      if (configPath != null) {
  +        if (configPath.startsWith("/")) {
  +          configPath =
  +            (configPath.length() > 1) ? configPath.substring(1) : "";
  +        }
  +
  +        // if the configPath is an empty string, then no point in trying
  +        if (configPath.length() >= 1) {
  +          // set up log path System property
  +          String logHome = getInitParameter(PARAM_LOG4J_LOG_HOME);
  +
  +          if (logHome != null) {
  +            // set up custom log path system property
  +            setFileAppenderSystemProperty(logHome, this);
  +          }
  +
  +          boolean isXMLConfigFile =
  +            (configPath.endsWith(".xml")) ? true : false;
  +          String contextPath = getServletContext().getRealPath("/");
  +
  +          if (contextPath != null) {
  +            // The webapp is deployed directly off the filesystem,
  +            // not from a .war file so we *can* do File IO.
  +            // This means we can use configureAndWatch() to re-read
  +            // the the config file at defined intervals.
  +            // Now let's check if the given configPath actually exists.
  +            if (logHome == null) {
  +              // no log path specified in web.xml. Setting to default
  +              logHome = contextPath + DEFAULT_LOG_HOME;
  +              setFileAppenderSystemProperty(logHome, this);
  +            }
   
  -    private final static String PARAM_LOG4J_CONFIG_PATH = "log4j-config";
  -    private final static String PARAM_LOG4J_WATCH_INTERVAL = "log4j-cron";
  -    private final static String PARAM_LOG4J_LOG_HOME = "log4j-log-home";
  -    private final static String DEFAULT_LOG_HOME = "WEB-INF" + File.separator + "logs";
  -
  -    private static Boolean CONFIGURED = Boolean.FALSE;
  -
  -    public void init() throws ServletException {
  -        if (CONFIGURED.equals(Boolean.FALSE)) {
  -            String configPath = getInitParameter(PARAM_LOG4J_CONFIG_PATH);
  -            // if the log4j-config parameter is not set, then no point in trying
  -            if (configPath!=null) {
  -                if (configPath.startsWith("/")) configPath = (configPath.length() > 1) ? configPath.substring(1) : "";
  -                // if the configPath is an empty string, then no point in trying
  -                if (configPath.length() >= 1) {
  -                    // set up log path System property
  -                    String logHome = getInitParameter(PARAM_LOG4J_LOG_HOME);
  -                    if (logHome!=null) {
  -                        // set up custom log path system property
  -                        setFileAppenderSystemProperty(logHome, this);
  +            String systemConfigPath =
  +              configPath.replace('/', File.separatorChar);
  +            File log4jFile = new File(contextPath + systemConfigPath);
  +
  +            if (log4jFile.canRead()) {
  +              log4jFile = null;
  +
  +              String timerInterval =
  +                getInitParameter(PARAM_LOG4J_WATCH_INTERVAL);
  +              long timerIntervalVal = 0L;
  +
  +              if (timerInterval != null) {
  +                try {
  +                  timerIntervalVal =
  +                    Integer.valueOf(timerInterval).longValue();
  +                } catch (NumberFormatException nfe) {
  +                  //ignore...we just won't use configureAndWatch if there is no
  +                  //valid int
  +                }
  +              }
  +
  +              synchronized (configured) {
  +                if (configured.equals(Boolean.FALSE)) {
  +                  setSelector();
  +                  log(
  +                    "Configuring Log4j from File: " + contextPath
  +                    + systemConfigPath);
  +
  +                  if (timerIntervalVal > 0) {
  +                    log(
  +                      "Configuring Log4j with watch interval: "
  +                      + timerIntervalVal + "ms");
  +
  +                    if (isXMLConfigFile) {
  +                      DOMConfigurator.configureAndWatch(
  +                        contextPath + systemConfigPath, timerIntervalVal);
  +                    } else {
  +                      PropertyConfigurator.configureAndWatch(
  +                        contextPath + systemConfigPath, timerIntervalVal);
                       }
  -                    boolean isXMLConfigFile = (configPath.endsWith(".xml")) ? true : false;
  -                    String contextPath = getServletContext().getRealPath("/");
  -                    if (contextPath!=null) {
  -                        // The webapp is deployed directly off the filesystem,
  -                        // not from a .war file so we *can* do File IO.
  -                        // This means we can use configureAndWatch() to re-read
  -                        // the the config file at defined intervals.
  -                        // Now let's check if the given configPath actually exists.
  -                        if (logHome==null) {
  -                            // no log path specified in web.xml. Setting to default
  -                            logHome = contextPath+DEFAULT_LOG_HOME;
  -                            setFileAppenderSystemProperty(logHome, this);
  -                        }
  -                        String systemConfigPath = configPath.replace('/', File.separatorChar);
  -                        File log4jFile = new File(contextPath+systemConfigPath);
  -                        if (log4jFile.canRead()) {
  -                            log4jFile = null;
  -                            String timerInterval = getInitParameter(PARAM_LOG4J_WATCH_INTERVAL);
  -                            long timerIntervalVal = 0L;
  -                            if (timerInterval!=null) {
  -                                try {
  -                                    timerIntervalVal = Integer.valueOf(timerInterval).longValue();
  -                                }
  -                                catch (NumberFormatException nfe) {}
  -                            }
  -                            synchronized (CONFIGURED) {
  -                                if (CONFIGURED.equals(Boolean.FALSE)) {
  -                                    initLoggerRepository();
  -                                    log("Configuring Log4j from File: "+contextPath+systemConfigPath);
  -                                    if (timerIntervalVal > 0) {
  -                                        log("Configuring Log4j with watch interval: "+timerIntervalVal+"ms");
  -                                        if (isXMLConfigFile) {
  -                                            DOMConfigurator.configureAndWatch(contextPath+systemConfigPath, timerIntervalVal);
  -                                        }
  -                                        else {
  -                                            PropertyConfigurator.configureAndWatch(contextPath+systemConfigPath, timerIntervalVal);
  -                                        }
  -                                    }
  -                                    else {
  -                                        if (isXMLConfigFile) {
  -                                            DOMConfigurator.configure(contextPath+systemConfigPath);
  -                                        }
  -                                        else {
  -                                            PropertyConfigurator.configure(contextPath+systemConfigPath);
  -                                        }
  -                                    }
  -                                    CONFIGURED = Boolean.TRUE;
  -                                } //end CONFIGURED check
  -                            } //end syncronized block
  -                        }
  -                        else {
  -                            // The given configPath does not exist.  So, let's just let Log4j look for the
  -                            // default files (log4j.properties or log4j.xml) on its own.
  -                            displayConfigNotFoundMessage();
  -                        } //end log4jFile.canRead() check
  +                  } else {
  +                    if (isXMLConfigFile) {
  +                      DOMConfigurator.configure(
  +                        contextPath + systemConfigPath);
  +                    } else {
  +                      PropertyConfigurator.configure(
  +                        contextPath + systemConfigPath);
                       }
  -                    else {
  -                        // The webapp is deployed from a .war file, not directly
  -                        // off the file system so we *cannot* do File IO.
  -                        // Note that we *won't* be able to use configureAndWatch() here
  -                        // because that requires an absolute system file path.
  -                        // Now let's check if the given configPath actually exists.
  -                        URL log4jURL = null;
  -                        try {
  -                            log4jURL = getServletContext().getResource("/"+configPath);
  -                        }
  -                        catch (MalformedURLException murle) {}
  -                        if (log4jURL!=null) {
  -                            synchronized (CONFIGURED) {
  -                                if (CONFIGURED.equals(Boolean.FALSE)) {
  -                                    initLoggerRepository();
  -                                    log("Configuring Log4j from URL at path: /"+configPath);
  -                                    if (isXMLConfigFile) {
  -                                        try {
  -                                            DOMConfigurator.configure(log4jURL);
  -                                            CONFIGURED = Boolean.TRUE;
  -                                        }
  -                                        //catch (javax.xml.parsers.FactoryConfigurationError fce) {}
  -                                        catch (Exception e) {
  -                                            //report errors to server logs
  -                                            LogLog.error(e.getMessage());
  -                                        }
  -                                    }
  -                                    else {
  -                                        Properties log4jProps = new Properties();
  -                                        try {
  -                                            log4jProps.load(log4jURL.openStream());
  -                                            PropertyConfigurator.configure(log4jProps);
  -                                            CONFIGURED = Boolean.TRUE;
  -                                        }
  -                                        //catch (IOException ioe) {}
  -                                        catch (Exception e) {
  -                                            //report errors to server logs
  -                                            LogLog.error(e.getMessage());
  -                                        }
  -                                    }
  -                                } //end CONFIGURED check
  -                            } //end syncronized block
  -                        }
  -                        else {
  -                            // The given configPath does not exist.  So, let's just let Log4j look for the
  -                            // default files (log4j.properties or log4j.xml) on its own.
  -                            displayConfigNotFoundMessage();
  -                        } //end log4jURL null check
  -                    } //end contextPath null check
  +                  }
  +
  +                  configured = Boolean.TRUE;
                   }
  -                else {
  -                    LogLog.error("Zero length Log4j config file path given.");
  -                    displayConfigNotFoundMessage();
  -                } //end configPath length check
  +
  +                //end configured check
  +              }
  +
  +              //end syncronized block
  +            } else {
  +              //The given configPath does not exist.  So, let's just let Log4j
  +              //look for the default files (log4j.properties or log4j.xml) on
  +              //its own.
  +              displayConfigNotFoundMessage();
               }
  -            else {
  -                LogLog.error("Missing log4j-config servlet parameter missing.");
  -                displayConfigNotFoundMessage();
  -            } //end configPath null check
  -        } //end CONFIGURED check
  -    } //end init() method
   
  -    private void displayConfigNotFoundMessage() {
  -        LogLog.warn("No Log4j configuration file found at given path. Falling back to Log4j auto-configuration.");
  -    }
  +            //end log4jFile.canRead() check
  +          } else {
  +            // The webapp is deployed from a .war file, not directly
  +            // off the file system so we *cannot* do File IO.
  +            // Note that we *won't* be able to use configureAndWatch() here
  +            // because that requires an absolute system file path.
  +            // Now let's check if the given configPath actually exists.
  +            URL log4jURL = null;
  +
  +            try {
  +              log4jURL = getServletContext().getResource("/" + configPath);
  +            } catch (MalformedURLException murle) {
  +              //ignore...we check for null later
  +            }
  +
  +            if (log4jURL != null) {
  +              synchronized (configured) {
  +                if (configured.equals(Boolean.FALSE)) {
  +                  setSelector();
  +                  log("Configuring Log4j from URL at path: /" + configPath);
  +
  +                  if (isXMLConfigFile) {
  +                    try {
  +                      DOMConfigurator.configure(log4jURL);
  +                      configured = Boolean.TRUE;
  +
  +                      //catch (javax.xml.parsers.FactoryConfigurationError fce
  +                      // ) {}
  +                    } catch (Exception e) {
  +                      //report errors to server logs
  +                      LogLog.error(e.getMessage());
  +                    }
  +                  } else {
  +                    Properties log4jProps = new Properties();
   
  -    private void setFileAppenderSystemProperty(String logHome, ServletConfig config) {
  -        File logHomeDir = new File(logHome);
  -        if (logHomeDir.exists() || logHomeDir.mkdirs()) {
  -            ServletContext context = config.getServletContext();
  -            String tempdir = ""+context.getAttribute("javax.servlet.context.tempdir");
  -            int lastSlash = tempdir.lastIndexOf(File.separator);
  -            if ((tempdir.length()-1) > lastSlash) {
  -                String logHomePropertyName = tempdir.substring(lastSlash+1) + ".log.home";
  -                context.log("Setting system property [ " + logHomePropertyName + " ] to [ " + logHome + " ]");
  -                System.setProperty(logHomePropertyName, logHome);
  +                    try {
  +                      log4jProps.load(log4jURL.openStream());
  +                      PropertyConfigurator.configure(log4jProps);
  +                      configured = Boolean.TRUE;
  +
  +                      //catch (IOException ioe) {}
  +                    } catch (Exception e) {
  +                      //report errors to server logs
  +                      LogLog.error(e.getMessage());
  +                    }
  +                  }
  +                }
  +
  +                //end configured check
  +              }
  +
  +              //end syncronized block
  +            } else {
  +              //The given configPath does not exist.  So, let's just let Log4j
  +              //look for the default files (log4j.properties or log4j.xml) on
  +              //its own.
  +              displayConfigNotFoundMessage();
               }
  +
  +            //end log4jURL null check
  +          }
  +
  +          //end contextPath null check
  +        } else {
  +          LogLog.error("Zero length Log4j config file path given.");
  +          displayConfigNotFoundMessage();
           }
  -    }
   
  -    private void initLoggerRepository() {
  -        ContextClassLoaderSelector.doIdempotentInitialization();
  +        //end configPath length check
  +      } else {
  +        LogLog.error("Missing log4j-config servlet parameter missing.");
  +        displayConfigNotFoundMessage();
  +      }
  +
  +      //end configPath null check
       }
   
  -    /**
  -     * Throws a ServletException.
  -     */
  -    public void doGet(HttpServletRequest req, HttpServletResponse res)
  -                                    throws ServletException, IOException {
  -        throw new ServletException("Servlet only used for Log4j initialization");
  +    //end configured check
  +  }
  +
  +  //end init() method
  +
  +  /**
  +   * standard configuration not found message
  +   */
  +  private void displayConfigNotFoundMessage() {
  +    LogLog.warn(
  +      "No Log4j configuration file found at given path. "
  +      + "Falling back to Log4j auto-configuration.");
  +  }
  +
  +  /**
  +   * sets the [webapp].log.home system property for use with a file appender.
  +   *
  +   * @param logHome the path to a logging directory
  +   * @param config the servlet config object for this servlet
  +   */
  +  private void setFileAppenderSystemProperty(
  +    String logHome, ServletConfig config) {
  +    File logHomeDir = new File(logHome);
  +
  +    if (logHomeDir.exists() || logHomeDir.mkdirs()) {
  +      ServletContext context = config.getServletContext();
  +      String tempdir =
  +        "" + context.getAttribute("javax.servlet.context.tempdir");
  +      int lastSlash = tempdir.lastIndexOf(File.separator);
  +
  +      if ((tempdir.length() - 1) > lastSlash) {
  +        String logHomePropertyName =
  +          tempdir.substring(lastSlash + 1) + ".log.home";
  +        context.log(
  +          "Setting system property [ " + logHomePropertyName + " ] to [ "
  +          + logHome + " ]");
  +        System.setProperty(logHomePropertyName, logHome);
  +      }
       }
  +  }
   
  -    public void doPost(HttpServletRequest req, HttpServletResponse res)
  -                                    throws ServletException, IOException {
  -        doGet(req, res);
  +  /**
  +   * Do idempotent initialization of the the logger repository.  Only one
  +   * repository selector may be set during runtime of log4j.  Therefore, this
  +   * method is only a guarantee that a repository selector will have been set.
  +   * It does not guarantee that your preferred selector will be used.  If
  +   * some other code sets the selector first, that is the selector that all
  +   * applications using Log4j will use, assuming log4j is running in a shared
  +   * class loader.
  +   */
  +  private void setSelector() {
  +    try {
  +      Object guard = new Object();
  +      ContextClassLoaderSelector crs = new ContextClassLoaderSelector();
  +      LogManager.setRepositorySelector(crs, guard);
  +    } catch (IllegalArgumentException iae) {
  +      //either ignore the exception or log the fact that the
  +      //setting of this custom repository selector failed because
  +      //another had been set previously and maybe we should set
  +      //"initialized" to "true" in here so this exception doesn't
  +      //occur again in this class
       }
  +  }
  +
  +  /**
  +   * Throws a ServletException because this servlet is not meant to be
  +   * accessed from the web.
  +   *
  +   * @param req the http servlet request
  +   * @param res the http servlet response
  +   * @throws ServletException indicates problem running servlet
  +   * @throws IOException indicates communication problem
  +   */
  +  public void doGet(HttpServletRequest req, HttpServletResponse res)
  +    throws ServletException, IOException {
  +    throw new ServletException("Servlet only used for Log4j initialization");
  +  }
  +
  +  /**
  +   * Throws a ServletException because this servlet is not meant to be
  +   * accessed from the web.
  +   *
  +   * @param req the http servlet request
  +   * @param res the http servlet response
  +   * @throws ServletException indicates problem running servlet
  +   * @throws IOException indicates communication problem
  +   */
  +  public void doPost(HttpServletRequest req, HttpServletResponse res)
  +    throws ServletException, IOException {
  +    doGet(req, res);
  +  }
   }
  
  
  

---------------------------------------------------------------------
To unsubscribe, e-mail: log4j-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: log4j-dev-help@jakarta.apache.org