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]>

Reply via email to