rsitze 2002/06/11 15:29:14
Modified: logging/src/java/org/apache/commons/logging LogFactory.java
Log:
Resolve NullPointerExceptions, remove redundant checks, minor refactoring to
facilitate readability.
Revision Changes Path
1.8 +110 -67
jakarta-commons/logging/src/java/org/apache/commons/logging/LogFactory.java
Index: LogFactory.java
===================================================================
RCS file:
/home/cvs/jakarta-commons/logging/src/java/org/apache/commons/logging/LogFactory.java,v
retrieving revision 1.7
retrieving revision 1.8
diff -u -r1.7 -r1.8
--- LogFactory.java 4 May 2002 19:50:29 -0000 1.7
+++ LogFactory.java 11 Jun 2002 22:29:14 -0000 1.8
@@ -71,6 +71,7 @@
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.Properties;
+import java.lang.SecurityException;
/**
@@ -257,22 +258,21 @@
public static LogFactory getFactory() throws LogConfigurationException {
// Identify the class loader we will be using
- ClassLoader classLoader = findClassLoader();
+ ClassLoader contextClassLoader = getContextClassLoader();
// Return any previously registered factory for this class loader
- LogFactory factory = (LogFactory) factories.get(classLoader);
- if (factory != null) {
- return (factory);
- }
-
+ LogFactory factory = getCachedFactory(contextClassLoader);
+ if (factory != null)
+ return factory;
+
// First, try the system property
try {
String factoryClass = System.getProperty(FACTORY_PROPERTY);
if (factoryClass != null) {
- factory = newFactory(factoryClass, classLoader);
+ factory = newFactory(factoryClass, contextClassLoader);
}
} catch (SecurityException e) {
- ;
+ ; // ignore
}
// Second, try to find a service by using the JDK1.3 jar
@@ -281,14 +281,11 @@
// CLASSPATH or equivalent ). This is similar with the second
// step, except that it uses the (standard?) jdk1.3 location in the jar.
- if( factory==null ) {
+ if (factory == null) {
try {
- InputStream is=null;
- if (classLoader == null) {
- is=ClassLoader.getSystemResourceAsStream( SERVICE_ID );
- } else {
- is=classLoader.getResourceAsStream( SERVICE_ID );
- }
+ InputStream is = (contextClassLoader == null
+ ? ClassLoader.getSystemResourceAsStream(
SERVICE_ID )
+ : contextClassLoader.getResourceAsStream(
SERVICE_ID ));
if( is != null ) {
// This code is needed by EBCDIC and other strange systems.
@@ -306,7 +303,7 @@
if (factoryClassName != null &&
! "".equals(factoryClassName)) {
- factory= newFactory( factoryClassName, classLoader );
+ factory= newFactory( factoryClassName, contextClassLoader );
}
}
} catch( Exception ex ) {
@@ -327,7 +324,7 @@
try {
InputStream stream =
- classLoader.getResourceAsStream(FACTORY_PROPERTIES);
+ contextClassLoader.getResourceAsStream(FACTORY_PROPERTIES);
if (stream != null) {
props = new Properties();
props.load(stream);
@@ -337,7 +334,7 @@
if (factoryClass == null) {
factoryClass = FACTORY_DEFAULT;
}
- factory = newFactory(factoryClass, classLoader);
+ factory = newFactory(factoryClass, contextClassLoader);
}
}
// the properties will be set at the end.
@@ -359,10 +356,7 @@
}
}
- // Cache and return the new factory instance
- factories.put(classLoader, factory);
- return (factory);
-
+ return factory;
}
@@ -428,51 +422,92 @@
/**
- * Return the class loader to be used for loading the selected
- * <code>LogFactory</code> implementation class. On a JDK 1.2 or later
- * system, the context class loader for the current thread will be used
- * if it is present.
+ * Return the thread context class loader if available.
+ * Otherwise return null.
+ *
+ * The thread context class loader is available for JDK 1.2
+ * or later, if certain security conditions are met.
*
* @exception LogConfigurationException if a suitable class loader
- * cannot be identified
+ * cannot be identified.
*/
- protected static ClassLoader findClassLoader()
- throws LogConfigurationException {
+ protected static ClassLoader getContextClassLoader()
+ throws LogConfigurationException
+ {
+ ClassLoader classLoader = null;
- // Are we running on a JDK 1.2 or later system?
- Method method = null;
try {
- method = Thread.class.getMethod("getContextClassLoader", null);
- } catch (NoSuchMethodException e) {
- // Assume we are running on JDK 1.1
- return (LogFactory.class.getClassLoader());
- }
+ // Are we running on a JDK 1.2 or later system?
+ Method method = Thread.class.getMethod("getContextClassLoader", null);
- // Get the thread context class loader (if there is one)
- ClassLoader classLoader = null;
- try {
- classLoader = (ClassLoader)
- method.invoke(Thread.currentThread(), null);
- if (classLoader == null) {
- classLoader = LogFactory.class.getClassLoader();
+ // Get the thread context class loader (if there is one)
+ try {
+ classLoader = (ClassLoader)method.invoke(Thread.currentThread(),
null);
+ } catch (IllegalAccessException e) {
+ throw new LogConfigurationException
+ ("Unexpected IllegalAccessException", e);
+ } catch (InvocationTargetException e) {
+ /**
+ * InvocationTargetException is thrown by 'invoke' when
+ * the method being invoked (getContextClassLoader) throws
+ * an exception.
+ *
+ * getContextClassLoader() throws SecurityException when
+ * the context class loader isn't an ancestor of the
+ * calling class's class loader, or if security
+ * permissions are restricted.
+ *
+ * In the first case (not related), we want to ignore and
+ * keep going. We cannot help but also ignore the second
+ * with the logic below, but other calls elsewhere (to
+ * obtain a class loader) will trigger this exception where
+ * we can make a distinction.
+ */
+ if (e.getTargetException() instanceof SecurityException) {
+ ; // ignore
+ } else {
+ // Capture 'e.getTargetException()' exception for details
+ // alternate: log 'e.getTargetException()', and pass back 'e'.
+ throw new LogConfigurationException
+ ("Unexpected InvocationTargetException",
e.getTargetException());
+ }
}
- } catch (IllegalAccessException e) {
- throw new LogConfigurationException
- ("Unexpected IllegalAccessException", e);
- } catch (InvocationTargetException e) {
- throw new LogConfigurationException
- ("Unexpected InvocationTargetException", e);
+ } catch (NoSuchMethodException e) {
+ // Assume we are running on JDK 1.1
+ classLoader = LogFactory.class.getClassLoader();
}
// Return the selected class loader
- return (classLoader);
-
+ return classLoader;
}
+ /**
+ * Check cached factories (keyed by classLoader)
+ */
+ private static LogFactory getCachedFactory(ClassLoader contextClassLoader)
+ {
+ LogFactory factory = null;
+
+ if (contextClassLoader != null)
+ factory = (LogFactory) factories.get(contextClassLoader);
+
+ if (factory==null)
+ factory = (LogFactory) factories.get(LogFactory.class.getClassLoader());
+
+ return factory;
+ }
+
+ private static void cacheFactory(ClassLoader classLoader, LogFactory factory)
+ {
+ if (classLoader != null && factory != null)
+ factories.put(classLoader, factory);
+ }
/**
* Return a new instance of the specified <code>LogFactory</code>
* implementation class, loaded by the specified class loader.
+ * If that fails, try the class loader used to load this
+ * (abstract) LogFactory.
*
* @param factoryClass Fully qualified name of the <code>LogFactory</code>
* implementation class
@@ -487,24 +522,32 @@
{
try {
+ if (classLoader == null)
+ classLoader = LogFactory.class.getClassLoader();
+
Class clazz = null;
- if (classLoader == null) {
- clazz = Class.forName(factoryClass);
- } else {
- try {
- // first the thread class loader
+ try {
+ // first the thread class loader
+ clazz = classLoader.loadClass(factoryClass);
+ } catch (ClassNotFoundException ex) {
+ // if this failed (i.e. no implementation is
+ // found in the webapp), try the caller's loader
+ // if we haven't already...
+ if (classLoader != LogFactory.class.getClassLoader()) {
+ classLoader = LogFactory.class.getClassLoader();
clazz = classLoader.loadClass(factoryClass);
- } catch( ClassNotFoundException ex ) {
- // if this failed ( i.e. no implementation is
- // found in the webapp itself ) try the
- // caller's loader
- clazz = Class.forName( factoryClass );
}
}
- return ((LogFactory) clazz.newInstance());
+
+ LogFactory factory = (LogFactory)clazz.newInstance();
+
+ // Cache using correct classLoader
+ cacheFactory(classLoader, factory);
+
+ return factory;
} catch (Exception e) {
throw new LogConfigurationException(e);
}
}
-}
+}
\ No newline at end of file
--
To unsubscribe, e-mail: <mailto:[EMAIL PROTECTED]>
For additional commands, e-mail: <mailto:[EMAIL PROTECTED]>