• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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      */
LogFactory()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      */
getAttribute(String name)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      */
getAttributeNames()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      */
getInstance(Class clazz)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      */
getInstance(String name)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      */
release()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      */
removeAttribute(String name)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      */
setAttribute(String name, Object value)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      */
getFactory()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      */
getLog(Class clazz)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      */
getLog(String name)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      */
release(ClassLoader classLoader)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      */
releaseAll()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      */
objectId(Object o)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      */
createFactory(String factoryClass, ClassLoader classLoader)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      */
directGetContextClassLoader()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      */
getContextClassLoader()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      */
getClassLoader(Class clazz)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      */
isDiagnosticsEnabled()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      */
logRawDiagnostic(String msg)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      */
newFactory(final String factoryClass, final ClassLoader classLoader, final ClassLoader contextClassLoader)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      */
newFactory(final String factoryClass, final ClassLoader classLoader)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 }