001/* 002 * Licensed to the Apache Software Foundation (ASF) under one or more 003 * contributor license agreements. See the NOTICE file distributed with 004 * this work for additional information regarding copyright ownership. 005 * The ASF licenses this file to You under the Apache license, Version 2.0 006 * (the "License"); you may not use this file except in compliance with 007 * the License. You may obtain a copy of the License at 008 * 009 * http://www.apache.org/licenses/LICENSE-2.0 010 * 011 * Unless required by applicable law or agreed to in writing, software 012 * distributed under the License is distributed on an "AS IS" BASIS, 013 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 014 * See the license for the specific language governing permissions and 015 * limitations under the license. 016 */ 017package org.apache.logging.log4j.core.config; 018 019import java.net.URI; 020import java.util.Map; 021 022import org.apache.logging.log4j.Level; 023import org.apache.logging.log4j.LogManager; 024import org.apache.logging.log4j.Logger; 025import org.apache.logging.log4j.core.LoggerContext; 026import org.apache.logging.log4j.core.impl.Log4jContextFactory; 027import org.apache.logging.log4j.core.util.NetUtils; 028import org.apache.logging.log4j.spi.LoggerContextFactory; 029import org.apache.logging.log4j.status.StatusLogger; 030import org.apache.logging.log4j.util.Strings; 031 032/** 033 * Initializes and configure the Logging system. This class provides several ways to construct a LoggerContext using 034 * the location of a configuration file, a context name, and various optional parameters. 035 */ 036public final class Configurator { 037 038 private static final String FQCN = Configurator.class.getName(); 039 040 private static final Logger LOGGER = StatusLogger.getLogger(); 041 042 private static Log4jContextFactory getFactory() { 043 final LoggerContextFactory factory = LogManager.getFactory(); 044 if (factory instanceof Log4jContextFactory) { 045 return (Log4jContextFactory) factory; 046 } else if (factory != null) { 047 LOGGER.error("LogManager returned an instance of {} which does not implement {}. Unable to initialize Log4j.", 048 factory.getClass().getName(), Log4jContextFactory.class.getName()); 049 return null; 050 } else { 051 LOGGER.fatal("LogManager did not return a LoggerContextFactory. This indicates something has gone terribly wrong!"); 052 return null; 053 } 054 } 055 056 /** 057 * Initializes the Logging Context. 058 * @param loader The ClassLoader for the Context (or null). 059 * @param source The InputSource for the configuration. 060 * @return The LoggerContext. 061 */ 062 public static LoggerContext initialize(final ClassLoader loader, 063 final ConfigurationSource source) { 064 return initialize(loader, source, null); 065 } 066 067 /** 068 * Initializes the Logging Context. 069 * @param loader The ClassLoader for the Context (or null). 070 * @param source The InputSource for the configuration. 071 * @param externalContext The external context to be attached to the LoggerContext. 072 * @return The LoggerContext. 073 */ 074 075 public static LoggerContext initialize(final ClassLoader loader, 076 final ConfigurationSource source, 077 final Object externalContext) 078 { 079 080 try { 081 final Log4jContextFactory factory = getFactory(); 082 return factory == null ? null : 083 factory.getContext(FQCN, loader, externalContext, false, source); 084 } catch (final Exception ex) { 085 LOGGER.error("There was a problem obtaining a LoggerContext using the configuration source [{}]", source, ex); 086 } 087 return null; 088 } 089 090 /** 091 * Initializes the Logging Context. 092 * @param name The Context name. 093 * @param loader The ClassLoader for the Context (or null). 094 * @param configLocation The configuration for the logging context. 095 * @return The LoggerContext or null if an error occurred (check the status logger). 096 */ 097 public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation) { 098 return initialize(name, loader, configLocation, null); 099 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}