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 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 }