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.ArrayList; 021import java.util.List; 022import java.util.Map; 023 024import org.apache.logging.log4j.Level; 025import org.apache.logging.log4j.LogManager; 026import org.apache.logging.log4j.Logger; 027import org.apache.logging.log4j.core.LoggerContext; 028import org.apache.logging.log4j.core.impl.Log4jContextFactory; 029import org.apache.logging.log4j.core.util.NetUtils; 030import org.apache.logging.log4j.spi.LoggerContextFactory; 031import org.apache.logging.log4j.status.StatusLogger; 032import org.apache.logging.log4j.util.Strings; 033 034/** 035 * Initializes and configure the Logging system. This class provides several ways to construct a LoggerContext using 036 * the location of a configuration file, a context name, and various optional parameters. 037 */ 038public final class Configurator { 039 040 private static final String FQCN = Configurator.class.getName(); 041 042 private static final Logger LOGGER = StatusLogger.getLogger(); 043 044 private static Log4jContextFactory getFactory() { 045 final LoggerContextFactory factory = LogManager.getFactory(); 046 if (factory instanceof Log4jContextFactory) { 047 return (Log4jContextFactory) factory; 048 } else if (factory != null) { 049 LOGGER.error("LogManager returned an instance of {} which does not implement {}. Unable to initialize Log4j.", 050 factory.getClass().getName(), Log4jContextFactory.class.getName()); 051 return null; 052 } else { 053 LOGGER.fatal("LogManager did not return a LoggerContextFactory. This indicates something has gone terribly wrong!"); 054 return null; 055 } 056 } 057 058 /** 059 * Initializes the Logging Context. 060 * @param loader The ClassLoader for the Context (or null). 061 * @param source The InputSource for the configuration. 062 * @return The LoggerContext. 063 */ 064 public static LoggerContext initialize(final ClassLoader loader, 065 final ConfigurationSource source) { 066 return initialize(loader, source, null); 067 } 068 069 /** 070 * Initializes the Logging Context. 071 * @param loader The ClassLoader for the Context (or null). 072 * @param source The InputSource for the configuration. 073 * @param externalContext The external context to be attached to the LoggerContext. 074 * @return The LoggerContext. 075 */ 076 077 public static LoggerContext initialize(final ClassLoader loader, 078 final ConfigurationSource source, 079 final Object externalContext) 080 { 081 082 try { 083 final Log4jContextFactory factory = getFactory(); 084 return factory == null ? null : 085 factory.getContext(FQCN, loader, externalContext, false, source); 086 } catch (final Exception ex) { 087 LOGGER.error("There was a problem obtaining a LoggerContext using the configuration source [{}]", source, ex); 088 } 089 return null; 090 } 091 092 /** 093 * Initializes the Logging Context. 094 * @param name The Context name. 095 * @param loader The ClassLoader for the Context (or null). 096 * @param configLocation The configuration for the logging context. 097 * @return The LoggerContext or null if an error occurred (check the status logger). 098 */ 099 public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation) { 100 return initialize(name, loader, configLocation, null); 101 102 } 103 104 /** 105 * Initializes the Logging Context. 106 * @param name The Context name. 107 * @param loader The ClassLoader for the Context (or null). 108 * @param configLocation The configuration for the logging context (or null, or blank). 109 * @param externalContext The external context to be attached to the LoggerContext 110 * @return The LoggerContext or null if an error occurred (check the status logger). 111 */ 112 public static LoggerContext initialize(final String name, final ClassLoader loader, final String configLocation, 113 final Object externalContext) { 114 if (Strings.isBlank(configLocation)) { 115 return initialize(name, loader, (URI) null, externalContext); 116 } 117 if (configLocation.contains(",")) { 118 String[] parts = configLocation.split(","); 119 String scheme = null; 120 List<URI> uris = new ArrayList<>(parts.length); 121 for (String part : parts) { 122 URI uri = NetUtils.toURI(scheme != null ? scheme + ":" + part.trim() : part.trim()); 123 if (scheme == null && uri.getScheme() != null) { 124 scheme = uri.getScheme(); 125 } 126 uris.add(uri); 127 } 128 return initialize(name, loader, uris, externalContext); 129 } else { 130 return initialize(name, loader, NetUtils.toURI(configLocation), externalContext); 131 } 132 } 133 134 /** 135 * Initializes the Logging Context. 136 * @param name The Context name. 137 * @param loader The ClassLoader for the Context (or null). 138 * @param configLocation The configuration for the logging context. 139 * @return The LoggerContext. 140 */ 141 public static LoggerContext initialize(final String name, final ClassLoader loader, final URI configLocation) { 142 return initialize(name, loader, configLocation, null); 143 } 144 145 /** 146 * Initializes the Logging Context. 147 * @param name The Context name. 148 * @param loader The ClassLoader for the Context (or null). 149 * @param configLocation The configuration for the logging context (or null). 150 * @param externalContext The external context to be attached to the LoggerContext 151 * @return The LoggerContext. 152 */ 153 public static LoggerContext initialize(final String name, final ClassLoader loader, final URI configLocation, 154 final Object externalContext) { 155 156 try { 157 final Log4jContextFactory factory = getFactory(); 158 return factory == null ? null : 159 factory.getContext(FQCN, loader, externalContext, false, configLocation, name); 160 } catch (final Exception ex) { 161 LOGGER.error("There was a problem initializing the LoggerContext [{}] using configuration at [{}].", 162 name, configLocation, ex); 163 } 164 return null; 165 } 166 167 public static LoggerContext initialize(final String name, final ClassLoader loader, final List<URI> configLocations, 168 final Object externalContext) { 169 try { 170 final Log4jContextFactory factory = getFactory(); 171 return factory == null ? 172 null : 173 factory.getContext(FQCN, loader, externalContext, false, configLocations, name); 174 } catch (final Exception ex) { 175 LOGGER.error("There was a problem initializing the LoggerContext [{}] using configurations at [{}].", name, 176 configLocations, ex); 177 } 178 return null; 179 } 180 181 /** 182 * Initializes the Logging Context. 183 * @param name The Context name. 184 * @param configLocation The configuration for the logging context. 185 * @return The LoggerContext or null if an error occurred (check the status logger). 186 */ 187 public static LoggerContext initialize(final String name, final String configLocation) { 188 return initialize(name, null, configLocation); 189 } 190 191 /** 192 * Initializes the Logging Context. 193 * @param configuration The Configuration. 194 * @return The LoggerContext. 195 */ 196 public static LoggerContext initialize(Configuration configuration) { 197 return initialize(null, configuration, null); 198 } 199 200 /** 201 * Initializes the Logging Context. 202 * @param loader The ClassLoader. 203 * @param configuration The Configuration. 204 * @return The LoggerContext. 205 */ 206 public static LoggerContext initialize(final ClassLoader loader, Configuration configuration) { 207 return initialize(loader, configuration, null); 208 } 209 210 /** 211 * Initializes the Logging Context. 212 * @param loader The ClassLoader. 213 * @param configuration The Configuration. 214 * @param externalContext - The external context to be attached to the LoggerContext. 215 * @return The LoggerContext. 216 */ 217 public static LoggerContext initialize(final ClassLoader loader, Configuration configuration, final Object externalContext) { 218 try { 219 final Log4jContextFactory factory = getFactory(); 220 return factory == null ? null : 221 factory.getContext(FQCN, loader, externalContext, false, configuration); 222 } catch (final Exception ex) { 223 LOGGER.error("There was a problem initializing the LoggerContext using configuration {}", 224 configuration.getName(), ex); 225 } 226 return null; 227 } 228 229 /** 230 * Sets the levels of <code>parentLogger</code> and all 'child' loggers to the given <code>level</code>. 231 * @param parentLogger the parent logger 232 * @param level the new level 233 */ 234 public static void setAllLevels(final String parentLogger, final Level level) { 235 // 1) get logger config 236 // 2) if exact match, use it, if not, create it. 237 // 3) set level on logger config 238 // 4) update child logger configs with level 239 // 5) update loggers 240 final LoggerContext loggerContext = LoggerContext.getContext(false); 241 final Configuration config = loggerContext.getConfiguration(); 242 boolean set = setLevel(parentLogger, level, config); 243 for (final Map.Entry<String, LoggerConfig> entry : config.getLoggers().entrySet()) { 244 if (entry.getKey().startsWith(parentLogger)) { 245 set |= setLevel(entry.getValue(), level); 246 } 247 } 248 if (set) { 249 loggerContext.updateLoggers(); 250 } 251 } 252 253 private static boolean setLevel(final LoggerConfig loggerConfig, final Level level) { 254 final boolean set = !loggerConfig.getLevel().equals(level); 255 if (set) { 256 loggerConfig.setLevel(level); 257 } 258 return set; 259 } 260 261 /** 262 * Sets logger levels. 263 * 264 * @param levelMap 265 * a levelMap where keys are level names and values are new 266 * Levels. 267 */ 268 public static void setLevel(final Map<String, Level> levelMap) { 269 final LoggerContext loggerContext = LoggerContext.getContext(false); 270 final Configuration config = loggerContext.getConfiguration(); 271 boolean set = false; 272 for (final Map.Entry<String, Level> entry : levelMap.entrySet()) { 273 final String loggerName = entry.getKey(); 274 final Level level = entry.getValue(); 275 set |= setLevel(loggerName, level, config); 276 } 277 if (set) { 278 loggerContext.updateLoggers(); 279 } 280 } 281 282 /** 283 * Sets a logger's level. 284 * 285 * @param loggerName 286 * the logger name 287 * @param level 288 * the new level 289 */ 290 public static void setLevel(final String loggerName, final Level level) { 291 final LoggerContext loggerContext = LoggerContext.getContext(false); 292 if (Strings.isEmpty(loggerName)) { 293 setRootLevel(level); 294 } else { 295 if (setLevel(loggerName, level, loggerContext.getConfiguration())) { 296 loggerContext.updateLoggers(); 297 } 298 } 299 } 300 301 private static boolean setLevel(final String loggerName, final Level level, final Configuration config) { 302 boolean set; 303 LoggerConfig loggerConfig = config.getLoggerConfig(loggerName); 304 if (!loggerName.equals(loggerConfig.getName())) { 305 // TODO Should additivity be inherited? 306 loggerConfig = new LoggerConfig(loggerName, level, true); 307 config.addLogger(loggerName, loggerConfig); 308 loggerConfig.setLevel(level); 309 set = true; 310 } else { 311 set = setLevel(loggerConfig, level); 312 } 313 return set; 314 } 315 316 /** 317 * Sets the root logger's level. 318 * 319 * @param level 320 * the new level 321 */ 322 public static void setRootLevel(final Level level) { 323 final LoggerContext loggerContext = LoggerContext.getContext(false); 324 final LoggerConfig loggerConfig = loggerContext.getConfiguration().getRootLogger(); 325 if (!loggerConfig.getLevel().equals(level)) { 326 loggerConfig.setLevel(level); 327 loggerContext.updateLoggers(); 328 } 329 } 330 331 /** 332 * Shuts down the given logging context. 333 * @param ctx the logging context to shut down, may be null. 334 */ 335 public static void shutdown(final LoggerContext ctx) { 336 if (ctx != null) { 337 ctx.stop(); 338 } 339 } 340 341 private Configurator() { 342 // empty 343 } 344}