You are viewing a plain text version of this content. The canonical link for it is here.
Posted to dev@commons.apache.org by rd...@apache.org on 2006/03/07 22:54:58 UTC
svn commit: r384025 -
/jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java
Author: rdonkin
Date: Tue Mar 7 13:54:57 2006
New Revision: 384025
URL: http://svn.apache.org/viewcvs?rev=384025&view=rev
Log:
Improved diagnostics and added more information to the message thrown when a custom LogFactory cannot be loaded due to classloader incompatibilities.
Modified:
jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java
Modified: jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java
URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java?rev=384025&r1=384024&r2=384025&view=diff
==============================================================================
--- jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java (original)
+++ jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java Tue Mar 7 13:54:57 2006
@@ -1101,13 +1101,29 @@
// 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() + "'."
- + " Perhaps you have multiple copies of LogFactory in"
- + " the classpath? If so, consider using the"
- + " commons-logging-adapters.jar file.";
-
+ + 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://jakarta.apache.org/commons/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://jakarta.apache.org/commons/logging/troubleshooting.html.";
+
if (isDiagnosticsEnabled()) {
logDiagnostic(msg);
}
@@ -1171,6 +1187,70 @@
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>Class</code> is assignable from the
+ */
+ 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
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org
Re: svn commit: r384025 -
/jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java
Posted by robert burrell donkin <ro...@blueyonder.co.uk>.
please take a look and check for typo's, bugs etc.
i'm working on something for the troubleshooting documentation about
this.
- robert
On Tue, 2006-03-07 at 21:54 +0000, rdonkin@apache.org wrote:
> Author: rdonkin
> Date: Tue Mar 7 13:54:57 2006
> New Revision: 384025
>
> URL: http://svn.apache.org/viewcvs?rev=384025&view=rev
> Log:
> Improved diagnostics and added more information to the message thrown when a custom LogFactory cannot be loaded due to classloader incompatibilities.
>
> Modified:
> jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java
>
> Modified: jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java
> URL: http://svn.apache.org/viewcvs/jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java?rev=384025&r1=384024&r2=384025&view=diff
> ==============================================================================
> --- jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java (original)
> +++ jakarta/commons/proper/logging/trunk/src/java/org/apache/commons/logging/LogFactory.java Tue Mar 7 13:54:57 2006
> @@ -1101,13 +1101,29 @@
> // 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() + "'."
> - + " Perhaps you have multiple copies of LogFactory in"
> - + " the classpath? If so, consider using the"
> - + " commons-logging-adapters.jar file.";
> -
> + + 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://jakarta.apache.org/commons/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://jakarta.apache.org/commons/logging/troubleshooting.html.";
> +
> if (isDiagnosticsEnabled()) {
> logDiagnostic(msg);
> }
> @@ -1171,6 +1187,70 @@
> 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>Class</code> is assignable from the
> + */
> + 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
>
>
>
> ---------------------------------------------------------------------
> To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
> For additional commands, e-mail: commons-dev-help@jakarta.apache.org
>
>
---------------------------------------------------------------------
To unsubscribe, e-mail: commons-dev-unsubscribe@jakarta.apache.org
For additional commands, e-mail: commons-dev-help@jakarta.apache.org