Improvements to the new LogFactory APIs, based on feedback from Costin and
Jon plus some additional thought about using it in a multi-class-loader
environment (like Tomcat):
* Changed newFactory() to getFactory(), and implemented a cache of
previously created factory instances (one per class loader). This
avoids potentially expensive and redundant discovery operations.
* Added convenient static getLog() method so a typical application
component can initialize it's Log instance like this:
Log log = LogFactory.getLog("com.mycompany.mypackage.MyClass");
* Added variants of getInstance() and getLog() that take a Class
parameter instead of a String. LogSource had this convenience
feature, and there's no reason not to keep it.
* Added release() and releaseAll() methods to instruct the factory
instances to release any cached references to other LogFactory
or Log instances. This is important, for example, if you put
commons-logging.jar in Tomcat's shared "lib" directory, and then
use the application reload facility. The references maintained
here would otherwise prevent garbage collection of the old
webapp class loader once a reload takes place.
* Added a note on getInstance() that you can make no assumptions
about whether or not the actual Log instance you get back is
shared or not. The actual sharability is a feature of the
LogFactory implementation you are using, and what kind of a
class loader environment you ae installing.
* Deprecated LogSource, but left it there to ease transition of
existing code using it.
git-svn-id: https://svn.apache.org/repos/asf/jakarta/commons/proper/logging/trunk@138858 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* $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 $
|
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//logging/src/java/org/apache/commons/logging/LogFactory.java,v 1.2 2002/02/14 00:19:03 craigmcc Exp $
|
||||||
* $Revision: 1.1 $
|
* $Revision: 1.2 $
|
||||||
* $Date: 2002/02/13 02:18:11 $
|
* $Date: 2002/02/14 00:19:03 $
|
||||||
*
|
*
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*
|
*
|
||||||
@@ -67,6 +67,7 @@ import java.io.IOException;
|
|||||||
import java.lang.reflect.InvocationTargetException;
|
import java.lang.reflect.InvocationTargetException;
|
||||||
import java.lang.reflect.Method;
|
import java.lang.reflect.Method;
|
||||||
import java.util.Enumeration;
|
import java.util.Enumeration;
|
||||||
|
import java.util.Hashtable;
|
||||||
import java.util.Properties;
|
import java.util.Properties;
|
||||||
|
|
||||||
|
|
||||||
@@ -81,7 +82,7 @@ import java.util.Properties;
|
|||||||
*
|
*
|
||||||
* @author Craig R. McClanahan
|
* @author Craig R. McClanahan
|
||||||
* @author Costin Manolache
|
* @author Costin Manolache
|
||||||
* @version $Revision: 1.1 $ $Date: 2002/02/13 02:18:11 $
|
* @version $Revision: 1.2 $ $Date: 2002/02/14 00:19:03 $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public abstract class LogFactory {
|
public abstract class LogFactory {
|
||||||
@@ -142,10 +143,29 @@ public abstract class LogFactory {
|
|||||||
public abstract String[] getAttributeNames();
|
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,
|
* <p>Construct (if necessary) and return a <code>Log</code> instance,
|
||||||
* using the factory's current set of configuration attributes.</p>
|
* 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
|
* @param name Logical name of the <code>Log</code> instance to be
|
||||||
* returned (the meaning of this name is only known to the underlying
|
* returned (the meaning of this name is only known to the underlying
|
||||||
* logging implementation that is being wrapped)
|
* logging implementation that is being wrapped)
|
||||||
@@ -157,6 +177,16 @@ public abstract class LogFactory {
|
|||||||
throws LogConfigurationException;
|
throws LogConfigurationException;
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release any internal references to previously created {@link Log}
|
||||||
|
* instances returned by this factory. This is useful 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.
|
* Remove any configuration attribute associated with the specified name.
|
||||||
* If there is no such attribute, no action is taken.
|
* If there is no such attribute, no action is taken.
|
||||||
@@ -178,13 +208,23 @@ public abstract class LogFactory {
|
|||||||
public abstract void setAttribute(String name, Object value);
|
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
|
// --------------------------------------------------------- Static Methods
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Construct and return a new <code>LogFactory</code> instance, using
|
* <p>Construct (if necessary) and return a <code>LogFactory</code>
|
||||||
* the following ordered lookup procedure to determine the name of the
|
* instance, using the following ordered lookup procedure to determine
|
||||||
* implementation class to be loaded:</p>
|
* the name of the implementation class to be loaded:</p>
|
||||||
* <ul>
|
* <ul>
|
||||||
* <li>The <code>org.apache.commons.logging.LogFactory</code> system
|
* <li>The <code>org.apache.commons.logging.LogFactory</code> system
|
||||||
* property.</li>
|
* property.</li>
|
||||||
@@ -205,22 +245,29 @@ public abstract class LogFactory {
|
|||||||
* @exception LogConfigurationException if the implementation class is not
|
* @exception LogConfigurationException if the implementation class is not
|
||||||
* available or cannot be instantiated.
|
* available or cannot be instantiated.
|
||||||
*/
|
*/
|
||||||
public static LogFactory newFactory() throws LogConfigurationException {
|
public static LogFactory getFactory() throws LogConfigurationException {
|
||||||
|
|
||||||
// Identify the class loader we will be using
|
// Identify the class loader we will be using
|
||||||
ClassLoader classLoader = findClassLoader();
|
ClassLoader classLoader = findClassLoader();
|
||||||
|
|
||||||
|
// Return any previously registered factory for this class loader
|
||||||
|
LogFactory factory = (LogFactory) factories.get(classLoader);
|
||||||
|
if (factory != null) {
|
||||||
|
return (factory);
|
||||||
|
}
|
||||||
|
|
||||||
// First, try the system property
|
// First, try the system property
|
||||||
try {
|
try {
|
||||||
String factoryClass = System.getProperty(FACTORY_PROPERTY);
|
String factoryClass = System.getProperty(FACTORY_PROPERTY);
|
||||||
if (factoryClass != null) {
|
if (factoryClass != null) {
|
||||||
return (newInstance(factoryClass, classLoader));
|
factory = newFactory(factoryClass, classLoader);
|
||||||
}
|
}
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
;
|
;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Second, try a properties file
|
// Second, try a properties file
|
||||||
|
if (factory == null) {
|
||||||
try {
|
try {
|
||||||
InputStream stream =
|
InputStream stream =
|
||||||
classLoader.getResourceAsStream(FACTORY_PROPERTIES);
|
classLoader.getResourceAsStream(FACTORY_PROPERTIES);
|
||||||
@@ -230,23 +277,86 @@ public abstract class LogFactory {
|
|||||||
stream.close();
|
stream.close();
|
||||||
String factoryClass = props.getProperty(FACTORY_PROPERTY);
|
String factoryClass = props.getProperty(FACTORY_PROPERTY);
|
||||||
if (factoryClass != null) {
|
if (factoryClass != null) {
|
||||||
LogFactory instance =
|
factory = newFactory(factoryClass, classLoader);
|
||||||
newInstance(factoryClass, classLoader);
|
|
||||||
Enumeration names = props.propertyNames();
|
Enumeration names = props.propertyNames();
|
||||||
while (names.hasMoreElements()) {
|
while (names.hasMoreElements()) {
|
||||||
String name = (String) names.nextElement();
|
String name = (String) names.nextElement();
|
||||||
String value = props.getProperty(name);
|
String value = props.getProperty(name);
|
||||||
instance.setAttribute(name, value);
|
factory.setAttribute(name, value);
|
||||||
}
|
}
|
||||||
return (instance);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException e) {
|
} catch (IOException e) {
|
||||||
} catch (SecurityException e) {
|
} catch (SecurityException e) {
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// Third, try the fallback implementation class
|
// Third, try the fallback implementation class
|
||||||
return (newInstance(FACTORY_DEFAULT, classLoader));
|
if (factory == null) {
|
||||||
|
factory = newFactory(FACTORY_DEFAULT, classLoader);
|
||||||
|
}
|
||||||
|
|
||||||
|
// Cache and return the new factory instance
|
||||||
|
factories.put(classLoader, factory);
|
||||||
|
return (factory);
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Convenience method to return a named logger, without the application
|
||||||
|
* having to care about factories.
|
||||||
|
*
|
||||||
|
* @param clazz Class for 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, after calling the instance method <code>release()</code> on
|
||||||
|
* each of them. This is useful 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();
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -308,7 +418,7 @@ public abstract class LogFactory {
|
|||||||
* @exception LogConfigurationException if a suitable instance
|
* @exception LogConfigurationException if a suitable instance
|
||||||
* cannot be created
|
* cannot be created
|
||||||
*/
|
*/
|
||||||
private static LogFactory newInstance(String factoryClass,
|
protected static LogFactory newFactory(String factoryClass,
|
||||||
ClassLoader classLoader)
|
ClassLoader classLoader)
|
||||||
throws LogConfigurationException {
|
throws LogConfigurationException {
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//logging/src/java/org/apache/commons/logging/LogSource.java,v 1.12 2002/02/03 01:31:54 sanders Exp $
|
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//logging/src/java/org/apache/commons/logging/LogSource.java,v 1.13 2002/02/14 00:19:03 craigmcc Exp $
|
||||||
* $Revision: 1.12 $
|
* $Revision: 1.13 $
|
||||||
* $Date: 2002/02/03 01:31:54 $
|
* $Date: 2002/02/14 00:19:03 $
|
||||||
*
|
*
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*
|
*
|
||||||
@@ -93,8 +93,11 @@ import org.apache.commons.logging.impl.NoOpLog;
|
|||||||
* <li>At runtime, call <code>LogSource.setLogImplementation()</code>.</li>
|
* <li>At runtime, call <code>LogSource.setLogImplementation()</code>.</li>
|
||||||
* </ul>
|
* </ul>
|
||||||
*
|
*
|
||||||
|
* @deprecated Use {@link LogFactory} instead - The default factory
|
||||||
|
* implementation performs exactly the same algorithm as this class did
|
||||||
|
*
|
||||||
* @author Rod Waldhoff
|
* @author Rod Waldhoff
|
||||||
* @version $Id: LogSource.java,v 1.12 2002/02/03 01:31:54 sanders Exp $
|
* @version $Id: LogSource.java,v 1.13 2002/02/14 00:19:03 craigmcc Exp $
|
||||||
*/
|
*/
|
||||||
public class LogSource {
|
public class LogSource {
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
/*
|
/*
|
||||||
* $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 $
|
* $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//logging/src/java/org/apache/commons/logging/impl/LogFactoryImpl.java,v 1.2 2002/02/14 00:19:03 craigmcc Exp $
|
||||||
* $Revision: 1.1 $
|
* $Revision: 1.2 $
|
||||||
* $Date: 2002/02/13 02:18:11 $
|
* $Date: 2002/02/14 00:19:03 $
|
||||||
*
|
*
|
||||||
* ====================================================================
|
* ====================================================================
|
||||||
*
|
*
|
||||||
@@ -101,7 +101,7 @@ import org.apache.commons.logging.LogSource;
|
|||||||
*
|
*
|
||||||
* @author Rod Waldhoff
|
* @author Rod Waldhoff
|
||||||
* @author Craig R. McClanahan
|
* @author Craig R. McClanahan
|
||||||
* @version $Revision: 1.1 $ $Date: 2002/02/13 02:18:11 $
|
* @version $Revision: 1.2 $ $Date: 2002/02/14 00:19:03 $
|
||||||
*/
|
*/
|
||||||
|
|
||||||
public class LogFactoryImpl extends LogFactory {
|
public class LogFactoryImpl extends LogFactory {
|
||||||
@@ -228,10 +228,33 @@ public class LogFactoryImpl extends LogFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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 Log getInstance(Class clazz)
|
||||||
|
throws LogConfigurationException {
|
||||||
|
|
||||||
|
return (getInstance(clazz.getName()));
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* <p>Construct (if necessary) and return a <code>Log</code> instance,
|
* <p>Construct (if necessary) and return a <code>Log</code> instance,
|
||||||
* using the factory's current set of configuration attributes.</p>
|
* 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
|
* @param name Logical name of the <code>Log</code> instance to be
|
||||||
* returned (the meaning of this name is only known to the underlying
|
* returned (the meaning of this name is only known to the underlying
|
||||||
* logging implementation that is being wrapped)
|
* logging implementation that is being wrapped)
|
||||||
@@ -252,6 +275,20 @@ public class LogFactoryImpl extends LogFactory {
|
|||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Release any internal references to previously created {@link Log}
|
||||||
|
* instances returned by this factory. This is useful 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 void release() {
|
||||||
|
|
||||||
|
instances.clear();
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Remove any configuration attribute associated with the specified name.
|
* Remove any configuration attribute associated with the specified name.
|
||||||
* If there is no such attribute, no action is taken.
|
* If there is no such attribute, no action is taken.
|
||||||
|
|||||||
Reference in New Issue
Block a user