2 * Licensed to the Apache Software Foundation (ASF) under one or more
3 * contributor license agreements. See the NOTICE file distributed with
4 * this work for additional information regarding copyright ownership.
5 * The ASF licenses this file to You under the Apache License, Version 2.0
6 * (the "License"); you may not use this file except in compliance with
7 * the License. You may obtain a copy of the License at
9 * http://www.apache.org/licenses/LICENSE-2.0
11 * Unless required by applicable law or agreed to in writing, software
12 * distributed under the License is distributed on an "AS IS" BASIS,
13 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14 * See the License for the specific language governing permissions and
15 * limitations under the License.
18 package org.apache.log4j;
20 import org.apache.log4j.spi.LoggerRepository;
21 import org.apache.log4j.spi.LoggerFactory;
22 import org.apache.log4j.spi.RepositorySelector;
23 import org.apache.log4j.spi.DefaultRepositorySelector;
24 import org.apache.log4j.spi.RootLogger;
25 import org.apache.log4j.spi.NOPLoggerRepository;
26 import org.apache.log4j.helpers.Loader;
27 import org.apache.log4j.helpers.OptionConverter;
28 import org.apache.log4j.helpers.LogLog;
31 import java.net.MalformedURLException;
34 import java.util.Enumeration;
35 import java.io.StringWriter;
36 import java.io.PrintWriter;
39 * Gets {@link Logger} instances and operates on the current {@link LoggerRepository}.
42 * When the <code>LogManager</code> class is loaded into memory the default initialization procedure runs. The default initialization
43 * procedure</a> is described in the <a href="../../../../manual.html#defaultInit">short log4j manual</a>.
46 * @author Ceki Gülcü
48 public class LogManager {
51 * @deprecated This variable is for internal use only. It will
52 * become package protected in future versions.
54 static public final String DEFAULT_CONFIGURATION_FILE = "log4j.properties";
56 static final String DEFAULT_XML_CONFIGURATION_FILE = "log4j.xml";
59 * @deprecated This variable is for internal use only. It will
60 * become private in future versions.
62 static final public String DEFAULT_CONFIGURATION_KEY="log4j.configuration";
65 * @deprecated This variable is for internal use only. It will
66 * become private in future versions.
68 static final public String CONFIGURATOR_CLASS_KEY="log4j.configuratorClass";
71 * @deprecated This variable is for internal use only. It will
72 * become private in future versions.
74 public static final String DEFAULT_INIT_OVERRIDE_KEY =
75 "log4j.defaultInitOverride";
78 static private Object guard = null;
79 static private RepositorySelector repositorySelector;
82 // By default we use a DefaultRepositorySelector which always returns 'h'.
83 Hierarchy h = new Hierarchy(new RootLogger(Level.DEBUG));
84 repositorySelector = new DefaultRepositorySelector(h);
86 /** Search for the properties file log4j.properties in the CLASSPATH. */
87 String override =OptionConverter.getSystemProperty(DEFAULT_INIT_OVERRIDE_KEY,
90 // if there is no default init override, then get the resource
91 // specified by the user or the default config file.
92 if(override == null || "false".equalsIgnoreCase(override)) {
94 String configurationOptionStr = OptionConverter.getSystemProperty(
95 DEFAULT_CONFIGURATION_KEY,
98 String configuratorClassName = OptionConverter.getSystemProperty(
99 CONFIGURATOR_CLASS_KEY,
104 // if the user has not specified the log4j.configuration
105 // property, we search first for the file "log4j.xml" and then
106 // "log4j.properties"
107 if(configurationOptionStr == null) {
108 url = Loader.getResource(DEFAULT_XML_CONFIGURATION_FILE);
110 url = Loader.getResource(DEFAULT_CONFIGURATION_FILE);
114 url = new URL(configurationOptionStr);
115 } catch (MalformedURLException ex) {
116 // so, resource is not a URL:
117 // attempt to get the resource from the class path
118 url = Loader.getResource(configurationOptionStr);
122 // If we have a non-null url, then delegate the rest of the
123 // configuration to the OptionConverter.selectAndConfigure
126 LogLog.debug("Using URL ["+url+"] for automatic log4j configuration.");
128 OptionConverter.selectAndConfigure(url, configuratorClassName,
129 LogManager.getLoggerRepository());
130 } catch (NoClassDefFoundError e) {
131 LogLog.warn("Error during default initialization", e);
134 LogLog.debug("Could not find resource: ["+configurationOptionStr+"].");
137 LogLog.debug("Default initialization of overridden by " +
138 DEFAULT_INIT_OVERRIDE_KEY + "property.");
143 Sets <code>LoggerFactory</code> but only if the correct
144 <em>guard</em> is passed as parameter.
146 <p>Initally the guard is null. If the guard is
147 <code>null</code>, then invoking this method sets the logger
148 factory and the guard. Following invocations will throw a {@link
149 IllegalArgumentException}, unless the previously set
150 <code>guard</code> is passed as the second parameter.
152 <p>This allows a high-level component to set the {@link
153 RepositorySelector} used by the <code>LogManager</code>.
155 <p>For example, when tomcat starts it will be able to install its
156 own repository selector. However, if and when Tomcat is embedded
157 within JBoss, then JBoss will install its own repository selector
158 and Tomcat will use the repository selector set by its container,
162 void setRepositorySelector(RepositorySelector selector, Object guard)
163 throws IllegalArgumentException {
164 if((LogManager.guard != null) && (LogManager.guard != guard)) {
165 throw new IllegalArgumentException(
166 "Attempted to reset the LoggerFactory without possessing the guard.");
169 if(selector == null) {
170 throw new IllegalArgumentException("RepositorySelector must be non-null.");
173 LogManager.guard = guard;
174 LogManager.repositorySelector = selector;
179 * This method tests if called from a method that
180 * is known to result in class members being abnormally
181 * set to null but is assumed to be harmless since the
182 * all classes are in the process of being unloaded.
184 * @param ex exception used to determine calling stack.
185 * @return true if calling stack is recognized as likely safe.
187 private static boolean isLikelySafeScenario(final Exception ex) {
188 StringWriter stringWriter = new StringWriter();
189 ex.printStackTrace(new PrintWriter(stringWriter));
190 String msg = stringWriter.toString();
191 return msg.indexOf("org.apache.catalina.loader.WebappClassLoader.stop") != -1;
196 LoggerRepository getLoggerRepository() {
197 if (repositorySelector == null) {
198 repositorySelector = new DefaultRepositorySelector(new NOPLoggerRepository());
200 Exception ex = new IllegalStateException("Class invariant violation");
202 "log4j called after unloading, see http://logging.apache.org/log4j/1.2/faq.html#unload.";
203 if (isLikelySafeScenario(ex)) {
204 LogLog.debug(msg, ex);
206 LogLog.error(msg, ex);
209 return repositorySelector.getLoggerRepository();
213 Retrieve the appropriate root logger.
217 Logger getRootLogger() {
218 // Delegate the actual manufacturing of the logger to the logger repository.
219 return getLoggerRepository().getRootLogger();
223 Retrieve the appropriate {@link Logger} instance.
227 Logger getLogger(final String name) {
228 // Delegate the actual manufacturing of the logger to the logger repository.
229 return getLoggerRepository().getLogger(name);
233 Retrieve the appropriate {@link Logger} instance.
237 Logger getLogger(final Class clazz) {
238 // Delegate the actual manufacturing of the logger to the logger repository.
239 return getLoggerRepository().getLogger(clazz.getName());
244 Retrieve the appropriate {@link Logger} instance.
248 Logger getLogger(final String name, final LoggerFactory factory) {
249 // Delegate the actual manufacturing of the logger to the logger repository.
250 return getLoggerRepository().getLogger(name, factory);
255 Logger exists(final String name) {
256 return getLoggerRepository().exists(name);
261 Enumeration getCurrentLoggers() {
262 return getLoggerRepository().getCurrentLoggers();
268 getLoggerRepository().shutdown();
273 void resetConfiguration() {
274 getLoggerRepository().resetConfiguration();