in src/main/java/org/apache/commons/logging/impl/LogFactoryImpl.java [323:481]
private Log createLogFromClass(final String logAdapterClassName,
final String logCategory,
final boolean affectState)
throws LogConfigurationException {
if (isDiagnosticsEnabled()) {
logDiagnostic("Attempting to instantiate '" + logAdapterClassName + "'");
}
final Object[] params = { logCategory };
Log logAdapter = null;
Constructor<?> constructor = null;
Class<?> logAdapterClass = null;
ClassLoader currentCL = getBaseClassLoader();
for(;;) {
// Loop through the class loader hierarchy trying to find
// a viable class loader.
logDiagnostic("Trying to load '" + logAdapterClassName + "' from class loader " + 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 class loader is doing
// something weird.
URL url;
final 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<?> clazz;
try {
clazz = Class.forName(logAdapterClassName, true, currentCL);
} catch (final ClassNotFoundException originalClassNotFoundException) {
// The current class loader was unable to find the log adapter
// in this or any ancestor class loader. 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 class loader " +
objectId(currentCL) + ": " + trim(msg));
try {
// Try the class class loader.
// This may work in cases where the TCCL
// does not contain the code executed or JCL.
// This behavior 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.
clazz = Class.forName(logAdapterClassName);
} catch (final 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 class loader: " + trim(msg));
break;
}
}
constructor = clazz.getConstructor(logConstructorSignature);
final 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 = clazz;
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, clazz);
} catch (final 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 class loader. There's no point in trying higher up
// in the hierarchy in this case.
final String msg = e.getMessage();
logDiagnostic("The log adapter '" + logAdapterClassName +
"' is missing dependencies when loaded via class loader " + objectId(currentCL) +
": " + trim(msg));
break;
} catch (final 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.
final String msg = e.getMessage();
logDiagnostic("The log adapter '" + logAdapterClassName +
"' is unable to initialize itself when loaded via class loader " + objectId(currentCL) +
": " + trim(msg));
break;
} catch (final LogConfigurationException e) {
// call to handleFlawedHierarchy above must have thrown
// a LogConfigurationException, so just throw it on
throw e;
} catch (final Throwable t) {
handleThrowable(t); // may re-throw t
// handleFlawedDiscovery will determine whether this is a fatal
// problem or not. If it is fatal, then a LogConfigurationException
// will be thrown.
handleFlawedDiscovery(logAdapterClassName, t);
}
if (currentCL == null) {
break;
}
// try the parent class loader
// currentCL = currentCL.getParent();
currentCL = getParentClassLoader(currentCL);
}
if (logAdapterClass != null && affectState) {
// We've succeeded, so set instance fields
this.logClassName = logAdapterClassName;
this.logConstructor = constructor;
// Identify the {@code setLogFactory} method (if there is one)
try {
this.logMethod = logAdapterClass.getMethod("setLogFactory", logMethodSignature);
logDiagnostic("Found method setLogFactory(LogFactory) in '" + logAdapterClassName + "'");
} catch (final Throwable t) {
handleThrowable(t); // may re-throw t
this.logMethod = null;
logDiagnostic("[INFO] '" + logAdapterClassName + "' from class loader " + objectId(currentCL) +
" does not declare optional method " + "setLogFactory(LogFactory)");
}
logDiagnostic("Log adapter '" + logAdapterClassName + "' from class loader " +
objectId(logAdapterClass.getClassLoader()) + " has been selected for use.");
}
return logAdapter;
}