mwomack 2002/12/23 10:02:28
Modified: src/java/org/apache/log4j/selectors
ContextClassLoaderSelector.java
Log:
Changes from Jacob Kjome to implement doIdempotentInitialization().
Revision Changes Path
1.2 +38 -149
jakarta-log4j/src/java/org/apache/log4j/selectors/ContextClassLoaderSelector.java
Index: ContextClassLoaderSelector.java
===================================================================
RCS file:
/home/cvs/jakarta-log4j/src/java/org/apache/log4j/selectors/ContextClassLoaderSelector.java,v
retrieving revision 1.1
retrieving revision 1.2
diff -u -r1.1 -r1.2
--- ContextClassLoaderSelector.java 13 Dec 2002 07:51:15 -0000 1.1
+++ ContextClassLoaderSelector.java 23 Dec 2002 18:02:28 -0000 1.2
@@ -17,162 +17,51 @@
import java.util.Map;
import java.util.WeakHashMap;
-
/**
- * ContextClassLoaderSelector
- *
- * <p>This class is provided as an example of a <code>RepositorySelector</code>
- * that uses ClassLoaders as a context to select a </code>LoggerRepository
- * </code> within a J2EE container, such as Tomcat. Because the implementation
- * of class loading can vary greatly between J2EE containers, this class is
- * considered <bold>experimental</bold>. No guarantees are made that this
- * class will work in every J2EE container, and the implementation of this
- * class may change greatly in the future. While it useful, it is primarily
- * provided as a "point of discussion" for creating other repository
- * selectors for specific J2EE containers. It has been tested primarily
- * with Tomcat 4.0.x.
- *
- * <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" repository selector. Each classloader provides
- * a unique 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.x.x and
- * probably a multitude of others. However, Tomcat 4.x.x is the only container
- * currently tested.</p>
- *
- * @author Jacob Kjome <[EMAIL PROTECTED]>
- * @since 1.3
+ * @author Jacob Kjome
*/
public class ContextClassLoaderSelector implements RepositorySelector {
- // key: current thread's ContextClassLoader,
- // value: Hierarchy instance
- final private static Map hierMap =
- Collections.synchronizedMap(new WeakHashMap());
-
- // key: current thread's ContextClassLoader,
- // value: Log4jCRS instance
- final private static Map crsMap =
- Collections.synchronizedMap(new WeakHashMap());
-
- // static initializer
- static {
- // This should only ever be called once in this class' entire existence.
- // The only way to override it is to pass in the exact same guard object
- // that we set here...which is next to impossible unless we store a
- // reference to it. We will not do that unless it becomes a requirement
- // in the future.
- Object guard = new Object();
- LogManager.setRepositorySelector(new ContextClassLoaderSelector(), guard);
- }
+ // 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);
- /**
- * default constructor
- */
- public ContextClassLoaderSelector() {}
-
- /**
- * This provides access to the hierarchy object which is associated with
- * the current webapp.
- *
- * @param the contextual classloader of the current webapp.
- *
- * @return the Hierarchy instance associated with the current webapp.
- * May be null.
- */
- public static Hierarchy getHierarchy(ClassLoader cl) {
- return (Hierarchy) hierMap.get(cl);
- }
-
- /**
- * This provides access to the ContextClassLoaderSelector object which
- * was used to create the hierarchy for the current web-application.
- * This can be used to remove the instances of both the hierarchy and
- * the Log4jCRS objects at application shutdown.
- *
- * @param the contextual classloader of the current webapp.
- *
- * @return the ContextClassLoaderSelector instance associated with the
- * current webapp. May be null.
- */
- public static ContextClassLoaderSelector getCRS(ClassLoader cl) {
- return (ContextClassLoaderSelector) crsMap.get(cl);
- }
-
- /**
- * This provides access to the LoggerRepository. Generally, this method
- * isn't called directly by the developer, rather, it is called
- * automatically by Log4j because setRepositorySelector was called on the
- * LogManager with an instance of this class.
- *
- * <p>the returned value is guaranteed to be non-null</p>
- *
- * @return the LoggerRepository, or Hierachy, associated with the current
- * webapp. Guaranteed to be non-null.
- */
- 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;
+ }
- if(hierarchy == null) {
- hierarchy = setGetLoggerRepository(cl);
- }
- return hierarchy;
- }
-
- /**
- * This generates the new hierachy and stores the instances of both the
- * hierarchy and ContextClassLoaderSelector in Maps in order to make
- * them retrievable at a later date by each individual webapp.
- *
- * @param the contextual classloader of the current webapp.
- *
- * @return a generated Hierarchy instance
- */
- private Hierarchy setGetLoggerRepository(ClassLoader cl) {
- Hierarchy hierarchy = new Hierarchy(new RootCategory((Level) Level.DEBUG));
- hierMap.put(cl, hierarchy);
- crsMap.put(cl, this);
- 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
+ }
}
+ }
- /**
- * The Container should initialize the logger repository for each
- * webapp upon startup or reload. In this case, it is controllable
- * via each webapp.
- */
- public void initLoggerRepository() {
- ClassLoader cl = Thread.currentThread().getContextClassLoader();
- setGetLoggerRepository(cl);
- }
+}
- /**
- * The Container should remove the entry when the webapp is removed or
- * restarted. In this case, it is controllable via each webapp.
- *
- * @param the contextual classloader of the current webapp.
- */
- public void remove(ClassLoader cl) {
- hierMap.remove(cl);
- crsMap.remove(cl);
- }
-}
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>