View Javadoc

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