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ülcü
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", i.e. is the same as the
325 * return value of the Object.toString() method, but works even when the
326 * specified object's class has overridden 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 }