[slf4j-dev] svn commit: r195 - slf4j/trunk/src/java/org/apache/commons/logging

ceki at slf4j.org ceki at slf4j.org
Fri Aug 26 15:31:15 CEST 2005


Author: ceki
Date: Fri Aug 26 15:31:14 2005
New Revision: 195

Added:
   slf4j/trunk/src/java/org/apache/commons/logging/Log.java
   slf4j/trunk/src/java/org/apache/commons/logging/LogConfigurationException.java
   slf4j/trunk/src/java/org/apache/commons/logging/LogFactory.java
Log:
original version from Jakarta

Added: slf4j/trunk/src/java/org/apache/commons/logging/Log.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/src/java/org/apache/commons/logging/Log.java	Fri Aug 26 15:31:14 2005
@@ -0,0 +1,233 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+
+package org.apache.commons.logging;
+
+/**
+ * <p>A simple logging interface abstracting logging APIs.  In order to be
+ * instantiated successfully by {@link LogFactory}, classes that implement
+ * this interface must have a constructor that takes a single String
+ * parameter representing the "name" of this Log.</p>
+ *
+ * <p> The six logging levels used by <code>Log</code> are (in order):
+ * <ol>
+ * <li>trace (the least serious)</li>
+ * <li>debug</li>
+ * <li>info</li>
+ * <li>warn</li>
+ * <li>error</li>
+ * <li>fatal (the most serious)</li>
+ * </ol>
+ * The mapping of these log levels to the concepts used by the underlying
+ * logging system is implementation dependent.
+ * The implemention should ensure, though, that this ordering behaves
+ * as expected.</p>
+ *
+ * <p>Performance is often a logging concern.
+ * By examining the appropriate property,
+ * a component can avoid expensive operations (producing information
+ * to be logged).</p>
+ *
+ * <p> For example,
+ * <code><pre>
+ *    if (log.isDebugEnabled()) {
+ *        ... do something expensive ...
+ *        log.debug(theResult);
+ *    }
+ * </pre></code>
+ * </p>
+ *
+ * <p>Configuration of the underlying logging system will generally be done
+ * external to the Logging APIs, through whatever mechanism is supported by
+ * that system.</p>
+ *
+ * @author <a href="mailto:sanders at apache.org">Scott Sanders</a>
+ * @author Rod Waldhoff
+ * @version $Id: Log.java,v 1.19 2004/06/06 21:16:04 rdonkin Exp $
+ */
+public interface Log {
+
+
+    // ----------------------------------------------------- Logging Properties
+
+
+    /**
+     * <p> Is debug logging currently enabled? </p>
+     *
+     * <p> Call this method to prevent having to perform expensive operations
+     * (for example, <code>String</code> concatenation)
+     * when the log level is more than debug. </p>
+     */
+    public boolean isDebugEnabled();
+
+
+    /**
+     * <p> Is error logging currently enabled? </p>
+     *
+     * <p> Call this method to prevent having to perform expensive operations
+     * (for example, <code>String</code> concatenation)
+     * when the log level is more than error. </p>
+     */
+    public boolean isErrorEnabled();
+
+
+    /**
+     * <p> Is fatal logging currently enabled? </p>
+     *
+     * <p> Call this method to prevent having to perform expensive operations
+     * (for example, <code>String</code> concatenation)
+     * when the log level is more than fatal. </p>
+     */
+    public boolean isFatalEnabled();
+
+
+    /**
+     * <p> Is info logging currently enabled? </p>
+     *
+     * <p> Call this method to prevent having to perform expensive operations
+     * (for example, <code>String</code> concatenation)
+     * when the log level is more than info. </p>
+     */
+    public boolean isInfoEnabled();
+
+
+    /**
+     * <p> Is trace logging currently enabled? </p>
+     *
+     * <p> Call this method to prevent having to perform expensive operations
+     * (for example, <code>String</code> concatenation)
+     * when the log level is more than trace. </p>
+     */
+    public boolean isTraceEnabled();
+
+
+    /**
+     * <p> Is warn logging currently enabled? </p>
+     *
+     * <p> Call this method to prevent having to perform expensive operations
+     * (for example, <code>String</code> concatenation)
+     * when the log level is more than warn. </p>
+     */
+    public boolean isWarnEnabled();
+
+
+    // -------------------------------------------------------- Logging Methods
+
+
+    /**
+     * <p> Log a message with trace log level. </p>
+     *
+     * @param message log this message
+     */
+    public void trace(Object message);
+
+
+    /**
+     * <p> Log an error with trace log level. </p>
+     *
+     * @param message log this message
+     * @param t log this cause
+     */
+    public void trace(Object message, Throwable t);
+
+
+    /**
+     * <p> Log a message with debug log level. </p>
+     *
+     * @param message log this message
+     */
+    public void debug(Object message);
+
+
+    /**
+     * <p> Log an error with debug log level. </p>
+     *
+     * @param message log this message
+     * @param t log this cause
+     */
+    public void debug(Object message, Throwable t);
+
+
+    /**
+     * <p> Log a message with info log level. </p>
+     *
+     * @param message log this message
+     */
+    public void info(Object message);
+
+
+    /**
+     * <p> Log an error with info log level. </p>
+     *
+     * @param message log this message
+     * @param t log this cause
+     */
+    public void info(Object message, Throwable t);
+
+
+    /**
+     * <p> Log a message with warn log level. </p>
+     *
+     * @param message log this message
+     */
+    public void warn(Object message);
+
+
+    /**
+     * <p> Log an error with warn log level. </p>
+     *
+     * @param message log this message
+     * @param t log this cause
+     */
+    public void warn(Object message, Throwable t);
+
+
+    /**
+     * <p> Log a message with error log level. </p>
+     *
+     * @param message log this message
+     */
+    public void error(Object message);
+
+
+    /**
+     * <p> Log an error with error log level. </p>
+     *
+     * @param message log this message
+     * @param t log this cause
+     */
+    public void error(Object message, Throwable t);
+
+
+    /**
+     * <p> Log a message with fatal log level. </p>
+     *
+     * @param message log this message
+     */
+    public void fatal(Object message);
+
+
+    /**
+     * <p> Log an error with fatal log level. </p>
+     *
+     * @param message log this message
+     * @param t log this cause
+     */
+    public void fatal(Object message, Throwable t);
+
+
+}

Added: slf4j/trunk/src/java/org/apache/commons/logging/LogConfigurationException.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/src/java/org/apache/commons/logging/LogConfigurationException.java	Fri Aug 26 15:31:14 2005
@@ -0,0 +1,97 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+package org.apache.commons.logging;
+
+
+/**
+ * <p>An exception that is thrown only if a suitable <code>LogFactory</code>
+ * or <code>Log</code> instance cannot be created by the corresponding
+ * factory methods.</p>
+ *
+ * @author Craig R. McClanahan
+ * @version $Revision: 1.6 $ $Date: 2004/02/28 21:46:45 $
+ */
+
+public class LogConfigurationException extends RuntimeException {
+
+
+    /**
+     * Construct a new exception with <code>null</code> as its detail message.
+     */
+    public LogConfigurationException() {
+
+        super();
+
+    }
+
+
+    /**
+     * Construct a new exception with the specified detail message.
+     *
+     * @param message The detail message
+     */
+    public LogConfigurationException(String message) {
+
+        super(message);
+
+    }
+
+
+    /**
+     * Construct a new exception with the specified cause and a derived
+     * detail message.
+     *
+     * @param cause The underlying cause
+     */
+    public LogConfigurationException(Throwable cause) {
+
+        this((cause == null) ? null : cause.toString(), cause);
+
+    }
+
+
+    /**
+     * Construct a new exception with the specified detail message and cause.
+     *
+     * @param message The detail message
+     * @param cause The underlying cause
+     */
+    public LogConfigurationException(String message, Throwable cause) {
+
+        super(message + " (Caused by " + cause + ")");
+        this.cause = cause; // Two-argument version requires JDK 1.4 or later
+
+    }
+
+
+    /**
+     * The underlying cause of this exception.
+     */
+    protected Throwable cause = null;
+
+
+    /**
+     * Return the underlying cause of this exception (if any).
+     */
+    public Throwable getCause() {
+
+        return (this.cause);
+
+    }
+
+
+}

Added: slf4j/trunk/src/java/org/apache/commons/logging/LogFactory.java
==============================================================================
--- (empty file)
+++ slf4j/trunk/src/java/org/apache/commons/logging/LogFactory.java	Fri Aug 26 15:31:14 2005
@@ -0,0 +1,604 @@
+/*
+ * Copyright 2001-2004 The Apache Software Foundation.
+ * 
+ * Licensed under the Apache License, Version 2.0 (the "License");
+ * you may not use this file except in compliance with the License.
+ * You may obtain a copy of the License at
+ * 
+ *      http://www.apache.org/licenses/LICENSE-2.0
+ * 
+ * Unless required by applicable law or agreed to in writing, software
+ * distributed under the License is distributed on an "AS IS" BASIS,
+ * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
+ * See the License for the specific language governing permissions and
+ * limitations under the License.
+ */ 
+
+package org.apache.commons.logging;
+
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.security.AccessController;
+import java.security.PrivilegedAction;
+import java.util.Enumeration;
+import java.util.Hashtable;
+import java.util.Properties;
+
+
+/**
+ * <p>Factory for creating {@link Log} instances, with discovery and
+ * configuration features similar to that employed by standard Java APIs
+ * such as JAXP.</p>
+ *
+ * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation is heavily
+ * based on the SAXParserFactory and DocumentBuilderFactory implementations
+ * (corresponding to the JAXP pluggability APIs) found in Apache Xerces.</p>
+ *
+ * @author Craig R. McClanahan
+ * @author Costin Manolache
+ * @author Richard A. Sitze
+ * @version $Revision: 1.27 $ $Date: 2004/06/06 21:15:12 $
+ */
+
+public abstract class LogFactory {
+
+
+    // ----------------------------------------------------- Manifest Constants
+
+
+    /**
+     * The name of the property used to identify the LogFactory implementation
+     * class name.
+     */
+    public static final String FACTORY_PROPERTY =
+        "org.apache.commons.logging.LogFactory";
+
+    /**
+     * The fully qualified class name of the fallback <code>LogFactory</code>
+     * implementation class to use, if no other can be found.
+     */
+    public static final String FACTORY_DEFAULT =
+        "org.apache.commons.logging.impl.LogFactoryImpl";
+
+    /**
+     * The name of the properties file to search for.
+     */
+    public static final String FACTORY_PROPERTIES =
+        "commons-logging.properties";
+
+    /**
+     * JDK1.3+ <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider">
+     * 'Service Provider' specification</a>.
+     * 
+     */
+    protected static final String SERVICE_ID =
+        "META-INF/services/org.apache.commons.logging.LogFactory";
+
+
+    // ----------------------------------------------------------- Constructors
+
+
+    /**
+     * Protected constructor that is not available for public use.
+     */
+    protected LogFactory() { }
+
+
+    // --------------------------------------------------------- Public Methods
+
+
+    /**
+     * Return the configuration attribute with the specified name (if any),
+     * or <code>null</code> if there is no such attribute.
+     *
+     * @param name Name of the attribute to return
+     */
+    public abstract Object getAttribute(String name);
+
+
+    /**
+     * Return an array containing the names of all currently defined
+     * configuration attributes.  If there are no such attributes, a zero
+     * length array is returned.
+     */
+    public abstract String[] getAttributeNames();
+
+
+    /**
+     * Convenience method to derive a name from the specified class and
+     * call <code>getInstance(String)</code> with it.
+     *
+     * @param clazz Class for which a suitable Log name will be derived
+     *
+     * @exception LogConfigurationException if a suitable <code>Log</code>
+     *  instance cannot be returned
+     */
+    public abstract Log getInstance(Class clazz)
+        throws LogConfigurationException;
+
+
+    /**
+     * <p>Construct (if necessary) and return a <code>Log</code> instance,
+     * using the factory's current set of configuration attributes.</p>
+     *
+     * <p><strong>NOTE</strong> - Depending upon the implementation of
+     * the <code>LogFactory</code> you are using, the <code>Log</code>
+     * instance you are returned may or may not be local to the current
+     * application, and may or may not be returned again on a subsequent
+     * call with the same name argument.</p>
+     *
+     * @param name Logical name of the <code>Log</code> instance to be
+     *  returned (the meaning of this name is only known to the underlying
+     *  logging implementation that is being wrapped)
+     *
+     * @exception LogConfigurationException if a suitable <code>Log</code>
+     *  instance cannot be returned
+     */
+    public abstract Log getInstance(String name)
+        throws LogConfigurationException;
+
+
+    /**
+     * Release any internal references to previously created {@link Log}
+     * instances returned by this factory.  This is useful in environments
+     * like servlet containers, which implement application reloading by
+     * throwing away a ClassLoader.  Dangling references to objects in that
+     * class loader would prevent garbage collection.
+     */
+    public abstract void release();
+
+
+    /**
+     * Remove any configuration attribute associated with the specified name.
+     * If there is no such attribute, no action is taken.
+     *
+     * @param name Name of the attribute to remove
+     */
+    public abstract void removeAttribute(String name);
+
+
+    /**
+     * Set the configuration attribute with the specified name.  Calling
+     * this with a <code>null</code> value is equivalent to calling
+     * <code>removeAttribute(name)</code>.
+     *
+     * @param name Name of the attribute to set
+     * @param value Value of the attribute to set, or <code>null</code>
+     *  to remove any setting for this attribute
+     */
+    public abstract void setAttribute(String name, Object value);
+
+
+    // ------------------------------------------------------- Static Variables
+
+
+    /**
+     * The previously constructed <code>LogFactory</code> instances, keyed by
+     * the <code>ClassLoader</code> with which it was created.
+     */
+    protected static Hashtable factories = new Hashtable();
+
+
+    // --------------------------------------------------------- Static Methods
+
+
+    /**
+     * <p>Construct (if necessary) and return a <code>LogFactory</code>
+     * instance, using the following ordered lookup procedure to determine
+     * the name of the implementation class to be loaded.</p>
+     * <ul>
+     * <li>The <code>org.apache.commons.logging.LogFactory</code> system
+     *     property.</li>
+     * <li>The JDK 1.3 Service Discovery mechanism</li>
+     * <li>Use the properties file <code>commons-logging.properties</code>
+     *     file, if found in the class path of this class.  The configuration
+     *     file is in standard <code>java.util.Properties</code> format and
+     *     contains the fully qualified name of the implementation class
+     *     with the key being the system property defined above.</li>
+     * <li>Fall back to a default implementation class
+     *     (<code>org.apache.commons.logging.impl.LogFactoryImpl</code>).</li>
+     * </ul>
+     *
+     * <p><em>NOTE</em> - If the properties file method of identifying the
+     * <code>LogFactory</code> implementation class is utilized, all of the
+     * properties defined in this file will be set as configuration attributes
+     * on the corresponding <code>LogFactory</code> instance.</p>
+     *
+     * @exception LogConfigurationException if the implementation class is not
+     *  available or cannot be instantiated.
+     */
+    public static LogFactory getFactory() throws LogConfigurationException {
+
+        // Identify the class loader we will be using
+        ClassLoader contextClassLoader =
+            (ClassLoader)AccessController.doPrivileged(
+                new PrivilegedAction() {
+                    public Object run() {
+                        return getContextClassLoader();
+                    }
+                });
+
+        // Return any previously registered factory for this class loader
+        LogFactory factory = getCachedFactory(contextClassLoader);
+        if (factory != null)
+            return factory;
+
+
+        // Load properties file.
+        // Will be used one way or another in the end.
+
+        Properties props=null;
+        try {
+            InputStream stream = getResourceAsStream(contextClassLoader,
+                                                     FACTORY_PROPERTIES);
+
+            if (stream != null) {
+                props = new Properties();
+                props.load(stream);
+                stream.close();
+            }
+        } catch (IOException e) {
+        } catch (SecurityException e) {
+        }
+
+
+        // First, try the system property
+        try {
+            String factoryClass = System.getProperty(FACTORY_PROPERTY);
+            if (factoryClass != null) {
+                factory = newFactory(factoryClass, contextClassLoader);
+            }
+        } catch (SecurityException e) {
+            ;  // ignore
+        }
+
+
+        // Second, try to find a service by using the JDK1.3 jar
+        // discovery mechanism. This will allow users to plug a logger
+        // by just placing it in the lib/ directory of the webapp ( or in
+        // CLASSPATH or equivalent ). This is similar to the second
+        // step, except that it uses the (standard?) jdk1.3 location in the jar.
+
+        if (factory == null) {
+            try {
+                InputStream is = getResourceAsStream(contextClassLoader,
+                                                     SERVICE_ID);
+
+                if( is != null ) {
+                    // This code is needed by EBCDIC and other strange systems.
+                    // It's a fix for bugs reported in xerces
+                    BufferedReader rd;
+                    try {
+                        rd = new BufferedReader(new InputStreamReader(is, "UTF-8"));
+                    } catch (java.io.UnsupportedEncodingException e) {
+                        rd = new BufferedReader(new InputStreamReader(is));
+                    }
+
+                    String factoryClassName = rd.readLine();
+                    rd.close();
+
+                    if (factoryClassName != null &&
+                        ! "".equals(factoryClassName)) {
+
+                        factory= newFactory( factoryClassName, contextClassLoader );
+                    }
+                }
+            } catch( Exception ex ) {
+                ;
+            }
+        }
+
+
+        // Third try a properties file.
+        // If the properties file exists, it'll be read and the properties
+        // used. IMHO ( costin ) System property and JDK1.3 jar service
+        // should be enough for detecting the class name. The properties
+        // should be used to set the attributes ( which may be specific to
+        // the webapp, even if a default logger is set at JVM level by a
+        // system property )
+
+        if (factory == null  &&  props != null) {
+            String factoryClass = props.getProperty(FACTORY_PROPERTY);
+            if (factoryClass != null) {
+                factory = newFactory(factoryClass, contextClassLoader);
+            }
+        }
+
+
+        // Fourth, try the fallback implementation class
+
+        if (factory == null) {
+            factory = newFactory(FACTORY_DEFAULT, LogFactory.class.getClassLoader());
+        }
+
+        if (factory != null) {
+            /**
+             * Always cache using context class loader.
+             */
+            cacheFactory(contextClassLoader, factory);
+
+            if( props!=null ) {
+                Enumeration names = props.propertyNames();
+                while (names.hasMoreElements()) {
+                    String name = (String) names.nextElement();
+                    String value = props.getProperty(name);
+                    factory.setAttribute(name, value);
+                }
+            }
+        }
+
+        return factory;
+    }
+
+
+    /**
+     * Convenience method to return a named logger, without the application
+     * having to care about factories.
+     *
+     * @param clazz Class from which a log name will be derived
+     *
+     * @exception LogConfigurationException if a suitable <code>Log</code>
+     *  instance cannot be returned
+     */
+    public static Log getLog(Class clazz)
+        throws LogConfigurationException {
+
+        return (getFactory().getInstance(clazz));
+
+    }
+
+
+    /**
+     * Convenience method to return a named logger, without the application
+     * having to care about factories.
+     *
+     * @param name Logical name of the <code>Log</code> instance to be
+     *  returned (the meaning of this name is only known to the underlying
+     *  logging implementation that is being wrapped)
+     *
+     * @exception LogConfigurationException if a suitable <code>Log</code>
+     *  instance cannot be returned
+     */
+    public static Log getLog(String name)
+        throws LogConfigurationException {
+
+        return (getFactory().getInstance(name));
+
+    }
+
+
+    /**
+     * Release any internal references to previously created {@link LogFactory}
+     * instances that have been associated with the specified class loader
+     * (if any), after calling the instance method <code>release()</code> on
+     * each of them.
+     *
+     * @param classLoader ClassLoader for which to release the LogFactory
+     */
+    public static void release(ClassLoader classLoader) {
+
+        synchronized (factories) {
+            LogFactory factory = (LogFactory) factories.get(classLoader);
+            if (factory != null) {
+                factory.release();
+                factories.remove(classLoader);
+            }
+        }
+
+    }
+
+
+    /**
+     * Release any internal references to previously created {@link LogFactory}
+     * instances, after calling the instance method <code>release()</code> on
+     * each of them.  This is useful in environments like servlet containers,
+     * which implement application reloading by throwing away a ClassLoader.
+     * Dangling references to objects in that class loader would prevent
+     * garbage collection.
+     */
+    public static void releaseAll() {
+
+        synchronized (factories) {
+            Enumeration elements = factories.elements();
+            while (elements.hasMoreElements()) {
+                LogFactory element = (LogFactory) elements.nextElement();
+                element.release();
+            }
+            factories.clear();
+        }
+
+    }
+
+
+    // ------------------------------------------------------ Protected Methods
+
+
+    /**
+     * Return the thread context class loader if available.
+     * Otherwise return null.
+     *
+     * The thread context class loader is available for JDK 1.2
+     * or later, if certain security conditions are met.
+     *
+     * @exception LogConfigurationException if a suitable class loader
+     * cannot be identified.
+     */
+    protected static ClassLoader getContextClassLoader()
+        throws LogConfigurationException
+    {
+        ClassLoader classLoader = null;
+
+        try {
+            // Are we running on a JDK 1.2 or later system?
+            Method method = Thread.class.getMethod("getContextClassLoader", null);
+
+            // Get the thread context class loader (if there is one)
+            try {
+                classLoader = (ClassLoader)method.invoke(Thread.currentThread(), null);
+            } catch (IllegalAccessException e) {
+                throw new LogConfigurationException
+                    ("Unexpected IllegalAccessException", e);
+            } catch (InvocationTargetException e) {
+                /**
+                 * InvocationTargetException is thrown by 'invoke' when
+                 * the method being invoked (getContextClassLoader) throws
+                 * an exception.
+                 *
+                 * getContextClassLoader() throws SecurityException when
+                 * the context class loader isn't an ancestor of the
+                 * calling class's class loader, or if security
+                 * permissions are restricted.
+                 *
+                 * In the first case (not related), we want to ignore and
+                 * keep going.  We cannot help but also ignore the second
+                 * with the logic below, but other calls elsewhere (to
+                 * obtain a class loader) will trigger this exception where
+                 * we can make a distinction.
+                 */
+                if (e.getTargetException() instanceof SecurityException) {
+                    ;  // ignore
+                } else {
+                    // Capture 'e.getTargetException()' exception for details
+                    // alternate: log 'e.getTargetException()', and pass back 'e'.
+                    throw new LogConfigurationException
+                        ("Unexpected InvocationTargetException", e.getTargetException());
+                }
+            }
+        } catch (NoSuchMethodException e) {
+            // Assume we are running on JDK 1.1
+            classLoader = LogFactory.class.getClassLoader();
+        }
+
+        // Return the selected class loader
+        return classLoader;
+    }
+
+    /**
+     * Check cached factories (keyed by contextClassLoader)
+     */
+    private static LogFactory getCachedFactory(ClassLoader contextClassLoader)
+    {
+        LogFactory factory = null;
+
+        if (contextClassLoader != null)
+            factory = (LogFactory) factories.get(contextClassLoader);
+
+        return factory;
+    }
+
+    private static void cacheFactory(ClassLoader classLoader, LogFactory factory)
+    {
+        if (classLoader != null && factory != null)
+            factories.put(classLoader, factory);
+    }
+
+    /**
+     * Return a new instance of the specified <code>LogFactory</code>
+     * implementation class, loaded by the specified class loader.
+     * If that fails, try the class loader used to load this
+     * (abstract) LogFactory.
+     *
+     * @param factoryClass Fully qualified name of the <code>LogFactory</code>
+     *  implementation class
+     * @param classLoader ClassLoader from which to load this class
+     *
+     * @exception LogConfigurationException if a suitable instance
+     *  cannot be created
+     */
+    protected static LogFactory newFactory(final String factoryClass,
+                                           final ClassLoader classLoader)
+        throws LogConfigurationException
+    {
+        Object result = AccessController.doPrivileged(
+            new PrivilegedAction() {
+                public Object run() {
+                    // This will be used to diagnose bad configurations
+                    // and allow a useful message to be sent to the user
+                    Class logFactoryClass = null;
+                    try {
+                        if (classLoader != null) {
+                            try {
+                                // First the given class loader param (thread class loader)
+
+                                // Warning: must typecast here & allow exception
+                                // to be generated/caught & recast properly.
+                                logFactoryClass = classLoader.loadClass(factoryClass);
+                                return (LogFactory) logFactoryClass.newInstance();
+
+                            } catch (ClassNotFoundException ex) {
+                                if (classLoader == LogFactory.class.getClassLoader()) {
+                                    // Nothing more to try, onwards.
+                                    throw ex;
+                                }
+                                // ignore exception, continue
+                            } catch (NoClassDefFoundError e) {
+                                if (classLoader == LogFactory.class.getClassLoader()) {
+                                    // Nothing more to try, onwards.
+                                    throw e;
+                                }
+
+                            } catch(ClassCastException e){
+
+                              if (classLoader == LogFactory.class.getClassLoader()) {
+                                    // Nothing more to try, onwards (bug in loader implementation).
+                                    throw e;
+                               }
+                            }
+                            // Ignore exception, continue
+                        }
+
+                        /* At this point, either classLoader == null, OR
+                         * classLoader was unable to load factoryClass.
+                         * Try the class loader that loaded this class:
+                         * LogFactory.getClassLoader().
+                         *
+                         * Notes:
+                         * a) LogFactory.class.getClassLoader() may return 'null'
+                         *    if LogFactory is loaded by the bootstrap classloader.
+                         * b) The Java endorsed library mechanism is instead
+                         *    Class.forName(factoryClass);
+                         */
+                        // Warning: must typecast here & allow exception
+                        // to be generated/caught & recast properly.
+                        logFactoryClass = Class.forName(factoryClass);
+                        return (LogFactory) logFactoryClass.newInstance();
+                    } catch (Exception e) {
+                        // Check to see if we've got a bad configuration
+                        if (logFactoryClass != null
+                            && !LogFactory.class.isAssignableFrom(logFactoryClass)) {
+                            return new LogConfigurationException(
+                                "The chosen LogFactory implementation does not extend LogFactory."
+                                + " Please check your configuration.",
+                                e);
+                        }
+                        return new LogConfigurationException(e);
+                    }
+                }
+            });
+
+        if (result instanceof LogConfigurationException)
+            throw (LogConfigurationException)result;
+
+        return (LogFactory)result;
+    }
+
+    private static InputStream getResourceAsStream(final ClassLoader loader,
+                                                   final String name)
+    {
+        return (InputStream)AccessController.doPrivileged(
+            new PrivilegedAction() {
+                public Object run() {
+                    if (loader != null) {
+                        return loader.getResourceAsStream(name);
+                    } else {
+                        return ClassLoader.getSystemResourceAsStream(name);
+                    }
+                }
+            });
+    }
+}



More information about the slf4j-dev mailing list