View Javadoc
1   /*
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
8    *
9    *      http://www.apache.org/licenses/LICENSE-2.0
10   *
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.
16   */
17  package org.apache.logging.log4j.core.config;
18  
19  import java.net.URI;
20  import java.util.Map;
21  
22  import org.apache.logging.log4j.Level;
23  import org.apache.logging.log4j.LogManager;
24  import org.apache.logging.log4j.Logger;
25  import org.apache.logging.log4j.core.LoggerContext;
26  import org.apache.logging.log4j.core.impl.Log4jContextFactory;
27  import org.apache.logging.log4j.core.util.NetUtils;
28  import org.apache.logging.log4j.spi.LoggerContextFactory;
29  import org.apache.logging.log4j.status.StatusLogger;
30  import org.apache.logging.log4j.util.Strings;
31  
32  /**
33   * Initializes and configure the Logging system. This class provides several ways to construct a LoggerContext using
34   * the location of a configuration file, a context name, and various optional parameters.
35   */
36  public final class Configurator {
37  
38      private static final String FQCN = Configurator.class.getName();
39  
40      private static final Logger LOGGER = StatusLogger.getLogger();
41  
42      private static Log4jContextFactory getFactory() {
43          final LoggerContextFactory factory = LogManager.getFactory();
44          if (factory instanceof Log4jContextFactory) {
45              return (Log4jContextFactory) factory;
46          } else if (factory != null) {
47              LOGGER.error("LogManager returned an instance of {} which does not implement {}. Unable to initialize Log4j.",
48                      factory.getClass().getName(), Log4jContextFactory.class.getName());
49              return null;
50          } else {
51              LOGGER.fatal("LogManager did not return a LoggerContextFactory. This indicates something has gone terribly wrong!");
52              return null;
53          }
54      }
55  
56      /**
57       * Initializes the Logging Context.
58       * @param loader The ClassLoader for the Context (or null).
59       * @param source The InputSource for the configuration.
60       * @return The LoggerContext.
61       */
62      public static LoggerContext initialize(final ClassLoader loader,
63                                             final ConfigurationSource source) {
64          return initialize(loader, source, null);
65      }
66  
67      /**
68       * Initializes the Logging Context.
69       * @param loader The ClassLoader for the Context (or null).
70       * @param source The InputSource for the configuration.
71       * @param externalContext The external context to be attached to the LoggerContext.
72       * @return The LoggerContext.
73       */
74  
75      public static LoggerContext initialize(final ClassLoader loader,
76                                             final ConfigurationSource source,
77                                             final Object externalContext)
78      {
79  
80          try {
81              final Log4jContextFactory factory = getFactory();
82              return factory == null ? null :
83                      factory.getContext(FQCN, loader, externalContext, false, source);
84          } catch (final Exception ex) {
85              LOGGER.error("There was a problem obtaining a LoggerContext using the configuration source [{}]", source, ex);
86          }
87          return null;
88      }
89  
90      /**
91       * Initializes the Logging Context.
92       * @param name The Context name.
93       * @param loader The ClassLoader for the Context (or null).
94       * @param configLocation The configuration for the logging context.
95       * @return The LoggerContext or null if an error occurred (check the status logger).
96       */
97      public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation) {
98          return initialize(name, loader, configLocation, null);
99  
100     }
101 
102     /**
103      * Initializes the Logging Context.
104      * @param name The Context name.
105      * @param loader The ClassLoader for the Context (or null).
106      * @param configLocation The configuration for the logging context (or null, or blank).
107      * @param externalContext The external context to be attached to the LoggerContext
108      * @return The LoggerContext or null if an error occurred (check the status logger).
109      */
110     public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation,
111             final Object externalContext) {
112         final URI uri = Strings.isBlank(configLocation) ? null : NetUtils.toURI(configLocation);
113         return initialize(name, loader, uri, externalContext);
114     }
115 
116     /**
117      * Initializes the Logging Context.
118      * @param name The Context name.
119      * @param loader The ClassLoader for the Context (or null).
120      * @param configLocation The configuration for the logging context.
121      * @return The LoggerContext.
122      */
123     public static LoggerContext initialize(final String name, final ClassLoader loader, final URI configLocation) {
124         return initialize(name, loader, configLocation, null);
125     }
126 
127     /**
128      * Initializes the Logging Context.
129      * @param name The Context name.
130      * @param loader The ClassLoader for the Context (or null).
131      * @param configLocation The configuration for the logging context (or null).
132      * @param externalContext The external context to be attached to the LoggerContext
133      * @return The LoggerContext.
134      */
135     public static LoggerContext initialize(final String name, final ClassLoader loader, final URI configLocation,
136                                            final Object externalContext) {
137 
138         try {
139             final Log4jContextFactory factory = getFactory();
140             return factory == null ? null :
141                     factory.getContext(FQCN, loader, externalContext, false, configLocation, name);
142         } catch (final Exception ex) {
143             LOGGER.error("There was a problem initializing the LoggerContext [{}] using configuration at [{}].",
144                     name, configLocation, ex);
145         }
146         return null;
147     }
148 
149     /**
150      * Initializes the Logging Context.
151      * @param name The Context name.
152      * @param configLocation The configuration for the logging context.
153      * @return The LoggerContext or null if an error occurred (check the status logger).
154      */
155     public static LoggerContext initialize(final String name, final String configLocation) {
156         return initialize(name, null, configLocation);
157     }
158 
159     /**
160      * Initializes the Logging Context.
161      * @param configuration The Configuration.
162      * @return The LoggerContext.
163      */
164     public static LoggerContext initialize(Configuration configuration) {
165         return initialize(null, configuration, null);
166     }
167 
168     /**
169      * Initializes the Logging Context.
170      * @param loader The ClassLoader.
171      * @param configuration The Configuration.
172      * @return The LoggerContext.
173      */
174     public static LoggerContext initialize(final ClassLoader loader, Configuration configuration) {
175         return initialize(loader, configuration, null);
176     }
177 
178     /**
179      * Initializes the Logging Context.
180      * @param loader The ClassLoader.
181      * @param configuration The Configuration.
182      * @param externalContext - The external context to be attached to the LoggerContext.
183      * @return The LoggerContext.
184      */
185     public static LoggerContext initialize(final ClassLoader loader, Configuration configuration, final Object externalContext) {
186         try {
187             final Log4jContextFactory factory = getFactory();
188             return factory == null ? null :
189                     factory.getContext(FQCN, loader, externalContext, false, configuration);
190         } catch (final Exception ex) {
191             LOGGER.error("There was a problem initializing the LoggerContext using configuration {}",
192                     configuration.getName(), ex);
193         }
194         return null;
195     }
196 
197     /**
198      * Sets the levels of <code>parentLogger</code> and all 'child' loggers to the given <code>level</code>.
199      * @param parentLogger the parent logger
200      * @param level the new level
201      */
202     public static void setAllLevels(final String parentLogger, final Level level) {
203         // 1) get logger config
204         // 2) if exact match, use it, if not, create it.
205         // 3) set level on logger config 
206         // 4) update child logger configs with level
207         // 5) update loggers
208         final LoggerContext loggerContext = LoggerContext.getContext(false);
209         final Configuration config = loggerContext.getConfiguration();
210         boolean set = setLevel(parentLogger, level, config);
211         for (final Map.Entry<String, LoggerConfig> entry : config.getLoggers().entrySet()) {
212             if (entry.getKey().startsWith(parentLogger)) {
213                 set |= setLevel(entry.getValue(), level);
214             }
215         }
216         if (set) {
217             loggerContext.updateLoggers();
218         }
219     }
220 
221     private static boolean setLevel(final LoggerConfig loggerConfig, final Level level) {
222         final boolean set = !loggerConfig.getLevel().equals(level);
223         if (set) {
224             loggerConfig.setLevel(level);
225         }
226         return set;
227     }
228     
229     /**
230      * Sets logger levels.
231      * 
232      * @param levelMap
233      *            a levelMap where keys are level names and values are new
234      *            Levels.
235      */
236     public static void setLevel(final Map<String, Level> levelMap) {
237         final LoggerContext loggerContext = LoggerContext.getContext(false);
238         final Configuration config = loggerContext.getConfiguration();
239         boolean set = false;
240         for (final Map.Entry<String, Level> entry : levelMap.entrySet()) {
241             final String loggerName = entry.getKey();
242             final Level level = entry.getValue();
243             set |= setLevel(loggerName, level, config);
244         }
245         if (set) {
246             loggerContext.updateLoggers();
247         }
248     }
249 
250     /**
251      * Sets a logger's level.
252      * 
253      * @param loggerName
254      *            the logger name
255      * @param level
256      *            the new level
257      */
258     public static void setLevel(final String loggerName, final Level level) {
259         final LoggerContext loggerContext = LoggerContext.getContext(false);
260         if (Strings.isEmpty(loggerName)) {
261             setRootLevel(level);
262         } else {
263             if (setLevel(loggerName, level, loggerContext.getConfiguration())) {
264                 loggerContext.updateLoggers();
265             }
266         }
267     }
268 
269     private static boolean setLevel(final String loggerName, final Level level, final Configuration config) {
270         boolean set;
271         LoggerConfig loggerConfig = config.getLoggerConfig(loggerName);
272         if (!loggerName.equals(loggerConfig.getName())) {
273             // TODO Should additivity be inherited?
274             loggerConfig = new LoggerConfig(loggerName, level, true);
275             config.addLogger(loggerName, loggerConfig);
276             loggerConfig.setLevel(level);
277             set = true;
278         } else {
279             set = setLevel(loggerConfig, level);
280         }
281         return set;
282     }
283 
284     /**
285      * Sets the root logger's level.
286      * 
287      * @param level
288      *            the new level
289      */
290     public static void setRootLevel(final Level level) {
291         final LoggerContext loggerContext = LoggerContext.getContext(false);
292         final LoggerConfig loggerConfig = loggerContext.getConfiguration().getRootLogger();
293         if (!loggerConfig.getLevel().equals(level)) {
294             loggerConfig.setLevel(level);
295             loggerContext.updateLoggers();
296         }
297     }
298 
299     /**
300      * Shuts down the given logging context.
301      * @param ctx the logging context to shut down, may be null.
302      */
303     public static void shutdown(final LoggerContext ctx) {
304         if (ctx != null) {
305             ctx.stop();
306         }
307     }
308 
309     private Configurator() {
310         // empty
311     }
312 }