001: /*
002: * Copyright 2001-2004 The Apache Software Foundation.
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016:
017: package org.apache.commons.logging.impl;
018:
019: import java.util.Enumeration;
020: import java.util.HashMap;
021: import java.util.Hashtable;
022: import java.util.Map;
023: import java.util.Vector;
024:
025: import org.apache.commons.logging.Log;
026: import org.apache.commons.logging.LogConfigurationException;
027: import org.apache.commons.logging.LogFactory;
028: import org.slf4j.Logger;
029: import org.slf4j.LoggerFactory;
030: import org.slf4j.spi.LocationAwareLogger;
031:
032: /**
033: * <p>
034: * Concrete subclass of {@link LogFactory} which always delegates to the
035: * {@link LoggerFactory org.slf4j.LoggerFactory} class.
036: *
037: * <p>
038: * This factory generates instances of {@link SLF4JLog}. It will remember
039: * previously created instances for the same name, and will return them on
040: * repeated requests to the <code>getInstance()</code> method.
041: *
042: * <p>
043: * This implementation ignores any configured attributes.
044: * </p>
045: *
046: * @author Rod Waldhoff
047: * @author Craig R. McClanahan
048: * @author Richard A. Sitze
049: * @author Ceki Gülcü
050: */
051:
052: public class SLF4JLogFactory extends LogFactory {
053:
054: // ----------------------------------------------------------- Constructors
055:
056: /**
057: * The {@link org.apache.commons.logging.Log}instances that have already been
058: * created, keyed by logger name.
059: */
060: Map loggerMap;
061:
062: /**
063: * Public no-arguments constructor required by the lookup mechanism.
064: */
065: public SLF4JLogFactory() {
066: loggerMap = new HashMap();
067: }
068:
069: // ----------------------------------------------------- Manifest Constants
070:
071: /**
072: * The name of the system property identifying our {@link Log}implementation
073: * class.
074: */
075: public static final String LOG_PROPERTY = "org.apache.commons.logging.Log";
076:
077: // ----------------------------------------------------- Instance Variables
078:
079: /**
080: * Configuration attributes.
081: */
082: protected Hashtable attributes = new Hashtable();
083:
084: // --------------------------------------------------------- Public Methods
085:
086: /**
087: * Return the configuration attribute with the specified name (if any), or
088: * <code>null</code> if there is no such attribute.
089: *
090: * @param name
091: * Name of the attribute to return
092: */
093: public Object getAttribute(String name) {
094:
095: return (attributes.get(name));
096:
097: }
098:
099: /**
100: * Return an array containing the names of all currently defined configuration
101: * attributes. If there are no such attributes, a zero length array is
102: * returned.
103: */
104: public String[] getAttributeNames() {
105:
106: Vector names = new Vector();
107: Enumeration keys = attributes.keys();
108: while (keys.hasMoreElements()) {
109: names.addElement((String) keys.nextElement());
110: }
111: String results[] = new String[names.size()];
112: for (int i = 0; i < results.length; i++) {
113: results[i] = (String) names.elementAt(i);
114: }
115: return (results);
116:
117: }
118:
119: /**
120: * Convenience method to derive a name from the specified class and call
121: * <code>getInstance(String)</code> with it.
122: *
123: * @param clazz
124: * Class for which a suitable Log name will be derived
125: *
126: * @exception LogConfigurationException
127: * if a suitable <code>Log</code> instance cannot be returned
128: */
129: public Log getInstance(Class clazz)
130: throws LogConfigurationException {
131:
132: return (getInstance(clazz.getName()));
133:
134: }
135:
136: /**
137: * <p>
138: * Construct (if necessary) and return a <code>Log</code> instance, using
139: * the factory's current set of configuration attributes.
140: * </p>
141: *
142: * @param name
143: * Logical name of the <code>Log</code> instance to be returned
144: * (the meaning of this name is only known to the underlying logging
145: * implementation that is being wrapped)
146: *
147: * @exception LogConfigurationException
148: * if a suitable <code>Log</code> instance cannot be returned
149: */
150: public Log getInstance(String name)
151: throws LogConfigurationException {
152: Log instance = null;
153: // protect against concurrent access of loggerMap
154: synchronized (this ) {
155: instance = (Log) loggerMap.get(name);
156: if (instance == null) {
157: Logger logger = LoggerFactory.getLogger(name);
158: if (logger instanceof LocationAwareLogger) {
159: instance = new SLF4JLocationAwareLog(
160: (LocationAwareLogger) logger);
161: } else {
162: instance = new SLF4JLog(logger);
163: }
164: loggerMap.put(name, instance);
165: }
166: }
167: return (instance);
168:
169: }
170:
171: /**
172: * Release any internal references to previously created
173: * {@link org.apache.commons.logging.Log}instances returned by this factory.
174: * This is useful in environments like servlet containers, which implement
175: * application reloading by throwing away a ClassLoader. Dangling references
176: * to objects in that class loader would prevent garbage collection.
177: */
178: public void release() {
179: // This method is never called by jcl-over-slf4j classes. However,
180: // in certain deployment scenarios, in particular if jcl104-over-slf4j.jar
181: // is
182: // in the the web-app class loader and the official commons-logging.jar is
183: // deployed in some parent class loader (e.g. commons/lib), then it is
184: // possible
185: // for the parent class loader to mask the classes shipping in
186: // jcl104-over-slf4j.jar.
187: System.out.println("WARN: The method " + SLF4JLogFactory.class
188: + "#release() was invoked.");
189: System.out
190: .println("WARN: Please see http://www.slf4j.org/codes.html#release for an explanation.");
191: System.out.flush();
192: }
193:
194: /**
195: * Remove any configuration attribute associated with the specified name. If
196: * there is no such attribute, no action is taken.
197: *
198: * @param name
199: * Name of the attribute to remove
200: */
201: public void removeAttribute(String name) {
202: attributes.remove(name);
203: }
204:
205: /**
206: * Set the configuration attribute with the specified name. Calling this with
207: * a <code>null</code> value is equivalent to calling
208: * <code>removeAttribute(name)</code>.
209: *
210: * @param name
211: * Name of the attribute to set
212: * @param value
213: * Value of the attribute to set, or <code>null</code> to remove
214: * any setting for this attribute
215: */
216: public void setAttribute(String name, Object value) {
217:
218: if (value == null) {
219: attributes.remove(name);
220: } else {
221: attributes.put(name, value);
222: }
223:
224: }
225: }
|