diff options
author | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:18 -0800 |
---|---|---|
committer | The Android Open Source Project <initial-contribution@android.com> | 2009-03-03 18:28:18 -0800 |
commit | e5d9544310b857f3ee9ec172bdbff8077323f9a1 (patch) | |
tree | 4b825dc642cb6eb9a060e54bf8d69288fbee4904 /src/org/apache/commons/logging | |
parent | 8b7d40049e7f35f9770fc024363a9fa6e88dff15 (diff) | |
download | external_apache-http-e5d9544310b857f3ee9ec172bdbff8077323f9a1.zip external_apache-http-e5d9544310b857f3ee9ec172bdbff8077323f9a1.tar.gz external_apache-http-e5d9544310b857f3ee9ec172bdbff8077323f9a1.tar.bz2 |
auto import from //depot/cupcake/@135843
Diffstat (limited to 'src/org/apache/commons/logging')
-rw-r--r-- | src/org/apache/commons/logging/Log.java | 245 | ||||
-rw-r--r-- | src/org/apache/commons/logging/LogConfigurationException.java | 97 | ||||
-rw-r--r-- | src/org/apache/commons/logging/LogFactory.java | 1740 | ||||
-rw-r--r-- | src/org/apache/commons/logging/LogSource.java | 261 | ||||
-rw-r--r-- | src/org/apache/commons/logging/impl/Jdk14Logger.java | 303 | ||||
-rw-r--r-- | src/org/apache/commons/logging/impl/LogFactoryImpl.java | 1400 | ||||
-rw-r--r-- | src/org/apache/commons/logging/impl/NoOpLog.java | 106 | ||||
-rw-r--r-- | src/org/apache/commons/logging/impl/SimpleLog.java | 709 | ||||
-rw-r--r-- | src/org/apache/commons/logging/impl/WeakHashtable.java | 478 | ||||
-rw-r--r-- | src/org/apache/commons/logging/impl/package.html | 21 | ||||
-rw-r--r-- | src/org/apache/commons/logging/package.html | 254 |
11 files changed, 0 insertions, 5614 deletions
diff --git a/src/org/apache/commons/logging/Log.java b/src/org/apache/commons/logging/Log.java deleted file mode 100644 index 9203f3f..0000000 --- a/src/org/apache/commons/logging/Log.java +++ /dev/null @@ -1,245 +0,0 @@ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging; - -/** - * <p>A simple logging interface abstracting logging APIs. In order to be - * instantiated successfully by {@link LogFactory}, classes that implement - * this interface must have a constructor that takes a single String - * parameter representing the "name" of this Log.</p> - * - * <p> The six logging levels used by <code>Log</code> are (in order): - * <ol> - * <li>trace (the least serious)</li> - * <li>debug</li> - * <li>info</li> - * <li>warn</li> - * <li>error</li> - * <li>fatal (the most serious)</li> - * </ol> - * The mapping of these log levels to the concepts used by the underlying - * logging system is implementation dependent. - * The implemention should ensure, though, that this ordering behaves - * as expected.</p> - * - * <p>Performance is often a logging concern. - * By examining the appropriate property, - * a component can avoid expensive operations (producing information - * to be logged).</p> - * - * <p> For example, - * <code><pre> - * if (log.isDebugEnabled()) { - * ... do something expensive ... - * log.debug(theResult); - * } - * </pre></code> - * </p> - * - * <p>Configuration of the underlying logging system will generally be done - * external to the Logging APIs, through whatever mechanism is supported by - * that system.</p> - * - * @author <a href="mailto:sanders@apache.org">Scott Sanders</a> - * @author Rod Waldhoff - * @version $Id: Log.java 381838 2006-02-28 23:57:11Z skitching $ - */ -public interface Log { - - - // ----------------------------------------------------- Logging Properties - - - /** - * <p> Is debug logging currently enabled? </p> - * - * <p> Call this method to prevent having to perform expensive operations - * (for example, <code>String</code> concatenation) - * when the log level is more than debug. </p> - * - * @return true if debug is enabled in the underlying logger. - */ - public boolean isDebugEnabled(); - - - /** - * <p> Is error logging currently enabled? </p> - * - * <p> Call this method to prevent having to perform expensive operations - * (for example, <code>String</code> concatenation) - * when the log level is more than error. </p> - * - * @return true if error is enabled in the underlying logger. - */ - public boolean isErrorEnabled(); - - - /** - * <p> Is fatal logging currently enabled? </p> - * - * <p> Call this method to prevent having to perform expensive operations - * (for example, <code>String</code> concatenation) - * when the log level is more than fatal. </p> - * - * @return true if fatal is enabled in the underlying logger. - */ - public boolean isFatalEnabled(); - - - /** - * <p> Is info logging currently enabled? </p> - * - * <p> Call this method to prevent having to perform expensive operations - * (for example, <code>String</code> concatenation) - * when the log level is more than info. </p> - * - * @return true if info is enabled in the underlying logger. - */ - public boolean isInfoEnabled(); - - - /** - * <p> Is trace logging currently enabled? </p> - * - * <p> Call this method to prevent having to perform expensive operations - * (for example, <code>String</code> concatenation) - * when the log level is more than trace. </p> - * - * @return true if trace is enabled in the underlying logger. - */ - public boolean isTraceEnabled(); - - - /** - * <p> Is warn logging currently enabled? </p> - * - * <p> Call this method to prevent having to perform expensive operations - * (for example, <code>String</code> concatenation) - * when the log level is more than warn. </p> - * - * @return true if warn is enabled in the underlying logger. - */ - public boolean isWarnEnabled(); - - - // -------------------------------------------------------- Logging Methods - - - /** - * <p> Log a message with trace log level. </p> - * - * @param message log this message - */ - public void trace(Object message); - - - /** - * <p> Log an error with trace log level. </p> - * - * @param message log this message - * @param t log this cause - */ - public void trace(Object message, Throwable t); - - - /** - * <p> Log a message with debug log level. </p> - * - * @param message log this message - */ - public void debug(Object message); - - - /** - * <p> Log an error with debug log level. </p> - * - * @param message log this message - * @param t log this cause - */ - public void debug(Object message, Throwable t); - - - /** - * <p> Log a message with info log level. </p> - * - * @param message log this message - */ - public void info(Object message); - - - /** - * <p> Log an error with info log level. </p> - * - * @param message log this message - * @param t log this cause - */ - public void info(Object message, Throwable t); - - - /** - * <p> Log a message with warn log level. </p> - * - * @param message log this message - */ - public void warn(Object message); - - - /** - * <p> Log an error with warn log level. </p> - * - * @param message log this message - * @param t log this cause - */ - public void warn(Object message, Throwable t); - - - /** - * <p> Log a message with error log level. </p> - * - * @param message log this message - */ - public void error(Object message); - - - /** - * <p> Log an error with error log level. </p> - * - * @param message log this message - * @param t log this cause - */ - public void error(Object message, Throwable t); - - - /** - * <p> Log a message with fatal log level. </p> - * - * @param message log this message - */ - public void fatal(Object message); - - - /** - * <p> Log an error with fatal log level. </p> - * - * @param message log this message - * @param t log this cause - */ - public void fatal(Object message, Throwable t); - - -} diff --git a/src/org/apache/commons/logging/LogConfigurationException.java b/src/org/apache/commons/logging/LogConfigurationException.java deleted file mode 100644 index b34387b..0000000 --- a/src/org/apache/commons/logging/LogConfigurationException.java +++ /dev/null @@ -1,97 +0,0 @@ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - - -/** - * <p>An exception that is thrown only if a suitable <code>LogFactory</code> - * or <code>Log</code> instance cannot be created by the corresponding - * factory methods.</p> - * - * @author Craig R. McClanahan - * @version $Revision: 155426 $ $Date: 2005-02-26 13:10:49 +0000 (Sat, 26 Feb 2005) $ - */ - -public class LogConfigurationException extends RuntimeException { - - - /** - * Construct a new exception with <code>null</code> as its detail message. - */ - public LogConfigurationException() { - - super(); - - } - - - /** - * Construct a new exception with the specified detail message. - * - * @param message The detail message - */ - public LogConfigurationException(String message) { - - super(message); - - } - - - /** - * Construct a new exception with the specified cause and a derived - * detail message. - * - * @param cause The underlying cause - */ - public LogConfigurationException(Throwable cause) { - - this((cause == null) ? null : cause.toString(), cause); - - } - - - /** - * Construct a new exception with the specified detail message and cause. - * - * @param message The detail message - * @param cause The underlying cause - */ - public LogConfigurationException(String message, Throwable cause) { - - super(message + " (Caused by " + cause + ")"); - this.cause = cause; // Two-argument version requires JDK 1.4 or later - - } - - - /** - * The underlying cause of this exception. - */ - protected Throwable cause = null; - - - /** - * Return the underlying cause of this exception (if any). - */ - public Throwable getCause() { - - return (this.cause); - - } - - -} diff --git a/src/org/apache/commons/logging/LogFactory.java b/src/org/apache/commons/logging/LogFactory.java deleted file mode 100644 index 107d0f7..0000000 --- a/src/org/apache/commons/logging/LogFactory.java +++ /dev/null @@ -1,1740 +0,0 @@ -/* - * Copyright 2001-2006 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - - -import java.io.BufferedReader; -import java.io.FileOutputStream; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.io.PrintStream; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Properties; - - -/** - * <p>Factory for creating {@link Log} instances, with discovery and - * configuration features similar to that employed by standard Java APIs - * such as JAXP.</p> - * - * <p><strong>IMPLEMENTATION NOTE</strong> - This implementation is heavily - * based on the SAXParserFactory and DocumentBuilderFactory implementations - * (corresponding to the JAXP pluggability APIs) found in Apache Xerces.</p> - * - * @author Craig R. McClanahan - * @author Costin Manolache - * @author Richard A. Sitze - * @version $Revision: 399431 $ $Date: 2006-05-03 21:58:34 +0100 (Wed, 03 May 2006) $ - */ - -public abstract class LogFactory { - - - // ----------------------------------------------------- Manifest Constants - - /** - * The name (<code>priority</code>) of the key in the config file used to - * specify the priority of that particular config file. The associated value - * is a floating-point number; higher values take priority over lower values. - */ - public static final String PRIORITY_KEY = "priority"; - - /** - * The name (<code>use_tccl</code>) of the key in the config file used - * to specify whether logging classes should be loaded via the thread - * context class loader (TCCL), or not. By default, the TCCL is used. - */ - public static final String TCCL_KEY = "use_tccl"; - - /** - * The name (<code>org.apache.commons.logging.LogFactory</code>) of the property - * used to identify the LogFactory implementation - * class name. This can be used as a system property, or as an entry in a - * configuration properties file. - */ - public static final String FACTORY_PROPERTY = - "org.apache.commons.logging.LogFactory"; - - /** - * The fully qualified class name of the fallback <code>LogFactory</code> - * implementation class to use, if no other can be found. - */ - public static final String FACTORY_DEFAULT = - "org.apache.commons.logging.impl.LogFactoryImpl"; - - /** - * The name (<code>commons-logging.properties</code>) of the properties file to search for. - */ - public static final String FACTORY_PROPERTIES = - "commons-logging.properties"; - - /** - * JDK1.3+ <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider"> - * 'Service Provider' specification</a>. - * - */ - protected static final String SERVICE_ID = - "META-INF/services/org.apache.commons.logging.LogFactory"; - - /** - * The name (<code>org.apache.commons.logging.diagnostics.dest</code>) - * of the property used to enable internal commons-logging - * diagnostic output, in order to get information on what logging - * implementations are being discovered, what classloaders they - * are loaded through, etc. - * <p> - * If a system property of this name is set then the value is - * assumed to be the name of a file. The special strings - * STDOUT or STDERR (case-sensitive) indicate output to - * System.out and System.err respectively. - * <p> - * Diagnostic logging should be used only to debug problematic - * configurations and should not be set in normal production use. - */ - public static final String DIAGNOSTICS_DEST_PROPERTY = - "org.apache.commons.logging.diagnostics.dest"; - - /** - * When null (the usual case), no diagnostic output will be - * generated by LogFactory or LogFactoryImpl. When non-null, - * interesting events will be written to the specified object. - */ - private static PrintStream diagnosticsStream = null; - - /** - * A string that gets prefixed to every message output by the - * logDiagnostic method, so that users can clearly see which - * LogFactory class is generating the output. - */ - private static String diagnosticPrefix; - - /** - * <p>Setting this system property - * (<code>org.apache.commons.logging.LogFactory.HashtableImpl</code>) - * value allows the <code>Hashtable</code> used to store - * classloaders to be substituted by an alternative implementation. - * </p> - * <p> - * <strong>Note:</strong> <code>LogFactory</code> will print: - * <code><pre> - * [ERROR] LogFactory: Load of custom hashtable failed</em> - * </pre></code> - * to system error and then continue using a standard Hashtable. - * </p> - * <p> - * <strong>Usage:</strong> Set this property when Java is invoked - * and <code>LogFactory</code> will attempt to load a new instance - * of the given implementation class. - * For example, running the following ant scriplet: - * <code><pre> - * <java classname="${test.runner}" fork="yes" failonerror="${test.failonerror}"> - * ... - * <sysproperty - * key="org.apache.commons.logging.LogFactory.HashtableImpl" - * value="org.apache.commons.logging.AltHashtable"/> - * </java> - * </pre></code> - * will mean that <code>LogFactory</code> will load an instance of - * <code>org.apache.commons.logging.AltHashtable</code>. - * </p> - * <p> - * A typical use case is to allow a custom - * Hashtable implementation using weak references to be substituted. - * This will allow classloaders to be garbage collected without - * the need to release them (on 1.3+ JVMs only, of course ;) - * </p> - */ - public static final String HASHTABLE_IMPLEMENTATION_PROPERTY = - "org.apache.commons.logging.LogFactory.HashtableImpl"; - /** Name used to load the weak hashtable implementation by names */ - private static final String WEAK_HASHTABLE_CLASSNAME = - "org.apache.commons.logging.impl.WeakHashtable"; - - /** - * A reference to the classloader that loaded this class. This is the - * same as LogFactory.class.getClassLoader(). However computing this - * value isn't quite as simple as that, as we potentially need to use - * AccessControllers etc. It's more efficient to compute it once and - * cache it here. - */ - private static ClassLoader thisClassLoader; - - // ----------------------------------------------------------- Constructors - - - /** - * Protected constructor that is not available for public use. - */ - protected LogFactory() { - } - - // --------------------------------------------------------- Public Methods - - - /** - * Return the configuration attribute with the specified name (if any), - * or <code>null</code> if there is no such attribute. - * - * @param name Name of the attribute to return - */ - public abstract Object getAttribute(String name); - - - /** - * Return an array containing the names of all currently defined - * configuration attributes. If there are no such attributes, a zero - * length array is returned. - */ - public abstract String[] getAttributeNames(); - - - /** - * Convenience method to derive a name from the specified class and - * call <code>getInstance(String)</code> with it. - * - * @param clazz Class for which a suitable Log name will be derived - * - * @exception LogConfigurationException if a suitable <code>Log</code> - * instance cannot be returned - */ - public abstract Log getInstance(Class clazz) - throws LogConfigurationException; - - - /** - * <p>Construct (if necessary) and return a <code>Log</code> instance, - * using the factory's current set of configuration attributes.</p> - * - * <p><strong>NOTE</strong> - Depending upon the implementation of - * the <code>LogFactory</code> you are using, the <code>Log</code> - * 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.</p> - * - * @param name Logical name of the <code>Log</code> instance to be - * returned (the meaning of this name is only known to the underlying - * logging implementation that is being wrapped) - * - * @exception LogConfigurationException if a suitable <code>Log</code> - * instance cannot be returned - */ - public abstract Log getInstance(String name) - throws LogConfigurationException; - - - /** - * Release any internal references to previously created {@link 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. - */ - public abstract void release(); - - - /** - * Remove any configuration attribute associated with the specified name. - * If there is no such attribute, no action is taken. - * - * @param name Name of the attribute to remove - */ - public abstract void removeAttribute(String name); - - - /** - * Set the configuration attribute with the specified name. Calling - * this with a <code>null</code> value is equivalent to calling - * <code>removeAttribute(name)</code>. - * - * @param name Name of the attribute to set - * @param value Value of the attribute to set, or <code>null</code> - * to remove any setting for this attribute - */ - public abstract void setAttribute(String name, Object value); - - - // ------------------------------------------------------- Static Variables - - - /** - * The previously constructed <code>LogFactory</code> instances, keyed by - * the <code>ClassLoader</code> with which it was created. - */ - protected static Hashtable factories = null; - - /** - * Prevously constructed <code>LogFactory</code> instance as in the - * <code>factories</code> map, but for the case where - * <code>getClassLoader</code> returns <code>null</code>. - * This can happen when: - * <ul> - * <li>using JDK1.1 and the calling code is loaded via the system - * classloader (very common)</li> - * <li>using JDK1.2+ and the calling code is loaded via the boot - * classloader (only likely for embedded systems work).</li> - * </ul> - * Note that <code>factories</code> is a <i>Hashtable</i> (not a HashMap), - * and hashtables don't allow null as a key. - */ - protected static LogFactory nullClassLoaderFactory = null; - - /** - * Create the hashtable which will be used to store a map of - * (context-classloader -> logfactory-object). Version 1.2+ of Java - * supports "weak references", allowing a custom Hashtable class - * to be used which uses only weak references to its keys. Using weak - * references can fix memory leaks on webapp unload in some cases (though - * not all). Version 1.1 of Java does not support weak references, so we - * must dynamically determine which we are using. And just for fun, this - * code also supports the ability for a system property to specify an - * arbitrary Hashtable implementation name. - * <p> - * Note that the correct way to ensure no memory leaks occur is to ensure - * that LogFactory.release(contextClassLoader) is called whenever a - * webapp is undeployed. - */ - private static final Hashtable createFactoryStore() { - Hashtable result = null; - String storeImplementationClass - = System.getProperty(HASHTABLE_IMPLEMENTATION_PROPERTY); - if (storeImplementationClass == null) { - storeImplementationClass = WEAK_HASHTABLE_CLASSNAME; - } - try { - Class implementationClass = Class.forName(storeImplementationClass); - result = (Hashtable) implementationClass.newInstance(); - - } catch (Throwable t) { - // ignore - if (!WEAK_HASHTABLE_CLASSNAME.equals(storeImplementationClass)) { - // if the user's trying to set up a custom implementation, give a clue - if (isDiagnosticsEnabled()) { - // use internal logging to issue the warning - logDiagnostic("[ERROR] LogFactory: Load of custom hashtable failed"); - } else { - // we *really* want this output, even if diagnostics weren't - // explicitly enabled by the user. - System.err.println("[ERROR] LogFactory: Load of custom hashtable failed"); - } - } - } - if (result == null) { - result = new Hashtable(); - } - return result; - } - - - // --------------------------------------------------------- Static Methods - - /** - * <p>Construct (if necessary) and return a <code>LogFactory</code> - * instance, using the following ordered lookup procedure to determine - * the name of the implementation class to be loaded.</p> - * <ul> - * <li>The <code>org.apache.commons.logging.LogFactory</code> system - * property.</li> - * <li>The JDK 1.3 Service Discovery mechanism</li> - * <li>Use the properties file <code>commons-logging.properties</code> - * file, if found in the class path of this class. The configuration - * file is in standard <code>java.util.Properties</code> format and - * contains the fully qualified name of the implementation class - * with the key being the system property defined above.</li> - * <li>Fall back to a default implementation class - * (<code>org.apache.commons.logging.impl.LogFactoryImpl</code>).</li> - * </ul> - * - * <p><em>NOTE</em> - If the properties file method of identifying the - * <code>LogFactory</code> implementation class is utilized, all of the - * properties defined in this file will be set as configuration attributes - * on the corresponding <code>LogFactory</code> instance.</p> - * - * <p><em>NOTE</em> - In a multithreaded environment it is possible - * that two different instances will be returned for the same - * classloader environment. - * </p> - * - * @exception LogConfigurationException if the implementation class is not - * available or cannot be instantiated. - */ - public static LogFactory getFactory() throws LogConfigurationException { - // Identify the class loader we will be using - ClassLoader contextClassLoader = getContextClassLoader(); - - if (contextClassLoader == null) { - // This is an odd enough situation to report about. This - // output will be a nuisance on JDK1.1, as the system - // classloader is null in that environment. - if (isDiagnosticsEnabled()) { - logDiagnostic("Context classloader is null."); - } - } - - // Return any previously registered factory for this class loader - LogFactory factory = getCachedFactory(contextClassLoader); - if (factory != null) { - return factory; - } - - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] LogFactory implementation requested for the first time for context classloader " - + objectId(contextClassLoader)); - logHierarchy("[LOOKUP] ", contextClassLoader); - } - - // Load properties file. - // - // If the properties file exists, then its contents are used as - // "attributes" on the LogFactory implementation class. One particular - // property may also control which LogFactory concrete subclass is - // used, but only if other discovery mechanisms fail.. - // - // As the properties file (if it exists) will be used one way or - // another in the end we may as well look for it first. - - Properties props = getConfigurationFile(contextClassLoader, FACTORY_PROPERTIES); - - // Determine whether we will be using the thread context class loader to - // load logging classes or not by checking the loaded properties file (if any). - ClassLoader baseClassLoader = contextClassLoader; - if (props != null) { - String useTCCLStr = props.getProperty(TCCL_KEY); - if (useTCCLStr != null) { - // The Boolean.valueOf(useTCCLStr).booleanValue() formulation - // is required for Java 1.2 compatability. - if (Boolean.valueOf(useTCCLStr).booleanValue() == false) { - // Don't use current context classloader when locating any - // LogFactory or Log classes, just use the class that loaded - // this abstract class. When this class is deployed in a shared - // classpath of a container, it means webapps cannot deploy their - // own logging implementations. It also means that it is up to the - // implementation whether to load library-specific config files - // from the TCCL or not. - baseClassLoader = thisClassLoader; - } - } - } - - // Determine which concrete LogFactory subclass to use. - // First, try a global system property - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Looking for system property [" + FACTORY_PROPERTY - + "] to define the LogFactory subclass to use..."); - } - - try { - String factoryClass = System.getProperty(FACTORY_PROPERTY); - if (factoryClass != null) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Creating an instance of LogFactory class '" + factoryClass - + "' as specified by system property " + FACTORY_PROPERTY); - } - - factory = newFactory(factoryClass, baseClassLoader, contextClassLoader); - } else { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] No system property [" + FACTORY_PROPERTY - + "] defined."); - } - } - } catch (SecurityException e) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] A security exception occurred while trying to create an" - + " instance of the custom factory class" - + ": [" + e.getMessage().trim() - + "]. Trying alternative implementations..."); - } - ; // ignore - } catch(RuntimeException e) { - // This is not consistent with the behaviour when a bad LogFactory class is - // specified in a services file. - // - // One possible exception that can occur here is a ClassCastException when - // the specified class wasn't castable to this LogFactory type. - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] An exception occurred while trying to create an" - + " instance of the custom factory class" - + ": [" + e.getMessage().trim() - + "] as specified by a system property."); - } - throw e; - } - - - // Second, try to find a service by using the JDK1.3 class - // discovery mechanism, which involves putting a file with the name - // of an interface class in the META-INF/services directory, where the - // contents of the file is a single line specifying a concrete class - // that implements the desired interface. - - if (factory == null) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Looking for a resource file of name [" + SERVICE_ID - + "] to define the LogFactory subclass to use..."); - } - try { - InputStream is = getResourceAsStream(contextClassLoader, - SERVICE_ID); - - if( is != null ) { - // This code is needed by EBCDIC and other strange systems. - // It's a fix for bugs reported in xerces - BufferedReader rd; - try { - rd = new BufferedReader(new InputStreamReader(is, "UTF-8")); - } catch (java.io.UnsupportedEncodingException e) { - rd = new BufferedReader(new InputStreamReader(is)); - } - - String factoryClassName = rd.readLine(); - rd.close(); - - if (factoryClassName != null && - ! "".equals(factoryClassName)) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Creating an instance of LogFactory class " + factoryClassName - + " as specified by file '" + SERVICE_ID - + "' which was present in the path of the context" - + " classloader."); - } - factory = newFactory(factoryClassName, baseClassLoader, contextClassLoader ); - } - } else { - // is == null - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] No resource file with name '" + SERVICE_ID - + "' found."); - } - } - } catch( Exception ex ) { - // note: if the specified LogFactory class wasn't compatible with LogFactory - // for some reason, a ClassCastException will be caught here, and attempts will - // continue to find a compatible class. - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] A security exception occurred while trying to create an" - + " instance of the custom factory class" - + ": [" + ex.getMessage().trim() - + "]. Trying alternative implementations..."); - } - ; // ignore - } - } - - - // Third try looking into the properties file read earlier (if found) - - if (factory == null) { - if (props != null) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Looking in properties file for entry with key '" - + FACTORY_PROPERTY - + "' to define the LogFactory subclass to use..."); - } - String factoryClass = props.getProperty(FACTORY_PROPERTY); - if (factoryClass != null) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Properties file specifies LogFactory subclass '" - + factoryClass + "'"); - } - factory = newFactory(factoryClass, baseClassLoader, contextClassLoader); - - // TODO: think about whether we need to handle exceptions from newFactory - } else { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Properties file has no entry specifying LogFactory subclass."); - } - } - } else { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] No properties file available to determine" - + " LogFactory subclass from.."); - } - } - } - - - // Fourth, try the fallback implementation class - - if (factory == null) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Loading the default LogFactory implementation '" + FACTORY_DEFAULT - + "' via the same classloader that loaded this LogFactory" - + " class (ie not looking in the context classloader)."); - } - - // Note: unlike the above code which can try to load custom LogFactory - // implementations via the TCCL, we don't try to load the default LogFactory - // implementation via the context classloader because: - // * that can cause problems (see comments in newFactory method) - // * no-one should be customising the code of the default class - // Yes, we do give up the ability for the child to ship a newer - // version of the LogFactoryImpl class and have it used dynamically - // by an old LogFactory class in the parent, but that isn't - // necessarily a good idea anyway. - factory = newFactory(FACTORY_DEFAULT, thisClassLoader, contextClassLoader); - } - - if (factory != null) { - /** - * Always cache using context class loader. - */ - cacheFactory(contextClassLoader, factory); - - if( props!=null ) { - Enumeration names = props.propertyNames(); - while (names.hasMoreElements()) { - String name = (String) names.nextElement(); - String value = props.getProperty(name); - factory.setAttribute(name, value); - } - } - } - - return factory; - } - - - /** - * Convenience method to return a named logger, without the application - * having to care about factories. - * - * @param clazz Class from which a log name will be derived - * - * @exception LogConfigurationException if a suitable <code>Log</code> - * instance cannot be returned - */ - public static Log getLog(Class clazz) - throws LogConfigurationException { - - // BEGIN android-added - return getLog(clazz.getName()); - // END android-added - // BEGIN android-deleted - //return (getFactory().getInstance(clazz)); - // END android-deleted - - } - - - /** - * Convenience method to return a named logger, without the application - * having to care about factories. - * - * @param name Logical name of the <code>Log</code> instance to be - * returned (the meaning of this name is only known to the underlying - * logging implementation that is being wrapped) - * - * @exception LogConfigurationException if a suitable <code>Log</code> - * instance cannot be returned - */ - public static Log getLog(String name) - throws LogConfigurationException { - - // BEGIN android-added - return new org.apache.commons.logging.impl.Jdk14Logger(name); - // END android-added - // BEGIN android-deleted - //return (getFactory().getInstance(name)); - // END android-deleted - - } - - - /** - * Release any internal references to previously created {@link LogFactory} - * instances that have been associated with the specified class loader - * (if any), after calling the instance method <code>release()</code> on - * each of them. - * - * @param classLoader ClassLoader for which to release the LogFactory - */ - public static void release(ClassLoader classLoader) { - - if (isDiagnosticsEnabled()) { - logDiagnostic("Releasing factory for classloader " + objectId(classLoader)); - } - synchronized (factories) { - if (classLoader == null) { - if (nullClassLoaderFactory != null) { - nullClassLoaderFactory.release(); - nullClassLoaderFactory = null; - } - } else { - LogFactory factory = (LogFactory) factories.get(classLoader); - if (factory != null) { - factory.release(); - factories.remove(classLoader); - } - } - } - - } - - - /** - * Release any internal references to previously created {@link LogFactory} - * instances, after calling the instance method <code>release()</code> on - * each of them. 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. - */ - public static void releaseAll() { - - if (isDiagnosticsEnabled()) { - logDiagnostic("Releasing factory for all classloaders."); - } - synchronized (factories) { - Enumeration elements = factories.elements(); - while (elements.hasMoreElements()) { - LogFactory element = (LogFactory) elements.nextElement(); - element.release(); - } - factories.clear(); - - if (nullClassLoaderFactory != null) { - nullClassLoaderFactory.release(); - nullClassLoaderFactory = null; - } - } - - } - - - // ------------------------------------------------------ Protected Methods - - /** - * Safely get access to the classloader for the specified class. - * <p> - * Theoretically, calling getClassLoader can throw a security exception, - * and so should be done under an AccessController in order to provide - * maximum flexibility. However in practice people don't appear to use - * security policies that forbid getClassLoader calls. So for the moment - * all code is written to call this method rather than Class.getClassLoader, - * so that we could put AccessController stuff in this method without any - * disruption later if we need to. - * <p> - * Even when using an AccessController, however, this method can still - * throw SecurityException. Commons-logging basically relies on the - * ability to access classloaders, ie a policy that forbids all - * classloader access will also prevent commons-logging from working: - * currently this method will throw an exception preventing the entire app - * from starting up. Maybe it would be good to detect this situation and - * just disable all commons-logging? Not high priority though - as stated - * above, security policies that prevent classloader access aren't common. - * - * @since 1.1 - */ - protected static ClassLoader getClassLoader(Class clazz) { - try { - return clazz.getClassLoader(); - } catch(SecurityException ex) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Unable to get classloader for class '" + clazz - + "' due to security restrictions - " + ex.getMessage()); - } - throw ex; - } - } - - /** - * Calls LogFactory.directGetContextClassLoader under the control of an - * AccessController class. This means that java code running under a - * security manager that forbids access to ClassLoaders will still work - * if this class is given appropriate privileges, even when the caller - * doesn't have such privileges. Without using an AccessController, the - * the entire call stack must have the privilege before the call is - * allowed. - * - * @return the context classloader associated with the current thread, - * or null if security doesn't allow it. - * - * @throws LogConfigurationException if there was some weird error while - * attempting to get the context classloader. - * - * @throws SecurityException if the current java security policy doesn't - * allow this class to access the context classloader. - */ - protected static ClassLoader getContextClassLoader() - throws LogConfigurationException { - - return (ClassLoader)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return directGetContextClassLoader(); - } - }); - } - - /** - * Return the thread context class loader if available; otherwise return - * null. - * <p> - * Most/all code should call getContextClassLoader rather than calling - * this method directly. - * <p> - * The thread context class loader is available for JDK 1.2 - * or later, if certain security conditions are met. - * <p> - * Note that no internal logging is done within this method because - * this method is called every time LogFactory.getLogger() is called, - * and we don't want too much output generated here. - * - * @exception LogConfigurationException if a suitable class loader - * cannot be identified. - * - * @exception SecurityException if the java security policy forbids - * access to the context classloader from one of the classes in the - * current call stack. - * @since 1.1 - */ - protected static ClassLoader directGetContextClassLoader() - throws LogConfigurationException - { - ClassLoader classLoader = null; - - try { - // Are we running on a JDK 1.2 or later system? - Method method = Thread.class.getMethod("getContextClassLoader", - (Class[]) null); - - // Get the thread context class loader (if there is one) - try { - classLoader = (ClassLoader)method.invoke(Thread.currentThread(), - (Object[]) 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 (NoSuchMethodException e) { - // Assume we are running on JDK 1.1 - classLoader = getClassLoader(LogFactory.class); - - // We deliberately don't log a message here to outputStream; - // this message would be output for every call to LogFactory.getLog() - // when running on JDK1.1 - // - // if (outputStream != null) { - // outputStream.println( - // "Method Thread.getContextClassLoader does not exist;" - // + " assuming this is JDK 1.1, and that the context" - // + " classloader is the same as the class that loaded" - // + " the concrete LogFactory class."); - // } - - } - - // Return the selected class loader - return classLoader; - } - - /** - * Check cached factories (keyed by contextClassLoader) - * - * @param contextClassLoader is the context classloader associated - * with the current thread. This allows separate LogFactory objects - * per component within a container, provided each component has - * a distinct context classloader set. This parameter may be null - * in JDK1.1, and in embedded systems where jcl-using code is - * placed in the bootclasspath. - * - * @return the factory associated with the specified classloader if - * one has previously been created, or null if this is the first time - * we have seen this particular classloader. - */ - private static LogFactory getCachedFactory(ClassLoader contextClassLoader) - { - LogFactory factory = null; - - if (contextClassLoader == null) { - // We have to handle this specially, as factories is a Hashtable - // and those don't accept null as a key value. - // - // nb: nullClassLoaderFactory might be null. That's ok. - factory = nullClassLoaderFactory; - } else { - factory = (LogFactory) factories.get(contextClassLoader); - } - - return factory; - } - - /** - * Remember this factory, so later calls to LogFactory.getCachedFactory - * can return the previously created object (together with all its - * cached Log objects). - * - * @param classLoader should be the current context classloader. Note that - * this can be null under some circumstances; this is ok. - * - * @param factory should be the factory to cache. This should never be null. - */ - private static void cacheFactory(ClassLoader classLoader, LogFactory factory) - { - // Ideally we would assert(factory != null) here. However reporting - // errors from within a logging implementation is a little tricky! - - if (factory != null) { - if (classLoader == null) { - nullClassLoaderFactory = factory; - } else { - 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. - * <p> - * <h2>ClassLoader conflicts</h2> - * Note that there can be problems if the specified ClassLoader is not the - * same as the classloader that loaded this class, ie when loading a - * concrete LogFactory subclass via a context classloader. - * <p> - * The problem is the same one that can occur when loading a concrete Log - * subclass via a context classloader. - * <p> - * The problem occurs when code running in the context classloader calls - * class X which was loaded via a parent classloader, and class X then calls - * LogFactory.getFactory (either directly or via LogFactory.getLog). Because - * class X was loaded via the parent, it binds to LogFactory loaded via - * the parent. When the code in this method finds some LogFactoryYYYY - * class in the child (context) classloader, and there also happens to be a - * LogFactory class defined in the child classloader, then LogFactoryYYYY - * will be bound to LogFactory@childloader. It cannot be cast to - * LogFactory@parentloader, ie this method cannot return the object as - * the desired type. Note that it doesn't matter if the LogFactory class - * in the child classloader is identical to the LogFactory class in the - * parent classloader, they are not compatible. - * <p> - * The solution taken here is to simply print out an error message when - * this occurs then throw an exception. The deployer of the application - * must ensure they remove all occurrences of the LogFactory class from - * the child classloader in order to resolve the issue. Note that they - * do not have to move the custom LogFactory subclass; that is ok as - * long as the only LogFactory class it can find to bind to is in the - * parent classloader. - * <p> - * @param factoryClass Fully qualified name of the <code>LogFactory</code> - * implementation class - * @param classLoader ClassLoader from which to load this class - * @param contextClassLoader is the context that this new factory will - * manage logging for. - * - * @exception LogConfigurationException if a suitable instance - * cannot be created - * @since 1.1 - */ - protected static LogFactory newFactory(final String factoryClass, - final ClassLoader classLoader, - final ClassLoader contextClassLoader) - throws LogConfigurationException - { - // Note that any unchecked exceptions thrown by the createFactory - // method will propagate out of this method; in particular a - // ClassCastException can be thrown. - Object result = AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return createFactory(factoryClass, classLoader); - } - }); - - if (result instanceof LogConfigurationException) { - LogConfigurationException ex = (LogConfigurationException) result; - if (isDiagnosticsEnabled()) { - logDiagnostic( - "An error occurred while loading the factory class:" - + ex.getMessage()); - } - throw ex; - } - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Created object " + objectId(result) - + " to manage classloader " + objectId(contextClassLoader)); - } - return (LogFactory)result; - } - - /** - * Method provided for backwards compatibility; see newFactory version that - * takes 3 parameters. - * <p> - * This method would only ever be called in some rather odd situation. - * Note that this method is static, so overriding in a subclass doesn't - * have any effect unless this method is called from a method in that - * subclass. However this method only makes sense to use from the - * getFactory method, and as that is almost always invoked via - * LogFactory.getFactory, any custom definition in a subclass would be - * pointless. Only a class with a custom getFactory method, then invoked - * directly via CustomFactoryImpl.getFactory or similar would ever call - * this. Anyway, it's here just in case, though the "managed class loader" - * value output to the diagnostics will not report the correct value. - */ - protected static LogFactory newFactory(final String factoryClass, - final ClassLoader classLoader) { - return newFactory(factoryClass, classLoader, null); - } - - /** - * Implements the operations described in the javadoc for newFactory. - * - * @param factoryClass - * - * @param classLoader used to load the specified factory class. This is - * expected to be either the TCCL or the classloader which loaded this - * class. Note that the classloader which loaded this class might be - * "null" (ie the bootloader) for embedded systems. - * - * @return either a LogFactory object or a LogConfigurationException object. - * @since 1.1 - */ - protected static Object createFactory(String factoryClass, ClassLoader classLoader) { - - // This will be used to diagnose bad configurations - // and allow a useful message to be sent to the user - Class logFactoryClass = null; - try { - if (classLoader != null) { - try { - // First the given class loader param (thread class loader) - - // Warning: must typecast here & allow exception - // to be generated/caught & recast properly. - logFactoryClass = classLoader.loadClass(factoryClass); - if (LogFactory.class.isAssignableFrom(logFactoryClass)) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Loaded class " + logFactoryClass.getName() - + " from classloader " + objectId(classLoader)); - } - } else { - // - // This indicates a problem with the ClassLoader tree. - // 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://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); - } - - 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 PrivilegedAction() { - public Object run() { - try { - InputStream stream = url.openStream(); - if (stream != null) { - Properties props = new Properties(); - props.load(stream); - stream.close(); - return props; - } - } catch(IOException e) { - if (isDiagnosticsEnabled()) { - logDiagnostic("Unable to read URL " + url); - } - } - - return null; - } - }; - return (Properties) AccessController.doPrivileged(action); - } - - /** - * Locate a user-provided configuration file. - * <p> - * The classpath of the specified classLoader (usually the context classloader) - * is searched for properties files of the specified name. If none is found, - * null is returned. If more than one is found, then the file with the greatest - * value for its PRIORITY property is returned. If multiple files have the - * same PRIORITY value then the first in the classpath is returned. - * <p> - * This differs from the 1.0.x releases; those always use the first one found. - * However as the priority is a new field, this change is backwards compatible. - * <p> - * The purpose of the priority field is to allow a webserver administrator to - * override logging settings in all webapps by placing a commons-logging.properties - * file in a shared classpath location with a priority > 0; this overrides any - * commons-logging.properties files without priorities which are in the - * webapps. Webapps can also use explicit priorities to override a configuration - * file in the shared classpath if needed. - */ - private static final Properties getConfigurationFile( - ClassLoader classLoader, String fileName) { - - Properties props = null; - double priority = 0.0; - URL propsUrl = null; - try { - Enumeration urls = getResources(classLoader, fileName); - - if (urls == null) { - return null; - } - - while (urls.hasMoreElements()) { - URL url = (URL) urls.nextElement(); - - Properties newProps = getProperties(url); - if (newProps != null) { - if (props == null) { - propsUrl = url; - props = newProps; - String priorityStr = props.getProperty(PRIORITY_KEY); - priority = 0.0; - if (priorityStr != null) { - priority = Double.parseDouble(priorityStr); - } - - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Properties file found at '" + url + "'" - + " with priority " + priority); - } - } else { - String newPriorityStr = newProps.getProperty(PRIORITY_KEY); - double newPriority = 0.0; - if (newPriorityStr != null) { - newPriority = Double.parseDouble(newPriorityStr); - } - - if (newPriority > priority) { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Properties file at '" + url + "'" - + " with priority " + newPriority - + " overrides file at '" + propsUrl + "'" - + " with priority " + priority); - } - - propsUrl = url; - props = newProps; - priority = newPriority; - } else { - if (isDiagnosticsEnabled()) { - logDiagnostic( - "[LOOKUP] Properties file at '" + url + "'" - + " with priority " + newPriority - + " does not override file at '" + propsUrl + "'" - + " with priority " + priority); - } - } - } - - } - } - } catch (SecurityException e) { - if (isDiagnosticsEnabled()) { - logDiagnostic("SecurityException thrown while trying to find/read config files."); - } - } - - if (isDiagnosticsEnabled()) { - if (props == null) { - logDiagnostic( - "[LOOKUP] No properties file of name '" + fileName - + "' found."); - } else { - logDiagnostic( - "[LOOKUP] Properties file of name '" + fileName - + "' found at '" + propsUrl + '"'); - } - } - - return props; - } - - /** - * Determines whether the user wants internal diagnostic output. If so, - * returns an appropriate writer object. Users can enable diagnostic - * output by setting the system property named {@link #DIAGNOSTICS_DEST_PROPERTY} to - * a filename, or the special values STDOUT or STDERR. - */ - private static void initDiagnostics() { - String dest; - try { - dest = System.getProperty(DIAGNOSTICS_DEST_PROPERTY); - if (dest == null) { - return; - } - } catch(SecurityException ex) { - // We must be running in some very secure environment. - // We just have to assume output is not wanted.. - return; - } - - if (dest.equals("STDOUT")) { - diagnosticsStream = System.out; - } else if (dest.equals("STDERR")) { - diagnosticsStream = System.err; - } else { - try { - // open the file in append mode - FileOutputStream fos = new FileOutputStream(dest, true); - diagnosticsStream = new PrintStream(fos); - } catch(IOException ex) { - // We should report this to the user - but how? - return; - } - } - - // In order to avoid confusion where multiple instances of JCL are - // being used via different classloaders within the same app, we - // ensure each logged message has a prefix of form - // [LogFactory from classloader OID] - // - // Note that this prefix should be kept consistent with that - // in LogFactoryImpl. However here we don't need to output info - // about the actual *instance* of LogFactory, as all methods that - // output diagnostics from this class are static. - String classLoaderName; - try { - ClassLoader classLoader = thisClassLoader; - if (thisClassLoader == null) { - classLoaderName = "BOOTLOADER"; - } else { - classLoaderName = objectId(classLoader); - } - } catch(SecurityException e) { - classLoaderName = "UNKNOWN"; - } - diagnosticPrefix = "[LogFactory from " + classLoaderName + "] "; - } - - /** - * Indicates true if the user has enabled internal logging. - * <p> - * By the way, sorry for the incorrect grammar, but calling this method - * areDiagnosticsEnabled just isn't java beans style. - * - * @return true if calls to logDiagnostic will have any effect. - * @since 1.1 - */ - protected static boolean isDiagnosticsEnabled() { - return diagnosticsStream != null; - } - - /** - * Write the specified message to the internal logging destination. - * <p> - * Note that this method is private; concrete subclasses of this class - * should not call it because the diagnosticPrefix string this - * method puts in front of all its messages is LogFactory@...., - * while subclasses should put SomeSubClass@... - * <p> - * Subclasses should instead compute their own prefix, then call - * logRawDiagnostic. Note that calling isDiagnosticsEnabled is - * fine for subclasses. - * <p> - * Note that it is safe to call this method before initDiagnostics - * is called; any output will just be ignored (as isDiagnosticsEnabled - * will return false). - * - * @param msg is the diagnostic message to be output. - */ - private static final void logDiagnostic(String msg) { - if (diagnosticsStream != null) { - diagnosticsStream.print(diagnosticPrefix); - diagnosticsStream.println(msg); - diagnosticsStream.flush(); - } - } - - /** - * Write the specified message to the internal logging destination. - * - * @param msg is the diagnostic message to be output. - * @since 1.1 - */ - protected static final void logRawDiagnostic(String msg) { - if (diagnosticsStream != null) { - diagnosticsStream.println(msg); - diagnosticsStream.flush(); - } - } - - /** - * Generate useful diagnostics regarding the classloader tree for - * the specified class. - * <p> - * As an example, if the specified class was loaded via a webapp's - * classloader, then you may get the following output: - * <pre> - * Class com.acme.Foo was loaded via classloader 11111 - * ClassLoader tree: 11111 -> 22222 (SYSTEM) -> 33333 -> BOOT - * </pre> - * <p> - * This method returns immediately if isDiagnosticsEnabled() - * returns false. - * - * @param clazz is the class whose classloader + tree are to be - * output. - */ - private static void logClassLoaderEnvironment(Class clazz) { - if (!isDiagnosticsEnabled()) { - return; - } - - try { - logDiagnostic("[ENV] Extension directories (java.ext.dir): " + System.getProperty("java.ext.dir")); - logDiagnostic("[ENV] Application classpath (java.class.path): " + System.getProperty("java.class.path")); - } catch(SecurityException ex) { - logDiagnostic("[ENV] Security setting prevent interrogation of system classpaths."); - } - - String className = clazz.getName(); - ClassLoader classLoader; - - try { - classLoader = getClassLoader(clazz); - } catch(SecurityException ex) { - // not much useful diagnostics we can print here! - logDiagnostic( - "[ENV] Security forbids determining the classloader for " + className); - return; - } - - logDiagnostic( - "[ENV] Class " + className + " was loaded via classloader " - + objectId(classLoader)); - logHierarchy("[ENV] Ancestry of classloader which loaded " + className + " is ", classLoader); - } - - /** - * Logs diagnostic messages about the given classloader - * and it's hierarchy. The prefix is prepended to the message - * and is intended to make it easier to understand the logs. - * @param prefix - * @param classLoader - */ - private static void logHierarchy(String prefix, ClassLoader classLoader) { - if (!isDiagnosticsEnabled()) { - return; - } - ClassLoader systemClassLoader; - if (classLoader != null) { - final String classLoaderString = classLoader.toString(); - logDiagnostic(prefix + objectId(classLoader) + " == '" + classLoaderString + "'"); - } - - try { - systemClassLoader = ClassLoader.getSystemClassLoader(); - } catch(SecurityException ex) { - logDiagnostic( - prefix + "Security forbids determining the system classloader."); - return; - } - if (classLoader != null) { - StringBuffer buf = new StringBuffer(prefix + "ClassLoader tree:"); - for(;;) { - buf.append(objectId(classLoader)); - if (classLoader == systemClassLoader) { - buf.append(" (SYSTEM) "); - } - - try { - classLoader = classLoader.getParent(); - } catch(SecurityException ex) { - buf.append(" --> SECRET"); - break; - } - - buf.append(" --> "); - if (classLoader == null) { - buf.append("BOOT"); - break; - } - } - logDiagnostic(buf.toString()); - } - } - - /** - * Returns a string that uniquely identifies the specified object, including - * its class. - * <p> - * The returned string is of form "classname@hashcode", ie is the same as - * the return value of the Object.toString() method, but works even when - * the specified object's class has overidden the toString method. - * - * @param o may be null. - * @return a string of form classname@hashcode, or "null" if param o is null. - * @since 1.1 - */ - public static String objectId(Object o) { - if (o == null) { - return "null"; - } else { - return o.getClass().getName() + "@" + System.identityHashCode(o); - } - } - - // ---------------------------------------------------------------------- - // Static initialiser block to perform initialisation at class load time. - // - // We can't do this in the class constructor, as there are many - // static methods on this class that can be called before any - // LogFactory instances are created, and they depend upon this - // stuff having been set up. - // - // Note that this block must come after any variable declarations used - // by any methods called from this block, as we want any static initialiser - // associated with the variable to run first. If static initialisers for - // variables run after this code, then (a) their value might be needed - // by methods called from here, and (b) they might *override* any value - // computed here! - // - // So the wisest thing to do is just to place this code at the very end - // of the class file. - // ---------------------------------------------------------------------- - - static { - // note: it's safe to call methods before initDiagnostics. - thisClassLoader = getClassLoader(LogFactory.class); - initDiagnostics(); - logClassLoaderEnvironment(LogFactory.class); - factories = createFactoryStore(); - if (isDiagnosticsEnabled()) { - logDiagnostic("BOOTSTRAP COMPLETED"); - } - } -} diff --git a/src/org/apache/commons/logging/LogSource.java b/src/org/apache/commons/logging/LogSource.java deleted file mode 100644 index e3c0603..0000000 --- a/src/org/apache/commons/logging/LogSource.java +++ /dev/null @@ -1,261 +0,0 @@ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging; - - -import java.lang.reflect.Constructor; -import java.util.Hashtable; - -import org.apache.commons.logging.impl.NoOpLog; - - -/** - * <p>Factory for creating {@link Log} instances. Applications should call - * the <code>makeNewLogInstance()</code> method to instantiate new instances - * of the configured {@link Log} implementation class.</p> - * - * <p>By default, calling <code>getInstance()</code> will use the following - * algorithm:</p> - * <ul> - * <li>If Log4J is available, return an instance of - * <code>org.apache.commons.logging.impl.Log4JLogger</code>.</li> - * <li>If JDK 1.4 or later is available, return an instance of - * <code>org.apache.commons.logging.impl.Jdk14Logger</code>.</li> - * <li>Otherwise, return an instance of - * <code>org.apache.commons.logging.impl.NoOpLog</code>.</li> - * </ul> - * - * <p>You can change the default behavior in one of two ways:</p> - * <ul> - * <li>On the startup command line, set the system property - * <code>org.apache.commons.logging.log</code> to the name of the - * <code>org.apache.commons.logging.Log</code> implementation class - * you want to use.</li> - * <li>At runtime, call <code>LogSource.setLogImplementation()</code>.</li> - * </ul> - * - * @deprecated Use {@link LogFactory} instead - The default factory - * implementation performs exactly the same algorithm as this class did - * - * @author Rod Waldhoff - * @version $Id: LogSource.java 155426 2005-02-26 13:10:49Z dirkv $ - */ -public class LogSource { - - // ------------------------------------------------------- Class Attributes - - static protected Hashtable logs = new Hashtable(); - - /** Is log4j available (in the current classpath) */ - static protected boolean log4jIsAvailable = false; - - /** Is JDK 1.4 logging available */ - static protected boolean jdk14IsAvailable = false; - - /** Constructor for current log class */ - static protected Constructor logImplctor = null; - - - // ----------------------------------------------------- Class Initializers - - static { - - // Is Log4J Available? - try { - if (null != Class.forName("org.apache.log4j.Logger")) { - log4jIsAvailable = true; - } else { - log4jIsAvailable = false; - } - } catch (Throwable t) { - log4jIsAvailable = false; - } - - // Is JDK 1.4 Logging Available? - try { - if ((null != Class.forName("java.util.logging.Logger")) && - (null != Class.forName("org.apache.commons.logging.impl.Jdk14Logger"))) { - jdk14IsAvailable = true; - } else { - jdk14IsAvailable = false; - } - } catch (Throwable t) { - jdk14IsAvailable = false; - } - - // Set the default Log implementation - String name = null; - try { - name = System.getProperty("org.apache.commons.logging.log"); - if (name == null) { - name = System.getProperty("org.apache.commons.logging.Log"); - } - } catch (Throwable t) { - } - if (name != null) { - try { - setLogImplementation(name); - } catch (Throwable t) { - try { - setLogImplementation - ("org.apache.commons.logging.impl.NoOpLog"); - } catch (Throwable u) { - ; - } - } - } else { - try { - if (log4jIsAvailable) { - setLogImplementation - ("org.apache.commons.logging.impl.Log4JLogger"); - } else if (jdk14IsAvailable) { - setLogImplementation - ("org.apache.commons.logging.impl.Jdk14Logger"); - } else { - setLogImplementation - ("org.apache.commons.logging.impl.NoOpLog"); - } - } catch (Throwable t) { - try { - setLogImplementation - ("org.apache.commons.logging.impl.NoOpLog"); - } catch (Throwable u) { - ; - } - } - } - - } - - - // ------------------------------------------------------------ Constructor - - - /** Don't allow others to create instances */ - private LogSource() { - } - - - // ---------------------------------------------------------- Class Methods - - - /** - * Set the log implementation/log implementation factory - * by the name of the class. The given class - * must implement {@link Log}, and provide a constructor that - * takes a single {@link String} argument (containing the name - * of the log). - */ - static public void setLogImplementation(String classname) throws - LinkageError, ExceptionInInitializerError, - NoSuchMethodException, SecurityException, - ClassNotFoundException { - try { - Class logclass = Class.forName(classname); - Class[] argtypes = new Class[1]; - argtypes[0] = "".getClass(); - logImplctor = logclass.getConstructor(argtypes); - } catch (Throwable t) { - logImplctor = null; - } - } - - - /** - * Set the log implementation/log implementation factory - * by class. The given class must implement {@link Log}, - * and provide a constructor that takes a single {@link String} - * argument (containing the name of the log). - */ - static public void setLogImplementation(Class logclass) throws - LinkageError, ExceptionInInitializerError, - NoSuchMethodException, SecurityException { - Class[] argtypes = new Class[1]; - argtypes[0] = "".getClass(); - logImplctor = logclass.getConstructor(argtypes); - } - - - /** Get a <code>Log</code> instance by class name */ - static public Log getInstance(String name) { - Log log = (Log) (logs.get(name)); - if (null == log) { - log = makeNewLogInstance(name); - logs.put(name, log); - } - return log; - } - - - /** Get a <code>Log</code> instance by class */ - static public Log getInstance(Class clazz) { - return getInstance(clazz.getName()); - } - - - /** - * Create a new {@link Log} implementation, based - * on the given <i>name</i>. - * <p> - * The specific {@link Log} implementation returned - * is determined by the value of the - * <tt>org.apache.commons.logging.log</tt> property. - * The value of <tt>org.apache.commons.logging.log</tt> may be set to - * the fully specified name of a class that implements - * the {@link Log} interface. This class must also - * have a public constructor that takes a single - * {@link String} argument (containing the <i>name</i> - * of the {@link Log} to be constructed. - * <p> - * When <tt>org.apache.commons.logging.log</tt> is not set, - * or when no corresponding class can be found, - * this method will return a Log4JLogger - * if the log4j Logger class is - * available in the {@link LogSource}'s classpath, or a - * Jdk14Logger if we are on a JDK 1.4 or later system, or - * NoOpLog if neither of the above conditions is true. - * - * @param name the log name (or category) - */ - static public Log makeNewLogInstance(String name) { - - Log log = null; - try { - Object[] args = new Object[1]; - args[0] = name; - log = (Log) (logImplctor.newInstance(args)); - } catch (Throwable t) { - log = null; - } - if (null == log) { - log = new NoOpLog(name); - } - return log; - - } - - - /** - * Returns a {@link String} array containing the names of - * all logs known to me. - */ - static public String[] getLogNames() { - return (String[]) (logs.keySet().toArray(new String[logs.size()])); - } - - -} diff --git a/src/org/apache/commons/logging/impl/Jdk14Logger.java b/src/org/apache/commons/logging/impl/Jdk14Logger.java deleted file mode 100644 index d4f840c..0000000 --- a/src/org/apache/commons/logging/impl/Jdk14Logger.java +++ /dev/null @@ -1,303 +0,0 @@ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - - -import java.io.Serializable; -import java.util.logging.Level; -import java.util.logging.Logger; - -import org.apache.commons.logging.Log; - - -/** - * <p>Implementation of the <code>org.apache.commons.logging.Log</code> - * interface that wraps the standard JDK logging mechanisms that were - * introduced in the Merlin release (JDK 1.4).</p> - * - * @author <a href="mailto:sanders@apache.org">Scott Sanders</a> - * @author <a href="mailto:bloritsch@apache.org">Berin Loritsch</a> - * @author <a href="mailto:donaldp@apache.org">Peter Donald</a> - * @version $Revision: 370652 $ $Date: 2006-01-19 22:23:48 +0000 (Thu, 19 Jan 2006) $ - */ - -public class Jdk14Logger implements Log, Serializable { - - /** - * This member variable simply ensures that any attempt to initialise - * this class in a pre-1.4 JVM will result in an ExceptionInInitializerError. - * It must not be private, as an optimising compiler could detect that it - * is not used and optimise it away. - */ - protected static final Level dummyLevel = Level.FINE; - - // ----------------------------------------------------------- Constructors - - - /** - * Construct a named instance of this Logger. - * - * @param name Name of the logger to be constructed - */ - public Jdk14Logger(String name) { - - this.name = name; - logger = getLogger(); - - } - - - // ----------------------------------------------------- Instance Variables - - - /** - * The underlying Logger implementation we are using. - */ - protected transient Logger logger = null; - - - /** - * The name of the logger we are wrapping. - */ - protected String name = null; - - - // --------------------------------------------------------- Public Methods - - private void log( Level level, String msg, Throwable ex ) { - - Logger logger = getLogger(); - if (logger.isLoggable(level)) { - // Hack (?) to get the stack trace. - Throwable dummyException=new Throwable(); - StackTraceElement locations[]=dummyException.getStackTrace(); - // Caller will be the third element - String cname="unknown"; - String method="unknown"; - if( locations!=null && locations.length >2 ) { - StackTraceElement caller=locations[2]; - cname=caller.getClassName(); - method=caller.getMethodName(); - } - if( ex==null ) { - logger.logp( level, cname, method, msg ); - } else { - logger.logp( level, cname, method, msg, ex ); - } - } - - } - - /** - * Logs a message with <code>java.util.logging.Level.FINE</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#debug(Object) - */ - public void debug(Object message) { - log(Level.FINE, String.valueOf(message), null); - } - - - /** - * Logs a message with <code>java.util.logging.Level.FINE</code>. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#debug(Object, Throwable) - */ - public void debug(Object message, Throwable exception) { - log(Level.FINE, String.valueOf(message), exception); - } - - - /** - * Logs a message with <code>java.util.logging.Level.SEVERE</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#error(Object) - */ - public void error(Object message) { - log(Level.SEVERE, String.valueOf(message), null); - } - - - /** - * Logs a message with <code>java.util.logging.Level.SEVERE</code>. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#error(Object, Throwable) - */ - public void error(Object message, Throwable exception) { - log(Level.SEVERE, String.valueOf(message), exception); - } - - - /** - * Logs a message with <code>java.util.logging.Level.SEVERE</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#fatal(Object) - */ - public void fatal(Object message) { - log(Level.SEVERE, String.valueOf(message), null); - } - - - /** - * Logs a message with <code>java.util.logging.Level.SEVERE</code>. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#fatal(Object, Throwable) - */ - public void fatal(Object message, Throwable exception) { - log(Level.SEVERE, String.valueOf(message), exception); - } - - - /** - * Return the native Logger instance we are using. - */ - public Logger getLogger() { - if (logger == null) { - logger = Logger.getLogger(name); - } - return (logger); - } - - - /** - * Logs a message with <code>java.util.logging.Level.INFO</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#info(Object) - */ - public void info(Object message) { - log(Level.INFO, String.valueOf(message), null); - } - - - /** - * Logs a message with <code>java.util.logging.Level.INFO</code>. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#info(Object, Throwable) - */ - public void info(Object message, Throwable exception) { - log(Level.INFO, String.valueOf(message), exception); - } - - - /** - * Is debug logging currently enabled? - */ - public boolean isDebugEnabled() { - return (getLogger().isLoggable(Level.FINE)); - } - - - /** - * Is error logging currently enabled? - */ - public boolean isErrorEnabled() { - return (getLogger().isLoggable(Level.SEVERE)); - } - - - /** - * Is fatal logging currently enabled? - */ - public boolean isFatalEnabled() { - return (getLogger().isLoggable(Level.SEVERE)); - } - - - /** - * Is info logging currently enabled? - */ - public boolean isInfoEnabled() { - return (getLogger().isLoggable(Level.INFO)); - } - - - /** - * Is trace logging currently enabled? - */ - public boolean isTraceEnabled() { - return (getLogger().isLoggable(Level.FINEST)); - } - - - /** - * Is warn logging currently enabled? - */ - public boolean isWarnEnabled() { - return (getLogger().isLoggable(Level.WARNING)); - } - - - /** - * Logs a message with <code>java.util.logging.Level.FINEST</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#trace(Object) - */ - public void trace(Object message) { - log(Level.FINEST, String.valueOf(message), null); - } - - - /** - * Logs a message with <code>java.util.logging.Level.FINEST</code>. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#trace(Object, Throwable) - */ - public void trace(Object message, Throwable exception) { - log(Level.FINEST, String.valueOf(message), exception); - } - - - /** - * Logs a message with <code>java.util.logging.Level.WARNING</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#warn(Object) - */ - public void warn(Object message) { - log(Level.WARNING, String.valueOf(message), null); - } - - - /** - * Logs a message with <code>java.util.logging.Level.WARNING</code>. - * - * @param message to log - * @param exception log this cause - * @see org.apache.commons.logging.Log#warn(Object, Throwable) - */ - public void warn(Object message, Throwable exception) { - log(Level.WARNING, String.valueOf(message), exception); - } - - -} diff --git a/src/org/apache/commons/logging/impl/LogFactoryImpl.java b/src/org/apache/commons/logging/impl/LogFactoryImpl.java deleted file mode 100644 index 8937b2f..0000000 --- a/src/org/apache/commons/logging/impl/LogFactoryImpl.java +++ /dev/null @@ -1,1400 +0,0 @@ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - -package org.apache.commons.logging.impl; - - -import java.lang.reflect.Constructor; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.net.URL; -import java.util.Enumeration; -import java.util.Hashtable; -import java.util.Vector; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogConfigurationException; -import org.apache.commons.logging.LogFactory; - - -/** - * <p>Concrete subclass of {@link LogFactory} that implements the - * following algorithm to dynamically select a logging implementation - * class to instantiate a wrapper for.</p> - * <ul> - * <li>Use a factory configuration attribute named - * <code>org.apache.commons.logging.Log</code> to identify the - * requested implementation class.</li> - * <li>Use the <code>org.apache.commons.logging.Log</code> system property - * to identify the requested implementation class.</li> - * <li>If <em>Log4J</em> is available, return an instance of - * <code>org.apache.commons.logging.impl.Log4JLogger</code>.</li> - * <li>If <em>JDK 1.4 or later</em> is available, return an instance of - * <code>org.apache.commons.logging.impl.Jdk14Logger</code>.</li> - * <li>Otherwise, return an instance of - * <code>org.apache.commons.logging.impl.SimpleLog</code>.</li> - * </ul> - * - * <p>If the selected {@link Log} implementation class has a - * <code>setLogFactory()</code> method that accepts a {@link LogFactory} - * parameter, this method will be called on each newly created instance - * to identify the associated factory. This makes factory configuration - * attributes available to the Log instance, if it so desires.</p> - * - * <p>This factory will remember previously created <code>Log</code> instances - * for the same name, and will return them on repeated requests to the - * <code>getInstance()</code> method.</p> - * - * @author Rod Waldhoff - * @author Craig R. McClanahan - * @author Richard A. Sitze - * @author Brian Stansberry - * @version $Revision: 399224 $ $Date: 2006-05-03 10:25:54 +0100 (Wed, 03 May 2006) $ - */ - -public class LogFactoryImpl extends LogFactory { - - - /** Log4JLogger class name */ - private static final String LOGGING_IMPL_LOG4J_LOGGER = "org.apache.commons.logging.impl.Log4JLogger"; - /** Jdk14Logger class name */ - private static final String LOGGING_IMPL_JDK14_LOGGER = "org.apache.commons.logging.impl.Jdk14Logger"; - /** Jdk13LumberjackLogger class name */ - private static final String LOGGING_IMPL_LUMBERJACK_LOGGER = "org.apache.commons.logging.impl.Jdk13LumberjackLogger"; - /** SimpleLog class name */ - private static final String LOGGING_IMPL_SIMPLE_LOGGER = "org.apache.commons.logging.impl.SimpleLog"; - - private static final String PKG_IMPL="org.apache.commons.logging.impl."; - private static final int PKG_LEN = PKG_IMPL.length(); - - // ----------------------------------------------------------- Constructors - - - - /** - * Public no-arguments constructor required by the lookup mechanism. - */ - public LogFactoryImpl() { - super(); - initDiagnostics(); // method on this object - if (isDiagnosticsEnabled()) { - logDiagnostic("Instance created."); - } - } - - - // ----------------------------------------------------- Manifest Constants - - - /** - * The name (<code>org.apache.commons.logging.Log</code>) of the system - * property identifying our {@link Log} implementation class. - */ - public static final String LOG_PROPERTY = - "org.apache.commons.logging.Log"; - - - /** - * The deprecated system property used for backwards compatibility with - * old versions of JCL. - */ - protected static final String LOG_PROPERTY_OLD = - "org.apache.commons.logging.log"; - - /** - * The name (<code>org.apache.commons.logging.Log.allowFlawedContext</code>) - * 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_CONTEXT_PROPERTY = - "org.apache.commons.logging.Log.allowFlawedContext"; - - /** - * The name (<code>org.apache.commons.logging.Log.allowFlawedDiscovery</code>) - * 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_DISCOVERY_PROPERTY = - "org.apache.commons.logging.Log.allowFlawedDiscovery"; - - /** - * The name (<code>org.apache.commons.logging.Log.allowFlawedHierarchy</code>) - * 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. - */ - public static final String ALLOW_FLAWED_HIERARCHY_PROPERTY = - "org.apache.commons.logging.Log.allowFlawedHierarchy"; - - - /** - * The 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 static final String[] classesToDiscover = { - LOGGING_IMPL_LOG4J_LOGGER, - "org.apache.commons.logging.impl.Jdk14Logger", - "org.apache.commons.logging.impl.Jdk13LumberjackLogger", - "org.apache.commons.logging.impl.SimpleLog" - }; - - - // ----------------------------------------------------- Instance Variables - - /** - * Determines whether logging classes should be loaded using the thread-context - * classloader, or via the classloader that loaded this LogFactoryImpl class. - */ - private boolean useTCCL = true; - - /** - * The string prefixed to every message output by the logDiagnostic method. - */ - private String diagnosticPrefix; - - - /** - * Configuration attributes. - */ - protected Hashtable attributes = new Hashtable(); - - - /** - * The {@link org.apache.commons.logging.Log} instances that have - * already been created, keyed by logger name. - */ - protected Hashtable instances = new Hashtable(); - - - /** - * Name of the class implementing the Log interface. - */ - private String logClassName; - - - /** - * The 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 <code>getLogConstructor()</code>, - * and then returned repeatedly. - */ - protected Constructor logConstructor = null; - - - /** - * The signature of the Constructor to be used. - */ - protected Class logConstructorSignature[] = - { java.lang.String.class }; - - - /** - * The one-argument <code>setLogFactory</code> method of the selected - * {@link org.apache.commons.logging.Log} method, if it exists. - */ - protected Method logMethod = null; - - - /** - * The signature of the <code>setLogFactory</code> method to be used. - */ - protected Class logMethodSignature[] = - { LogFactory.class }; - - /** - * See getBaseClassLoader and initConfiguration. - */ - private boolean allowFlawedContext; - - /** - * See handleFlawedDiscovery and initConfiguration. - */ - private boolean allowFlawedDiscovery; - - /** - * See handleFlawedHierarchy and initConfiguration. - */ - private boolean allowFlawedHierarchy; - - // --------------------------------------------------------- Public Methods - - - /** - * Return the configuration attribute with the specified name (if any), - * or <code>null</code> if there is no such attribute. - * - * @param name Name of the attribute to return - */ - public Object getAttribute(String name) { - - return (attributes.get(name)); - - } - - - /** - * Return an array containing the names of all currently defined - * configuration attributes. If there are no such attributes, a zero - * length array is returned. - */ - public String[] getAttributeNames() { - - 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); - - } - - - /** - * Convenience method to derive a name from the specified class and - * call <code>getInstance(String)</code> with it. - * - * @param clazz Class for which a suitable Log name will be derived - * - * @exception LogConfigurationException if a suitable <code>Log</code> - * instance cannot be returned - */ - public Log getInstance(Class clazz) throws LogConfigurationException { - - return (getInstance(clazz.getName())); - - } - - - /** - * <p>Construct (if necessary) and return a <code>Log</code> instance, - * using the factory's current set of configuration attributes.</p> - * - * <p><strong>NOTE</strong> - Depending upon the implementation of - * the <code>LogFactory</code> you are using, the <code>Log</code> - * 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.</p> - * - * @param name Logical name of the <code>Log</code> instance to be - * returned (the meaning of this name is only known to the underlying - * logging implementation that is being wrapped) - * - * @exception LogConfigurationException if a suitable <code>Log</code> - * instance cannot be returned - */ - public Log getInstance(String name) throws LogConfigurationException { - - Log instance = (Log) instances.get(name); - if (instance == null) { - instance = newInstance(name); - instances.put(name, instance); - } - return (instance); - - } - - - /** - * 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. - */ - public void release() { - - logDiagnostic("Releasing all known loggers"); - instances.clear(); - } - - - /** - * Remove any configuration attribute associated with the specified name. - * If there is no such attribute, no action is taken. - * - * @param name Name of the attribute to remove - */ - public void removeAttribute(String name) { - - attributes.remove(name); - - } - - - /** - * Set the configuration attribute with the specified name. Calling - * this with a <code>null</code> value is equivalent to calling - * <code>removeAttribute(name)</code>. - * <p> - * 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 - * <pre> - * LogFactory.getFactory().setAttribute(...) - * </pre> - * This must be done before the first Log object is created; configuration - * changes after that point will be ignored. - * <p> - * 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. - * - * @param name Name of the attribute to set - * @param value Value of the attribute to set, or <code>null</code> - * to remove any setting for this attribute - */ - public void setAttribute(String name, Object value) { - - 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(); - } - - } - - - // ------------------------------------------------------ - // Static Methods - // - // These methods only defined as workarounds for a java 1.2 bug; - // theoretically none of these are needed. - // ------------------------------------------------------ - - /** - * Gets the context classloader. - * This method is a workaround for a java 1.2 compiler bug. - * @since 1.1 - */ - protected static ClassLoader getContextClassLoader() throws LogConfigurationException { - return LogFactory.getContextClassLoader(); - } - - - /** - * Workaround for bug in Java1.2; in theory this method is not needed. - * See LogFactory.isDiagnosticsEnabled. - */ - protected static boolean isDiagnosticsEnabled() { - return LogFactory.isDiagnosticsEnabled(); - } - - - /** - * Workaround for bug in Java1.2; in theory this method is not needed. - * See LogFactory.getClassLoader. - * @since 1.1 - */ - protected static ClassLoader getClassLoader(Class clazz) { - return LogFactory.getClassLoader(clazz); - } - - - // ------------------------------------------------------ Protected Methods - - /** - * Calculate and cache a string that uniquely identifies this instance, - * including which classloader the object was loaded from. - * <p> - * This string will later be prefixed to each "internal logging" message - * emitted, so that users can clearly see any unexpected behaviour. - * <p> - * 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. - */ - private void initDiagnostics() { - // 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 + "] "; - } - - - /** - * Output a diagnostic message to a user-specified destination (if the - * user has enabled diagnostic logging). - * - * @param msg diagnostic message - * @since 1.1 - */ - protected void logDiagnostic(String msg) { - if (isDiagnosticsEnabled()) { - logRawDiagnostic(diagnosticPrefix + msg); - } - } - - /** - * Return the fully qualified Java classname of the {@link Log} - * implementation we will be using. - * - * @deprecated Never invoked by this class; subclasses should not assume - * it will be. - */ - protected String getLogClassName() { - - if (logClassName == null) { - discoverLogImplementation(getClass().getName()); - } - - return logClassName; - } - - - /** - * <p>Return the <code>Constructor</code> that can be called to instantiate - * new {@link org.apache.commons.logging.Log} instances.</p> - * - * <p><strong>IMPLEMENTATION NOTE</strong> - Race conditions caused by - * calling this method from more than one thread are ignored, because - * the same <code>Constructor</code> instance will ultimately be derived - * in all circumstances.</p> - * - * @exception LogConfigurationException if a suitable constructor - * cannot be returned - * - * @deprecated Never invoked by this class; subclasses should not assume - * it will be. - */ - protected Constructor getLogConstructor() - throws LogConfigurationException { - - // Return the previously identified Constructor (if any) - if (logConstructor == null) { - discoverLogImplementation(getClass().getName()); - } - - return logConstructor; - } - - - /** - * Is <em>JDK 1.3 with Lumberjack</em> logging available? - * - * @deprecated Never invoked by this class; subclasses should not assume - * it will be. - */ - protected boolean isJdk13LumberjackAvailable() { - return isLogLibraryAvailable( - "Jdk13Lumberjack", - "org.apache.commons.logging.impl.Jdk13LumberjackLogger"); - } - - - /** - * <p>Return <code>true</code> if <em>JDK 1.4 or later</em> logging - * is available. Also checks that the <code>Throwable</code> class - * supports <code>getStackTrace()</code>, which is required by - * Jdk14Logger.</p> - * - * @deprecated Never invoked by this class; subclasses should not assume - * it will be. - */ - protected boolean isJdk14Available() { - return isLogLibraryAvailable( - "Jdk14", - "org.apache.commons.logging.impl.Jdk14Logger"); - } - - - /** - * Is a <em>Log4J</em> implementation available? - * - * @deprecated Never invoked by this class; subclasses should not assume - * it will be. - */ - protected boolean isLog4JAvailable() { - return isLogLibraryAvailable( - "Log4J", - LOGGING_IMPL_LOG4J_LOGGER); - } - - - /** - * Create and return a new {@link org.apache.commons.logging.Log} - * instance for the specified name. - * - * @param name Name of the new logger - * - * @exception LogConfigurationException if a new instance cannot - * be created - */ - protected Log newInstance(String name) throws LogConfigurationException { - - 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); - } - } - - - // ------------------------------------------------------ Private Methods - - /** - * Utility method to check whether a particular logging library is - * present and available for use. Note that this does <i>not</i> - * affect the future behaviour of this class. - */ - private boolean isLogLibraryAvailable(String name, String classname) { - 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; - } - } - - /** - * Attempt to find an attribute (see method setAttribute) or a - * system property with the provided name and return its value. - * <p> - * 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. - * - * @return the value associated with the property, or null. - */ - private String getConfigurationValue(String property) { - 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; - } - - /** - * Get the setting for the user-configurable behaviour specified by key. - * If nothing has explicitly been set, then return dflt. - */ - private boolean getBooleanConfiguration(String key, boolean dflt) { - String val = getConfigurationValue(key); - if (val == null) - return dflt; - return Boolean.valueOf(val).booleanValue(); - } - - /** - * 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. - */ - private void initConfiguration() { - allowFlawedContext = getBooleanConfiguration(ALLOW_FLAWED_CONTEXT_PROPERTY, true); - allowFlawedDiscovery = getBooleanConfiguration(ALLOW_FLAWED_DISCOVERY_PROPERTY, true); - allowFlawedHierarchy = getBooleanConfiguration(ALLOW_FLAWED_HIERARCHY_PROPERTY, true); - } - - - /** - * Attempts to create a Log instance for the given category name. - * Follows the discovery process described in the class javadoc. - * - * @param logCategory the name of the log category - * - * @throws LogConfigurationException if an error in discovery occurs, - * or if no adapter at all can be instantiated - */ - private Log discoverLogImplementation(String logCategory) - throws LogConfigurationException - { - 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; - } - - - /** - * Appends message if the given name is similar to the candidate. - * @param messageBuffer <code>StringBuffer</code> the message should be appended to, - * not null - * @param name the (trimmed) name to be test against the candidate, not null - * @param candidate the candidate name (not null) - */ - private void informUponSimilarName(final StringBuffer messageBuffer, final String name, - final String 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("'?"); - } - } - - - /** - * 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}. - * - * @return classname specified by the user, or <code>null</code> - */ - private String findUserSpecifiedLogClassName() - { - 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; - } - - - /** - * Attempts to load the given class, find a suitable constructor, - * and instantiate an instance of Log. - * - * @param logAdapterClassName classname of the Log implementation - * - * @param logCategory argument to pass to the Log implementation's - * constructor - * - * @param affectState <code>true</code> if this object's state should - * be affected by this method call, <code>false</code> otherwise. - * - * @return an instance of the given class, or null if the logging - * library associated with the specified adapter is not available. - * - * @throws LogConfigurationException if there was a serious error with - * configuration and the handleFlawedDiscovery method decided this - * problem was fatal. - */ - private Log createLogFromClass(String logAdapterClassName, - String logCategory, - boolean affectState) - throws LogConfigurationException { - - 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; - } - - - /** - * Return the classloader from which we should try to load the logging - * adapter classes. - * <p> - * 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 <i>and</i> the allowFlawedContext option - * has been set then the classloader which loaded this class is returned - * instead. - * <p> - * 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. - * - */ - private ClassLoader getBaseClassLoader() throws LogConfigurationException { - 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; - } - - /** - * Given two related classloaders, return the one which is a child of - * the other. - * <p> - * @param c1 is a classloader (including the null classloader) - * @param c2 is a classloader (including the null classloader) - * - * @return c1 if it has c2 as an ancestor, c2 if it has c1 as an ancestor, - * and null if neither is an ancestor of the other. - */ - private ClassLoader getLowestClassLoader(ClassLoader c1, ClassLoader c2) { - // 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; - } - - /** - * Generates an internal diagnostic logging of the discovery failure and - * then throws a <code>LogConfigurationException</code> that wraps - * the passed <code>Throwable</code>. - * - * @param logAdapterClassName is the class name of the Log implementation - * that could not be instantiated. Cannot be <code>null</code>. - * - * @param classLoader is the classloader that we were trying to load the - * logAdapterClassName from when the exception occurred. - * - * @param discoveryFlaw is the Throwable created by the classloader - * - * @throws LogConfigurationException ALWAYS - */ - private void handleFlawedDiscovery(String logAdapterClassName, - ClassLoader classLoader, - Throwable discoveryFlaw) { - - if (isDiagnosticsEnabled()) { - logDiagnostic("Could not instantiate Log '" - + logAdapterClassName + "' -- " - + discoveryFlaw.getClass().getName() + ": " - + discoveryFlaw.getLocalizedMessage()); - } - - if (!allowFlawedDiscovery) { - throw new LogConfigurationException(discoveryFlaw); - } - } - - - /** - * Report a problem loading the log adapter, then either return - * (if the situation is considered recoverable) or throw a - * LogConfigurationException. - * <p> - * There are two possible reasons why we successfully loaded the - * specified log adapter class then failed to cast it to a Log object: - * <ol> - * <li>the specific class just doesn't implement the Log interface - * (user screwed up), or - * <li> the specified class has bound to a Log class loaded by some other - * classloader; Log@classloaderX cannot be cast to Log@classloaderY. - * </ol> - * <p> - * Here we try to figure out which case has occurred so we can give the - * user some reasonable feedback. - * - * @param badClassLoader is the classloader we loaded the problem class from, - * ie it is equivalent to badClass.getClassLoader(). - * - * @param badClass is a Class object with the desired name, but which - * does not implement Log correctly. - * - * @throws LogConfigurationException when the situation - * should not be recovered from. - */ - private void handleFlawedHierarchy(ClassLoader badClassLoader, Class badClass) - throws LogConfigurationException { - - 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()); - } - } - } -} diff --git a/src/org/apache/commons/logging/impl/NoOpLog.java b/src/org/apache/commons/logging/impl/NoOpLog.java deleted file mode 100644 index b698813..0000000 --- a/src/org/apache/commons/logging/impl/NoOpLog.java +++ /dev/null @@ -1,106 +0,0 @@ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - - -import java.io.Serializable; -import org.apache.commons.logging.Log; - - -/** - * <p>Trivial implementation of Log that throws away all messages. No - * configurable system properties are supported.</p> - * - * @author <a href="mailto:sanders@apache.org">Scott Sanders</a> - * @author Rod Waldhoff - * @version $Id: NoOpLog.java 155426 2005-02-26 13:10:49Z dirkv $ - */ -public class NoOpLog implements Log, Serializable { - - /** Convenience constructor */ - public NoOpLog() { } - /** Base constructor */ - public NoOpLog(String name) { } - /** Do nothing */ - public void trace(Object message) { } - /** Do nothing */ - public void trace(Object message, Throwable t) { } - /** Do nothing */ - public void debug(Object message) { } - /** Do nothing */ - public void debug(Object message, Throwable t) { } - /** Do nothing */ - public void info(Object message) { } - /** Do nothing */ - public void info(Object message, Throwable t) { } - /** Do nothing */ - public void warn(Object message) { } - /** Do nothing */ - public void warn(Object message, Throwable t) { } - /** Do nothing */ - public void error(Object message) { } - /** Do nothing */ - public void error(Object message, Throwable t) { } - /** Do nothing */ - public void fatal(Object message) { } - /** Do nothing */ - public void fatal(Object message, Throwable t) { } - - /** - * Debug is never enabled. - * - * @return false - */ - public final boolean isDebugEnabled() { return false; } - - /** - * Error is never enabled. - * - * @return false - */ - public final boolean isErrorEnabled() { return false; } - - /** - * Fatal is never enabled. - * - * @return false - */ - public final boolean isFatalEnabled() { return false; } - - /** - * Info is never enabled. - * - * @return false - */ - public final boolean isInfoEnabled() { return false; } - - /** - * Trace is never enabled. - * - * @return false - */ - public final boolean isTraceEnabled() { return false; } - - /** - * Warn is never enabled. - * - * @return false - */ - public final boolean isWarnEnabled() { return false; } - -} diff --git a/src/org/apache/commons/logging/impl/SimpleLog.java b/src/org/apache/commons/logging/impl/SimpleLog.java deleted file mode 100644 index 6b643d3..0000000 --- a/src/org/apache/commons/logging/impl/SimpleLog.java +++ /dev/null @@ -1,709 +0,0 @@ -/* - * Copyright 2001-2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - -import java.io.InputStream; -import java.io.Serializable; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.security.AccessController; -import java.security.PrivilegedAction; -import java.text.DateFormat; -import java.text.SimpleDateFormat; -import java.util.Date; -import java.util.Properties; - -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogConfigurationException; - -/** - * <p>Simple implementation of Log that sends all enabled log messages, - * for all defined loggers, to System.err. The following system properties - * are supported to configure the behavior of this logger:</p> - * <ul> - * <li><code>org.apache.commons.logging.simplelog.defaultlog</code> - - * Default logging detail level for all instances of SimpleLog. - * Must be one of ("trace", "debug", "info", "warn", "error", or "fatal"). - * If not specified, defaults to "info". </li> - * <li><code>org.apache.commons.logging.simplelog.log.xxxxx</code> - - * Logging detail level for a SimpleLog instance named "xxxxx". - * Must be one of ("trace", "debug", "info", "warn", "error", or "fatal"). - * If not specified, the default logging detail level is used.</li> - * <li><code>org.apache.commons.logging.simplelog.showlogname</code> - - * Set to <code>true</code> if you want the Log instance name to be - * included in output messages. Defaults to <code>false</code>.</li> - * <li><code>org.apache.commons.logging.simplelog.showShortLogname</code> - - * Set to <code>true</code> if you want the last component of the name to be - * included in output messages. Defaults to <code>true</code>.</li> - * <li><code>org.apache.commons.logging.simplelog.showdatetime</code> - - * Set to <code>true</code> if you want the current date and time - * to be included in output messages. Default is <code>false</code>.</li> - * <li><code>org.apache.commons.logging.simplelog.dateTimeFormat</code> - - * The date and time format to be used in the output messages. - * The pattern describing the date and time format is the same that is - * used in <code>java.text.SimpleDateFormat</code>. If the format is not - * specified or is invalid, the default format is used. - * The default format is <code>yyyy/MM/dd HH:mm:ss:SSS zzz</code>.</li> - * </ul> - * - * <p>In addition to looking for system properties with the names specified - * above, this implementation also checks for a class loader resource named - * <code>"simplelog.properties"</code>, and includes any matching definitions - * from this resource (if it exists).</p> - * - * @author <a href="mailto:sanders@apache.org">Scott Sanders</a> - * @author Rod Waldhoff - * @author Robert Burrell Donkin - * - * @version $Id: SimpleLog.java 399221 2006-05-03 09:20:24Z dennisl $ - */ -public class SimpleLog implements Log, Serializable { - - - // ------------------------------------------------------- Class Attributes - - /** All system properties used by <code>SimpleLog</code> start with this */ - static protected final String systemPrefix = - "org.apache.commons.logging.simplelog."; - - /** Properties loaded from simplelog.properties */ - static protected final Properties simpleLogProps = new Properties(); - - /** The default format to use when formating dates */ - static protected final String DEFAULT_DATE_TIME_FORMAT = - "yyyy/MM/dd HH:mm:ss:SSS zzz"; - - /** Include the instance name in the log message? */ - static protected boolean showLogName = false; - /** Include the short name ( last component ) of the logger in the log - * message. Defaults to true - otherwise we'll be lost in a flood of - * messages without knowing who sends them. - */ - static protected boolean showShortName = true; - /** Include the current time in the log message */ - static protected boolean showDateTime = false; - /** The date and time format to use in the log message */ - static protected String dateTimeFormat = DEFAULT_DATE_TIME_FORMAT; - /** Used to format times */ - static protected DateFormat dateFormatter = null; - - // ---------------------------------------------------- Log Level Constants - - - /** "Trace" level logging. */ - public static final int LOG_LEVEL_TRACE = 1; - /** "Debug" level logging. */ - public static final int LOG_LEVEL_DEBUG = 2; - /** "Info" level logging. */ - public static final int LOG_LEVEL_INFO = 3; - /** "Warn" level logging. */ - public static final int LOG_LEVEL_WARN = 4; - /** "Error" level logging. */ - public static final int LOG_LEVEL_ERROR = 5; - /** "Fatal" level logging. */ - public static final int LOG_LEVEL_FATAL = 6; - - /** Enable all logging levels */ - public static final int LOG_LEVEL_ALL = (LOG_LEVEL_TRACE - 1); - - /** Enable no logging levels */ - public static final int LOG_LEVEL_OFF = (LOG_LEVEL_FATAL + 1); - - // ------------------------------------------------------------ Initializer - - private static String getStringProperty(String name) { - String prop = null; - try { - prop = System.getProperty(name); - } catch (SecurityException e) { - ; // Ignore - } - return (prop == null) ? simpleLogProps.getProperty(name) : prop; - } - - private static String getStringProperty(String name, String dephault) { - String prop = getStringProperty(name); - return (prop == null) ? dephault : prop; - } - - private static boolean getBooleanProperty(String name, boolean dephault) { - String prop = getStringProperty(name); - return (prop == null) ? dephault : "true".equalsIgnoreCase(prop); - } - - // Initialize class attributes. - // Load properties file, if found. - // Override with system properties. - static { - // Add props from the resource simplelog.properties - InputStream in = getResourceAsStream("simplelog.properties"); - if(null != in) { - try { - simpleLogProps.load(in); - in.close(); - } catch(java.io.IOException e) { - // ignored - } - } - - showLogName = getBooleanProperty( systemPrefix + "showlogname", showLogName); - showShortName = getBooleanProperty( systemPrefix + "showShortLogname", showShortName); - showDateTime = getBooleanProperty( systemPrefix + "showdatetime", showDateTime); - - if(showDateTime) { - dateTimeFormat = getStringProperty(systemPrefix + "dateTimeFormat", - dateTimeFormat); - try { - dateFormatter = new SimpleDateFormat(dateTimeFormat); - } catch(IllegalArgumentException e) { - // If the format pattern is invalid - use the default format - dateTimeFormat = DEFAULT_DATE_TIME_FORMAT; - dateFormatter = new SimpleDateFormat(dateTimeFormat); - } - } - } - - - // ------------------------------------------------------------- Attributes - - /** The name of this simple log instance */ - protected String logName = null; - /** The current log level */ - protected int currentLogLevel; - /** The short name of this simple log instance */ - private String shortLogName = null; - - - // ------------------------------------------------------------ Constructor - - /** - * Construct a simple log with given name. - * - * @param name log name - */ - public SimpleLog(String name) { - - logName = name; - - // Set initial log level - // Used to be: set default log level to ERROR - // IMHO it should be lower, but at least info ( costin ). - setLevel(SimpleLog.LOG_LEVEL_INFO); - - // Set log level from properties - String lvl = getStringProperty(systemPrefix + "log." + logName); - int i = String.valueOf(name).lastIndexOf("."); - while(null == lvl && i > -1) { - name = name.substring(0,i); - lvl = getStringProperty(systemPrefix + "log." + name); - i = String.valueOf(name).lastIndexOf("."); - } - - if(null == lvl) { - lvl = getStringProperty(systemPrefix + "defaultlog"); - } - - if("all".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_ALL); - } else if("trace".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_TRACE); - } else if("debug".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_DEBUG); - } else if("info".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_INFO); - } else if("warn".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_WARN); - } else if("error".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_ERROR); - } else if("fatal".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_FATAL); - } else if("off".equalsIgnoreCase(lvl)) { - setLevel(SimpleLog.LOG_LEVEL_OFF); - } - - } - - - // -------------------------------------------------------- Properties - - /** - * <p> Set logging level. </p> - * - * @param currentLogLevel new logging level - */ - public void setLevel(int currentLogLevel) { - - this.currentLogLevel = currentLogLevel; - - } - - - /** - * <p> Get logging level. </p> - */ - public int getLevel() { - - return currentLogLevel; - } - - - // -------------------------------------------------------- Logging Methods - - - /** - * <p> Do the actual logging. - * This method assembles the message - * and then calls <code>write()</code> to cause it to be written.</p> - * - * @param type One of the LOG_LEVEL_XXX constants defining the log level - * @param message The message itself (typically a String) - * @param t The exception whose stack trace should be logged - */ - protected void log(int type, Object message, Throwable t) { - // Use a string buffer for better performance - StringBuffer buf = new StringBuffer(); - - // Append date-time if so configured - if(showDateTime) { - buf.append(dateFormatter.format(new Date())); - buf.append(" "); - } - - // Append a readable representation of the log level - switch(type) { - case SimpleLog.LOG_LEVEL_TRACE: buf.append("[TRACE] "); break; - case SimpleLog.LOG_LEVEL_DEBUG: buf.append("[DEBUG] "); break; - case SimpleLog.LOG_LEVEL_INFO: buf.append("[INFO] "); break; - case SimpleLog.LOG_LEVEL_WARN: buf.append("[WARN] "); break; - case SimpleLog.LOG_LEVEL_ERROR: buf.append("[ERROR] "); break; - case SimpleLog.LOG_LEVEL_FATAL: buf.append("[FATAL] "); break; - } - - // Append the name of the log instance if so configured - if( showShortName) { - if( shortLogName==null ) { - // Cut all but the last component of the name for both styles - shortLogName = logName.substring(logName.lastIndexOf(".") + 1); - shortLogName = - shortLogName.substring(shortLogName.lastIndexOf("/") + 1); - } - buf.append(String.valueOf(shortLogName)).append(" - "); - } else if(showLogName) { - buf.append(String.valueOf(logName)).append(" - "); - } - - // Append the message - buf.append(String.valueOf(message)); - - // Append stack trace if not null - if(t != null) { - buf.append(" <"); - buf.append(t.toString()); - buf.append(">"); - - java.io.StringWriter sw= new java.io.StringWriter(1024); - java.io.PrintWriter pw= new java.io.PrintWriter(sw); - t.printStackTrace(pw); - pw.close(); - buf.append(sw.toString()); - } - - // Print to the appropriate destination - write(buf); - - } - - - /** - * <p>Write the content of the message accumulated in the specified - * <code>StringBuffer</code> to the appropriate output destination. The - * default implementation writes to <code>System.err</code>.</p> - * - * @param buffer A <code>StringBuffer</code> containing the accumulated - * text to be logged - */ - protected void write(StringBuffer buffer) { - - System.err.println(buffer.toString()); - - } - - - /** - * Is the given log level currently enabled? - * - * @param logLevel is this level enabled? - */ - protected boolean isLevelEnabled(int logLevel) { - // log level are numerically ordered so can use simple numeric - // comparison - return (logLevel >= currentLogLevel); - } - - - // -------------------------------------------------------- Log Implementation - - - /** - * Logs a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#debug(Object) - */ - public final void debug(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) { - log(SimpleLog.LOG_LEVEL_DEBUG, message, null); - } - } - - - /** - * Logs a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG</code>. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#debug(Object, Throwable) - */ - public final void debug(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG)) { - log(SimpleLog.LOG_LEVEL_DEBUG, message, t); - } - } - - - /** - * Logs a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#trace(Object) - */ - public final void trace(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) { - log(SimpleLog.LOG_LEVEL_TRACE, message, null); - } - } - - - /** - * Logs a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE</code>. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#trace(Object, Throwable) - */ - public final void trace(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE)) { - log(SimpleLog.LOG_LEVEL_TRACE, message, t); - } - } - - - /** - * Logs a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#info(Object) - */ - public final void info(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) { - log(SimpleLog.LOG_LEVEL_INFO,message,null); - } - } - - - /** - * Logs a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO</code>. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#info(Object, Throwable) - */ - public final void info(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_INFO)) { - log(SimpleLog.LOG_LEVEL_INFO, message, t); - } - } - - - /** - * Logs a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#warn(Object) - */ - public final void warn(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) { - log(SimpleLog.LOG_LEVEL_WARN, message, null); - } - } - - - /** - * Logs a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN</code>. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#warn(Object, Throwable) - */ - public final void warn(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_WARN)) { - log(SimpleLog.LOG_LEVEL_WARN, message, t); - } - } - - - /** - * Logs a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#error(Object) - */ - public final void error(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) { - log(SimpleLog.LOG_LEVEL_ERROR, message, null); - } - } - - - /** - * Logs a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR</code>. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#error(Object, Throwable) - */ - public final void error(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR)) { - log(SimpleLog.LOG_LEVEL_ERROR, message, t); - } - } - - - /** - * Log a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL</code>. - * - * @param message to log - * @see org.apache.commons.logging.Log#fatal(Object) - */ - public final void fatal(Object message) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) { - log(SimpleLog.LOG_LEVEL_FATAL, message, null); - } - } - - - /** - * Logs a message with - * <code>org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL</code>. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#fatal(Object, Throwable) - */ - public final void fatal(Object message, Throwable t) { - - if (isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL)) { - log(SimpleLog.LOG_LEVEL_FATAL, message, t); - } - } - - - /** - * <p> Are debug messages currently enabled? </p> - * - * <p> This allows expensive operations such as <code>String</code> - * concatenation to be avoided when the message will be ignored by the - * logger. </p> - */ - public final boolean isDebugEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG); - } - - - /** - * <p> Are error messages currently enabled? </p> - * - * <p> This allows expensive operations such as <code>String</code> - * concatenation to be avoided when the message will be ignored by the - * logger. </p> - */ - public final boolean isErrorEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR); - } - - - /** - * <p> Are fatal messages currently enabled? </p> - * - * <p> This allows expensive operations such as <code>String</code> - * concatenation to be avoided when the message will be ignored by the - * logger. </p> - */ - public final boolean isFatalEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL); - } - - - /** - * <p> Are info messages currently enabled? </p> - * - * <p> This allows expensive operations such as <code>String</code> - * concatenation to be avoided when the message will be ignored by the - * logger. </p> - */ - public final boolean isInfoEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_INFO); - } - - - /** - * <p> Are trace messages currently enabled? </p> - * - * <p> This allows expensive operations such as <code>String</code> - * concatenation to be avoided when the message will be ignored by the - * logger. </p> - */ - public final boolean isTraceEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE); - } - - - /** - * <p> Are warn messages currently enabled? </p> - * - * <p> This allows expensive operations such as <code>String</code> - * concatenation to be avoided when the message will be ignored by the - * logger. </p> - */ - public final boolean isWarnEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_WARN); - } - - - /** - * 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. - */ - private static ClassLoader getContextClassLoader() - { - ClassLoader classLoader = null; - - if (classLoader == null) { - try { - // Are we running on a JDK 1.2 or later system? - Method method = Thread.class.getMethod("getContextClassLoader", - (Class[]) null); - - // Get the thread context class loader (if there is one) - try { - classLoader = (ClassLoader)method.invoke(Thread.currentThread(), - (Object[]) null); - - } catch (IllegalAccessException e) { - ; // ignore - } 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 (NoSuchMethodException e) { - // Assume we are running on JDK 1.1 - ; // ignore - } - } - - if (classLoader == null) { - classLoader = SimpleLog.class.getClassLoader(); - } - - // Return the selected class loader - return classLoader; - } - - private static InputStream getResourceAsStream(final String name) - { - return (InputStream)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - ClassLoader threadCL = getContextClassLoader(); - - if (threadCL != null) { - return threadCL.getResourceAsStream(name); - } else { - return ClassLoader.getSystemResourceAsStream(name); - } - } - }); - } -} - diff --git a/src/org/apache/commons/logging/impl/WeakHashtable.java b/src/org/apache/commons/logging/impl/WeakHashtable.java deleted file mode 100644 index e4749b6..0000000 --- a/src/org/apache/commons/logging/impl/WeakHashtable.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Copyright 2004 The Apache Software Foundation. - * - * Licensed under the Apache License, Version 2.0 (the "License"); - * you may not use this file except in compliance with the License. - * You may obtain a copy of the License at - * - * http://www.apache.org/licenses/LICENSE-2.0 - * - * Unless required by applicable law or agreed to in writing, software - * distributed under the License is distributed on an "AS IS" BASIS, - * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - * See the License for the specific language governing permissions and - * limitations under the License. - */ - - -package org.apache.commons.logging.impl; - -import java.lang.ref.ReferenceQueue; -import java.lang.ref.WeakReference; -import java.util.*; - -/** - * <p>Implementation of <code>Hashtable</code> that uses <code>WeakReference</code>'s - * to hold its keys thus allowing them to be reclaimed by the garbage collector. - * The associated values are retained using strong references.</p> - * - * <p>This class follows the symantics of <code>Hashtable</code> as closely as - * possible. It therefore does not accept null values or keys.</p> - * - * <p><strong>Note:</strong> - * This is <em>not</em> intended to be a general purpose hash table replacement. - * This implementation is also tuned towards a particular purpose: for use as a replacement - * for <code>Hashtable</code> in <code>LogFactory</code>. This application requires - * good liveliness for <code>get</code> and <code>put</code>. Various tradeoffs - * have been made with this in mind. - * </p> - * <p> - * <strong>Usage:</strong> typical use case is as a drop-in replacement - * for the <code>Hashtable</code> used in <code>LogFactory</code> for J2EE enviroments - * running 1.3+ JVMs. Use of this class <i>in most cases</i> (see below) will - * allow classloaders to be collected by the garbage collector without the need - * to call {@link org.apache.commons.logging.LogFactory#release(ClassLoader) LogFactory.release(ClassLoader)}. - * </p> - * - * <p><code>org.apache.commons.logging.LogFactory</code> checks whether this class - * can be supported by the current JVM, and if so then uses it to store - * references to the <code>LogFactory</code> implementationd it loads - * (rather than using a standard Hashtable instance). - * Having this class used instead of <code>Hashtable</code> solves - * certain issues related to dynamic reloading of applications in J2EE-style - * environments. However this class requires java 1.3 or later (due to its use - * of <code>java.lang.ref.WeakReference</code> and associates). - * And by the way, this extends <code>Hashtable</code> rather than <code>HashMap</code> - * for backwards compatibility reasons. See the documentation - * for method <code>LogFactory.createFactoryStore</code> for more details.</p> - * - * <p>The reason all this is necessary is due to a issue which - * arises during hot deploy in a J2EE-like containers. - * Each component running in the container owns one or more classloaders; when - * the component loads a LogFactory instance via the component classloader - * a reference to it gets stored in the static LogFactory.factories member, - * keyed by the component's classloader so different components don't - * stomp on each other. When the component is later unloaded, the container - * sets the component's classloader to null with the intent that all the - * component's classes get garbage-collected. However there's still a - * reference to the component's classloader from a key in the "global" - * <code>LogFactory</code>'s factories member! If <code>LogFactory.release()</code> - * is called whenever component is unloaded, the classloaders will be correctly - * garbage collected; this <i>should</i> be done by any container that - * bundles commons-logging by default. However, holding the classloader - * references weakly ensures that the classloader will be garbage collected - * without the container performing this step. </p> - * - * <p> - * <strong>Limitations:</strong> - * There is still one (unusual) scenario in which a component will not - * be correctly unloaded without an explicit release. Though weak references - * are used for its keys, it is necessary to use strong references for its values. - * </p> - * - * <p> If the abstract class <code>LogFactory</code> is - * loaded by the container classloader but a subclass of - * <code>LogFactory</code> [LogFactory1] is loaded by the component's - * classloader and an instance stored in the static map associated with the - * base LogFactory class, then there is a strong reference from the LogFactory - * class to the LogFactory1 instance (as normal) and a strong reference from - * the LogFactory1 instance to the component classloader via - * <code>getClass().getClassLoader()</code>. This chain of references will prevent - * collection of the child classloader.</p> - * - * <p> - * Such a situation occurs when the commons-logging.jar is - * loaded by a parent classloader (e.g. a server level classloader in a - * servlet container) and a custom <code>LogFactory</code> implementation is - * loaded by a child classloader (e.g. a web app classloader).</p> - * - * <p>To avoid this scenario, ensure - * that any custom LogFactory subclass is loaded by the same classloader as - * the base <code>LogFactory</code>. Creating custom LogFactory subclasses is, - * however, rare. The standard LogFactoryImpl class should be sufficient - * for most or all users.</p> - * - * - * @author Brian Stansberry - * - * @since 1.1 - */ -public final class WeakHashtable extends Hashtable { - - /** - * The maximum number of times put() or remove() can be called before - * the map will be purged of all cleared entries. - */ - private static final int MAX_CHANGES_BEFORE_PURGE = 100; - - /** - * The maximum number of times put() or remove() can be called before - * the map will be purged of one cleared entry. - */ - private static final int PARTIAL_PURGE_COUNT = 10; - - /* ReferenceQueue we check for gc'd keys */ - private ReferenceQueue queue = new ReferenceQueue(); - /* Counter used to control how often we purge gc'd entries */ - private int changeCount = 0; - - /** - * Constructs a WeakHashtable with the Hashtable default - * capacity and load factor. - */ - public WeakHashtable() {} - - - /** - *@see Hashtable - */ - public boolean containsKey(Object key) { - // purge should not be required - Referenced referenced = new Referenced(key); - return super.containsKey(referenced); - } - - /** - *@see Hashtable - */ - public Enumeration elements() { - purge(); - return super.elements(); - } - - /** - *@see Hashtable - */ - public Set entrySet() { - purge(); - Set referencedEntries = super.entrySet(); - Set unreferencedEntries = new HashSet(); - for (Iterator it=referencedEntries.iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - Referenced referencedKey = (Referenced) entry.getKey(); - Object key = referencedKey.getValue(); - Object value = entry.getValue(); - if (key != null) { - Entry dereferencedEntry = new Entry(key, value); - unreferencedEntries.add(dereferencedEntry); - } - } - return unreferencedEntries; - } - - /** - *@see Hashtable - */ - public Object get(Object key) { - // for performance reasons, no purge - Referenced referenceKey = new Referenced(key); - return super.get(referenceKey); - } - - /** - *@see Hashtable - */ - public Enumeration keys() { - purge(); - final Enumeration enumer = super.keys(); - return new Enumeration() { - public boolean hasMoreElements() { - return enumer.hasMoreElements(); - } - public Object nextElement() { - Referenced nextReference = (Referenced) enumer.nextElement(); - return nextReference.getValue(); - } - }; - } - - - /** - *@see Hashtable - */ - public Set keySet() { - purge(); - Set referencedKeys = super.keySet(); - Set unreferencedKeys = new HashSet(); - for (Iterator it=referencedKeys.iterator(); it.hasNext();) { - Referenced referenceKey = (Referenced) it.next(); - Object keyValue = referenceKey.getValue(); - if (keyValue != null) { - unreferencedKeys.add(keyValue); - } - } - return unreferencedKeys; - } - - /** - *@see Hashtable - */ - public Object put(Object key, Object value) { - // check for nulls, ensuring symantics match superclass - if (key == null) { - throw new NullPointerException("Null keys are not allowed"); - } - if (value == null) { - throw new NullPointerException("Null values are not allowed"); - } - - // for performance reasons, only purge every - // MAX_CHANGES_BEFORE_PURGE times - if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) { - purge(); - changeCount = 0; - } - // do a partial purge more often - else if ((changeCount % PARTIAL_PURGE_COUNT) == 0) { - purgeOne(); - } - - Object result = null; - Referenced keyRef = new Referenced(key, queue); - return super.put(keyRef, value); - } - - /** - *@see Hashtable - */ - public void putAll(Map t) { - if (t != null) { - Set entrySet = t.entrySet(); - for (Iterator it=entrySet.iterator(); it.hasNext();) { - Map.Entry entry = (Map.Entry) it.next(); - put(entry.getKey(), entry.getValue()); - } - } - } - - /** - *@see Hashtable - */ - public Collection values() { - purge(); - return super.values(); - } - - /** - *@see Hashtable - */ - public Object remove(Object key) { - // for performance reasons, only purge every - // MAX_CHANGES_BEFORE_PURGE times - if (changeCount++ > MAX_CHANGES_BEFORE_PURGE) { - purge(); - changeCount = 0; - } - // do a partial purge more often - else if ((changeCount % PARTIAL_PURGE_COUNT) == 0) { - purgeOne(); - } - return super.remove(new Referenced(key)); - } - - /** - *@see Hashtable - */ - public boolean isEmpty() { - purge(); - return super.isEmpty(); - } - - /** - *@see Hashtable - */ - public int size() { - purge(); - return super.size(); - } - - /** - *@see Hashtable - */ - public String toString() { - purge(); - return super.toString(); - } - - /** - * @see Hashtable - */ - protected void rehash() { - // purge here to save the effort of rehashing dead entries - purge(); - super.rehash(); - } - - /** - * Purges all entries whose wrapped keys - * have been garbage collected. - */ - private void purge() { - synchronized (queue) { - WeakKey key; - while ((key = (WeakKey) queue.poll()) != null) { - super.remove(key.getReferenced()); - } - } - } - - /** - * Purges one entry whose wrapped key - * has been garbage collected. - */ - private void purgeOne() { - - synchronized (queue) { - WeakKey key = (WeakKey) queue.poll(); - if (key != null) { - super.remove(key.getReferenced()); - } - } - } - - /** Entry implementation */ - private final static class Entry implements Map.Entry { - - private final Object key; - private final Object value; - - private Entry(Object key, Object value) { - this.key = key; - this.value = value; - } - - public boolean equals(Object o) { - boolean result = false; - if (o != null && o instanceof Map.Entry) { - Map.Entry entry = (Map.Entry) o; - result = (getKey()==null ? - entry.getKey() == null : - getKey().equals(entry.getKey())) - && - (getValue()==null ? - entry.getValue() == null : - getValue().equals(entry.getValue())); - } - return result; - } - - public int hashCode() { - - return (getKey()==null ? 0 : getKey().hashCode()) ^ - (getValue()==null ? 0 : getValue().hashCode()); - } - - public Object setValue(Object value) { - throw new UnsupportedOperationException("Entry.setValue is not supported."); - } - - public Object getValue() { - return value; - } - - public Object getKey() { - return key; - } - } - - - /** Wrapper giving correct symantics for equals and hashcode */ - private final static class Referenced { - - private final WeakReference reference; - private final int hashCode; - - /** - * - * @throws NullPointerException if referant is <code>null</code> - */ - private Referenced(Object referant) { - reference = new WeakReference(referant); - // Calc a permanent hashCode so calls to Hashtable.remove() - // work if the WeakReference has been cleared - hashCode = referant.hashCode(); - } - - /** - * - * @throws NullPointerException if key is <code>null</code> - */ - private Referenced(Object key, ReferenceQueue queue) { - reference = new WeakKey(key, queue, this); - // Calc a permanent hashCode so calls to Hashtable.remove() - // work if the WeakReference has been cleared - hashCode = key.hashCode(); - - } - - public int hashCode() { - return hashCode; - } - - private Object getValue() { - return reference.get(); - } - - public boolean equals(Object o) { - boolean result = false; - if (o instanceof Referenced) { - Referenced otherKey = (Referenced) o; - Object thisKeyValue = getValue(); - Object otherKeyValue = otherKey.getValue(); - if (thisKeyValue == null) { - result = (otherKeyValue == null); - - // Since our hashcode was calculated from the original - // non-null referant, the above check breaks the - // hashcode/equals contract, as two cleared Referenced - // objects could test equal but have different hashcodes. - // We can reduce (not eliminate) the chance of this - // happening by comparing hashcodes. - if (result == true) { - result = (this.hashCode() == otherKey.hashCode()); - } - // In any case, as our c'tor does not allow null referants - // and Hashtable does not do equality checks between - // existing keys, normal hashtable operations should never - // result in an equals comparison between null referants - } - else - { - result = thisKeyValue.equals(otherKeyValue); - } - } - return result; - } - } - - /** - * WeakReference subclass that holds a hard reference to an - * associated <code>value</code> and also makes accessible - * the Referenced object holding it. - */ - private final static class WeakKey extends WeakReference { - - private final Referenced referenced; - - private WeakKey(Object key, - ReferenceQueue queue, - Referenced referenced) { - super(key, queue); - this.referenced = referenced; - } - - private Referenced getReferenced() { - return referenced; - } - } -} diff --git a/src/org/apache/commons/logging/impl/package.html b/src/org/apache/commons/logging/impl/package.html deleted file mode 100644 index eb26b76..0000000 --- a/src/org/apache/commons/logging/impl/package.html +++ /dev/null @@ -1,21 +0,0 @@ -<!-- - - Copyright 2001-2004 The Apache Software Foundation. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ---> - -<body> -<p>Concrete implementations of commons-logging wrapper APIs.</p> -</body> diff --git a/src/org/apache/commons/logging/package.html b/src/org/apache/commons/logging/package.html deleted file mode 100644 index cfde4f0..0000000 --- a/src/org/apache/commons/logging/package.html +++ /dev/null @@ -1,254 +0,0 @@ -<!-- - - Copyright 2001-2004 The Apache Software Foundation. - - Licensed under the Apache License, Version 2.0 (the "License"); - you may not use this file except in compliance with the License. - You may obtain a copy of the License at - - http://www.apache.org/licenses/LICENSE-2.0 - - Unless required by applicable law or agreed to in writing, software - distributed under the License is distributed on an "AS IS" BASIS, - WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. - See the License for the specific language governing permissions and - limitations under the License. - ---> - -<body> -<p>Simple wrapper API around multiple logging APIs.</p> - - -<h3>Overview</h3> - -<p>This package provides an API for logging in server-based applications that -can be used around a variety of different logging implementations, including -prebuilt support for the following:</p> -<ul> -<li><a href="http://logging.apache.org/log4j/">Log4J</a> (version 1.2 or later) - from Apache's Jakarta project. Each named <a href="Log.html">Log</a> - instance is connected to a corresponding Log4J Logger.</li> -<li><a href="http://java.sun.com/j2se/1.4/docs/guide/util/logging/index.html"> - JDK Logging API</a>, included in JDK 1.4 or later systems. Each named - <a href="Log.html">Log</a> instance is connected to a corresponding - <code>java.util.logging.Logger</code> instance.</li> -<li><a href="http://avalon.apache.org/logkit/">LogKit</a> from Apache's - Avalon project. Each named <a href="Log.html">Log</a> instance is - connected to a corresponding LogKit <code>Logger</code>.</li> -<li><a href="impl/NoOpLog.html">NoOpLog</a> implementation that simply swallows - all log output, for all named <a href="Log.html">Log</a> instances.</li> -<li><a href="impl/SimpleLog.html">SimpleLog</a> implementation that writes all - log output, for all named <a href="Log.html">Log</a> instances, to - System.err.</li> -</ul> - - -<h3>Quick Start Guide</h3> - -<p>For those impatient to just get on with it, the following example -illustrates the typical declaration and use of a logger that is named (by -convention) after the calling class: - -<pre> - import org.apache.commons.logging.Log; - import org.apache.commons.logging.LogFactory; - - public class Foo { - - private Log log = LogFactory.getLog(Foo.class); - - public void foo() { - ... - try { - if (log.isDebugEnabled()) { - log.debug("About to do something to object " + name); - } - name.bar(); - } catch (IllegalStateException e) { - log.error("Something bad happened to " + name, e); - } - ... - } -</pre> - -<p>Unless you configure things differently, all log output will be written -to System.err. Therefore, you really will want to review the remainder of -this page in order to understand how to configure logging for your -application.</p> - - -<h3>Configuring the Commons Logging Package</h3> - - -<h4>Choosing a <code>LogFactory</code> Implementation</h4> - -<p>From an application perspective, the first requirement is to retrieve an -object reference to the <code>LogFactory</code> instance that will be used -to create <code><a href="Log.html">Log</a></code> instances for this -application. This is normally accomplished by calling the static -<code>getFactory()</code> method. This method implements the following -discovery algorithm to select the name of the <code>LogFactory</code> -implementation class this application wants to use:</p> -<ul> -<li>Check for a system property named - <code>org.apache.commons.logging.LogFactory</code>.</li> -<li>Use the JDK 1.3 JAR Services Discovery mechanism (see - <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html"> - http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html</a> for - more information) to look for a resource named - <code>META-INF/services/org.apache.commons.logging.LogFactory</code> - whose first line is assumed to contain the desired class name.</li> -<li>Look for a properties file named <code>commons-logging.properties</code> - visible in the application class path, with a property named - <code>org.apache.commons.logging.LogFactory</code> defining the - desired implementation class name.</li> -<li>Fall back to a default implementation, which is described - further below.</li> -</ul> - -<p>If a <code>commons-logging.properties</code> file is found, all of the -properties defined there are also used to set configuration attributes on -the instantiated <code>LogFactory</code> instance.</p> - -<p>Once an implementation class name is selected, the corresponding class is -loaded from the current Thread context class loader (if there is one), or -from the class loader that loaded the <code>LogFactory</code> class itself -otherwise. This allows a copy of <code>commons-logging.jar</code> to be -shared in a multiple class loader environment (such as a servlet container), -but still allow each web application to provide its own <code>LogFactory</code> -implementation, if it so desires. An instance of this class will then be -created, and cached per class loader. - - -<h4>The Default <code>LogFactory</code> Implementation</h4> - -<p>The Logging Package APIs include a default <code>LogFactory</code> -implementation class (<a href="impl/LogFactoryImpl.html"> -org.apache.commons.logging.impl.LogFactoryImpl</a>) that is selected if no -other implementation class name can be discovered. Its primary purpose is -to create (as necessary) and return <a href="Log.html">Log</a> instances -in response to calls to the <code>getInstance()</code> method. The default -implementation uses the following rules:</p> -<ul> -<li>At most one <code>Log</code> instance of the same name will be created. - Subsequent <code>getInstance()</code> calls to the same - <code>LogFactory</code> instance, with the same name or <code>Class</code> - parameter, will return the same <code>Log</code> instance.</li> -<li>When a new <code>Log</code> instance must be created, the default - <code>LogFactory</code> implementation uses the following discovery - process: - <ul> - <li>Look for a configuration attribute of this factory named - <code>org.apache.commons.logging.Log</code> (for backwards - compatibility to pre-1.0 versions of this API, an attribute - <code>org.apache.commons.logging.log</code> is also consulted).</li> - <li>Look for a system property named - <code>org.apache.commons.logging.Log</code> (for backwards - compatibility to pre-1.0 versions of this API, a system property - <code>org.apache.commons.logging.log</code> is also consulted).</li> - <li>If the Log4J logging system is available in the application - class path, use the corresponding wrapper class - (<a href="impl/Log4JLogger.html">Log4JLogger</a>).</li> - <li>If the application is executing on a JDK 1.4 system, use - the corresponding wrapper class - (<a href="impl/Jdk14Logger.html">Jdk14Logger</a>).</li> - <li>Fall back to the default simple logging implementation - (<a href="impl/SimpleLog.html">SimpleLog</a>).</li> - </ul></li> -<li>Load the class of the specified name from the thread context class - loader (if any), or from the class loader that loaded the - <code>LogFactory</code> class otherwise.</li> -<li>Instantiate an instance of the selected <code>Log</code> - implementation class, passing the specified name as the single - argument to its constructor.</li> -</ul> - -<p>See the <a href="impl/SimpleLog.html">SimpleLog</a> JavaDocs for detailed -configuration information for this default implementation.</p> - - -<h4>Configuring the Underlying Logging System</h4> - -<p>The basic principle is that the user is totally responsible for the -configuration of the underlying logging system. -Commons-logging should not change the existing configuration.</p> - -<p>Each individual <a href="Log.html">Log</a> implementation may -support its own configuration properties. These will be documented in the -class descriptions for the corresponding implementation class.</p> - -<p>Finally, some <code>Log</code> implementations (such as the one for Log4J) -require an external configuration file for the entire logging environment. -This file should be prepared in a manner that is specific to the actual logging -technology being used.</p> - - -<h3>Using the Logging Package APIs</h3> - -<p>Use of the Logging Package APIs, from the perspective of an application -component, consists of the following steps:</p> -<ol> -<li>Acquire a reference to an instance of - <a href="Log.html">org.apache.commons.logging.Log</a>, by calling the - factory method - <a href="LogFactory.html#getInstance(java.lang.String)"> - LogFactory.getInstance(String name)</a>. Your application can contain - references to multiple loggers that are used for different - purposes. A typical scenario for a server application is to have each - major component of the server use its own Log instance.</li> -<li>Cause messages to be logged (if the corresponding detail level is enabled) - by calling appropriate methods (<code>trace()</code>, <code>debug()</code>, - <code>info()</code>, <code>warn()</code>, <code>error</code>, and - <code>fatal()</code>).</li> -</ol> - -<p>For convenience, <code>LogFactory</code> also offers a static method -<code>getLog()</code> that combines the typical two-step pattern:</p> -<pre> - Log log = LogFactory.getFactory().getInstance(Foo.class); -</pre> -<p>into a single method call:</p> -<pre> - Log log = LogFactory.getLog(Foo.class); -</pre> - -<p>For example, you might use the following technique to initialize and -use a <a href="Log.html">Log</a> instance in an application component:</p> -<pre> -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - -public class MyComponent { - - protected Log log = - LogFactory.getLog(MyComponent.class); - - // Called once at startup time - public void start() { - ... - log.info("MyComponent started"); - ... - } - - // Called once at shutdown time - public void stop() { - ... - log.info("MyComponent stopped"); - ... - } - - // Called repeatedly to process a particular argument value - // which you want logged if debugging is enabled - public void process(String value) { - ... - // Do the string concatenation only if logging is enabled - if (log.isDebugEnabled()) - log.debug("MyComponent processing " + value); - ... - } - -} -</pre> - -</body> |