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