SLF4JLogFactory.java revision 7ba0605dc97fb81bde8311510d27b3ccba170008
1/** 2 * Copyright (c) 2004-2011 QOS.ch 3 * All rights reserved. 4 * 5 * Permission is hereby granted, free of charge, to any person obtaining 6 * a copy of this software and associated documentation files (the 7 * "Software"), to deal in the Software without restriction, including 8 * without limitation the rights to use, copy, modify, merge, publish, 9 * distribute, sublicense, and/or sell copies of the Software, and to 10 * permit persons to whom the Software is furnished to do so, subject to 11 * the following conditions: 12 * 13 * The above copyright notice and this permission notice shall be 14 * included in all copies or substantial portions of the Software. 15 * 16 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 17 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF 18 * MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 19 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE 20 * LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION 21 * OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION 22 * WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. 23 * 24 */ 25package org.apache.commons.logging.impl; 26 27import java.util.ArrayList; 28import java.util.Enumeration; 29import java.util.HashMap; 30import java.util.Hashtable; 31import java.util.List; 32import java.util.Map; 33 34import org.apache.commons.logging.Log; 35import org.apache.commons.logging.LogConfigurationException; 36import org.apache.commons.logging.LogFactory; 37import org.slf4j.Logger; 38import org.slf4j.LoggerFactory; 39import org.slf4j.spi.LocationAwareLogger; 40 41/** 42 * <p> 43 * Concrete subclass of {@link LogFactory} which always delegates to the 44 * {@link LoggerFactory org.slf4j.LoggerFactory} class. 45 * 46 * <p> 47 * This factory generates instances of {@link SLF4JLog}. It will remember 48 * previously created instances for the same name, and will return them on 49 * repeated requests to the <code>getInstance()</code> method. 50 * 51 * <p> 52 * This implementation ignores any configured attributes. 53 * </p> 54 * 55 * @author Rod Waldhoff 56 * @author Craig R. McClanahan 57 * @author Richard A. Sitze 58 * @author Ceki Gülcü 59 */ 60 61public class SLF4JLogFactory extends LogFactory { 62 63 // ----------------------------------------------------------- Constructors 64 65 /** 66 * The {@link org.apache.commons.logging.Log}instances that have already been 67 * created, keyed by logger name. 68 */ 69 Map loggerMap; 70 71 /** 72 * Public no-arguments constructor required by the lookup mechanism. 73 */ 74 public SLF4JLogFactory() { 75 loggerMap = new HashMap(); 76 } 77 78 // ----------------------------------------------------- Manifest Constants 79 80 /** 81 * The name of the system property identifying our {@link Log}implementation 82 * class. 83 */ 84 public static final String LOG_PROPERTY = "org.apache.commons.logging.Log"; 85 86 // ----------------------------------------------------- Instance Variables 87 88 /** 89 * Configuration attributes. 90 */ 91 protected Hashtable attributes = new Hashtable(); 92 93 // --------------------------------------------------------- Public Methods 94 95 /** 96 * Return the configuration attribute with the specified name (if any), or 97 * <code>null</code> if there is no such attribute. 98 * 99 * @param name 100 * Name of the attribute to return 101 */ 102 public Object getAttribute(String name) { 103 104 return (attributes.get(name)); 105 106 } 107 108 /** 109 * Return an array containing the names of all currently defined configuration 110 * attributes. If there are no such attributes, a zero length array is 111 * returned. 112 */ 113 public String[] getAttributeNames() { 114 115 List names = new ArrayList(); 116 Enumeration keys = attributes.keys(); 117 while (keys.hasMoreElements()) { 118 names.add((String) keys.nextElement()); 119 } 120 String results[] = new String[names.size()]; 121 for (int i = 0; i < results.length; i++) { 122 results[i] = (String) names.get(i); 123 } 124 return (results); 125 126 } 127 128 /** 129 * Convenience method to derive a name from the specified class and call 130 * <code>getInstance(String)</code> with it. 131 * 132 * @param clazz 133 * Class for which a suitable Log name will be derived 134 * 135 * @exception LogConfigurationException 136 * if a suitable <code>Log</code> instance cannot be returned 137 */ 138 public Log getInstance(Class clazz) throws LogConfigurationException { 139 140 return (getInstance(clazz.getName())); 141 142 } 143 144 /** 145 * <p> 146 * Construct (if necessary) and return a <code>Log</code> instance, using 147 * the factory's current set of configuration attributes. 148 * </p> 149 * 150 * @param name 151 * Logical name of the <code>Log</code> instance to be returned 152 * (the meaning of this name is only known to the underlying logging 153 * implementation that is being wrapped) 154 * 155 * @exception LogConfigurationException 156 * if a suitable <code>Log</code> instance cannot be returned 157 */ 158 public Log getInstance(String name) throws LogConfigurationException { 159 Log instance = null; 160 // protect against concurrent access of loggerMap 161 synchronized (loggerMap) { 162 instance = (Log) loggerMap.get(name); 163 if (instance == null) { 164 Logger logger = LoggerFactory.getLogger(name); 165 if(logger instanceof LocationAwareLogger) { 166 instance = new SLF4JLocationAwareLog((LocationAwareLogger) logger); 167 } else { 168 instance = new SLF4JLog(logger); 169 } 170 loggerMap.put(name, instance); 171 } 172 } 173 return (instance); 174 175 } 176 177 /** 178 * Release any internal references to previously created 179 * {@link org.apache.commons.logging.Log}instances returned by this factory. 180 * This is useful in environments like servlet containers, which implement 181 * application reloading by throwing away a ClassLoader. Dangling references 182 * to objects in that class loader would prevent garbage collection. 183 */ 184 public void release() { 185 // This method is never called by jcl-over-slf4j classes. However, 186 // in certain deployment scenarios, in particular if jcl-over-slf4j.jar 187 // is 188 // in the the web-app class loader and the official commons-logging.jar is 189 // deployed in some parent class loader (e.g. commons/lib), then it is 190 // possible 191 // for the parent class loader to mask the classes shipping in 192 // jcl-over-slf4j.jar. 193 System.out.println("WARN: The method " + SLF4JLogFactory.class 194 + "#release() was invoked."); 195 System.out 196 .println("WARN: Please see http://www.slf4j.org/codes.html#release for an explanation."); 197 System.out.flush(); 198 } 199 200 /** 201 * Remove any configuration attribute associated with the specified name. If 202 * there is no such attribute, no action is taken. 203 * 204 * @param name 205 * Name of the attribute to remove 206 */ 207 public void removeAttribute(String name) { 208 attributes.remove(name); 209 } 210 211 /** 212 * Set the configuration attribute with the specified name. Calling this with 213 * a <code>null</code> value is equivalent to calling 214 * <code>removeAttribute(name)</code>. 215 * 216 * @param name 217 * Name of the attribute to set 218 * @param value 219 * Value of the attribute to set, or <code>null</code> to remove 220 * any setting for this attribute 221 */ 222 public void setAttribute(String name, Object value) { 223 224 if (value == null) { 225 attributes.remove(name); 226 } else { 227 attributes.put(name, value); 228 } 229 230 } 231}