<commit_before>/*
 * Copyright 2012-2014 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.logging;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.ApplicationPid;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.util.ClassUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

/**
 * An {@link ApplicationListener} 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 LoggingApplicationListener}.
 * <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 <NAME>
 * @author <NAME>
 */
public class LoggingApplicationListener implements SmartApplicationListener {

	private static final Map<String, String> ENVIRONMENT_SYSTEM_PROPERTY_MAPPING;

	public static final String PID_KEY = "PID";

	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_KEY, PID_KEY);
	}

	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.apache.catalina");
		LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.eclipse.jetty");
		LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.hibernate.tool.hbm2ddl");
	}

	private static Class<?>[] EVENT_TYPES = { ApplicationStartedEvent.class,
			ApplicationEnvironmentPreparedEvent.class };

	private final Log logger = LogFactory.getLog(getClass());

	private int order = Ordered.HIGHEST_PRECEDENCE + 11;

	private boolean parseArgs = true;

	private LogLevel springBootLogging = null;

	@Override
	public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
		for (Class<?> type : EVENT_TYPES) {
			if (type.isAssignableFrom(eventType)) {
				return true;
			}
		}
		return false;
	}

	@Override
	public boolean supportsSourceType(Class<?> sourceType) {
		return SpringApplication.class.isAssignableFrom(sourceType);
	}

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ApplicationEnvironmentPreparedEvent) {
			ApplicationEnvironmentPreparedEvent available = (ApplicationEnvironmentPreparedEvent) event;
			initialize(available.getEnvironment(), available.getSpringApplication()
					.getClassLoader());
		}
		else {
			if (System.getProperty(PID_KEY) == null) {
				System.setProperty(PID_KEY, new ApplicationPid().toString());
			}
			LoggingSystem loggingSystem = LoggingSystem.get(ClassUtils
					.getDefaultClassLoader());
			loggingSystem.beforeInitialize();
		}
	}

	/**
	 * Initialize the logging system according to preferences expressed through the
	 * {@link Environment} and the classpath.
	 */
	protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {
		initializeEarlyLoggingLevel(environment);
		cleanLogTempProperty();
		LoggingSystem system = LoggingSystem.get(classLoader);
		boolean systemEnvironmentChanged = mapSystemPropertiesFromSpring(environment);
		if (systemEnvironmentChanged) {
			// Re-initialize the defaults in case the system Environment changed
			system.beforeInitialize();
		}
		initializeSystem(environment, system);
		initializeFinalLoggingLevels(environment, system);
	}

	private void initializeEarlyLoggingLevel(ConfigurableEnvironment environment) {
		if (this.parseArgs && this.springBootLogging == null) {
			if (environment.containsProperty("debug")) {
				this.springBootLogging = LogLevel.DEBUG;
			}
			if (environment.containsProperty("trace")) {
				this.springBootLogging = LogLevel.TRACE;
			}
		}
	}

	private void cleanLogTempProperty() {
		// Logback won't read backslashes so add a clean path for it to use
		if (!StringUtils.hasLength(System.getProperty("LOG_TEMP"))) {
			String path = System.getProperty("java.io.tmpdir");
			path = StringUtils.cleanPath(path);
			if (path.endsWith("/")) {
				path = path.substring(0, path.length() - 1);
			}
			System.setProperty("LOG_TEMP", path);
		}
	}

	private boolean mapSystemPropertiesFromSpring(Environment environment) {
		boolean changed = false;
		for (Map.Entry<String, String> mapping : ENVIRONMENT_SYSTEM_PROPERTY_MAPPING
				.entrySet()) {
			String springName = mapping.getKey();
			String systemName = mapping.getValue();
			if (environment.containsProperty(springName)) {
				System.setProperty(systemName, environment.getProperty(springName));
				changed = true;
			}
		}
		return changed;
	}

	private void initializeSystem(ConfigurableEnvironment environment,
			LoggingSystem system) {<commit_msg>Ensure java.io.tmpdir is available before using it<commit_after>/*
 * Copyright 2012-2014 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.logging;

import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.Map.Entry;

import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.springframework.boot.ApplicationPid;
import org.springframework.boot.SpringApplication;
import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener;
import org.springframework.context.event.SmartApplicationListener;
import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment;
import org.springframework.core.env.Environment;
import org.springframework.util.ClassUtils;
import org.springframework.util.LinkedMultiValueMap;
import org.springframework.util.MultiValueMap;
import org.springframework.util.ResourceUtils;
import org.springframework.util.StringUtils;

/**
 * An {@link ApplicationListener} 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 LoggingApplicationListener}.
 * <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 <NAME>
 * @author <NAME>
 */
public class LoggingApplicationListener implements SmartApplicationListener {

	private static final Map<String, String> ENVIRONMENT_SYSTEM_PROPERTY_MAPPING;

	public static final String PID_KEY = "PID";

	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_KEY, PID_KEY);
	}

	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.apache.catalina");
		LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.eclipse.jetty");
		LOG_LEVEL_LOGGERS.add(LogLevel.TRACE, "org.hibernate.tool.hbm2ddl");
	}

	private static Class<?>[] EVENT_TYPES = { ApplicationStartedEvent.class,
			ApplicationEnvironmentPreparedEvent.class };

	private final Log logger = LogFactory.getLog(getClass());

	private int order = Ordered.HIGHEST_PRECEDENCE + 11;

	private boolean parseArgs = true;

	private LogLevel springBootLogging = null;

	@Override
	public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
		for (Class<?> type : EVENT_TYPES) {
			if (type.isAssignableFrom(eventType)) {
				return true;
			}
		}
		return false;
	}

	@Override
	public boolean supportsSourceType(Class<?> sourceType) {
		return SpringApplication.class.isAssignableFrom(sourceType);
	}

	@Override
	public void onApplicationEvent(ApplicationEvent event) {
		if (event instanceof ApplicationEnvironmentPreparedEvent) {
			ApplicationEnvironmentPreparedEvent available = (ApplicationEnvironmentPreparedEvent) event;
			initialize(available.getEnvironment(), available.getSpringApplication()
					.getClassLoader());
		}
		else {
			if (System.getProperty(PID_KEY) == null) {
				System.setProperty(PID_KEY, new ApplicationPid().toString());
			}
			LoggingSystem loggingSystem = LoggingSystem.get(ClassUtils
					.getDefaultClassLoader());
			loggingSystem.beforeInitialize();
		}
	}

	/**
	 * Initialize the logging system according to preferences expressed through the
	 * {@link Environment} and the classpath.
	 */
	protected void initialize(ConfigurableEnvironment environment, ClassLoader classLoader) {
		initializeEarlyLoggingLevel(environment);
		cleanLogTempProperty();
		LoggingSystem system = LoggingSystem.get(classLoader);
		boolean systemEnvironmentChanged = mapSystemPropertiesFromSpring(environment);
		if (systemEnvironmentChanged) {
			// Re-initialize the defaults in case the system Environment changed
			system.beforeInitialize();
		}
		initializeSystem(environment, system);
		initializeFinalLoggingLevels(environment, system);
	}

	private void initializeEarlyLoggingLevel(ConfigurableEnvironment environment) {
		if (this.parseArgs && this.springBootLogging == null) {
			if (environment.containsProperty("debug")) {
				this.springBootLogging = LogLevel.DEBUG;
			}
			if (environment.containsProperty("trace")) {
				this.springBootLogging = LogLevel.TRACE;
			}
		}
	}

	private void cleanLogTempProperty() {
		// Logback won't read backslashes so add a clean path for it to use
		if (!StringUtils.hasLength(System.getProperty("LOG_TEMP"))) {
			String path = System.getProperty("java.io.tmpdir");
            if (path!=null) {
				path = StringUtils.cleanPath(path);
				if (path.endsWith("/")) {
					path = path.substring(0, path.length() - 1);
				}
				System.setProperty("LOG_TEMP", path);
            }
		}
	}

	private boolean mapSystemPropertiesFromSpring(Environment environment) {
		boolean changed = false;
		for (Map.Entry<String, String> mapping : ENVIRONMENT_SYSTEM_PROPERTY_MAPPING
				.entrySet()) {
			String springName = mapping.getKey();
			String systemName = mapping.getValue();
			if (environment.containsProperty(springName)) {
				System.setProperty(systemName, environment.getProperty(springName));
				changed = true;
			}
		}
		return changed;
	}

	private void initializeSystem(ConfigurableEnvironment environment,
			LoggingSystem system) {
{'fraction_non_alphanumeric': 0.09960369881109643, 'fraction_numerical': 0.002906208718626156, 'mean_word_length': 5.2002457002457, 'pattern_counts': {'":': 0, '<': 95, '<?xml version=': 0, '>': 95, 'https://': 0, 'lorem ipsum': 0, 'www.': 2, 'xml': 4}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5400578', 'n_tokens_mistral': 4530, 'n_tokens_neox': 4231, 'n_words': 1150}