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 Ceki Gülcü <ce...@qos.ch> on 2003/02/15 16:08:26 UTC

Re[2]: cvs commit: jakarta-log4j-sandbox/src/java/org/apache/log4j/selector ContextClassLoaderSelector.java

Hi Jake,

Nothing prevents you from instantiating a ContextClassLoaderSelector 
instance in InitContextListener. I'll supply the patch in the next few minutes.

At 11:03 14.02.2003 -0600, you wrote:
>Hello Ceki,
>
>No, I haven't as of yet.  I'll try that this weekend.
>
>BTW, before you mentioned that doIdempotentInitialization() should be
>moved from the ContextClassLoaderSelector to whatever code that is
>performing initializatiion, such as the InitContextListener.  However,
>I don't see how this is possible given the contents of the
>initialization method...
>
>     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
>             }
>         }
>     }
>
>Note the "SINGLETON" variable sent into setRepositorySelector.  This
>is a private variable that is the singleton instance of the
>ContextClassLoader...
>
>     /**
>      * singleton instance for this class
>      */
>     private static final ContextClassLoaderSelector SINGLETON =
>         new ContextClassLoaderSelector();
>
>
>How could this be moved into an outside class performing
>initialization?  This is why I suggested that
>doIdempotentInitialization() be added to the RepositorySelector
>interface.  However, I do realize that there are implications in
>backward compatibility with other classes implementing this interface.
>
>The issue is that we need to provide a standard way to install custom
>repository selectors without referring to any specific repository
>selector in the initialization class as is being done with
>ContextClassLoaderSelector inside InitContextListener.
>
>It would make it easier if I could count on
>doIdempotentInitialization() existing in each and every class that
>implements RepositorySelector.  If this was done, then we could create
>a factory class which any particular initialization class could use
>and pass in a variable defining the preferred repository selector.
>The value of the passed-in variable could be set as a system variable,
>passed in as a context-parameter, or whatever.  The factory would then
>invoke doIdempotentInitialization() on the preferred repository
>selector and everything would be set up.
>
>The above is what I am looking for, ideally.  I need some advice as to
>what will be possible given the design goals of Log4j, and then within
>those constraints, how would I genericize the installation of
>repository selectors?
>
>thanks,
>
>Jake
>
>Friday, February 14, 2003, 9:32:26 AM, you wrote:
>
>CG> Jake,
>
>CG> Have you already tried using JNDI-based RepositorySelector?
>
>CG> At 05:58 14.02.2003 +0000, you wrote:
> >>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: log4j-dev-unsubscribe@jakarta.apache.org
> >>For additional commands, e-mail: log4j-dev-help@jakarta.apache.org
>
>CG> --
>CG> Ceki
>
>
>CG> ---------------------------------------------------------------------
>CG> To unsubscribe, e-mail: log4j-dev-unsubscribe@jakarta.apache.org
>CG> For additional commands, e-mail: log4j-dev-help@jakarta.apache.org
>
>
>
>--
>Best regards,
>  Jacob                            mailto:hoju@visi.com
>
>
>---------------------------------------------------------------------
>To unsubscribe, e-mail: log4j-dev-unsubscribe@jakarta.apache.org
>For additional commands, e-mail: log4j-dev-help@jakarta.apache.org

--
Ceki 


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


Re[2]: cvs commit: jakarta-log4j-sandbox/src/java/org/apache/log4j/selector ContextClassLoaderSelector.java

Posted by Ceki Gülcü <ce...@qos.ch>.
The promised patches are included as attachments.

Please also note the page http://qos.ch/containers/sc.html moved to 
http://qos.ch/logging/sc.html


At 16:08 15.02.2003 +0100, you wrote:

>Hi Jake,
>
>Nothing prevents you from instantiating a ContextClassLoaderSelector 
>instance in InitContextListener. I'll supply the patch in the next few minutes.
>
>At 11:03 14.02.2003 -0600, you wrote:
>>Hello Ceki,
>>
>>No, I haven't as of yet.  I'll try that this weekend.
>>
>>BTW, before you mentioned that doIdempotentInitialization() should be
>>moved from the ContextClassLoaderSelector to whatever code that is
>>performing initializatiion, such as the InitContextListener.  However,
>>I don't see how this is possible given the contents of the
>>initialization method...
>>
>>     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
>>             }
>>         }
>>     }
>>
>>Note the "SINGLETON" variable sent into setRepositorySelector.  This
>>is a private variable that is the singleton instance of the
>>ContextClassLoader...
>>
>>     /**
>>      * singleton instance for this class
>>      */
>>     private static final ContextClassLoaderSelector SINGLETON =
>>         new ContextClassLoaderSelector();
>>
>
>--
>Ceki