Home | History | Annotate | Download | only in logging
      1 /*
      2  * Copyright 2001-2004 The Apache Software Foundation.
      3  *
      4  * Licensed under the Apache License, Version 2.0 (the "License");
      5  * you may not use this file except in compliance with the License.
      6  * You may obtain a copy of the License at
      7  *
      8  *      http://www.apache.org/licenses/LICENSE-2.0
      9  *
     10  * Unless required by applicable law or agreed to in writing, software
     11  * distributed under the License is distributed on an "AS IS" BASIS,
     12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     13  * See the License for the specific language governing permissions and
     14  * limitations under the License.
     15  */
     16 
     17 package org.apache.commons.logging;
     18 
     19 import java.util.Hashtable;
     20 
     21 import org.apache.commons.logging.impl.SLF4JLogFactory;
     22 
     23 /**
     24  * <p>
     25  * Factory for creating {@link Log} instances, which always delegates to an
     26  * instance of {@link SLF4JLogFactory}.
     27  *
     28  * </p>
     29  *
     30  * @author Craig R. McClanahan
     31  * @author Costin Manolache
     32  * @author Richard A. Sitze
     33  * @author Ceki G&uuml;lc&uuml;
     34  */
     35 
     36 @SuppressWarnings("rawtypes")
     37 public abstract class LogFactory {
     38 
     39     static String UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J = "http://www.slf4j.org/codes.html#unsupported_operation_in_jcl_over_slf4j";
     40 
     41     static LogFactory logFactory = new SLF4JLogFactory();
     42 
     43     /**
     44      * The name (<code>priority</code>) of the key in the config file used to
     45      * specify the priority of that particular config file. The associated value
     46      * is a floating-point number; higher values take priority over lower values.
     47      *
     48      * <p>
     49      * This property is not used but preserved here for compatibility.
     50      */
     51     public static final String PRIORITY_KEY = "priority";
     52 
     53     /**
     54      * The name (<code>use_tccl</code>) of the key in the config file used to
     55      * specify whether logging classes should be loaded via the thread context
     56      * class loader (TCCL), or not. By default, the TCCL is used.
     57      *
     58      * <p>
     59      * This property is not used but preserved here for compatibility.
     60      */
     61     public static final String TCCL_KEY = "use_tccl";
     62 
     63     /**
     64      * The name of the property used to identify the LogFactory implementation
     65      * class name.
     66      * <p>
     67      * This property is not used but preserved here for compatibility.
     68      */
     69     public static final String FACTORY_PROPERTY = "org.apache.commons.logging.LogFactory";
     70 
     71     /**
     72      * The fully qualified class name of the fallback <code>LogFactory</code>
     73      * implementation class to use, if no other can be found.
     74      *
     75      * <p>
     76      * This property is not used but preserved here for compatibility.
     77      */
     78     public static final String FACTORY_DEFAULT = "org.apache.commons.logging.impl.SLF4JLogFactory";
     79 
     80     /**
     81      * The name of the properties file to search for.
     82      * <p>
     83      * This property is not used but preserved here for compatibility.
     84      */
     85     public static final String FACTORY_PROPERTIES = "commons-logging.properties";
     86 
     87     /**
     88      * JDK1.3+ <a href="http://java.sun.com/j2se/1.3/docs/guide/jar/jar.html#Service%20Provider">
     89      * 'Service Provider' specification</a>.
     90      * <p>
     91      * This property is not used but preserved here for compatibility.
     92      */
     93     protected static final String SERVICE_ID = "META-INF/services/org.apache.commons.logging.LogFactory";
     94 
     95     /**
     96      * The name (<code>org.apache.commons.logging.diagnostics.dest</code>) of
     97      * the property used to enable internal commons-logging diagnostic output, in
     98      * order to get information on what logging implementations are being
     99      * discovered, what classloaders they are loaded through, etc.
    100      *
    101      * <p>
    102      * This property is not used but preserved here for compatibility.
    103      */
    104     public static final String DIAGNOSTICS_DEST_PROPERTY = "org.apache.commons.logging.diagnostics.dest";
    105 
    106     /**
    107      * <p>
    108      * Setting this system property value allows the <code>Hashtable</code> used
    109      * to store classloaders to be substituted by an alternative implementation.
    110      * <p>
    111      * This property is not used but preserved here for compatibility.
    112      */
    113     public static final String HASHTABLE_IMPLEMENTATION_PROPERTY = "org.apache.commons.logging.LogFactory.HashtableImpl";
    114 
    115     /**
    116      * The previously constructed <code>LogFactory</code> instances, keyed by
    117      * the <code>ClassLoader</code> with which it was created.
    118      *
    119      * <p>
    120      * This property is not used but preserved here for compatibility.
    121      */
    122     protected static Hashtable factories = null;
    123 
    124     /**
    125      * <p>
    126      * This property is not used but preserved here for compatibility.
    127      */
    128     protected static LogFactory nullClassLoaderFactory = null;
    129 
    130     /**
    131      * Protected constructor that is not available for public use.
    132      */
    133     protected LogFactory() {
    134     }
    135 
    136     // --------------------------------------------------------- Public Methods
    137 
    138     /**
    139      * Return the configuration attribute with the specified name (if any), or
    140      * <code>null</code> if there is no such attribute.
    141      *
    142      * @param name Name of the attribute to return
    143      * @return configuration attribute
    144      */
    145     public abstract Object getAttribute(String name);
    146 
    147     /**
    148      * Return an array containing the names of all currently defined configuration
    149      * attributes. If there are no such attributes, a zero length array is
    150      * returned.
    151      *
    152      * @return names of all currently defined configuration attributes
    153      */
    154     public abstract String[] getAttributeNames();
    155 
    156     /**
    157      * Convenience method to derive a name from the specified class and call
    158      * <code>getInstance(String)</code> with it.
    159      *
    160      * @param clazz
    161      *                Class for which a suitable Log name will be derived
    162      *
    163      * @exception LogConfigurationException
    164      *                    if a suitable <code>Log</code> instance cannot be
    165      *                    returned
    166      */
    167     public abstract Log getInstance(Class clazz) throws LogConfigurationException;
    168 
    169     /**
    170      * <p>
    171      * Construct (if necessary) and return a <code>Log</code> instance, using
    172      * the factory's current set of configuration attributes.
    173      * </p>
    174      *
    175      * <p>
    176      * <strong>NOTE </strong>- Depending upon the implementation of the
    177      * <code>LogFactory</code> you are using, the <code>Log</code> instance
    178      * you are returned may or may not be local to the current application, and
    179      * may or may not be returned again on a subsequent call with the same name
    180      * argument.
    181      * </p>
    182      *
    183      * @param name
    184      *                Logical name of the <code>Log</code> instance to be
    185      *                returned (the meaning of this name is only known to the
    186      *                underlying logging implementation that is being wrapped)
    187      *
    188      * @exception LogConfigurationException
    189      *                    if a suitable <code>Log</code> instance cannot be
    190      *                    returned
    191      */
    192     public abstract Log getInstance(String name) throws LogConfigurationException;
    193 
    194     /**
    195      * Release any internal references to previously created {@link Log}instances
    196      * returned by this factory. This is useful in environments like servlet
    197      * containers, which implement application reloading by throwing away a
    198      * ClassLoader. Dangling references to objects in that class loader would
    199      * prevent garbage collection.
    200      */
    201     public abstract void release();
    202 
    203     /**
    204      * Remove any configuration attribute associated with the specified name. If
    205      * there is no such attribute, no action is taken.
    206      *
    207      * @param name
    208      *                Name of the attribute to remove
    209      */
    210     public abstract void removeAttribute(String name);
    211 
    212     /**
    213      * Set the configuration attribute with the specified name. Calling this with
    214      * a <code>null</code> value is equivalent to calling
    215      * <code>removeAttribute(name)</code>.
    216      *
    217      * @param name
    218      *                Name of the attribute to set
    219      * @param value
    220      *                Value of the attribute to set, or <code>null</code> to
    221      *                remove any setting for this attribute
    222      */
    223     public abstract void setAttribute(String name, Object value);
    224 
    225     // --------------------------------------------------------- Static Methods
    226 
    227     /**
    228      * <p>
    229      * Construct (if necessary) and return a <code>LogFactory</code> instance,
    230      * using the following ordered lookup procedure to determine the name of the
    231      * implementation class to be loaded.
    232      * </p>
    233      * <ul>
    234      * <li>The <code>org.apache.commons.logging.LogFactory</code> system
    235      * property.</li>
    236      * <li>The JDK 1.3 Service Discovery mechanism</li>
    237      * <li>Use the properties file <code>commons-logging.properties</code>
    238      * file, if found in the class path of this class. The configuration file is
    239      * in standard <code>java.util.Properties</code> format and contains the
    240      * fully qualified name of the implementation class with the key being the
    241      * system property defined above.</li>
    242      * <li>Fall back to a default implementation class (
    243      * <code>org.apache.commons.logging.impl.SLF4FLogFactory</code>).</li>
    244      * </ul>
    245      *
    246      * <p>
    247      * <em>NOTE</em>- If the properties file method of identifying the
    248      * <code>LogFactory</code> implementation class is utilized, all of the
    249      * properties defined in this file will be set as configuration attributes on
    250      * the corresponding <code>LogFactory</code> instance.
    251      * </p>
    252      *
    253      * @exception LogConfigurationException
    254      *                    if the implementation class is not available or cannot
    255      *                    be instantiated.
    256      */
    257     public static LogFactory getFactory() throws LogConfigurationException {
    258         return logFactory;
    259     }
    260 
    261     /**
    262      * Convenience method to return a named logger, without the application having
    263      * to care about factories.
    264      *
    265      * @param clazz
    266      *                Class from which a log name will be derived
    267      *
    268      * @exception LogConfigurationException
    269      *                    if a suitable <code>Log</code> instance cannot be
    270      *                    returned
    271      */
    272     public static Log getLog(Class clazz) throws LogConfigurationException {
    273         return (getFactory().getInstance(clazz));
    274     }
    275 
    276     /**
    277      * Convenience method to return a named logger, without the application having
    278      * to care about factories.
    279      *
    280      * @param name
    281      *                Logical name of the <code>Log</code> instance to be
    282      *                returned (the meaning of this name is only known to the
    283      *                underlying logging implementation that is being wrapped)
    284      *
    285      * @exception LogConfigurationException
    286      *                    if a suitable <code>Log</code> instance cannot be
    287      *                    returned
    288      */
    289     public static Log getLog(String name) throws LogConfigurationException {
    290         return (getFactory().getInstance(name));
    291     }
    292 
    293     /**
    294      * Release any internal references to previously created {@link LogFactory}
    295      * instances that have been associated with the specified class loader (if
    296      * any), after calling the instance method <code>release()</code> on each of
    297      * them.
    298      *
    299      * @param classLoader
    300      *                ClassLoader for which to release the LogFactory
    301      */
    302     public static void release(ClassLoader classLoader) {
    303         // since SLF4J based JCL does not make use of classloaders, there is nothing
    304         // to do here
    305     }
    306 
    307     /**
    308      * Release any internal references to previously created {@link LogFactory}
    309      * instances, after calling the instance method <code>release()</code> on
    310      * each of them. This is useful in environments like servlet containers, which
    311      * implement application reloading by throwing away a ClassLoader. Dangling
    312      * references to objects in that class loader would prevent garbage
    313      * collection.
    314      */
    315     public static void releaseAll() {
    316         // since SLF4J based JCL does not make use of classloaders, there is nothing
    317         // to do here
    318     }
    319 
    320     /**
    321      * Returns a string that uniquely identifies the specified object, including
    322      * its class.
    323      * <p>
    324      * The returned string is of form "classname@hashcode", ie is the same as the
    325      * return value of the Object.toString() method, but works even when the
    326      * specified object's class has overidden the toString method.
    327      *
    328      * @param o
    329      *                may be null.
    330      * @return a string of form classname@hashcode, or "null" if param o is null.
    331      * @since 1.1
    332      */
    333     public static String objectId(Object o) {
    334         if (o == null) {
    335             return "null";
    336         } else {
    337             return o.getClass().getName() + "@" + System.identityHashCode(o);
    338         }
    339     }
    340 
    341     // protected methods which were added in JCL 1.1. These are not used
    342     // by SLF4JLogFactory
    343 
    344     /**
    345      * This method exists to ensure signature compatibility.
    346      */
    347     protected static Object createFactory(String factoryClass, ClassLoader classLoader) {
    348         throw new UnsupportedOperationException("Operation [factoryClass] is not supported in jcl-over-slf4j. See also "
    349                         + UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J);
    350     }
    351 
    352     /**
    353      * This method exists to ensure signature compatibility.
    354      */
    355     protected static ClassLoader directGetContextClassLoader() {
    356         throw new UnsupportedOperationException("Operation [directGetContextClassLoader] is not supported in jcl-over-slf4j. See also "
    357                         + UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J);
    358     }
    359 
    360     /**
    361      * This method exists to ensure signature compatibility.
    362      */
    363     protected static ClassLoader getContextClassLoader() throws LogConfigurationException {
    364         throw new UnsupportedOperationException("Operation [getContextClassLoader] is not supported in jcl-over-slf4j. See also "
    365                         + UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J);
    366     }
    367 
    368     /**
    369      * This method exists to ensure signature compatibility.
    370      */
    371     protected static ClassLoader getClassLoader(Class clazz) {
    372         throw new UnsupportedOperationException("Operation [getClassLoader] is not supported in jcl-over-slf4j. See also "
    373                         + UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J);
    374     }
    375 
    376     /**
    377      * This method exists to ensure signature compatibility.
    378      */
    379     protected static boolean isDiagnosticsEnabled() {
    380         throw new UnsupportedOperationException("Operation [isDiagnosticsEnabled] is not supported in jcl-over-slf4j. See also "
    381                         + UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J);
    382     }
    383 
    384     /**
    385      * This method exists to ensure signature compatibility.
    386      */
    387     protected static void logRawDiagnostic(String msg) {
    388         throw new UnsupportedOperationException("Operation [logRawDiagnostic] is not supported in jcl-over-slf4j. See also "
    389                         + UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J);
    390     }
    391 
    392     /**
    393      * This method exists to ensure signature compatibility.
    394      */
    395     protected static LogFactory newFactory(final String factoryClass, final ClassLoader classLoader, final ClassLoader contextClassLoader) {
    396         throw new UnsupportedOperationException("Operation [logRawDiagnostic] is not supported in jcl-over-slf4j. See also "
    397                         + UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J);
    398     }
    399 
    400     /**
    401      * This method exists to ensure signature compatibility.
    402      */
    403     protected static LogFactory newFactory(final String factoryClass, final ClassLoader classLoader) {
    404         throw new UnsupportedOperationException("Operation [newFactory] is not supported in jcl-over-slf4j. See also "
    405                         + UNSUPPORTED_OPERATION_IN_JCL_OVER_SLF4J);
    406     }
    407 
    408 }