View Javadoc

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