Fields Summary |
---|
private static final String | LOGGING_IMPL_LOG4J_LOGGERLog4JLogger class name |
private static final String | LOGGING_IMPL_JDK14_LOGGERJdk14Logger class name |
private static final String | LOGGING_IMPL_LUMBERJACK_LOGGERJdk13LumberjackLogger class name |
private static final String | LOGGING_IMPL_SIMPLE_LOGGERSimpleLog class name |
private static final String | PKG_IMPL |
private static final int | PKG_LEN |
public static final String | LOG_PROPERTYThe name (org.apache.commons.logging.Log ) of the system
property identifying our {@link Log} implementation class. |
protected static final String | LOG_PROPERTY_OLDThe deprecated system property used for backwards compatibility with
old versions of JCL. |
public static final String | ALLOW_FLAWED_CONTEXT_PROPERTYThe name (org.apache.commons.logging.Log.allowFlawedContext )
of the system property which can be set true/false to
determine system behaviour when a bad context-classloader is encountered.
When set to false, a LogConfigurationException is thrown if
LogFactoryImpl is loaded via a child classloader of the TCCL (this
should never happen in sane systems).
Default behaviour: true (tolerates bad context classloaders)
See also method setAttribute. |
public static final String | ALLOW_FLAWED_DISCOVERY_PROPERTYThe name (org.apache.commons.logging.Log.allowFlawedDiscovery )
of the system property which can be set true/false to
determine system behaviour when a bad logging adapter class is
encountered during logging discovery. When set to false, an
exception will be thrown and the app will fail to start. When set
to true, discovery will continue (though the user might end up
with a different logging implementation than they expected).
Default behaviour: true (tolerates bad logging adapters)
See also method setAttribute. |
public static final String | ALLOW_FLAWED_HIERARCHY_PROPERTYThe name (org.apache.commons.logging.Log.allowFlawedHierarchy )
of the system property which can be set true/false to
determine system behaviour when a logging adapter class is
encountered which has bound to the wrong Log class implementation.
When set to false, an exception will be thrown and the app will fail
to start. When set to true, discovery will continue (though the user
might end up with a different logging implementation than they expected).
Default behaviour: true (tolerates bad Log class hierarchy)
See also method setAttribute. |
private static final String[] | classesToDiscoverThe names of classes that will be tried (in order) as logging
adapters. Each class is expected to implement the Log interface,
and to throw NoClassDefFound or ExceptionInInitializerError when
loaded if the underlying logging library is not available. Any
other error indicates that the underlying logging library is available
but broken/unusable for some reason. |
private boolean | useTCCLDetermines whether logging classes should be loaded using the thread-context
classloader, or via the classloader that loaded this LogFactoryImpl class. |
private String | diagnosticPrefixThe string prefixed to every message output by the logDiagnostic method. |
protected Hashtable | attributesConfiguration attributes. |
protected Hashtable | instancesThe {@link org.apache.commons.logging.Log} instances that have
already been created, keyed by logger name. |
private String | logClassNameName of the class implementing the Log interface. |
protected Constructor | logConstructorThe one-argument constructor of the
{@link org.apache.commons.logging.Log}
implementation class that will be used to create new instances.
This value is initialized by getLogConstructor() ,
and then returned repeatedly. |
protected Class[] | logConstructorSignatureThe signature of the Constructor to be used. |
protected Method | logMethodThe one-argument setLogFactory method of the selected
{@link org.apache.commons.logging.Log} method, if it exists. |
protected Class[] | logMethodSignatureThe signature of the setLogFactory method to be used. |
private boolean | allowFlawedContextSee getBaseClassLoader and initConfiguration. |
private boolean | allowFlawedDiscoverySee handleFlawedDiscovery and initConfiguration. |
private boolean | allowFlawedHierarchySee handleFlawedHierarchy and initConfiguration. |
Methods Summary |
---|
private org.apache.commons.logging.Log | createLogFromClass(java.lang.String logAdapterClassName, java.lang.String logCategory, boolean affectState)Attempts to load the given class, find a suitable constructor,
and instantiate an instance of Log.
if (isDiagnosticsEnabled()) {
logDiagnostic("Attempting to instantiate '" + logAdapterClassName + "'");
}
Object[] params = { logCategory };
Log logAdapter = null;
Constructor constructor = null;
Class logAdapterClass = null;
ClassLoader currentCL = getBaseClassLoader();
for(;;) {
// Loop through the classloader hierarchy trying to find
// a viable classloader.
logDiagnostic(
"Trying to load '"
+ logAdapterClassName
+ "' from classloader "
+ objectId(currentCL));
try {
if (isDiagnosticsEnabled()) {
// Show the location of the first occurrence of the .class file
// in the classpath. This is the location that ClassLoader.loadClass
// will load the class from -- unless the classloader is doing
// something weird.
URL url;
String resourceName = logAdapterClassName.replace('.", '/") + ".class";
if (currentCL != null) {
url = currentCL.getResource(resourceName );
} else {
url = ClassLoader.getSystemResource(resourceName + ".class");
}
if (url == null) {
logDiagnostic("Class '" + logAdapterClassName + "' [" + resourceName + "] cannot be found.");
} else {
logDiagnostic("Class '" + logAdapterClassName + "' was found at '" + url + "'");
}
}
Class c = null;
try {
c = Class.forName(logAdapterClassName, true, currentCL);
} catch (ClassNotFoundException originalClassNotFoundException) {
// The current classloader was unable to find the log adapter
// in this or any ancestor classloader. There's no point in
// trying higher up in the hierarchy in this case..
String msg = "" + originalClassNotFoundException.getMessage();
logDiagnostic(
"The log adapter '"
+ logAdapterClassName
+ "' is not available via classloader "
+ objectId(currentCL)
+ ": "
+ msg.trim());
try {
// Try the class classloader.
// This may work in cases where the TCCL
// does not contain the code executed or JCL.
// This behaviour indicates that the application
// classloading strategy is not consistent with the
// Java 1.2 classloading guidelines but JCL can
// and so should handle this case.
c = Class.forName(logAdapterClassName);
} catch (ClassNotFoundException secondaryClassNotFoundException) {
// no point continuing: this adapter isn't available
msg = "" + secondaryClassNotFoundException.getMessage();
logDiagnostic(
"The log adapter '"
+ logAdapterClassName
+ "' is not available via the LogFactoryImpl class classloader: "
+ msg.trim());
break;
}
}
constructor = c.getConstructor(logConstructorSignature);
Object o = constructor.newInstance(params);
// Note that we do this test after trying to create an instance
// [rather than testing Log.class.isAssignableFrom(c)] so that
// we don't complain about Log hierarchy problems when the
// adapter couldn't be instantiated anyway.
if (o instanceof Log) {
logAdapterClass = c;
logAdapter = (Log) o;
break;
}
// Oops, we have a potential problem here. An adapter class
// has been found and its underlying lib is present too, but
// there are multiple Log interface classes available making it
// impossible to cast to the type the caller wanted. We
// certainly can't use this logger, but we need to know whether
// to keep on discovering or terminate now.
//
// The handleFlawedHierarchy method will throw
// LogConfigurationException if it regards this problem as
// fatal, and just return if not.
handleFlawedHierarchy(currentCL, c);
} catch (NoClassDefFoundError e) {
// We were able to load the adapter but it had references to
// other classes that could not be found. This simply means that
// the underlying logger library is not present in this or any
// ancestor classloader. There's no point in trying higher up
// in the hierarchy in this case..
String msg = "" + e.getMessage();
logDiagnostic(
"The log adapter '"
+ logAdapterClassName
+ "' is missing dependencies when loaded via classloader "
+ objectId(currentCL)
+ ": "
+ msg.trim());
break;
} catch (ExceptionInInitializerError e) {
// A static initializer block or the initializer code associated
// with a static variable on the log adapter class has thrown
// an exception.
//
// We treat this as meaning the adapter's underlying logging
// library could not be found.
String msg = "" + e.getMessage();
logDiagnostic(
"The log adapter '"
+ logAdapterClassName
+ "' is unable to initialize itself when loaded via classloader "
+ objectId(currentCL)
+ ": "
+ msg.trim());
break;
} catch(LogConfigurationException e) {
// call to handleFlawedHierarchy above must have thrown
// a LogConfigurationException, so just throw it on
throw e;
} catch(Throwable t) {
// handleFlawedDiscovery will determine whether this is a fatal
// problem or not. If it is fatal, then a LogConfigurationException
// will be thrown.
handleFlawedDiscovery(logAdapterClassName, currentCL, t);
}
if (currentCL == null) {
break;
}
// try the parent classloader
currentCL = currentCL.getParent();
}
if ((logAdapter != null) && affectState) {
// We've succeeded, so set instance fields
this.logClassName = logAdapterClassName;
this.logConstructor = constructor;
// Identify the <code>setLogFactory</code> method (if there is one)
try {
this.logMethod = logAdapterClass.getMethod("setLogFactory",
logMethodSignature);
logDiagnostic("Found method setLogFactory(LogFactory) in '"
+ logAdapterClassName + "'");
} catch (Throwable t) {
this.logMethod = null;
logDiagnostic(
"[INFO] '" + logAdapterClassName
+ "' from classloader " + objectId(currentCL)
+ " does not declare optional method "
+ "setLogFactory(LogFactory)");
}
logDiagnostic(
"Log adapter '" + logAdapterClassName
+ "' from classloader " + objectId(logAdapterClass.getClassLoader())
+ " has been selected for use.");
}
return logAdapter;
|
private org.apache.commons.logging.Log | discoverLogImplementation(java.lang.String logCategory)Attempts to create a Log instance for the given category name.
Follows the discovery process described in the class javadoc.
if (isDiagnosticsEnabled()) {
logDiagnostic("Discovering a Log implementation...");
}
initConfiguration();
Log result = null;
// See if the user specified the Log implementation to use
String specifiedLogClassName = findUserSpecifiedLogClassName();
if (specifiedLogClassName != null) {
if (isDiagnosticsEnabled()) {
logDiagnostic("Attempting to load user-specified log class '" +
specifiedLogClassName + "'...");
}
result = createLogFromClass(specifiedLogClassName,
logCategory,
true);
if (result == null) {
StringBuffer messageBuffer = new StringBuffer("User-specified log class '");
messageBuffer.append(specifiedLogClassName);
messageBuffer.append("' cannot be found or is not useable.");
// Mistyping or misspelling names is a common fault.
// Construct a good error message, if we can
if (specifiedLogClassName != null) {
informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LOG4J_LOGGER);
informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_JDK14_LOGGER);
informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_LUMBERJACK_LOGGER);
informUponSimilarName(messageBuffer, specifiedLogClassName, LOGGING_IMPL_SIMPLE_LOGGER);
}
throw new LogConfigurationException(messageBuffer.toString());
}
return result;
}
// No user specified log; try to discover what's on the classpath
//
// Note that we deliberately loop here over classesToDiscover and
// expect method createLogFromClass to loop over the possible source
// classloaders. The effect is:
// for each discoverable log adapter
// for each possible classloader
// see if it works
//
// It appears reasonable at first glance to do the opposite:
// for each possible classloader
// for each discoverable log adapter
// see if it works
//
// The latter certainly has advantages for user-installable logging
// libraries such as log4j; in a webapp for example this code should
// first check whether the user has provided any of the possible
// logging libraries before looking in the parent classloader.
// Unfortunately, however, Jdk14Logger will always work in jvm>=1.4,
// and SimpleLog will always work in any JVM. So the loop would never
// ever look for logging libraries in the parent classpath. Yet many
// users would expect that putting log4j there would cause it to be
// detected (and this is the historical JCL behaviour). So we go with
// the first approach. A user that has bundled a specific logging lib
// in a webapp should use a commons-logging.properties file or a
// service file in META-INF to force use of that logging lib anyway,
// rather than relying on discovery.
if (isDiagnosticsEnabled()) {
logDiagnostic(
"No user-specified Log implementation; performing discovery" +
" using the standard supported logging implementations...");
}
for(int i=0; (i<classesToDiscover.length) && (result == null); ++i) {
result = createLogFromClass(classesToDiscover[i], logCategory, true);
}
if (result == null) {
throw new LogConfigurationException
("No suitable Log implementation");
}
return result;
|
private java.lang.String | findUserSpecifiedLogClassName()Checks system properties and the attribute map for
a Log implementation specified by the user under the
property names {@link #LOG_PROPERTY} or {@link #LOG_PROPERTY_OLD}.
if (isDiagnosticsEnabled()) {
logDiagnostic("Trying to get log class from attribute '" + LOG_PROPERTY + "'");
}
String specifiedClass = (String) getAttribute(LOG_PROPERTY);
if (specifiedClass == null) { // @deprecated
if (isDiagnosticsEnabled()) {
logDiagnostic("Trying to get log class from attribute '" +
LOG_PROPERTY_OLD + "'");
}
specifiedClass = (String) getAttribute(LOG_PROPERTY_OLD);
}
if (specifiedClass == null) {
if (isDiagnosticsEnabled()) {
logDiagnostic("Trying to get log class from system property '" +
LOG_PROPERTY + "'");
}
try {
specifiedClass = System.getProperty(LOG_PROPERTY);
} catch (SecurityException e) {
if (isDiagnosticsEnabled()) {
logDiagnostic("No access allowed to system property '" +
LOG_PROPERTY + "' - " + e.getMessage());
}
}
}
if (specifiedClass == null) { // @deprecated
if (isDiagnosticsEnabled()) {
logDiagnostic("Trying to get log class from system property '" +
LOG_PROPERTY_OLD + "'");
}
try {
specifiedClass = System.getProperty(LOG_PROPERTY_OLD);
} catch (SecurityException e) {
if (isDiagnosticsEnabled()) {
logDiagnostic("No access allowed to system property '" +
LOG_PROPERTY_OLD + "' - " + e.getMessage());
}
}
}
// Remove any whitespace; it's never valid in a classname so its
// presence just means a user mistake. As we know what they meant,
// we may as well strip the spaces.
if (specifiedClass != null) {
specifiedClass = specifiedClass.trim();
}
return specifiedClass;
|
public java.lang.Object | getAttribute(java.lang.String name)Return the configuration attribute with the specified name (if any),
or null if there is no such attribute.
// --------------------------------------------------------- Public Methods
return (attributes.get(name));
|
public java.lang.String[] | getAttributeNames()Return an array containing the names of all currently defined
configuration attributes. If there are no such attributes, a zero
length array is returned.
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);
|
private java.lang.ClassLoader | getBaseClassLoader()Return the classloader from which we should try to load the logging
adapter classes.
This method usually returns the context classloader. However if it
is discovered that the classloader which loaded this class is a child
of the context classloader and the allowFlawedContext option
has been set then the classloader which loaded this class is returned
instead.
The only time when the classloader which loaded this class is a
descendant (rather than the same as or an ancestor of the context
classloader) is when an app has created custom classloaders but
failed to correctly set the context classloader. This is a bug in
the calling application; however we provide the option for JCL to
simply generate a warning rather than fail outright.
ClassLoader thisClassLoader = getClassLoader(LogFactoryImpl.class);
if (useTCCL == false) {
return thisClassLoader;
}
ClassLoader contextClassLoader = getContextClassLoader();
ClassLoader baseClassLoader = getLowestClassLoader(
contextClassLoader, thisClassLoader);
if (baseClassLoader == null) {
// The two classloaders are not part of a parent child relationship.
// In some classloading setups (e.g. JBoss with its
// UnifiedLoaderRepository) this can still work, so if user hasn't
// forbidden it, just return the contextClassLoader.
if (allowFlawedContext) {
if (isDiagnosticsEnabled()) {
logDiagnostic(
"[WARNING] the context classloader is not part of a"
+ " parent-child relationship with the classloader that"
+ " loaded LogFactoryImpl.");
}
// If contextClassLoader were null, getLowestClassLoader() would
// have returned thisClassLoader. The fact we are here means
// contextClassLoader is not null, so we can just return it.
return contextClassLoader;
}
else {
throw new LogConfigurationException(
"Bad classloader hierarchy; LogFactoryImpl was loaded via"
+ " a classloader that is not related to the current context"
+ " classloader.");
}
}
if (baseClassLoader != contextClassLoader) {
// We really should just use the contextClassLoader as the starting
// point for scanning for log adapter classes. However it is expected
// that there are a number of broken systems out there which create
// custom classloaders but fail to set the context classloader so
// we handle those flawed systems anyway.
if (allowFlawedContext) {
if (isDiagnosticsEnabled()) {
logDiagnostic(
"Warning: the context classloader is an ancestor of the"
+ " classloader that loaded LogFactoryImpl; it should be"
+ " the same or a descendant. The application using"
+ " commons-logging should ensure the context classloader"
+ " is used correctly.");
}
} else {
throw new LogConfigurationException(
"Bad classloader hierarchy; LogFactoryImpl was loaded via"
+ " a classloader that is not related to the current context"
+ " classloader.");
}
}
return baseClassLoader;
|
private boolean | getBooleanConfiguration(java.lang.String key, boolean dflt)Get the setting for the user-configurable behaviour specified by key.
If nothing has explicitly been set, then return dflt.
String val = getConfigurationValue(key);
if (val == null)
return dflt;
return Boolean.valueOf(val).booleanValue();
|
protected static java.lang.ClassLoader | getClassLoader(java.lang.Class clazz)Workaround for bug in Java1.2; in theory this method is not needed.
See LogFactory.getClassLoader.
return LogFactory.getClassLoader(clazz);
|
private java.lang.String | getConfigurationValue(java.lang.String property)Attempt to find an attribute (see method setAttribute) or a
system property with the provided name and return its value.
The attributes associated with this object are checked before
system properties in case someone has explicitly called setAttribute,
or a configuration property has been set in a commons-logging.properties
file.
if (isDiagnosticsEnabled()) {
logDiagnostic("[ENV] Trying to get configuration for item " + property);
}
Object valueObj = getAttribute(property);
if (valueObj != null) {
if (isDiagnosticsEnabled()) {
logDiagnostic("[ENV] Found LogFactory attribute [" + valueObj + "] for " + property);
}
return valueObj.toString();
}
if (isDiagnosticsEnabled()) {
logDiagnostic("[ENV] No LogFactory attribute found for " + property);
}
try {
String value = System.getProperty(property);
if (value != null) {
if (isDiagnosticsEnabled()) {
logDiagnostic("[ENV] Found system property [" + value + "] for " + property);
}
return value;
}
if (isDiagnosticsEnabled()) {
logDiagnostic("[ENV] No system property found for property " + property);
}
} catch (SecurityException e) {
if (isDiagnosticsEnabled()) {
logDiagnostic("[ENV] Security prevented reading system property " + property);
}
}
if (isDiagnosticsEnabled()) {
logDiagnostic("[ENV] No configuration defined for item " + property);
}
return null;
|
protected static java.lang.ClassLoader | getContextClassLoader()Gets the context classloader.
This method is a workaround for a java 1.2 compiler bug.
return LogFactory.getContextClassLoader();
|
public org.apache.commons.logging.Log | getInstance(java.lang.Class clazz)Convenience method to derive a name from the specified class and
call getInstance(String) with it.
return (getInstance(clazz.getName()));
|
public org.apache.commons.logging.Log | getInstance(java.lang.String name)Construct (if necessary) and return a Log instance,
using the factory's current set of configuration attributes.
NOTE - Depending upon the implementation of
the LogFactory you are using, the Log
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.
Log instance = (Log) instances.get(name);
if (instance == null) {
instance = newInstance(name);
instances.put(name, instance);
}
return (instance);
|
protected java.lang.String | getLogClassName()Return the fully qualified Java classname of the {@link Log}
implementation we will be using.
if (logClassName == null) {
discoverLogImplementation(getClass().getName());
}
return logClassName;
|
protected java.lang.reflect.Constructor | getLogConstructor()Return the Constructor that can be called to instantiate
new {@link org.apache.commons.logging.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.
// Return the previously identified Constructor (if any)
if (logConstructor == null) {
discoverLogImplementation(getClass().getName());
}
return logConstructor;
|
private java.lang.ClassLoader | getLowestClassLoader(java.lang.ClassLoader c1, java.lang.ClassLoader c2)Given two related classloaders, return the one which is a child of
the other.
// TODO: use AccessController when dealing with classloaders here
if (c1 == null)
return c2;
if (c2 == null)
return c1;
ClassLoader current;
// scan c1's ancestors to find c2
current = c1;
while (current != null) {
if (current == c2)
return c1;
current = current.getParent();
}
// scan c2's ancestors to find c1
current = c2;
while (current != null) {
if (current == c1)
return c2;
current = current.getParent();
}
return null;
|
private void | handleFlawedDiscovery(java.lang.String logAdapterClassName, java.lang.ClassLoader classLoader, java.lang.Throwable discoveryFlaw)Generates an internal diagnostic logging of the discovery failure and
then throws a LogConfigurationException that wraps
the passed Throwable .
if (isDiagnosticsEnabled()) {
logDiagnostic("Could not instantiate Log '"
+ logAdapterClassName + "' -- "
+ discoveryFlaw.getClass().getName() + ": "
+ discoveryFlaw.getLocalizedMessage());
}
if (!allowFlawedDiscovery) {
throw new LogConfigurationException(discoveryFlaw);
}
|
private void | handleFlawedHierarchy(java.lang.ClassLoader badClassLoader, java.lang.Class badClass)Report a problem loading the log adapter, then either return
(if the situation is considered recoverable) or throw a
LogConfigurationException.
There are two possible reasons why we successfully loaded the
specified log adapter class then failed to cast it to a Log object:
- the specific class just doesn't implement the Log interface
(user screwed up), or
- the specified class has bound to a Log class loaded by some other
classloader; Log@classloaderX cannot be cast to Log@classloaderY.
Here we try to figure out which case has occurred so we can give the
user some reasonable feedback.
boolean implementsLog = false;
String logInterfaceName = Log.class.getName();
Class interfaces[] = badClass.getInterfaces();
for (int i = 0; i < interfaces.length; i++) {
if (logInterfaceName.equals(interfaces[i].getName())) {
implementsLog = true;
break;
}
}
if (implementsLog) {
// the class does implement an interface called Log, but
// it is in the wrong classloader
if (isDiagnosticsEnabled()) {
try {
ClassLoader logInterfaceClassLoader = getClassLoader(Log.class);
logDiagnostic(
"Class '" + badClass.getName()
+ "' was found in classloader "
+ objectId(badClassLoader)
+ ". It is bound to a Log interface which is not"
+ " the one loaded from classloader "
+ objectId(logInterfaceClassLoader));
} catch (Throwable t) {
logDiagnostic(
"Error while trying to output diagnostics about"
+ " bad class '" + badClass + "'");
}
}
if (!allowFlawedHierarchy) {
StringBuffer msg = new StringBuffer();
msg.append("Terminating logging for this context ");
msg.append("due to bad log hierarchy. ");
msg.append("You have more than one version of '");
msg.append(Log.class.getName());
msg.append("' visible.");
if (isDiagnosticsEnabled()) {
logDiagnostic(msg.toString());
}
throw new LogConfigurationException(msg.toString());
}
if (isDiagnosticsEnabled()) {
StringBuffer msg = new StringBuffer();
msg.append("Warning: bad log hierarchy. ");
msg.append("You have more than one version of '");
msg.append(Log.class.getName());
msg.append("' visible.");
logDiagnostic(msg.toString());
}
} else {
// this is just a bad adapter class
if (!allowFlawedDiscovery) {
StringBuffer msg = new StringBuffer();
msg.append("Terminating logging for this context. ");
msg.append("Log class '");
msg.append(badClass.getName());
msg.append("' does not implement the Log interface.");
if (isDiagnosticsEnabled()) {
logDiagnostic(msg.toString());
}
throw new LogConfigurationException(msg.toString());
}
if (isDiagnosticsEnabled()) {
StringBuffer msg = new StringBuffer();
msg.append("[WARNING] Log class '");
msg.append(badClass.getName());
msg.append("' does not implement the Log interface.");
logDiagnostic(msg.toString());
}
}
|
private void | informUponSimilarName(java.lang.StringBuffer messageBuffer, java.lang.String name, java.lang.String candidate)Appends message if the given name is similar to the candidate.
if (name.equals(candidate)) {
// Don't suggest a name that is exactly the same as the one the
// user tried...
return;
}
// If the user provides a name that is in the right package, and gets
// the first 5 characters of the adapter class right (ignoring case),
// then suggest the candidate adapter class name.
if (name.regionMatches(true, 0, candidate, 0, PKG_LEN + 5)) {
messageBuffer.append(" Did you mean '");
messageBuffer.append(candidate);
messageBuffer.append("'?");
}
|
private void | initConfiguration()Initialize a number of variables that control the behaviour of this
class and that can be tweaked by the user. This is done when the first
logger is created, not in the constructor of this class, because we
need to give the user a chance to call method setAttribute in order to
configure this object.
allowFlawedContext = getBooleanConfiguration(ALLOW_FLAWED_CONTEXT_PROPERTY, true);
allowFlawedDiscovery = getBooleanConfiguration(ALLOW_FLAWED_DISCOVERY_PROPERTY, true);
allowFlawedHierarchy = getBooleanConfiguration(ALLOW_FLAWED_HIERARCHY_PROPERTY, true);
|
private void | initDiagnostics()Calculate and cache a string that uniquely identifies this instance,
including which classloader the object was loaded from.
This string will later be prefixed to each "internal logging" message
emitted, so that users can clearly see any unexpected behaviour.
Note that this method does not detect whether internal logging is
enabled or not, nor where to output stuff if it is; that is all
handled by the parent LogFactory class. This method just computes
its own unique prefix for log messages.
// It would be nice to include an identifier of the context classloader
// that this LogFactoryImpl object is responsible for. However that
// isn't possible as that information isn't available. It is possible
// to figure this out by looking at the logging from LogFactory to
// see the context & impl ids from when this object was instantiated,
// in order to link the impl id output as this object's prefix back to
// the context it is intended to manage.
// Note that this prefix should be kept consistent with that
// in LogFactory.
Class clazz = this.getClass();
ClassLoader classLoader = getClassLoader(clazz);
String classLoaderName;
try {
if (classLoader == null) {
classLoaderName = "BOOTLOADER";
} else {
classLoaderName = objectId(classLoader);
}
} catch(SecurityException e) {
classLoaderName = "UNKNOWN";
}
diagnosticPrefix = "[LogFactoryImpl@" + System.identityHashCode(this) + " from " + classLoaderName + "] ";
|
protected static boolean | isDiagnosticsEnabled()Workaround for bug in Java1.2; in theory this method is not needed.
See LogFactory.isDiagnosticsEnabled.
return LogFactory.isDiagnosticsEnabled();
|
protected boolean | isJdk13LumberjackAvailable()Is JDK 1.3 with Lumberjack logging available?
return isLogLibraryAvailable(
"Jdk13Lumberjack",
"org.apache.commons.logging.impl.Jdk13LumberjackLogger");
|
protected boolean | isJdk14Available()Return true if JDK 1.4 or later logging
is available. Also checks that the Throwable class
supports getStackTrace() , which is required by
Jdk14Logger.
return isLogLibraryAvailable(
"Jdk14",
"org.apache.commons.logging.impl.Jdk14Logger");
|
protected boolean | isLog4JAvailable()Is a Log4J implementation available?
return isLogLibraryAvailable(
"Log4J",
LOGGING_IMPL_LOG4J_LOGGER);
|
private boolean | isLogLibraryAvailable(java.lang.String name, java.lang.String classname)Utility method to check whether a particular logging library is
present and available for use. Note that this does not
affect the future behaviour of this class.
if (isDiagnosticsEnabled()) {
logDiagnostic("Checking for '" + name + "'.");
}
try {
Log log = createLogFromClass(
classname,
this.getClass().getName(), // dummy category
false);
if (log == null) {
if (isDiagnosticsEnabled()) {
logDiagnostic("Did not find '" + name + "'.");
}
return false;
} else {
if (isDiagnosticsEnabled()) {
logDiagnostic("Found '" + name + "'.");
}
return true;
}
} catch(LogConfigurationException e) {
if (isDiagnosticsEnabled()) {
logDiagnostic("Logging system '" + name + "' is available but not useable.");
}
return false;
}
|
protected void | logDiagnostic(java.lang.String msg)Output a diagnostic message to a user-specified destination (if the
user has enabled diagnostic logging).
if (isDiagnosticsEnabled()) {
logRawDiagnostic(diagnosticPrefix + msg);
}
|
protected org.apache.commons.logging.Log | newInstance(java.lang.String name)Create and return a new {@link org.apache.commons.logging.Log}
instance for the specified name.
Log instance = null;
try {
if (logConstructor == null) {
instance = discoverLogImplementation(name);
}
else {
Object params[] = { name };
instance = (Log) logConstructor.newInstance(params);
}
if (logMethod != null) {
Object params[] = { this };
logMethod.invoke(instance, params);
}
return (instance);
} catch (LogConfigurationException lce) {
// this type of exception means there was a problem in discovery
// and we've already output diagnostics about the issue, etc.;
// just pass it on
throw (LogConfigurationException) lce;
} catch (InvocationTargetException e) {
// A problem occurred invoking the Constructor or Method
// previously discovered
Throwable c = e.getTargetException();
if (c != null) {
throw new LogConfigurationException(c);
} else {
throw new LogConfigurationException(e);
}
} catch (Throwable t) {
// A problem occurred invoking the Constructor or Method
// previously discovered
throw new LogConfigurationException(t);
}
|
public void | release()Release any internal references to previously created
{@link org.apache.commons.logging.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.
logDiagnostic("Releasing all known loggers");
instances.clear();
|
public void | removeAttribute(java.lang.String name)Remove any configuration attribute associated with the specified name.
If there is no such attribute, no action is taken.
attributes.remove(name);
|
public void | setAttribute(java.lang.String name, java.lang.Object value)Set the configuration attribute with the specified name. Calling
this with a null value is equivalent to calling
removeAttribute(name) .
This method can be used to set logging configuration programmatically
rather than via system properties. It can also be used in code running
within a container (such as a webapp) to configure behaviour on a
per-component level instead of globally as system properties would do.
To use this method instead of a system property, call
LogFactory.getFactory().setAttribute(...)
This must be done before the first Log object is created; configuration
changes after that point will be ignored.
This method is also called automatically if LogFactory detects a
commons-logging.properties file; every entry in that file is set
automatically as an attribute here.
if (logConstructor != null) {
logDiagnostic("setAttribute: call too late; configuration already performed.");
}
if (value == null) {
attributes.remove(name);
} else {
attributes.put(name, value);
}
if (name.equals(TCCL_KEY)) {
useTCCL = Boolean.valueOf(value.toString()).booleanValue();
}
|