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/14 16:32:26 UTC

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

Jake,

Have you already tried using JNDI-based RepositorySelector?

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

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

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

Posted by Ceki Gülcü <ce...@qos.ch>.
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 Jacob Kjome <ho...@visi.com>.
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