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 }