Java tutorial
/* * Copyright 2012-2013 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.springframework.boot.context.initializer; import java.lang.management.ManagementFactory; import java.util.HashMap; import java.util.List; import java.util.Map; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplicationInitializer; import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LoggingSystem; import org.springframework.context.ApplicationContextInitializer; import org.springframework.context.ConfigurableApplicationContext; import org.springframework.core.Ordered; import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.Environment; import org.springframework.util.LinkedMultiValueMap; import org.springframework.util.MultiValueMap; import org.springframework.util.ResourceUtils; /** * An {@link ApplicationContextInitializer} that configures a logging framework depending * on what it finds on the classpath and in the {@link Environment}. If the environment * contains a property <code>logging.config</code> then that will be used to initialize * the logging system, otherwise a default location is used. The classpath is probed for * log4j and logback and if those are present they will be reconfigured, otherwise vanilla * <code>java.util.logging</code> will be used. </p> * * <p> * The default config locations are <code>classpath:log4j.properties</code> or * <code>classpath:log4j.xml</code> for log4j; <code>classpath:logback.xml</code> for * logback; and <code>classpath:logging.properties</code> for * <code>java.util.logging</code>. If the correct one of those files is not found then * some sensible defaults are adopted from files of the same name but in the package * containing {@link LoggingApplicationContextInitializer}. * </p> * * <p> * Some system properties may be set as side effects, and these can be useful if the * logging configuration supports placeholders (i.e. log4j or logback): * <ul> * <li><code>LOG_FILE</code> is set to the value of <code>logging.file</code> if found in * the environment</li> * <li><code>LOG_PATH</code> is set to the value of <code>logging.path</code> if found in * the environment</li> * <li><code>PID</code> is set to the value of the current process ID if it can be * determined</li> * </ul> * * @author Dave Syer * @author Phillip Webb */ public class LoggingApplicationContextInitializer implements ApplicationContextInitializer<ConfigurableApplicationContext>, SpringApplicationInitializer, Ordered { private static final Map<String, String> ENVIRONMENT_SYSTEM_PROPERTY_MAPPING; static { ENVIRONMENT_SYSTEM_PROPERTY_MAPPING = new HashMap<String, String>(); ENVIRONMENT_SYSTEM_PROPERTY_MAPPING.put("logging.file", "LOG_FILE"); ENVIRONMENT_SYSTEM_PROPERTY_MAPPING.put("logging.path", "LOG_PATH"); ENVIRONMENT_SYSTEM_PROPERTY_MAPPING.put("PID", "PID"); } private static MultiValueMap<LogLevel, String> LOG_LEVEL_LOGGERS; static { LOG_LEVEL_LOGGERS = new LinkedMultiValueMap<LogLevel, String>(); LOG_LEVEL_LOGGERS.add(LogLevel.DEBUG, "org.springframework.boot"); LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.springframework"); LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.apache.tomcat"); LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.eclipse.jetty"); LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.hibernate.tool.hbm2ddl"); } private final Log logger = LogFactory.getLog(getClass()); private int order = Integer.MIN_VALUE + 11; private boolean parseArgs = true; private LogLevel springBootLogging = null; @Override public void initialize(SpringApplication springApplication, String[] args) { if (System.getProperty("PID") == null) { System.setProperty("PID", getPid()); } LoggingSystem loggingSystem = LoggingSystem.get(springApplication.getClass().getClassLoader()); loggingSystem.beforeInitialize(); } /** * Initialize the logging system according to preferences expressed through the * {@link Environment} and the classpath. */ @Override public void initialize(ConfigurableApplicationContext applicationContext) { ConfigurableEnvironment environment = applicationContext.getEnvironment(); if (this.parseArgs && this.springBootLogging == null) { if (environment.containsProperty("debug")) { this.springBootLogging = LogLevel.DEBUG; } if (environment.containsProperty("trace")) { this.springBootLogging = LogLevel.TRACE; } } for (Map.Entry<String, String> mapping : ENVIRONMENT_SYSTEM_PROPERTY_MAPPING.entrySet()) { if (environment.containsProperty(mapping.getKey())) { System.setProperty(mapping.getValue(), environment.getProperty(mapping.getKey())); } } LoggingSystem system = LoggingSystem.get(applicationContext.getClassLoader()); // User specified configuration if (environment.containsProperty("logging.config")) { String value = environment.getProperty("logging.config"); try { ResourceUtils.getURL(value).openStream().close(); system.initialize(value); return; } catch (Exception ex) { // Swallow exception and continue } this.logger.warn("Logging environment value '" + value + "' cannot be opened and will be ignored"); } system.initialize(); if (this.springBootLogging != null) { initializeLogLevel(system, this.springBootLogging); } } protected void initializeLogLevel(LoggingSystem system, LogLevel level) { List<String> loggers = LOG_LEVEL_LOGGERS.get(level); if (loggers != null) { for (String logger : loggers) { system.setLogLevel(logger, level); } } } private String getPid() { String name = ManagementFactory.getRuntimeMXBean().getName(); if (name != null) { return name.split("@")[0]; } return "????"; } public void setOrder(int order) { this.order = order; } @Override public int getOrder() { return this.order; } /** * Sets a custom logging level to be used for Spring Boot and related libraries. * @param springBootLogging the logging level */ public void setSpringBootLogging(LogLevel springBootLogging) { this.springBootLogging = springBootLogging; } /** * Sets if initialization arguments should be parsed for {@literal --debug} and * {@literal --trace} options. Defaults to {@code true}. * @param parseArgs if arguments should be parsed */ public void setParseArgs(boolean parseArgs) { this.parseArgs = parseArgs; } }