From 885ab53f396b0fe4fd05cf0cd11a67c5b20a9a45 Mon Sep 17 00:00:00 2001 From: Rik Veenboer Date: Fri, 3 Jun 2011 16:04:40 +0000 Subject: [PATCH] Apache commons logging source files vervangen voor jar. Achtergebleven bestanden javazoom verwijderd. --- java/lib/commons-logging-1.1.1.jar | Bin 0 -> 60841 bytes java/lib/commons-logging-adapters-1.1.1.jar | Bin 0 -> 26520 bytes java/lib/commons-logging-api-1.1.1.jar | Bin 0 -> 52313 bytes java/src/org/apache/commons/logging/Log.java | 246 --- .../logging/LogConfigurationException.java | 98 - .../apache/commons/logging/LogFactory.java | 1824 ----------------- .../org/apache/commons/logging/LogSource.java | 262 --- .../commons/logging/impl/AvalonLogger.java | 292 --- .../logging/impl/Jdk13LumberjackLogger.java | 335 --- .../commons/logging/impl/Jdk14Logger.java | 304 --- .../commons/logging/impl/Log4JLogger.java | 342 ---- .../commons/logging/impl/LogFactoryImpl.java | 1500 -------------- .../commons/logging/impl/LogKitLogger.java | 294 --- .../apache/commons/logging/impl/NoOpLog.java | 107 - .../logging/impl/ServletContextCleaner.java | 138 -- .../commons/logging/impl/SimpleLog.java | 721 ------- .../commons/logging/impl/WeakHashtable.java | 478 ----- .../apache/commons/logging/impl/package.html | 22 - .../org/apache/commons/logging/package.html | 255 --- 19 files changed, 7218 deletions(-) create mode 100644 java/lib/commons-logging-1.1.1.jar create mode 100644 java/lib/commons-logging-adapters-1.1.1.jar create mode 100644 java/lib/commons-logging-api-1.1.1.jar delete mode 100644 java/src/org/apache/commons/logging/Log.java delete mode 100644 java/src/org/apache/commons/logging/LogConfigurationException.java delete mode 100644 java/src/org/apache/commons/logging/LogFactory.java delete mode 100644 java/src/org/apache/commons/logging/LogSource.java delete mode 100644 java/src/org/apache/commons/logging/impl/AvalonLogger.java delete mode 100644 java/src/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java delete mode 100644 java/src/org/apache/commons/logging/impl/Jdk14Logger.java delete mode 100644 java/src/org/apache/commons/logging/impl/Log4JLogger.java delete mode 100644 java/src/org/apache/commons/logging/impl/LogFactoryImpl.java delete mode 100644 java/src/org/apache/commons/logging/impl/LogKitLogger.java delete mode 100644 java/src/org/apache/commons/logging/impl/NoOpLog.java delete mode 100644 java/src/org/apache/commons/logging/impl/ServletContextCleaner.java delete mode 100644 java/src/org/apache/commons/logging/impl/SimpleLog.java delete mode 100644 java/src/org/apache/commons/logging/impl/WeakHashtable.java delete mode 100644 java/src/org/apache/commons/logging/impl/package.html delete mode 100644 java/src/org/apache/commons/logging/package.html diff --git a/java/lib/commons-logging-1.1.1.jar b/java/lib/commons-logging-1.1.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..8758a96b70cfba9466bacca19c0d99b87cf53734 GIT binary patch literal 60841 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
    {@^= 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 He!Ti0B=`{t literal 0 HcmV?d00001 diff --git a/java/lib/commons-logging-api-1.1.1.jar b/java/lib/commons-logging-api-1.1.1.jar new file mode 100644 index 0000000000000000000000000000000000000000..bd4511684badd0cc710df5169b98e7b8f351858e GIT binary patch literal 52313 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 literal 0 HcmV?d00001 diff --git a/java/src/org/apache/commons/logging/Log.java b/java/src/org/apache/commons/logging/Log.java deleted file mode 100644 index bf80bad..0000000 --- a/java/src/org/apache/commons/logging/Log.java +++ /dev/null @@ -1,246 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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; - -/** - *

    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.

    - * - *

    The six logging levels used by Log are (in order): - *

      - *
    1. trace (the least serious)
    2. - *
    3. debug
    4. - *
    5. info
    6. - *
    7. warn
    8. - *
    9. error
    10. - *
    11. fatal (the most serious)
    12. - *
    - * 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.

    - * - *

    Performance is often a logging concern. - * By examining the appropriate property, - * a component can avoid expensive operations (producing information - * to be logged).

    - * - *

    For example, - *

    - *    if (log.isDebugEnabled()) {
    - *        ... do something expensive ...
    - *        log.debug(theResult);
    - *    }
    - * 
    - *

    - * - *

    Configuration of the underlying logging system will generally be done - * external to the Logging APIs, through whatever mechanism is supported by - * that system.

    - * - * @author Scott Sanders - * @author Rod Waldhoff - * @version $Id: Log.java 424107 2006-07-20 23:15:42Z skitching $ - */ -public interface Log { - - - // ----------------------------------------------------- Logging Properties - - - /** - *

    Is debug logging currently enabled?

    - * - *

    Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than debug.

    - * - * @return true if debug is enabled in the underlying logger. - */ - public boolean isDebugEnabled(); - - - /** - *

    Is error logging currently enabled?

    - * - *

    Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than error.

    - * - * @return true if error is enabled in the underlying logger. - */ - public boolean isErrorEnabled(); - - - /** - *

    Is fatal logging currently enabled?

    - * - *

    Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than fatal.

    - * - * @return true if fatal is enabled in the underlying logger. - */ - public boolean isFatalEnabled(); - - - /** - *

    Is info logging currently enabled?

    - * - *

    Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than info.

    - * - * @return true if info is enabled in the underlying logger. - */ - public boolean isInfoEnabled(); - - - /** - *

    Is trace logging currently enabled?

    - * - *

    Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than trace.

    - * - * @return true if trace is enabled in the underlying logger. - */ - public boolean isTraceEnabled(); - - - /** - *

    Is warn logging currently enabled?

    - * - *

    Call this method to prevent having to perform expensive operations - * (for example, String concatenation) - * when the log level is more than warn.

    - * - * @return true if warn is enabled in the underlying logger. - */ - public boolean isWarnEnabled(); - - - // -------------------------------------------------------- Logging Methods - - - /** - *

    Log a message with trace log level.

    - * - * @param message log this message - */ - public void trace(Object message); - - - /** - *

    Log an error with trace log level.

    - * - * @param message log this message - * @param t log this cause - */ - public void trace(Object message, Throwable t); - - - /** - *

    Log a message with debug log level.

    - * - * @param message log this message - */ - public void debug(Object message); - - - /** - *

    Log an error with debug log level.

    - * - * @param message log this message - * @param t log this cause - */ - public void debug(Object message, Throwable t); - - - /** - *

    Log a message with info log level.

    - * - * @param message log this message - */ - public void info(Object message); - - - /** - *

    Log an error with info log level.

    - * - * @param message log this message - * @param t log this cause - */ - public void info(Object message, Throwable t); - - - /** - *

    Log a message with warn log level.

    - * - * @param message log this message - */ - public void warn(Object message); - - - /** - *

    Log an error with warn log level.

    - * - * @param message log this message - * @param t log this cause - */ - public void warn(Object message, Throwable t); - - - /** - *

    Log a message with error log level.

    - * - * @param message log this message - */ - public void error(Object message); - - - /** - *

    Log an error with error log level.

    - * - * @param message log this message - * @param t log this cause - */ - public void error(Object message, Throwable t); - - - /** - *

    Log a message with fatal log level.

    - * - * @param message log this message - */ - public void fatal(Object message); - - - /** - *

    Log an error with fatal log level.

    - * - * @param message log this message - * @param t log this cause - */ - public void fatal(Object message, Throwable t); - - -} diff --git a/java/src/org/apache/commons/logging/LogConfigurationException.java b/java/src/org/apache/commons/logging/LogConfigurationException.java deleted file mode 100644 index aae0708..0000000 --- a/java/src/org/apache/commons/logging/LogConfigurationException.java +++ /dev/null @@ -1,98 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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; - - -/** - *

    An exception that is thrown only if a suitable LogFactory - * or Log instance cannot be created by the corresponding - * factory methods.

    - * - * @author Craig R. McClanahan - * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 2006) $ - */ - -public class LogConfigurationException extends RuntimeException { - - - /** - * Construct a new exception with null 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/java/src/org/apache/commons/logging/LogFactory.java b/java/src/org/apache/commons/logging/LogFactory.java deleted file mode 100644 index f8b8955..0000000 --- a/java/src/org/apache/commons/logging/LogFactory.java +++ /dev/null @@ -1,1824 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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; - - -/** - *

    Factory for creating {@link Log} instances, with discovery and - * configuration features similar to that employed by standard Java APIs - * such as JAXP.

    - * - *

    IMPLEMENTATION NOTE - This implementation is heavily - * based on the SAXParserFactory and DocumentBuilderFactory implementations - * (corresponding to the JAXP pluggability APIs) found in Apache Xerces.

    - * - * @author Craig R. McClanahan - * @author Costin Manolache - * @author Richard A. Sitze - * @version $Revision: 593798 $ $Date: 2007-11-10 18:40:43 +0100 $ - */ - -public abstract class LogFactory { - // Implementation note re AccessController usage - // - // It is important to keep code invoked via an AccessController to small - // auditable blocks. Such code must carefully evaluate all user input - // (parameters, system properties, config file contents, etc). As an - // example, a Log implementation should not write to its logfile - // with an AccessController anywhere in the call stack, otherwise an - // insecure application could configure the log implementation to write - // to a protected file using the privileges granted to JCL rather than - // to the calling application. - // - // Under no circumstance should a non-private method return data that is - // retrieved via an AccessController. That would allow an insecure app - // to invoke that method and obtain data that it is not permitted to have. - // - // Invoking user-supplied code with an AccessController set is not a major - // issue (eg invoking the constructor of the class specified by - // HASHTABLE_IMPLEMENTATION_PROPERTY). That class will be in a different - // trust domain, and therefore must have permissions to do whatever it - // is trying to do regardless of the permissions granted to JCL. There is - // a slight issue in that untrusted code may point that environment var - // to another trusted library, in which case the code runs if both that - // lib and JCL have the necessary permissions even when the untrusted - // caller does not. That's a pretty hard route to exploit though. - - - // ----------------------------------------------------- Manifest Constants - - /** - * The name (priority) 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 (use_tccl) 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 (org.apache.commons.logging.LogFactory) 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 LogFactory - * implementation class to use, if no other can be found. - */ - public static final String FACTORY_DEFAULT = - "org.apache.commons.logging.impl.LogFactoryImpl"; - - /** - * The name (commons-logging.properties) of the properties file to search for. - */ - public static final String FACTORY_PROPERTIES = - "commons-logging.properties"; - - /** - * JDK1.3+ - * 'Service Provider' specification. - * - */ - protected static final String SERVICE_ID = - "META-INF/services/org.apache.commons.logging.LogFactory"; - - /** - * The name (org.apache.commons.logging.diagnostics.dest) - * 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. - *

    - * 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. - *

    - * 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; - - /** - *

    Setting this system property - * (org.apache.commons.logging.LogFactory.HashtableImpl) - * value allows the Hashtable used to store - * classloaders to be substituted by an alternative implementation. - *

    - *

    - * Note: LogFactory will print: - *

    -     * [ERROR] LogFactory: Load of custom hashtable failed
    -     * 
    - * to system error and then continue using a standard Hashtable. - *

    - *

    - * Usage: Set this property when Java is invoked - * and LogFactory will attempt to load a new instance - * of the given implementation class. - * For example, running the following ant scriplet: - *

    -     *  <java classname="${test.runner}" fork="yes" failonerror="${test.failonerror}">
    -     *     ...
    -     *     <sysproperty 
    -     *        key="org.apache.commons.logging.LogFactory.HashtableImpl"
    -     *        value="org.apache.commons.logging.AltHashtable"/>
    -     *  </java>
    -     * 
    - * will mean that LogFactory will load an instance of - * org.apache.commons.logging.AltHashtable. - *

    - *

    - * 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 ;) - *

    - */ - 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 null 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 getInstance(String) with it. - * - * @param clazz Class for which a suitable Log name will be derived - * - * @exception LogConfigurationException if a suitable Log - * instance cannot be returned - */ - public abstract Log getInstance(Class clazz) - throws LogConfigurationException; - - - /** - *

    Construct (if necessary) and return a Log instance, - * using the factory's current set of configuration attributes.

    - * - *

    NOTE - Depending upon the implementation of - * the LogFactory you are using, the Log - * 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.

    - * - * @param name Logical name of the Log 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 Log - * 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 null value is equivalent to calling - * removeAttribute(name). - * - * @param name Name of the attribute to set - * @param value Value of the attribute to set, or null - * to remove any setting for this attribute - */ - public abstract void setAttribute(String name, Object value); - - - // ------------------------------------------------------- Static Variables - - - /** - * The previously constructed LogFactory instances, keyed by - * the ClassLoader with which it was created. - */ - protected static Hashtable factories = null; - - /** - * Prevously constructed LogFactory instance as in the - * factories map, but for the case where - * getClassLoader returns null. - * This can happen when: - *
      - *
    • using JDK1.1 and the calling code is loaded via the system - * classloader (very common)
    • - *
    • using JDK1.2+ and the calling code is loaded via the boot - * classloader (only likely for embedded systems work).
    • - *
    - * Note that factories is a Hashtable (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. - *

    - * 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; - try { - storeImplementationClass = getSystemProperty(HASHTABLE_IMPLEMENTATION_PROPERTY, null); - } catch(SecurityException ex) { - // Permissions don't allow this to be accessed. Default to the "modern" - // weak hashtable implementation if it is available. - storeImplementationClass = null; - } - - 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 - - /** Utility method to safely trim a string. */ - private static String trim(String src) { - if (src == null) { - return null; - } - return src.trim(); - } - - /** - *

    Construct (if necessary) and return a LogFactory - * instance, using the following ordered lookup procedure to determine - * the name of the implementation class to be loaded.

    - *
      - *
    • The org.apache.commons.logging.LogFactory system - * property.
    • - *
    • The JDK 1.3 Service Discovery mechanism
    • - *
    • Use the properties file commons-logging.properties - * file, if found in the class path of this class. The configuration - * file is in standard java.util.Properties format and - * contains the fully qualified name of the implementation class - * with the key being the system property defined above.
    • - *
    • Fall back to a default implementation class - * (org.apache.commons.logging.impl.LogFactoryImpl).
    • - *
    - * - *

    NOTE - If the properties file method of identifying the - * LogFactory implementation class is utilized, all of the - * properties defined in this file will be set as configuration attributes - * on the corresponding LogFactory instance.

    - * - *

    NOTE - In a multithreaded environment it is possible - * that two different instances will be returned for the same - * classloader environment. - *

    - * - * @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 = getContextClassLoaderInternal(); - - 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 = getSystemProperty(FACTORY_PROPERTY, null); - 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" - + ": [" + trim(e.getMessage()) - + "]. 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" - + ": [" + trim(e.getMessage()) - + "] 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" - + ": [" + trim(ex.getMessage()) - + "]. 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 Log - * instance cannot be returned - */ - public static Log getLog(Class clazz) - throws LogConfigurationException { - - return (getFactory().getInstance(clazz)); - - } - - - /** - * Convenience method to return a named logger, without the application - * having to care about factories. - * - * @param name Logical name of the Log 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 Log - * instance cannot be returned - */ - public static Log getLog(String name) - throws LogConfigurationException { - - return (getFactory().getInstance(name)); - - } - - - /** - * 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 release() 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 release() 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. - *

    - * 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. - *

    - * 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. - *

    - * Note that returning an object fetched via an AccessController would - * technically be a security flaw anyway; untrusted code that has access - * to a trusted JCL library could use it to fetch the classloader for - * a class even when forbidden to do so directly. - * - * @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; - } - } - - /** - * Returns the current context classloader. - *

    - * In versions prior to 1.1, this method did not use an AccessController. - * In version 1.1, an AccessController wrapper was incorrectly added to - * this method, causing a minor security flaw. - *

    - * In version 1.1.1 this change was reverted; this method no longer uses - * an AccessController. User code wishing to obtain the context classloader - * must invoke this method via AccessController.doPrivileged if it needs - * support for that. - * - * @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 directGetContextClassLoader(); - } - - /** - * 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. - */ - private static ClassLoader getContextClassLoaderInternal() - throws LogConfigurationException { - return (ClassLoader)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return directGetContextClassLoader(); - } - }); - } - - /** - * Return the thread context class loader if available; otherwise return - * null. - *

    - * Most/all code should call getContextClassLoaderInternal rather than - * calling this method directly. - *

    - * The thread context class loader is available for JDK 1.2 - * or later, if certain security conditions are met. - *

    - * 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 LogFactory - * implementation class, loaded by the specified class loader. - * If that fails, try the class loader used to load this - * (abstract) LogFactory. - *

    - *

    ClassLoader conflicts

    - * 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. - *

    - * The problem is the same one that can occur when loading a concrete Log - * subclass via a context classloader. - *

    - * 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. - *

    - * 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. - *

    - * @param factoryClass Fully qualified name of the LogFactory - * 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. - *

    - * 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://commons.apache.org/logging/tech.html. " + - "If you have not explicitly specified a custom LogFactory then it is likely that " + - "the container has set one without your knowledge. " + - "In this case, consider using the commons-logging-adapters.jar file or " + - "specifying the standard LogFactory from the command line. "; - } else { - msg = msg + "Please check the custom implementation. "; - } - msg = msg + "Help can be found @http://commons.apache.org/logging/troubleshooting.html."; - - if (isDiagnosticsEnabled()) { - logDiagnostic(msg); - } - - ClassCastException ex = new ClassCastException(msg); - throw ex; - } - - // Ignore exception, continue. Presumably the classloader was the - // TCCL; the code below will try to load the class via thisClassLoader. - // This will handle the case where the original calling class is in - // a shared classpath but the TCCL has a copy of LogFactory and the - // specified LogFactory implementation; we will fall back to using the - // LogFactory implementation from the same classloader as this class. - // - // Issue: this doesn't handle the reverse case, where this LogFactory - // is in the webapp, and the specified LogFactory implementation is - // in a shared classpath. In that case: - // (a) the class really does implement LogFactory (bad log msg above) - // (b) the fallback code will result in exactly the same problem. - } - } - - /* At this point, either classLoader == null, OR - * classLoader was unable to load factoryClass. - * - * In either case, we call Class.forName, which is equivalent - * to LogFactory.class.getClassLoader().load(name), ie we ignore - * the classloader parameter the caller passed, and fall back - * to trying the classloader associated with this class. See the - * javadoc for the newFactory method for more info on the - * consequences of this. - * - * Notes: - * * LogFactory.class.getClassLoader() may return 'null' - * if LogFactory is loaded by the bootstrap classloader. - */ - // Warning: must typecast here & allow exception - // to be generated/caught & recast properly. - if (isDiagnosticsEnabled()) { - logDiagnostic( - "Unable to load factory class via classloader " - + objectId(classLoader) - + " - trying the classloader associated with this LogFactory."); - } - logFactoryClass = Class.forName(factoryClass); - return (LogFactory) logFactoryClass.newInstance(); - } catch (Exception e) { - // Check to see if we've got a bad configuration - if (isDiagnosticsEnabled()) { - logDiagnostic("Unable to create LogFactory instance."); - } - if (logFactoryClass != null - && !LogFactory.class.isAssignableFrom(logFactoryClass)) { - - return new LogConfigurationException( - "The chosen LogFactory implementation does not extend LogFactory." - + " Please check your configuration.", - e); - } - return new LogConfigurationException(e); - } - } - - /** - * Determines whether the given class actually implements LogFactory. - * Diagnostic information is also logged. - *

    - * Usage: to diagnose whether a classloader conflict is the cause - * of incompatibility. The test used is whether the class is assignable from - * the LogFactory class loaded by the class's classloader. - * @param logFactoryClass Class which may implement LogFactory - * @return true if the logFactoryClass does extend - * LogFactory when that class is loaded via the same - * classloader that loaded the logFactoryClass. - */ - 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 running 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 - * running 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. - *

    - * 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. - *

    - * 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. - *

    - * 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. - *

    - * 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. - *

    - * 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. - *

    - * 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; - } - - /** - * Read the specified system property, using an AccessController so that - * the property can be read if JCL has been granted the appropriate - * security rights even if the calling code has not. - *

    - * Take care not to expose the value returned by this method to the - * calling application in any way; otherwise the calling app can use that - * info to access data that should not be available to it. - */ - private static String getSystemProperty(final String key, final String def) - throws SecurityException { - return (String) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return System.getProperty(key, def); - } - }); - } - - /** - * 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 = getSystemProperty(DIAGNOSTICS_DEST_PROPERTY, null); - 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. - *

    - * 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. - *

    - * 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@... - *

    - * Subclasses should instead compute their own prefix, then call - * logRawDiagnostic. Note that calling isDiagnosticsEnabled is - * fine for subclasses. - *

    - * 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. - *

    - * As an example, if the specified class was loaded via a webapp's - * classloader, then you may get the following output: - *

    -     * Class com.acme.Foo was loaded via classloader 11111
    -     * ClassLoader tree: 11111 -> 22222 (SYSTEM) -> 33333 -> BOOT 
    -     * 
    - *

    - * 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 { - // Deliberately use System.getProperty here instead of getSystemProperty; if - // the overall security policy for the calling application forbids access to - // these variables then we do not want to output them to the diagnostic stream. - 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. - *

    - * 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 running first. If static initialisers for - // variables running 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 (though - // diagnostic output gets discarded). - thisClassLoader = getClassLoader(LogFactory.class); - initDiagnostics(); - logClassLoaderEnvironment(LogFactory.class); - factories = createFactoryStore(); - if (isDiagnosticsEnabled()) { - logDiagnostic("BOOTSTRAP COMPLETED"); - } - } -} diff --git a/java/src/org/apache/commons/logging/LogSource.java b/java/src/org/apache/commons/logging/LogSource.java deleted file mode 100644 index 9cb5f11..0000000 --- a/java/src/org/apache/commons/logging/LogSource.java +++ /dev/null @@ -1,262 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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; - - -/** - *

    Factory for creating {@link Log} instances. Applications should call - * the makeNewLogInstance() method to instantiate new instances - * of the configured {@link Log} implementation class.

    - * - *

    By default, calling getInstance() will use the following - * algorithm:

    - *
      - *
    • If Log4J is available, return an instance of - * org.apache.commons.logging.impl.Log4JLogger.
    • - *
    • If JDK 1.4 or later is available, return an instance of - * org.apache.commons.logging.impl.Jdk14Logger.
    • - *
    • Otherwise, return an instance of - * org.apache.commons.logging.impl.NoOpLog.
    • - *
    - * - *

    You can change the default behavior in one of two ways:

    - *
      - *
    • On the startup command line, set the system property - * org.apache.commons.logging.log to the name of the - * org.apache.commons.logging.Log implementation class - * you want to use.
    • - *
    • At runtime, call LogSource.setLogImplementation().
    • - *
    - * - * @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 424107 2006-07-20 23:15:42Z skitching $ - */ -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 Log 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 Log instance by class */ - static public Log getInstance(Class clazz) { - return getInstance(clazz.getName()); - } - - - /** - * Create a new {@link Log} implementation, based - * on the given name. - *

    - * The specific {@link Log} implementation returned - * is determined by the value of the - * org.apache.commons.logging.log property. - * The value of org.apache.commons.logging.log 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 name - * of the {@link Log} to be constructed. - *

    - * When org.apache.commons.logging.log 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/java/src/org/apache/commons/logging/impl/AvalonLogger.java b/java/src/org/apache/commons/logging/impl/AvalonLogger.java deleted file mode 100644 index df8398c..0000000 --- a/java/src/org/apache/commons/logging/impl/AvalonLogger.java +++ /dev/null @@ -1,292 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 org.apache.avalon.framework.logger.Logger; -import org.apache.commons.logging.Log; - -/** - *

    Implementation of commons-logging Log interface that delegates all - * logging calls to the Avalon logging abstraction: the Logger interface. - *

    - *

    - * There are two ways in which this class can be used: - *

    - *
      - *
    • the instance can be constructed with an Avalon logger - * (by calling {@link #AvalonLogger(Logger)}). In this case, it acts - * as a simple thin wrapping implementation over the logger. This is - * particularly useful when using a property setter. - *
    • - *
    • the {@link #setDefaultLogger} class property can be called which - * sets the ancesteral Avalon logger for this class. Any AvalonLogger - * instances created through the LogFactory mechanisms will output - * to child loggers of this Logger. - *
    • - *
    - *

    - * Note: AvalonLogger does not implement Serializable - * because the constructors available for it make this impossible to achieve in all - * circumstances; there is no way to "reconnect" to an underlying Logger object on - * deserialization if one was just passed in to the constructor of the original - * object. This class was marked Serializable in the 1.0.4 release of - * commons-logging, but this never actually worked (a NullPointerException would - * be thrown as soon as the deserialized object was used), so removing this marker - * is not considered to be an incompatible change. - *

    - * @author Neeme Praks - * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 2006) $ - */ -public class AvalonLogger implements Log { - - /** Ancesteral avalon logger */ - private static Logger defaultLogger = null; - /** Avalon logger used to perform log */ - private transient Logger logger = null; - - /** - * Constructs an AvalonLogger that outputs to the given - * Logger instance. - * @param logger the avalon logger implementation to delegate to - */ - public AvalonLogger(Logger logger) { - this.logger = logger; - } - - /** - * Constructs an AvalonLogger that will log to a child - * of the Logger set by calling {@link #setDefaultLogger}. - * @param name the name of the avalon logger implementation to delegate to - */ - public AvalonLogger(String name) { - if (defaultLogger == null) - throw new NullPointerException("default logger has to be specified if this constructor is used!"); - this.logger = defaultLogger.getChildLogger(name); - } - - /** - * Gets the Avalon logger implementation used to perform logging. - * @return avalon logger implementation - */ - public Logger getLogger() { - return logger; - } - - /** - * Sets the ancesteral Avalon logger from which the delegating loggers - * will descend. - * @param logger the default avalon logger, - * in case there is no logger instance supplied in constructor - */ - public static void setDefaultLogger(Logger logger) { - defaultLogger = logger; - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.debug. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#debug(Object, Throwable) - */ - public void debug(Object message, Throwable t) { - if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.debug. - * - * @param message to log. - * @see org.apache.commons.logging.Log#debug(Object) - */ - public void debug(Object message) { - if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message)); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.error. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#error(Object, Throwable) - */ - public void error(Object message, Throwable t) { - if (getLogger().isErrorEnabled()) getLogger().error(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.error. - * - * @param message to log - * @see org.apache.commons.logging.Log#error(Object) - */ - public void error(Object message) { - if (getLogger().isErrorEnabled()) getLogger().error(String.valueOf(message)); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.fatalError. - * - * @param message to log. - * @param t log this cause. - * @see org.apache.commons.logging.Log#fatal(Object, Throwable) - */ - public void fatal(Object message, Throwable t) { - if (getLogger().isFatalErrorEnabled()) getLogger().fatalError(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.fatalError. - * - * @param message to log - * @see org.apache.commons.logging.Log#fatal(Object) - */ - public void fatal(Object message) { - if (getLogger().isFatalErrorEnabled()) getLogger().fatalError(String.valueOf(message)); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.info. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#info(Object, Throwable) - */ - public void info(Object message, Throwable t) { - if (getLogger().isInfoEnabled()) getLogger().info(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.info. - * - * @param message to log - * @see org.apache.commons.logging.Log#info(Object) - */ - public void info(Object message) { - if (getLogger().isInfoEnabled()) getLogger().info(String.valueOf(message)); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.debug enabled? - * @see org.apache.commons.logging.Log#isDebugEnabled() - */ - public boolean isDebugEnabled() { - return getLogger().isDebugEnabled(); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.error enabled? - * @see org.apache.commons.logging.Log#isErrorEnabled() - */ - public boolean isErrorEnabled() { - return getLogger().isErrorEnabled(); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.fatalError enabled? - * @see org.apache.commons.logging.Log#isFatalEnabled() - */ - public boolean isFatalEnabled() { - return getLogger().isFatalErrorEnabled(); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.info enabled? - * @see org.apache.commons.logging.Log#isInfoEnabled() - */ - public boolean isInfoEnabled() { - return getLogger().isInfoEnabled(); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.debug enabled? - * @see org.apache.commons.logging.Log#isTraceEnabled() - */ - public boolean isTraceEnabled() { - return getLogger().isDebugEnabled(); - } - - /** - * Is logging to - * org.apache.avalon.framework.logger.Logger.warn enabled? - * @see org.apache.commons.logging.Log#isWarnEnabled() - */ - public boolean isWarnEnabled() { - return getLogger().isWarnEnabled(); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.debug. - * - * @param message to log. - * @param t log this cause. - * @see org.apache.commons.logging.Log#trace(Object, Throwable) - */ - public void trace(Object message, Throwable t) { - if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.debug. - * - * @param message to log - * @see org.apache.commons.logging.Log#trace(Object) - */ - public void trace(Object message) { - if (getLogger().isDebugEnabled()) getLogger().debug(String.valueOf(message)); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.warn. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#warn(Object, Throwable) - */ - public void warn(Object message, Throwable t) { - if (getLogger().isWarnEnabled()) getLogger().warn(String.valueOf(message), t); - } - - /** - * Logs a message with - * org.apache.avalon.framework.logger.Logger.warn. - * - * @param message to log - * @see org.apache.commons.logging.Log#warn(Object) - */ - public void warn(Object message) { - if (getLogger().isWarnEnabled()) getLogger().warn(String.valueOf(message)); - } - -} diff --git a/java/src/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java b/java/src/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java deleted file mode 100644 index 2188bdc..0000000 --- a/java/src/org/apache/commons/logging/impl/Jdk13LumberjackLogger.java +++ /dev/null @@ -1,335 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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 java.util.logging.LogRecord; -import java.util.StringTokenizer; -import java.io.PrintWriter; -import java.io.StringWriter; - -import org.apache.commons.logging.Log; - - -/** - *

    Implementation of the org.apache.commons.logging.Log - * interface that wraps the standard JDK logging mechanisms that are - * available in SourceForge's Lumberjack for JDKs prior to 1.4.

    - * - * @author Scott Sanders - * @author Berin Loritsch - * @author Peter Donald - * @author Vince Eagen - * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 2006) $ - * @since 1.1 - */ - -public class Jdk13LumberjackLogger implements Log, Serializable { - - - // ----------------------------------------------------- Instance Variables - - - /** - * The underlying Logger implementation we are using. - */ - protected transient Logger logger = null; - protected String name = null; - private String sourceClassName = "unknown"; - private String sourceMethodName = "unknown"; - private boolean classAndMethodFound = false; - - - /** - * 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 Jdk13LumberjackLogger(String name) { - - this.name = name; - logger = getLogger(); - - } - - - // --------------------------------------------------------- Public Methods - - - private void log( Level level, String msg, Throwable ex ) { - if( getLogger().isLoggable(level) ) { - LogRecord record = new LogRecord(level, msg); - if( !classAndMethodFound ) { - getClassAndMethod(); - } - record.setSourceClassName(sourceClassName); - record.setSourceMethodName(sourceMethodName); - if( ex != null ) { - record.setThrown(ex); - } - getLogger().log(record); - } - } - - /** - *

    Gets the class and method by looking at the stack trace for the - * first entry that is not this class.

    - */ - private void getClassAndMethod() { - try { - Throwable throwable = new Throwable(); - throwable.fillInStackTrace(); - StringWriter stringWriter = new StringWriter(); - PrintWriter printWriter = new PrintWriter( stringWriter ); - throwable.printStackTrace( printWriter ); - String traceString = stringWriter.getBuffer().toString(); - StringTokenizer tokenizer = - new StringTokenizer( traceString, "\n" ); - tokenizer.nextToken(); - String line = tokenizer.nextToken(); - while ( line.indexOf( this.getClass().getName() ) == -1 ) { - line = tokenizer.nextToken(); - } - while ( line.indexOf( this.getClass().getName() ) >= 0 ) { - line = tokenizer.nextToken(); - } - int start = line.indexOf( "at " ) + 3; - int end = line.indexOf( '(' ); - String temp = line.substring( start, end ); - int lastPeriod = temp.lastIndexOf( '.' ); - sourceClassName = temp.substring( 0, lastPeriod ); - sourceMethodName = temp.substring( lastPeriod + 1 ); - } catch ( Exception ex ) { - // ignore - leave class and methodname unknown - } - classAndMethodFound = true; - } - - /** - * Logs a message with java.util.logging.Level.FINE. - * - * @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 java.util.logging.Level.FINE. - * - * @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 java.util.logging.Level.SEVERE. - * - * @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 java.util.logging.Level.SEVERE. - * - * @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 java.util.logging.Level.SEVERE. - * - * @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 java.util.logging.Level.SEVERE. - * - * @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 java.util.logging.Level.INFO. - * - * @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 java.util.logging.Level.INFO. - * - * @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 java.util.logging.Level.FINEST. - * - * @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 java.util.logging.Level.FINEST. - * - * @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 java.util.logging.Level.WARNING. - * - * @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 java.util.logging.Level.WARNING. - * - * @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/java/src/org/apache/commons/logging/impl/Jdk14Logger.java b/java/src/org/apache/commons/logging/impl/Jdk14Logger.java deleted file mode 100644 index b8cb510..0000000 --- a/java/src/org/apache/commons/logging/impl/Jdk14Logger.java +++ /dev/null @@ -1,304 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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; - - -/** - *

    Implementation of the org.apache.commons.logging.Log - * interface that wraps the standard JDK logging mechanisms that were - * introduced in the Merlin release (JDK 1.4).

    - * - * @author Scott Sanders - * @author Berin Loritsch - * @author Peter Donald - * @version $Revision: 424107 $ $Date: 2006-07-21 01:15:42 +0200 (fr, 21 jul 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 java.util.logging.Level.FINE. - * - * @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 java.util.logging.Level.FINE. - * - * @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 java.util.logging.Level.SEVERE. - * - * @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 java.util.logging.Level.SEVERE. - * - * @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 java.util.logging.Level.SEVERE. - * - * @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 java.util.logging.Level.SEVERE. - * - * @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 java.util.logging.Level.INFO. - * - * @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 java.util.logging.Level.INFO. - * - * @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 java.util.logging.Level.FINEST. - * - * @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 java.util.logging.Level.FINEST. - * - * @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 java.util.logging.Level.WARNING. - * - * @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 java.util.logging.Level.WARNING. - * - * @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/java/src/org/apache/commons/logging/impl/Log4JLogger.java b/java/src/org/apache/commons/logging/impl/Log4JLogger.java deleted file mode 100644 index 56d421e..0000000 --- a/java/src/org/apache/commons/logging/impl/Log4JLogger.java +++ /dev/null @@ -1,342 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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; -import org.apache.log4j.Logger; -import org.apache.log4j.Priority; -import org.apache.log4j.Level; - -/** - * Implementation of {@link Log} that maps directly to a - * Logger for log4J version 1.2. - *

    - * Initial configuration of the corresponding Logger instances should be done - * in the usual manner, as outlined in the Log4J documentation. - *

    - * The reason this logger is distinct from the 1.3 logger is that in version 1.2 - * of Log4J: - *

      - *
    • class Logger takes Priority parameters not Level parameters. - *
    • class Level extends Priority - *
    - * Log4J1.3 is expected to change Level so it no longer extends Priority, which is - * a non-binary-compatible change. The class generated by compiling this code against - * log4j 1.2 will therefore not running against log4j 1.3. - * - * @author Scott Sanders - * @author Rod Waldhoff - * @author Robert Burrell Donkin - * @version $Id: Log4JLogger.java 479747 2006-11-27 20:15:01Z dennisl $ - */ - -public class Log4JLogger implements Log, Serializable { - - // ------------------------------------------------------------- Attributes - - /** The fully qualified name of the Log4JLogger class. */ - private static final String FQCN = Log4JLogger.class.getName(); - - /** Log to this logger */ - private transient Logger logger = null; - - /** Logger name */ - private String name = null; - - private static Priority traceLevel; - - // ------------------------------------------------------------ - // Static Initializer. - // - // Note that this must come after the static variable declarations - // otherwise initialiser expressions associated with those variables - // will override any settings done here. - // - // Verify that log4j is available, and that it is version 1.2. - // If an ExceptionInInitializerError is generated, then LogFactoryImpl - // will treat that as meaning that the appropriate underlying logging - // library is just not present - if discovery is in progress then - // discovery will continue. - // ------------------------------------------------------------ - - static { - if (!Priority.class.isAssignableFrom(Level.class)) { - // nope, this is log4j 1.3, so force an ExceptionInInitializerError - throw new InstantiationError("Log4J 1.2 not available"); - } - - // Releases of log4j1.2 >= 1.2.12 have Priority.TRACE available, earlier - // versions do not. If TRACE is not available, then we have to map - // calls to Log.trace(...) onto the DEBUG level. - - try { - traceLevel = (Priority) Level.class.getDeclaredField("TRACE").get(null); - } catch(Exception ex) { - // ok, trace not available - traceLevel = Priority.DEBUG; - } - } - - - // ------------------------------------------------------------ Constructor - - public Log4JLogger() { - } - - - /** - * Base constructor. - */ - public Log4JLogger(String name) { - this.name = name; - this.logger = getLogger(); - } - - /** - * For use with a log4j factory. - */ - public Log4JLogger(Logger logger ) { - if (logger == null) { - throw new IllegalArgumentException( - "Warning - null logger in constructor; possible log4j misconfiguration."); - } - this.name = logger.getName(); - this.logger=logger; - } - - - // --------------------------------------------------------- - // Implementation - // - // Note that in the methods below the Priority class is used to define - // levels even though the Level class is supported in 1.2. This is done - // so that at compile time the call definitely resolves to a call to - // a method that takes a Priority rather than one that takes a Level. - // - // The Category class (and hence its subclass Logger) in version 1.2 only - // has methods that take Priority objects. The Category class (and hence - // Logger class) in version 1.3 has methods that take both Priority and - // Level objects. This means that if we use Level here, and compile - // against log4j 1.3 then calls would be bound to the versions of - // methods taking Level objects and then would fail to running against - // version 1.2 of log4j. - // --------------------------------------------------------- - - - /** - * Logs a message with org.apache.log4j.Priority.TRACE. - * When using a log4j version that does not support the TRACE - * level, the message will be logged at the DEBUG level. - * - * @param message to log - * @see org.apache.commons.logging.Log#trace(Object) - */ - public void trace(Object message) { - getLogger().log(FQCN, traceLevel, message, null ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.TRACE. - * When using a log4j version that does not support the TRACE - * level, the message will be logged at the DEBUG level. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#trace(Object, Throwable) - */ - public void trace(Object message, Throwable t) { - getLogger().log(FQCN, traceLevel, message, t ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.DEBUG. - * - * @param message to log - * @see org.apache.commons.logging.Log#debug(Object) - */ - public void debug(Object message) { - getLogger().log(FQCN, Priority.DEBUG, message, null ); - } - - /** - * Logs a message with org.apache.log4j.Priority.DEBUG. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#debug(Object, Throwable) - */ - public void debug(Object message, Throwable t) { - getLogger().log(FQCN, Priority.DEBUG, message, t ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.INFO. - * - * @param message to log - * @see org.apache.commons.logging.Log#info(Object) - */ - public void info(Object message) { - getLogger().log(FQCN, Priority.INFO, message, null ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.INFO. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#info(Object, Throwable) - */ - public void info(Object message, Throwable t) { - getLogger().log(FQCN, Priority.INFO, message, t ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.WARN. - * - * @param message to log - * @see org.apache.commons.logging.Log#warn(Object) - */ - public void warn(Object message) { - getLogger().log(FQCN, Priority.WARN, message, null ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.WARN. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#warn(Object, Throwable) - */ - public void warn(Object message, Throwable t) { - getLogger().log(FQCN, Priority.WARN, message, t ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.ERROR. - * - * @param message to log - * @see org.apache.commons.logging.Log#error(Object) - */ - public void error(Object message) { - getLogger().log(FQCN, Priority.ERROR, message, null ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.ERROR. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#error(Object, Throwable) - */ - public void error(Object message, Throwable t) { - getLogger().log(FQCN, Priority.ERROR, message, t ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.FATAL. - * - * @param message to log - * @see org.apache.commons.logging.Log#fatal(Object) - */ - public void fatal(Object message) { - getLogger().log(FQCN, Priority.FATAL, message, null ); - } - - - /** - * Logs a message with org.apache.log4j.Priority.FATAL. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#fatal(Object, Throwable) - */ - public void fatal(Object message, Throwable t) { - getLogger().log(FQCN, Priority.FATAL, message, t ); - } - - - /** - * Return the native Logger instance we are using. - */ - public Logger getLogger() { - if (logger == null) { - logger = Logger.getLogger(name); - } - return (this.logger); - } - - - /** - * Check whether the Log4j Logger used is enabled for DEBUG priority. - */ - public boolean isDebugEnabled() { - return getLogger().isDebugEnabled(); - } - - - /** - * Check whether the Log4j Logger used is enabled for ERROR priority. - */ - public boolean isErrorEnabled() { - return getLogger().isEnabledFor(Priority.ERROR); - } - - - /** - * Check whether the Log4j Logger used is enabled for FATAL priority. - */ - public boolean isFatalEnabled() { - return getLogger().isEnabledFor(Priority.FATAL); - } - - - /** - * Check whether the Log4j Logger used is enabled for INFO priority. - */ - public boolean isInfoEnabled() { - return getLogger().isInfoEnabled(); - } - - - /** - * Check whether the Log4j Logger used is enabled for TRACE priority. - * When using a log4j version that does not support the TRACE level, this call - * will report whether DEBUG is enabled or not. - */ - public boolean isTraceEnabled() { - return getLogger().isEnabledFor(traceLevel); - } - - /** - * Check whether the Log4j Logger used is enabled for WARN priority. - */ - public boolean isWarnEnabled() { - return getLogger().isEnabledFor(Priority.WARN); - } -} diff --git a/java/src/org/apache/commons/logging/impl/LogFactoryImpl.java b/java/src/org/apache/commons/logging/impl/LogFactoryImpl.java deleted file mode 100644 index 20c8a36..0000000 --- a/java/src/org/apache/commons/logging/impl/LogFactoryImpl.java +++ /dev/null @@ -1,1500 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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.security.AccessController; -import java.security.PrivilegedAction; -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; - - -/** - *

    Concrete subclass of {@link LogFactory} that implements the - * following algorithm to dynamically select a logging implementation - * class to instantiate a wrapper for.

    - *
      - *
    • Use a factory configuration attribute named - * org.apache.commons.logging.Log to identify the - * requested implementation class.
    • - *
    • Use the org.apache.commons.logging.Log system property - * to identify the requested implementation class.
    • - *
    • If Log4J is available, return an instance of - * org.apache.commons.logging.impl.Log4JLogger.
    • - *
    • If JDK 1.4 or later is available, return an instance of - * org.apache.commons.logging.impl.Jdk14Logger.
    • - *
    • Otherwise, return an instance of - * org.apache.commons.logging.impl.SimpleLog.
    • - *
    - * - *

    If the selected {@link Log} implementation class has a - * setLogFactory() 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.

    - * - *

    This factory will remember previously created Log instances - * for the same name, and will return them on repeated requests to the - * getInstance() method.

    - * - * @author Rod Waldhoff - * @author Craig R. McClanahan - * @author Richard A. Sitze - * @author Brian Stansberry - * @version $Revision: 581090 $ $Date: 2007-10-02 00:01:06 +0200 (ti, 02 okt 2007) $ - */ - -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 (org.apache.commons.logging.Log) 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 (org.apache.commons.logging.Log.allowFlawedContext) - * 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 (org.apache.commons.logging.Log.allowFlawedDiscovery) - * 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 (org.apache.commons.logging.Log.allowFlawedHierarchy) - * 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 getLogConstructor(), - * 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 setLogFactory method of the selected - * {@link org.apache.commons.logging.Log} method, if it exists. - */ - protected Method logMethod = null; - - - /** - * The signature of the setLogFactory 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 null 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 getInstance(String) with it. - * - * @param clazz Class for which a suitable Log name will be derived - * - * @exception LogConfigurationException if a suitable Log - * instance cannot be returned - */ - public Log getInstance(Class clazz) throws LogConfigurationException { - - return (getInstance(clazz.getName())); - - } - - - /** - *

    Construct (if necessary) and return a Log instance, - * using the factory's current set of configuration attributes.

    - * - *

    NOTE - Depending upon the implementation of - * the LogFactory you are using, the Log - * 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.

    - * - * @param name Logical name of the Log 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 Log - * 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 null value is equivalent to calling - * removeAttribute(name). - *

    - * 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 - *

    -     * LogFactory.getFactory().setAttribute(...)
    -     * 
    - * This must be done before the first Log object is created; configuration - * changes after that point will be ignored. - *

    - * 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 null - * 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. - *

    - * This string will later be prefixed to each "internal logging" message - * emitted, so that users can clearly see any unexpected behaviour. - *

    - * 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; - } - - - /** - *

    Return the Constructor that can be called to instantiate - * new {@link org.apache.commons.logging.Log} instances.

    - * - *

    IMPLEMENTATION NOTE - Race conditions caused by - * calling this method from more than one thread are ignored, because - * the same Constructor instance will ultimately be derived - * in all circumstances.

    - * - * @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 JDK 1.3 with Lumberjack 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"); - } - - - /** - *

    Return true if JDK 1.4 or later logging - * is available. Also checks that the Throwable class - * supports getStackTrace(), which is required by - * Jdk14Logger.

    - * - * @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 Log4J 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 - - /** - * 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. - */ - private static ClassLoader getContextClassLoaderInternal() - throws LogConfigurationException { - return (ClassLoader)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return LogFactory.directGetContextClassLoader(); - } - }); - } - - /** - * Read the specified system property, using an AccessController so that - * the property can be read if JCL has been granted the appropriate - * security rights even if the calling code has not. - *

    - * Take care not to expose the value returned by this method to the - * calling application in any way; otherwise the calling app can use that - * info to access data that should not be available to it. - */ - private static String getSystemProperty(final String key, final String def) - throws SecurityException { - return (String) AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return System.getProperty(key, def); - } - }); - } - - /** - * Fetch the parent classloader of a specified classloader. - *

    - * If a SecurityException occurs, null is returned. - *

    - * Note that this method is non-static merely so logDiagnostic is available. - */ - private ClassLoader getParentClassLoader(final ClassLoader cl) { - try { - return (ClassLoader)AccessController.doPrivileged( - new PrivilegedAction() { - public Object run() { - return cl.getParent(); - } - }); - } catch(SecurityException ex) { - logDiagnostic("[SECURITY] Unable to obtain parent classloader"); - return null; - } - - } - - /** - * Utility method to check whether a particular logging library is - * present and available for use. Note that this does not - * 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. - *

    - * 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 { - // warning: minor security hole here, in that we potentially read a system - // property that the caller cannot, then output it in readable form as a - // diagnostic message. However it's only ever JCL-specific properties - // involved here, so the harm is truly trivial. - String value = getSystemProperty(property, null); - 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; (iStringBuffer 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 null - */ - 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 = getSystemProperty(LOG_PROPERTY, null); - } 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 = getSystemProperty(LOG_PROPERTY_OLD, null); - } 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 true if this object's state should - * be affected by this method call, false 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(); - currentCL = getParentClassLoader(currentCL); - } - - if ((logAdapter != null) && affectState) { - // We've succeeded, so set instance fields - this.logClassName = logAdapterClassName; - this.logConstructor = constructor; - - // Identify the setLogFactory 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. - *

    - * 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 and the allowFlawedContext option - * has been set then the classloader which loaded this class is returned - * instead. - *

    - * 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 = getContextClassLoaderInternal(); - - 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. - *

    - * @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 LogConfigurationException that wraps - * the passed Throwable. - * - * @param logAdapterClassName is the class name of the Log implementation - * that could not be instantiated. Cannot be null. - * - * @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 (discoveryFlaw instanceof InvocationTargetException ) { - // Ok, the lib is there but while trying to create a real underlying - // logger something failed in the underlying lib; display info about - // that if possible. - InvocationTargetException ite = (InvocationTargetException)discoveryFlaw; - Throwable cause = ite.getTargetException(); - if (cause != null) { - logDiagnostic("... InvocationTargetException: " + - cause.getClass().getName() + ": " + - cause.getLocalizedMessage()); - - if (cause instanceof ExceptionInInitializerError) { - ExceptionInInitializerError eiie = (ExceptionInInitializerError)cause; - Throwable cause2 = eiie.getException(); - if (cause2 != null) { - logDiagnostic("... ExceptionInInitializerError: " + - cause2.getClass().getName() + ": " + - cause2.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. - *

    - * There are two possible reasons why we successfully loaded the - * specified log adapter class then failed to cast it to a Log object: - *

      - *
    1. the specific class just doesn't implement the Log interface - * (user screwed up), or - *
    2. the specified class has bound to a Log class loaded by some other - * classloader; Log@classloaderX cannot be cast to Log@classloaderY. - *
    - *

    - * 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/java/src/org/apache/commons/logging/impl/LogKitLogger.java b/java/src/org/apache/commons/logging/impl/LogKitLogger.java deleted file mode 100644 index 5e6cf4b..0000000 --- a/java/src/org/apache/commons/logging/impl/LogKitLogger.java +++ /dev/null @@ -1,294 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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.log.Logger; -import org.apache.log.Hierarchy; -import org.apache.commons.logging.Log; - -/** - *

    Implementation of org.apache.commons.logging.Log - * that wraps the avalon-logkit - * logging system. Configuration of LogKit is left to the user. - *

    - * - *

    LogKit accepts only String messages. - * Therefore, this implementation converts object messages into strings - * by called their toString() method before logging them.

    - * - * @author Scott Sanders - * @author Robert Burrell Donkin - * @version $Id: LogKitLogger.java 424107 2006-07-20 23:15:42Z skitching $ - */ - -public class LogKitLogger implements Log, Serializable { - - - // ------------------------------------------------------------- Attributes - - - /** Logging goes to this LogKit logger */ - protected transient Logger logger = null; - - /** Name of this logger */ - protected String name = null; - - - // ------------------------------------------------------------ Constructor - - - /** - * Construct LogKitLogger which wraps the LogKit - * logger with given name. - * - * @param name log name - */ - public LogKitLogger(String name) { - this.name = name; - this.logger = getLogger(); - } - - - // --------------------------------------------------------- Public Methods - - - /** - *

    Return the underlying Logger we are using.

    - */ - public Logger getLogger() { - - if (logger == null) { - logger = Hierarchy.getDefaultHierarchy().getLoggerFor(name); - } - return (logger); - - } - - - // ----------------------------------------------------- Log Implementation - - - /** - * Logs a message with org.apache.log.Priority.DEBUG. - * - * @param message to log - * @see org.apache.commons.logging.Log#trace(Object) - */ - public void trace(Object message) { - debug(message); - } - - - /** - * Logs a message with org.apache.log.Priority.DEBUG. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#trace(Object, Throwable) - */ - public void trace(Object message, Throwable t) { - debug(message, t); - } - - - /** - * Logs a message with org.apache.log.Priority.DEBUG. - * - * @param message to log - * @see org.apache.commons.logging.Log#debug(Object) - */ - public void debug(Object message) { - if (message != null) { - getLogger().debug(String.valueOf(message)); - } - } - - - /** - * Logs a message with org.apache.log.Priority.DEBUG. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#debug(Object, Throwable) - */ - public void debug(Object message, Throwable t) { - if (message != null) { - getLogger().debug(String.valueOf(message), t); - } - } - - - /** - * Logs a message with org.apache.log.Priority.INFO. - * - * @param message to log - * @see org.apache.commons.logging.Log#info(Object) - */ - public void info(Object message) { - if (message != null) { - getLogger().info(String.valueOf(message)); - } - } - - - /** - * Logs a message with org.apache.log.Priority.INFO. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#info(Object, Throwable) - */ - public void info(Object message, Throwable t) { - if (message != null) { - getLogger().info(String.valueOf(message), t); - } - } - - - /** - * Logs a message with org.apache.log.Priority.WARN. - * - * @param message to log - * @see org.apache.commons.logging.Log#warn(Object) - */ - public void warn(Object message) { - if (message != null) { - getLogger().warn(String.valueOf(message)); - } - } - - - /** - * Logs a message with org.apache.log.Priority.WARN. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#warn(Object, Throwable) - */ - public void warn(Object message, Throwable t) { - if (message != null) { - getLogger().warn(String.valueOf(message), t); - } - } - - - /** - * Logs a message with org.apache.log.Priority.ERROR. - * - * @param message to log - * @see org.apache.commons.logging.Log#error(Object) - */ - public void error(Object message) { - if (message != null) { - getLogger().error(String.valueOf(message)); - } - } - - - /** - * Logs a message with org.apache.log.Priority.ERROR. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#error(Object, Throwable) - */ - public void error(Object message, Throwable t) { - if (message != null) { - getLogger().error(String.valueOf(message), t); - } - } - - - /** - * Logs a message with org.apache.log.Priority.FATAL_ERROR. - * - * @param message to log - * @see org.apache.commons.logging.Log#fatal(Object) - */ - public void fatal(Object message) { - if (message != null) { - getLogger().fatalError(String.valueOf(message)); - } - } - - - /** - * Logs a message with org.apache.log.Priority.FATAL_ERROR. - * - * @param message to log - * @param t log this cause - * @see org.apache.commons.logging.Log#fatal(Object, Throwable) - */ - public void fatal(Object message, Throwable t) { - if (message != null) { - getLogger().fatalError(String.valueOf(message), t); - } - } - - - /** - * Checks whether the LogKit logger will log messages of priority DEBUG. - */ - public boolean isDebugEnabled() { - return getLogger().isDebugEnabled(); - } - - - /** - * Checks whether the LogKit logger will log messages of priority ERROR. - */ - public boolean isErrorEnabled() { - return getLogger().isErrorEnabled(); - } - - - /** - * Checks whether the LogKit logger will log messages of priority FATAL_ERROR. - */ - public boolean isFatalEnabled() { - return getLogger().isFatalErrorEnabled(); - } - - - /** - * Checks whether the LogKit logger will log messages of priority INFO. - */ - public boolean isInfoEnabled() { - return getLogger().isInfoEnabled(); - } - - - /** - * Checks whether the LogKit logger will log messages of priority DEBUG. - */ - public boolean isTraceEnabled() { - return getLogger().isDebugEnabled(); - } - - - /** - * Checks whether the LogKit logger will log messages of priority WARN. - */ - public boolean isWarnEnabled() { - return getLogger().isWarnEnabled(); - } - - -} diff --git a/java/src/org/apache/commons/logging/impl/NoOpLog.java b/java/src/org/apache/commons/logging/impl/NoOpLog.java deleted file mode 100644 index a66bd10..0000000 --- a/java/src/org/apache/commons/logging/impl/NoOpLog.java +++ /dev/null @@ -1,107 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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; - - -/** - *

    Trivial implementation of Log that throws away all messages. No - * configurable system properties are supported.

    - * - * @author Scott Sanders - * @author Rod Waldhoff - * @version $Id: NoOpLog.java 424107 2006-07-20 23:15:42Z skitching $ - */ -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/java/src/org/apache/commons/logging/impl/ServletContextCleaner.java b/java/src/org/apache/commons/logging/impl/ServletContextCleaner.java deleted file mode 100644 index 046bf7e..0000000 --- a/java/src/org/apache/commons/logging/impl/ServletContextCleaner.java +++ /dev/null @@ -1,138 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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.InvocationTargetException; -import java.lang.reflect.Method; - -import javax.servlet.ServletContextEvent; -import javax.servlet.ServletContextListener; - -import org.apache.commons.logging.LogFactory; - - -/** - * This class is capable of receiving notifications about the undeployment of - * a webapp, and responds by ensuring that commons-logging releases all - * memory associated with the undeployed webapp. - *

    - * In general, the WeakHashtable support added in commons-logging release 1.1 - * ensures that logging classes do not hold references that prevent an - * undeployed webapp's memory from being garbage-collected even when multiple - * copies of commons-logging are deployed via multiple classloaders (a - * situation that earlier versions had problems with). However there are - * some rare cases where the WeakHashtable approach does not work; in these - * situations specifying this class as a listener for the web application will - * ensure that all references held by commons-logging are fully released. - *

    - * To use this class, configure the webapp deployment descriptor to call - * this class on webapp undeploy; the contextDestroyed method will tell - * every accessable LogFactory class that the entry in its map for the - * current webapp's context classloader should be cleared. - * - * @since 1.1 - */ - -public class ServletContextCleaner implements ServletContextListener { - - private Class[] RELEASE_SIGNATURE = {ClassLoader.class}; - - /** - * Invoked when a webapp is undeployed, this tells the LogFactory - * class to release any logging information related to the current - * contextClassloader. - */ - public void contextDestroyed(ServletContextEvent sce) { - ClassLoader tccl = Thread.currentThread().getContextClassLoader(); - - Object[] params = new Object[1]; - params[0] = tccl; - - // Walk up the tree of classloaders, finding all the available - // LogFactory classes and releasing any objects associated with - // the tccl (ie the webapp). - // - // When there is only one LogFactory in the classpath, and it - // is within the webapp being undeployed then there is no problem; - // garbage collection works fine. - // - // When there are multiple LogFactory classes in the classpath but - // parent-first classloading is used everywhere, this loop is really - // short. The first instance of LogFactory found will - // be the highest in the classpath, and then no more will be found. - // This is ok, as with this setup this will be the only LogFactory - // holding any data associated with the tccl being released. - // - // When there are multiple LogFactory classes in the classpath and - // child-first classloading is used in any classloader, then multiple - // LogFactory instances may hold info about this TCCL; whenever the - // webapp makes a call into a class loaded via an ancestor classloader - // and that class calls LogFactory the tccl gets registered in - // the LogFactory instance that is visible from the ancestor - // classloader. However the concrete logging library it points - // to is expected to have been loaded via the TCCL, so the - // underlying logging lib is only initialised/configured once. - // These references from ancestor LogFactory classes down to - // TCCL classloaders are held via weak references and so should - // be released but there are circumstances where they may not. - // Walking up the classloader ancestry ladder releasing - // the current tccl at each level tree, though, will definitely - // clear any problem references. - ClassLoader loader = tccl; - while (loader != null) { - // Load via the current loader. Note that if the class is not accessable - // via this loader, but is accessable via some ancestor then that class - // will be returned. - try { - Class logFactoryClass = loader.loadClass("org.apache.commons.logging.LogFactory"); - Method releaseMethod = logFactoryClass.getMethod("release", RELEASE_SIGNATURE); - releaseMethod.invoke(null, params); - loader = logFactoryClass.getClassLoader().getParent(); - } catch(ClassNotFoundException ex) { - // Neither the current classloader nor any of its ancestors could find - // the LogFactory class, so we can stop now. - loader = null; - } catch(NoSuchMethodException ex) { - // This is not expected; every version of JCL has this method - System.err.println("LogFactory instance found which does not support release method!"); - loader = null; - } catch(IllegalAccessException ex) { - // This is not expected; every ancestor class should be accessable - System.err.println("LogFactory instance found which is not accessable!"); - loader = null; - } catch(InvocationTargetException ex) { - // This is not expected - System.err.println("LogFactory instance release method failed!"); - loader = null; - } - } - - // Just to be sure, invoke release on the LogFactory that is visible from - // this ServletContextCleaner class too. This should already have been caught - // by the above loop but just in case... - LogFactory.release(tccl); - } - - /** - * Invoked when a webapp is deployed. Nothing needs to be done here. - */ - public void contextInitialized(ServletContextEvent sce) { - // do nothing - } -} diff --git a/java/src/org/apache/commons/logging/impl/SimpleLog.java b/java/src/org/apache/commons/logging/impl/SimpleLog.java deleted file mode 100644 index fe1a7c5..0000000 --- a/java/src/org/apache/commons/logging/impl/SimpleLog.java +++ /dev/null @@ -1,721 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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; - -/** - *

    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:

    - *
      - *
    • org.apache.commons.logging.simplelog.defaultlog - - * 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".
    • - *
    • org.apache.commons.logging.simplelog.log.xxxxx - - * 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.
    • - *
    • org.apache.commons.logging.simplelog.showlogname - - * Set to true if you want the Log instance name to be - * included in output messages. Defaults to false.
    • - *
    • org.apache.commons.logging.simplelog.showShortLogname - - * Set to true if you want the last component of the name to be - * included in output messages. Defaults to true.
    • - *
    • org.apache.commons.logging.simplelog.showdatetime - - * Set to true if you want the current date and time - * to be included in output messages. Default is false.
    • - *
    • org.apache.commons.logging.simplelog.dateTimeFormat - - * 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 java.text.SimpleDateFormat. If the format is not - * specified or is invalid, the default format is used. - * The default format is yyyy/MM/dd HH:mm:ss:SSS zzz.
    • - *
    - * - *

    In addition to looking for system properties with the names specified - * above, this implementation also checks for a class loader resource named - * "simplelog.properties", and includes any matching definitions - * from this resource (if it exists).

    - * - * @author Scott Sanders - * @author Rod Waldhoff - * @author Robert Burrell Donkin - * - * @version $Id: SimpleLog.java 581090 2007-10-01 22:01:06Z dennisl $ - */ -public class SimpleLog implements Log, Serializable { - - - // ------------------------------------------------------- Class Attributes - - /** All system properties used by SimpleLog 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. - *

    - * Any code that accesses this object should first obtain a lock on it, - * ie use synchronized(dateFormatter); this requirement was introduced - * in 1.1.1 to fix an existing thread safety bug (SimpleDateFormat.format - * is not thread-safe). - */ - 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 - - /** - *

    Set logging level.

    - * - * @param currentLogLevel new logging level - */ - public void setLevel(int currentLogLevel) { - - this.currentLogLevel = currentLogLevel; - - } - - - /** - *

    Get logging level.

    - */ - public int getLevel() { - - return currentLogLevel; - } - - - // -------------------------------------------------------- Logging Methods - - - /** - *

    Do the actual logging. - * This method assembles the message - * and then calls write() to cause it to be written.

    - * - * @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) { - Date now = new Date(); - String dateText; - synchronized(dateFormatter) { - dateText = dateFormatter.format(now); - } - buf.append(dateText); - 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); - - } - - - /** - *

    Write the content of the message accumulated in the specified - * StringBuffer to the appropriate output destination. The - * default implementation writes to System.err.

    - * - * @param buffer A StringBuffer 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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG. - * - * @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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_DEBUG. - * - * @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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE. - * - * @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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_TRACE. - * - * @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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO. - * - * @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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_INFO. - * - * @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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN. - * - * @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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_WARN. - * - * @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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR. - * - * @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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_ERROR. - * - * @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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL. - * - * @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 - * org.apache.commons.logging.impl.SimpleLog.LOG_LEVEL_FATAL. - * - * @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); - } - } - - - /** - *

    Are debug messages currently enabled?

    - * - *

    This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

    - */ - public final boolean isDebugEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_DEBUG); - } - - - /** - *

    Are error messages currently enabled?

    - * - *

    This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

    - */ - public final boolean isErrorEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_ERROR); - } - - - /** - *

    Are fatal messages currently enabled?

    - * - *

    This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

    - */ - public final boolean isFatalEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_FATAL); - } - - - /** - *

    Are info messages currently enabled?

    - * - *

    This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

    - */ - public final boolean isInfoEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_INFO); - } - - - /** - *

    Are trace messages currently enabled?

    - * - *

    This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

    - */ - public final boolean isTraceEnabled() { - - return isLevelEnabled(SimpleLog.LOG_LEVEL_TRACE); - } - - - /** - *

    Are warn messages currently enabled?

    - * - *

    This allows expensive operations such as String - * concatenation to be avoided when the message will be ignored by the - * logger.

    - */ - 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(), - (Class[]) 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/java/src/org/apache/commons/logging/impl/WeakHashtable.java b/java/src/org/apache/commons/logging/impl/WeakHashtable.java deleted file mode 100644 index 3748ceb..0000000 --- a/java/src/org/apache/commons/logging/impl/WeakHashtable.java +++ /dev/null @@ -1,478 +0,0 @@ -/* - * Licensed to the Apache Software Foundation (ASF) under one or more - * contributor license agreements. See the NOTICE file distributed with - * this work for additional information regarding copyright ownership. - * The ASF licenses this file to You 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.*; - -/** - *

    Implementation of Hashtable that uses WeakReference's - * to hold its keys thus allowing them to be reclaimed by the garbage collector. - * The associated values are retained using strong references.

    - * - *

    This class follows the symantics of Hashtable as closely as - * possible. It therefore does not accept null values or keys.

    - * - *

    Note: - * This is not intended to be a general purpose hash table replacement. - * This implementation is also tuned towards a particular purpose: for use as a replacement - * for Hashtable in LogFactory. This application requires - * good liveliness for get and put. Various tradeoffs - * have been made with this in mind. - *

    - *

    - * Usage: typical use case is as a drop-in replacement - * for the Hashtable used in LogFactory for J2EE enviroments - * running 1.3+ JVMs. Use of this class in most cases (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)}. - *

    - * - *

    org.apache.commons.logging.LogFactory checks whether this class - * can be supported by the current JVM, and if so then uses it to store - * references to the LogFactory implementationd it loads - * (rather than using a standard Hashtable instance). - * Having this class used instead of Hashtable 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 java.lang.ref.WeakReference and associates). - * And by the way, this extends Hashtable rather than HashMap - * for backwards compatibility reasons. See the documentation - * for method LogFactory.createFactoryStore for more details.

    - * - *

    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" - * LogFactory's factories member! If LogFactory.release() - * is called whenever component is unloaded, the classloaders will be correctly - * garbage collected; this should 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.

    - * - *

    - * Limitations: - * 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. - *

    - * - *

    If the abstract class LogFactory is - * loaded by the container classloader but a subclass of - * LogFactory [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 - * getClass().getClassLoader(). This chain of references will prevent - * collection of the child classloader.

    - * - *

    - * 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 LogFactory implementation is - * loaded by a child classloader (e.g. a web app classloader).

    - * - *

    To avoid this scenario, ensure - * that any custom LogFactory subclass is loaded by the same classloader as - * the base LogFactory. Creating custom LogFactory subclasses is, - * however, rare. The standard LogFactoryImpl class should be sufficient - * for most or all users.

    - * - * - * @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(); - } - - 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 null - */ - 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 null - */ - 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 value 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/java/src/org/apache/commons/logging/impl/package.html b/java/src/org/apache/commons/logging/impl/package.html deleted file mode 100644 index 0d37071..0000000 --- a/java/src/org/apache/commons/logging/impl/package.html +++ /dev/null @@ -1,22 +0,0 @@ - - - -

    Concrete implementations of commons-logging wrapper APIs.

    - diff --git a/java/src/org/apache/commons/logging/package.html b/java/src/org/apache/commons/logging/package.html deleted file mode 100644 index 6be8fd4..0000000 --- a/java/src/org/apache/commons/logging/package.html +++ /dev/null @@ -1,255 +0,0 @@ - - - -

    Simple wrapper API around multiple logging APIs.

    - - -

    Overview

    - -

    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:

    -
      -
    • Log4J (version 1.2 or later) - from Apache's Logging project. Each named Log - instance is connected to a corresponding Log4J Logger.
    • -
    • - JDK Logging API, included in JDK 1.4 or later systems. Each named - Log instance is connected to a corresponding - java.util.logging.Logger instance.
    • -
    • LogKit from Apache's - Avalon project. Each named Log instance is - connected to a corresponding LogKit Logger.
    • -
    • NoOpLog implementation that simply swallows - all log output, for all named Log instances.
    • -
    • SimpleLog implementation that writes all - log output, for all named Log instances, to - System.err.
    • -
    - - -

    Quick Start Guide

    - -

    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: - -

    -    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);
    -            }
    -            ...
    -        }
    -
    - -

    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.

    - - -

    Configuring the Commons Logging Package

    - - -

    Choosing a LogFactory Implementation

    - -

    From an application perspective, the first requirement is to retrieve an -object reference to the LogFactory instance that will be used -to create Log instances for this -application. This is normally accomplished by calling the static -getFactory() method. This method implements the following -discovery algorithm to select the name of the LogFactory -implementation class this application wants to use:

    -
      -
    • Check for a system property named - org.apache.commons.logging.LogFactory.
    • -
    • Use the JDK 1.3 JAR Services Discovery mechanism (see - - http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html for - more information) to look for a resource named - META-INF/services/org.apache.commons.logging.LogFactory - whose first line is assumed to contain the desired class name.
    • -
    • Look for a properties file named commons-logging.properties - visible in the application class path, with a property named - org.apache.commons.logging.LogFactory defining the - desired implementation class name.
    • -
    • Fall back to a default implementation, which is described - further below.
    • -
    - -

    If a commons-logging.properties file is found, all of the -properties defined there are also used to set configuration attributes on -the instantiated LogFactory instance.

    - -

    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 LogFactory class itself -otherwise. This allows a copy of commons-logging.jar to be -shared in a multiple class loader environment (such as a servlet container), -but still allow each web application to provide its own LogFactory -implementation, if it so desires. An instance of this class will then be -created, and cached per class loader. - - -

    The Default LogFactory Implementation

    - -

    The Logging Package APIs include a default LogFactory -implementation class ( -org.apache.commons.logging.impl.LogFactoryImpl) that is selected if no -other implementation class name can be discovered. Its primary purpose is -to create (as necessary) and return Log instances -in response to calls to the getInstance() method. The default -implementation uses the following rules:

    -
      -
    • At most one Log instance of the same name will be created. - Subsequent getInstance() calls to the same - LogFactory instance, with the same name or Class - parameter, will return the same Log instance.
    • -
    • When a new Log instance must be created, the default - LogFactory implementation uses the following discovery - process: -
        -
      • Look for a configuration attribute of this factory named - org.apache.commons.logging.Log (for backwards - compatibility to pre-1.0 versions of this API, an attribute - org.apache.commons.logging.log is also consulted).
      • -
      • Look for a system property named - org.apache.commons.logging.Log (for backwards - compatibility to pre-1.0 versions of this API, a system property - org.apache.commons.logging.log is also consulted).
      • -
      • If the Log4J logging system is available in the application - class path, use the corresponding wrapper class - (Log4JLogger).
      • -
      • If the application is executing on a JDK 1.4 system, use - the corresponding wrapper class - (Jdk14Logger).
      • -
      • Fall back to the default simple logging implementation - (SimpleLog).
      • -
    • -
    • Load the class of the specified name from the thread context class - loader (if any), or from the class loader that loaded the - LogFactory class otherwise.
    • -
    • Instantiate an instance of the selected Log - implementation class, passing the specified name as the single - argument to its constructor.
    • -
    - -

    See the SimpleLog JavaDocs for detailed -configuration information for this default implementation.

    - - -

    Configuring the Underlying Logging System

    - -

    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.

    - -

    Each individual Log implementation may -support its own configuration properties. These will be documented in the -class descriptions for the corresponding implementation class.

    - -

    Finally, some Log 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.

    - - -

    Using the Logging Package APIs

    - -

    Use of the Logging Package APIs, from the perspective of an application -component, consists of the following steps:

    -
      -
    1. Acquire a reference to an instance of - org.apache.commons.logging.Log, by calling the - factory method - - LogFactory.getInstance(String name). 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.
    2. -
    3. Cause messages to be logged (if the corresponding detail level is enabled) - by calling appropriate methods (trace(), debug(), - info(), warn(), error, and - fatal()).
    4. -
    - -

    For convenience, LogFactory also offers a static method -getLog() that combines the typical two-step pattern:

    -
    -  Log log = LogFactory.getFactory().getInstance(Foo.class);
    -
    -

    into a single method call:

    -
    -  Log log = LogFactory.getLog(Foo.class);
    -
    - -

    For example, you might use the following technique to initialize and -use a Log instance in an application component:

    -
    -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);
    -    ...
    -  }
    -
    -}
    -
    - -