diff --git a/src/java/org/apache/commons/logging/LogFactory.java b/src/java/org/apache/commons/logging/LogFactory.java new file mode 100644 index 0000000..badf32d --- /dev/null +++ b/src/java/org/apache/commons/logging/LogFactory.java @@ -0,0 +1,330 @@ +/* + * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//logging/src/java/org/apache/commons/logging/LogFactory.java,v 1.1 2002/02/13 02:18:11 craigmcc Exp $ + * $Revision: 1.1 $ + * $Date: 2002/02/13 02:18:11 $ + * + * ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999-2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.commons.logging; + + +import java.io.InputStream; +import java.io.IOException; +import java.lang.reflect.InvocationTargetException; +import java.lang.reflect.Method; +import java.util.Enumeration; +import java.util.Properties; + + +/** + *

Factory for creating {@link Log} instances, with discovery and + * configuration features similar to that employed by standard Java APIs + * such as JAXP.

+ * + *

IMPLEMENTATION NOTE - This implementation is heavily + * based on the SAXParserFactory and DocumentBuilderFactory implementations + * (corresponding to the JAXP pluggability APIs) found in Apache Xerces.

+ * + * @author Craig R. McClanahan + * @author Costin Manolache + * @version $Revision: 1.1 $ $Date: 2002/02/13 02:18:11 $ + */ + +public abstract class LogFactory { + + + // ----------------------------------------------------- Manifest Constants + + + /** + * The fully qualified class name of the fallback LogFactory + * implementation class to use, if no other can be found. + */ + protected static final String FACTORY_DEFAULT = + "org.apache.commons.logging.impl.LogFactoryImpl"; + + + /** + * The name of the properties file to search for. + */ + protected static final String FACTORY_PROPERTIES = + "commons-logging.properties"; + + + /** + * The name of the property used to identify the LogFactory implementation + * class name. + */ + public static final String FACTORY_PROPERTY = + "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 null 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(); + + + /** + *

Construct (if necessary) and return a Log instance, + * using the factory's current set of configuration attributes.

+ * + * @param name Logical name of the Log 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 Log + * instance cannot be returned + */ + public abstract Log getInstance(String name) + throws LogConfigurationException; + + + /** + * 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 null value is equivalent to calling + * removeAttribute(name). + * + * @param name Name of the attribute to set + * @param value Value of the attribute to set, or null + * to remove any setting for this attribute + */ + public abstract void setAttribute(String name, Object value); + + + // --------------------------------------------------------- Static Methods + + + /** + *

Construct and return a new LogFactory instance, using + * the following ordered lookup procedure to determine the name of the + * implementation class to be loaded:

+ * + * + *

NOTE - If the properties file method of identifying the + * LogFactory implementation class is utilized, all of the + * properties defined in this file will be set as configuration attributes + * on the corresponding LogFactory instance.

+ * + * @exception LogConfigurationException if the implementation class is not + * available or cannot be instantiated. + */ + public static LogFactory newFactory() throws LogConfigurationException { + + // Identify the class loader we will be using + ClassLoader classLoader = findClassLoader(); + + // First, try the system property + try { + String factoryClass = System.getProperty(FACTORY_PROPERTY); + if (factoryClass != null) { + return (newInstance(factoryClass, classLoader)); + } + } catch (SecurityException e) { + ; + } + + // Second, try a properties file + try { + InputStream stream = + classLoader.getResourceAsStream(FACTORY_PROPERTIES); + if (stream != null) { + Properties props = new Properties(); + props.load(stream); + stream.close(); + String factoryClass = props.getProperty(FACTORY_PROPERTY); + if (factoryClass != null) { + LogFactory instance = + newInstance(factoryClass, classLoader); + Enumeration names = props.propertyNames(); + while (names.hasMoreElements()) { + String name = (String) names.nextElement(); + String value = props.getProperty(name); + instance.setAttribute(name, value); + } + return (instance); + } + } + } catch (IOException e) { + } catch (SecurityException e) { + } + + // Third, try the fallback implementation class + return (newInstance(FACTORY_DEFAULT, classLoader)); + + } + + + // ------------------------------------------------------ Protected Methods + + + /** + * Return the class loader to be used for loading the selected + * LogFactory implementation class. On a JDK 1.2 or later + * system, the context class loader for the current thread will be used + * if it is present. + * + * @exception LogConfigurationException if a suitable class loader + * cannot be identified + */ + protected static ClassLoader findClassLoader() + throws LogConfigurationException { + + // Are we running on a JDK 1.2 or later system? + Method method = null; + try { + method = Thread.class.getMethod("getContextClassLoader", null); + } catch (NoSuchMethodException e) { + // Assume we are running on JDK 1.1 + return (LogFactory.class.getClassLoader()); + } + + // Get the thread context class loader (if there is one) + ClassLoader classLoader = null; + try { + classLoader = (ClassLoader) + method.invoke(Thread.currentThread(), null); + if (classLoader == null) { + classLoader = LogFactory.class.getClassLoader(); + } + } catch (IllegalAccessException e) { + throw new LogConfigurationException + ("Unexpected IllegalAccessException", e); + } catch (InvocationTargetException e) { + throw new LogConfigurationException + ("Unexpected InvocationTargetException", e); + } + + // Return the selected class loader + return (classLoader); + + } + + + /** + * Return a new instance of the specified LogFactory + * implementation class, loaded by the specified class loader. + * + * @param factoryClass Fully qualified name of the LogFactory + * implementation class + * @param classLoader ClassLoader from which to load this class + * + * @exception LogConfigurationException if a suitable instance + * cannot be created + */ + private static LogFactory newInstance(String factoryClass, + ClassLoader classLoader) + throws LogConfigurationException { + + try { + Class clazz = null; + if (classLoader == null) { + clazz = Class.forName(factoryClass); + } else { + clazz = classLoader.loadClass(factoryClass); + } + return ((LogFactory) clazz.newInstance()); + } catch (Exception e) { + throw new LogConfigurationException(e); + } + + } + + +} diff --git a/src/java/org/apache/commons/logging/impl/LogFactoryImpl.java b/src/java/org/apache/commons/logging/impl/LogFactoryImpl.java new file mode 100644 index 0000000..b32036f --- /dev/null +++ b/src/java/org/apache/commons/logging/impl/LogFactoryImpl.java @@ -0,0 +1,424 @@ +/* + * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//logging/src/java/org/apache/commons/logging/impl/LogFactoryImpl.java,v 1.1 2002/02/13 02:18:11 craigmcc Exp $ + * $Revision: 1.1 $ + * $Date: 2002/02/13 02:18:11 $ + * + * ==================================================================== + * + * The Apache Software License, Version 1.1 + * + * Copyright (c) 1999-2002 The Apache Software Foundation. All rights + * reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions + * are met: + * + * 1. Redistributions of source code must retain the above copyright + * notice, this list of conditions and the following disclaimer. + * + * 2. Redistributions in binary form must reproduce the above copyright + * notice, this list of conditions and the following disclaimer in + * the documentation and/or other materials provided with the + * distribution. + * + * 3. The end-user documentation included with the redistribution, if + * any, must include the following acknowlegement: + * "This product includes software developed by the + * Apache Software Foundation (http://www.apache.org/)." + * Alternately, this acknowlegement may appear in the software itself, + * if and wherever such third-party acknowlegements normally appear. + * + * 4. The names "The Jakarta Project", "Commons", and "Apache Software + * Foundation" must not be used to endorse or promote products derived + * from this software without prior written permission. For written + * permission, please contact apache@apache.org. + * + * 5. Products derived from this software may not be called "Apache" + * nor may "Apache" appear in their names without prior written + * permission of the Apache Group. + * + * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED + * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES + * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE + * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR + * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, + * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT + * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF + * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND + * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT + * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGE. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ + +package org.apache.commons.logging.impl; + + +import java.lang.reflect.Constructor; +import java.lang.reflect.Method; +import java.util.Enumeration; +import java.util.Hashtable; +import java.util.Vector; +import org.apache.commons.logging.Log; +import org.apache.commons.logging.LogConfigurationException; +import org.apache.commons.logging.LogFactory; +import org.apache.commons.logging.LogSource; + + +/** + *

Concrete subclass of {@link LogFactory} that implements the + * following algorithm to dynamically select a logging implementation + * class to instantiate a wrapper for:

+ * + * + *

If the selected {@link Log} implementation class has a + * setLogFactory() method that accepts a {@link LogFactory} + * parameter, this method will be called on each newly created instance + * to identify the associated factory. This makes factory configuration + * attributes available to the Log instance, if it so desires.

+ * + *

This factory will remember previously created Log instances + * for the same name, and will return them on repeated requests to the + * getInstance() method. This implementation ignores any + * configured attributes.

+ * + * @author Rod Waldhoff + * @author Craig R. McClanahan + * @version $Revision: 1.1 $ $Date: 2002/02/13 02:18:11 $ + */ + +public class LogFactoryImpl extends LogFactory { + + + // ----------------------------------------------------------- Constructors + + + /** + * Public no-arguments constructor required by the lookup mechanism. + */ + public LogFactoryImpl() { + + super(); + + } + + + // ----------------------------------------------------- Manifest Constants + + + /** + * The fully qualified name of the default {@link Log} implementation. + */ + public static final String LOG_DEFAULT = + "org.apache.commons.logging.NoOpLog"; + + + /** + * The name of the system property identifying our {@link Log} + * implementation class. + */ + public static final String LOG_PROPERTY = + "org.apache.commons.logging.Log"; + + + /** + * The deprecated system property used for backwards compatibility with + * the old {@link LogSource} class. + */ + protected static final String LOG_PROPERTY_OLD = + "org.apache.commons.logging.log"; + + + // ----------------------------------------------------- Instance Variables + + + /** + * The configuration attributes for this {@link LogFactory}. + */ + protected Hashtable attributes = new Hashtable(); + + + /** + * The {@link Log} instances that have already been created, keyed by + * logger name. + */ + protected Hashtable instances = new Hashtable(); + + + /** + * The one-argument constructor of the {@link Log} implementation class + * that will be used to create new instances. This value is initialized + * by getLogConstructor(), and then returned repeatedly. + */ + protected Constructor logConstructor = null; + + + /** + * The signature of the Constructor to be used. + */ + protected Class logConstructorSignature[] = + { java.lang.String.class }; + + + /** + * The one-argument setLogFactory method of the selected + * {@link Log} method, if it exists. + */ + protected Method logMethod = null; + + + /** + * The signature of the setLogFactory method to be used. + */ + protected Class logMethodSignature[] = + { LogFactory.class }; + + + // --------------------------------------------------------- Public Methods + + + /** + * Return the configuration attribute with the specified name (if any), + * or null if there is no such attribute. + * + * @param name Name of the attribute to return + */ + public Object getAttribute(String name) { + + return (attributes.get(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 String[] getAttributeNames() { + + Vector names = new Vector(); + Enumeration keys = attributes.keys(); + while (keys.hasMoreElements()) { + names.addElement((String) keys.nextElement()); + } + String results[] = new String[names.size()]; + for (int i = 0; i < results.length; i++) { + results[i] = (String) names.elementAt(i); + } + return (results); + + } + + + /** + *

Construct (if necessary) and return a Log instance, + * using the factory's current set of configuration attributes.

+ * + * @param name Logical name of the Log 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 Log + * instance cannot be returned + */ + public Log getInstance(String name) + throws LogConfigurationException { + + Log instance = (Log) instances.get(name); + if (instance != null) { + instance = newInstance(name); + instances.put(name, instance); + } + return (instance); + + } + + + /** + * 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 void removeAttribute(String name) { + + attributes.remove(name); + + } + + + /** + * Set the configuration attribute with the specified name. Calling + * this with a null value is equivalent to calling + * removeAttribute(name). + * + * @param name Name of the attribute to set + * @param value Value of the attribute to set, or null + * to remove any setting for this attribute + */ + public void setAttribute(String name, Object value) { + + if (value == null) { + attributes.remove(name); + } else { + attributes.put(name, value); + } + + } + + + // ------------------------------------------------------ Protected Methods + + + /** + *

Return the Constructor that can be called to instantiate + * new {@link Log} instances.

+ * + *

IMPLEMENTATION NOTE - Race conditions caused by + * calling this method from more than one thread are ignored, because + * the same Constructor instance will ultimately be derived + * in all circumstances.

+ * + * @exception LogConfigurationException if a suitable constructor + * cannot be returned + */ + protected Constructor getLogConstructor() + throws LogConfigurationException { + + // Return the previously identified Constructor (if any) + if (logConstructor != null) { + return (logConstructor); + } + + // Identify the Log implementation class we will be using + String logClassName = null; + try { + logClassName = System.getProperty(LOG_PROPERTY); + if (logClassName == null) { // @deprecated + logClassName = System.getProperty(LOG_PROPERTY_OLD); + } + if ((logClassName == null) && isLog4JAvailable()) { + logClassName = + "org.apache.commons.logging.impl.Log4JCategoryLog"; + } + if ((logClassName == null) && isJdk14Available()) { + logClassName = + "org.apache.commons.logging.impl.Jdk14Logger"; + } + if (logClassName == null) { + logClassName = + "org.apache.commons.logging.impl.NoOpLog"; + } + } catch (SecurityException e) { + } + + // Attempt to load the Log implementation class + Class logClass = null; + try { + logClass = findClassLoader().loadClass(logClassName); + if (!Log.class.isAssignableFrom(logClass)) { + throw new LogConfigurationException + ("Class " + logClassName + " does not implement Log"); + } + } catch (Throwable t) { + throw new LogConfigurationException(t); + } + + // Identify the setLogFactory method (if there is one) + try { + logMethod = logClass.getMethod("setLogFactory", + logMethodSignature); + } catch (Throwable t) { + logMethod = null; + } + + // Identify the corresponding constructor to be used + try { + logConstructor = logClass.getConstructor(logConstructorSignature); + return (logConstructor); + } catch (Throwable t) { + throw new LogConfigurationException + ("No suitable Log constructor", t); + } + + } + + + /** + * Is JDK 1.4 or later logging available? + */ + protected boolean isJdk14Available() { + + try { + findClassLoader().loadClass("java.util.logging.Logger"); + return (true); + } catch (Throwable t) { + return (false); + } + + } + + + /** + * Is a Log4J implementation available? + */ + protected boolean isLog4JAvailable() { + + try { + findClassLoader().loadClass("org.apache.log4j.Category"); + return (true); + } catch (Throwable t) { + return (false); + } + + } + + + /** + * Create and return a new {@link Log} instance for the specified name. + * + * @param name Name of the new logger + * + * @exception LogConfigurationException if a new instance cannot + * be created + */ + protected Log newInstance(String name) + throws LogConfigurationException { + + Log instance = null; + + try { + Object params[] = new Object[1]; + params[0] = name; + instance = (Log) getLogConstructor().newInstance(params); + if (logMethod != null) { + params[0] = this; + logMethod.invoke(instance, params); + } + return (instance); + } catch (Throwable t) { + throw new LogConfigurationException(t); + } + + } + + +}