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&uuml;lc&uuml;
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}