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