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