hoju 2003/02/13 21:58:56 Modified: src/java/org/apache/log4j/selector ContextClassLoaderSelector.java Log: Updated Javadoc. Also, modified code to conform to checkstyle. Jake Revision Changes Path 1.2 +94 -45 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.1 retrieving revision 1.2 diff -u -r1.1 -r1.2 --- ContextClassLoaderSelector.java 4 Feb 2003 06:28:16 -0000 1.1 +++ ContextClassLoaderSelector.java 14 Feb 2003 05:58:56 -0000 1.2 @@ -4,64 +4,113 @@ * 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.selector; -import org.apache.log4j.spi.RepositorySelector; -import org.apache.log4j.spi.LoggerRepository; -import org.apache.log4j.spi.RootCategory; 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; + import java.util.Collections; import java.util.Map; import java.util.WeakHashMap; + /** - * @author Jacob Kjome + * Log4j Contextual ClassLoader Selector + * + * <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> + * + * <p>By default, the class static <code>RepositorySelector</code> variable + * of the <code>LogManager</code> class is set to a trivial + * <code>RepositorySelector</code> implementation which always + * returns the same logger repository, which also happens to be a + * <code>Hierarchy</code> instance. In other words, by default log4j will use + * one hierarchy, the default hierarchy. This behavior can be overridden via + * the <code>LogManager</code>'s + * <code>setRepositorySelector(RepositorySelector, Object)</code> method.</p> + * + * <p>That is where this class enters the picture. It can be used to define a + * custom logger repository. It makes use of the fact that each webapp runs + * in its own classloader. This means we can track hierachies using the + * webapp classloader as the key to each individual hierarchy. That is what + * is meant by "contextual classloader" selector. Each classloader provides a + * unique logging context.</p> + * + * <p>Of course, this means that this class will only work in containers which + * provide for separate classloaders, so that is something to keep in mind. + * This methodology will certainly work in containers such as Tomcat 4/5 and + * probably a multitude of others. However, Tomcat 4.x.x and 5.x.x are the only + * containers currently tested.</p> + * + * @author Jacob Kjome + * @since 1.3 */ public class ContextClassLoaderSelector implements RepositorySelector { - - // key: current thread's ContextClassLoader, - // value: Hierarchy instance - final private static Map hierMap = Collections.synchronizedMap(new WeakHashMap()); - - final private static ContextClassLoaderSelector singleton = new ContextClassLoaderSelector(); - private static boolean initialized = false; - - private ContextClassLoaderSelector() {} - - public LoggerRepository getLoggerRepository() { - ClassLoader cl = Thread.currentThread().getContextClassLoader(); - Hierarchy hierarchy = (Hierarchy) hierMap.get(cl); - - if(hierarchy == null) { - hierarchy = new Hierarchy(new RootCategory((Level) Level.DEBUG)); - hierMap.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 - } + /** + * 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() { } - } -} + /** + * 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 + } + } + } +}
--------------------------------------------------------------------- To unsubscribe, e-mail: [EMAIL PROTECTED] For additional commands, e-mail: [EMAIL PROTECTED]