📄 logfactory.java
字号:
// An incompatible ClassLoader was used to load the
// implementation.
// As the same classes
// must be available in multiple class loaders,
// it is very likely that multiple JCL jars are present.
// The most likely fix for this
// problem is to remove the extra JCL jars from the
// ClassLoader hierarchy.
//
if (isDiagnosticsEnabled()) {
logDiagnostic(
"Factory class " + logFactoryClass.getName()
+ " loaded from classloader " + objectId(logFactoryClass.getClassLoader())
+ " does not extend '" + LogFactory.class.getName()
+ "' as loaded by this classloader.");
logHierarchy("[BAD CL TREE] ", classLoader);
}
}
return (LogFactory) logFactoryClass.newInstance();
} catch (ClassNotFoundException ex) {
if (classLoader == thisClassLoader) {
// Nothing more to try, onwards.
if (isDiagnosticsEnabled()) {
logDiagnostic(
"Unable to locate any class called '" + factoryClass
+ "' via classloader " + objectId(classLoader));
}
throw ex;
}
// ignore exception, continue
} catch (NoClassDefFoundError e) {
if (classLoader == thisClassLoader) {
// Nothing more to try, onwards.
if (isDiagnosticsEnabled()) {
logDiagnostic(
"Class '" + factoryClass + "' cannot be loaded"
+ " via classloader " + objectId(classLoader)
+ " - it depends on some other class that cannot"
+ " be found.");
}
throw e;
}
// ignore exception, continue
} catch(ClassCastException e) {
if (classLoader == thisClassLoader) {
// There's no point in falling through to the code below that
// tries again with thisClassLoader, because we've just tried
// loading with that loader (not the TCCL). Just throw an
// appropriate exception here.
final boolean implementsLogFactory = implementsLogFactory(logFactoryClass);
//
// Construct a good message: users may not actual expect that a custom implementation
// has been specified. Several well known containers use this mechanism to adapt JCL
// to their native logging system.
//
String msg =
"The application has specified that a custom LogFactory implementation should be used but " +
"Class '" + factoryClass + "' cannot be converted to '"
+ LogFactory.class.getName() + "'. ";
if (implementsLogFactory) {
msg = msg + "The conflict is caused by the presence of multiple LogFactory classes in incompatible classloaders. " +
"Background can be found in http://commons.apache.org/logging/tech.html. " +
"If you have not explicitly specified a custom LogFactory then it is likely that " +
"the container has set one without your knowledge. " +
"In this case, consider using the commons-logging-adapters.jar file or " +
"specifying the standard LogFactory from the command line. ";
} else {
msg = msg + "Please check the custom implementation. ";
}
msg = msg + "Help can be found @http://commons.apache.org/logging/troubleshooting.html.";
if (isDiagnosticsEnabled()) {
logDiagnostic(msg);
}
ClassCastException ex = new ClassCastException(msg);
throw ex;
}
// Ignore exception, continue. Presumably the classloader was the
// TCCL; the code below will try to load the class via thisClassLoader.
// This will handle the case where the original calling class is in
// a shared classpath but the TCCL has a copy of LogFactory and the
// specified LogFactory implementation; we will fall back to using the
// LogFactory implementation from the same classloader as this class.
//
// Issue: this doesn't handle the reverse case, where this LogFactory
// is in the webapp, and the specified LogFactory implementation is
// in a shared classpath. In that case:
// (a) the class really does implement LogFactory (bad log msg above)
// (b) the fallback code will result in exactly the same problem.
}
}
/* At this point, either classLoader == null, OR
* classLoader was unable to load factoryClass.
*
* In either case, we call Class.forName, which is equivalent
* to LogFactory.class.getClassLoader().load(name), ie we ignore
* the classloader parameter the caller passed, and fall back
* to trying the classloader associated with this class. See the
* javadoc for the newFactory method for more info on the
* consequences of this.
*
* Notes:
* * LogFactory.class.getClassLoader() may return 'null'
* if LogFactory is loaded by the bootstrap classloader.
*/
// Warning: must typecast here & allow exception
// to be generated/caught & recast properly.
if (isDiagnosticsEnabled()) {
logDiagnostic(
"Unable to load factory class via classloader "
+ objectId(classLoader)
+ " - trying the classloader associated with this LogFactory.");
}
logFactoryClass = Class.forName(factoryClass);
return (LogFactory) logFactoryClass.newInstance();
} catch (Exception e) {
// Check to see if we've got a bad configuration
if (isDiagnosticsEnabled()) {
logDiagnostic("Unable to create LogFactory instance.");
}
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);
}
}
/**
* Determines whether the given class actually implements <code>LogFactory</code>.
* Diagnostic information is also logged.
* <p>
* <strong>Usage:</strong> to diagnose whether a classloader conflict is the cause
* of incompatibility. The test used is whether the class is assignable from
* the <code>LogFactory</code> class loaded by the class's classloader.
* @param logFactoryClass <code>Class</code> which may implement <code>LogFactory</code>
* @return true if the <code>logFactoryClass</code> does extend
* <code>LogFactory</code> when that class is loaded via the same
* classloader that loaded the <code>logFactoryClass</code>.
*/
private static boolean implementsLogFactory(Class logFactoryClass) {
boolean implementsLogFactory = false;
if (logFactoryClass != null) {
try {
ClassLoader logFactoryClassLoader = logFactoryClass.getClassLoader();
if (logFactoryClassLoader == null) {
logDiagnostic("[CUSTOM LOG FACTORY] was loaded by the boot classloader");
} else {
logHierarchy("[CUSTOM LOG FACTORY] ", logFactoryClassLoader);
Class factoryFromCustomLoader
= Class.forName("org.apache.commons.logging.LogFactory", false, logFactoryClassLoader);
implementsLogFactory = factoryFromCustomLoader.isAssignableFrom(logFactoryClass);
if (implementsLogFactory) {
logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClass.getName()
+ " implements LogFactory but was loaded by an incompatible classloader.");
} else {
logDiagnostic("[CUSTOM LOG FACTORY] " + logFactoryClass.getName()
+ " does not implement LogFactory.");
}
}
} catch (SecurityException e) {
//
// The application is running within a hostile security environment.
// This will make it very hard to diagnose issues with JCL.
// Consider running less securely whilst debugging this issue.
//
logDiagnostic("[CUSTOM LOG FACTORY] SecurityException thrown whilst trying to determine whether " +
"the compatibility was caused by a classloader conflict: "
+ e.getMessage());
} catch (LinkageError e) {
//
// This should be an unusual circumstance.
// LinkageError's usually indicate that a dependent class has incompatibly changed.
// Another possibility may be an exception thrown by an initializer.
// Time for a clean rebuild?
//
logDiagnostic("[CUSTOM LOG FACTORY] LinkageError thrown whilst trying to determine whether " +
"the compatibility was caused by a classloader conflict: "
+ e.getMessage());
} catch (ClassNotFoundException e) {
//
// LogFactory cannot be loaded by the classloader which loaded the custom factory implementation.
// The custom implementation is not viable until this is corrected.
// Ensure that the JCL jar and the custom class are available from the same classloader.
// Running with diagnostics on should give information about the classloaders used
// to load the custom factory.
//
logDiagnostic("[CUSTOM LOG FACTORY] LogFactory class cannot be loaded by classloader which loaded the " +
"custom LogFactory implementation. Is the custom factory in the right classloader?");
}
}
return implementsLogFactory;
}
/**
* Applets may run in an environment where accessing resources of a loader is
* a secure operation, but where the commons-logging library has explicitly
* been granted permission for that operation. In this case, we need to
* run the operation using an AccessController.
*/
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);
}
}
});
}
/**
* Given a filename, return an enumeration of URLs pointing to
* all the occurrences of that filename in the classpath.
* <p>
* This is just like ClassLoader.getResources except that the
* operation is done under an AccessController so that this method will
* succeed when this jarfile is privileged but the caller is not.
* This method must therefore remain private to avoid security issues.
* <p>
* If no instances are found, an Enumeration is returned whose
* hasMoreElements method returns false (ie an "empty" enumeration).
* If resources could not be listed for some reason, null is returned.
*/
private static Enumeration getResources(final ClassLoader loader,
final String name)
{
PrivilegedAction action =
new PrivilegedAction() {
public Object run() {
try {
if (loader != null) {
return loader.getResources(name);
} else {
return ClassLoader.getSystemResources(name);
}
} catch(IOException e) {
if (isDiagnosticsEnabled()) {
logDiagnostic(
"Exception while trying to find configuration file "
+ name + ":" + e.getMessage());
}
return null;
} catch(NoSuchMethodError e) {
// we must be running on a 1.1 JVM which doesn't support
// ClassLoader.getSystemResources; just return null in
// this case.
return null;
}
}
};
Object result = AccessController.doPrivileged(action);
return (Enumeration) result;
}
/**
* Given a URL that refers to a .properties file, load that file.
* This is done under an AccessController so that this method will
* succeed when this jarfile is privileged but the caller is not.
* This method must therefore remain private to avoid security issues.
* <p>
* Null is returned if the URL cannot be opened.
*/
private static Properties getProperties(final URL url) {
PrivilegedAction action =
new Pr
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -