Merge branch '1.1.x'

This commit is contained in:
Andy Wilkinson 2015-01-14 15:08:33 +00:00
commit 0074e9de9d
8 changed files with 164 additions and 20 deletions

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -27,8 +27,10 @@ import org.springframework.boot.SpringApplication;
import org.springframework.boot.bind.RelaxedPropertyResolver; import org.springframework.boot.bind.RelaxedPropertyResolver;
import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent; import org.springframework.boot.context.event.ApplicationEnvironmentPreparedEvent;
import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.context.ApplicationContext;
import org.springframework.context.ApplicationEvent; import org.springframework.context.ApplicationEvent;
import org.springframework.context.ApplicationListener; import org.springframework.context.ApplicationListener;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.event.SmartApplicationListener; import org.springframework.context.event.SmartApplicationListener;
import org.springframework.core.Ordered; import org.springframework.core.Ordered;
import org.springframework.core.env.ConfigurableEnvironment; import org.springframework.core.env.ConfigurableEnvironment;
@ -56,6 +58,7 @@ import org.springframework.util.StringUtils;
* *
* @author Dave Syer * @author Dave Syer
* @author Phillip Webb * @author Phillip Webb
* @author Andy Wilkinson
* @see LoggingSystem#get(ClassLoader) * @see LoggingSystem#get(ClassLoader)
*/ */
public class LoggingApplicationListener implements SmartApplicationListener { public class LoggingApplicationListener implements SmartApplicationListener {
@ -95,6 +98,12 @@ public class LoggingApplicationListener implements SmartApplicationListener {
LOG_LEVEL_LOGGERS.add(LogLevel.DEBUG, "org.hibernate.SQL"); LOG_LEVEL_LOGGERS.add(LogLevel.DEBUG, "org.hibernate.SQL");
} }
private static Class<?>[] EVENT_TYPES = { ApplicationStartedEvent.class,
ApplicationEnvironmentPreparedEvent.class, ContextClosedEvent.class };
private static Class<?>[] SOURCE_TYPES = { SpringApplication.class,
ApplicationContext.class };
private final Log logger = LogFactory.getLog(getClass()); private final Log logger = LogFactory.getLog(getClass());
private LoggingSystem loggingSystem; private LoggingSystem loggingSystem;
@ -107,13 +116,21 @@ public class LoggingApplicationListener implements SmartApplicationListener {
@Override @Override
public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) { public boolean supportsEventType(Class<? extends ApplicationEvent> eventType) {
return ApplicationStartedEvent.class.isAssignableFrom(eventType) return isAssignableFrom(eventType, EVENT_TYPES);
|| ApplicationEnvironmentPreparedEvent.class.isAssignableFrom(eventType);
} }
@Override @Override
public boolean supportsSourceType(Class<?> sourceType) { public boolean supportsSourceType(Class<?> sourceType) {
return SpringApplication.class.isAssignableFrom(sourceType); return isAssignableFrom(sourceType, SOURCE_TYPES);
}
private boolean isAssignableFrom(Class<?> type, Class<?>[] supportedTypes) {
for (Class<?> supportedType : supportedTypes) {
if (supportedType.isAssignableFrom(type)) {
return true;
}
}
return false;
} }
@Override @Override
@ -124,6 +141,9 @@ public class LoggingApplicationListener implements SmartApplicationListener {
else if (event instanceof ApplicationEnvironmentPreparedEvent) { else if (event instanceof ApplicationEnvironmentPreparedEvent) {
onApplicationPreparedEvent((ApplicationEnvironmentPreparedEvent) event); onApplicationPreparedEvent((ApplicationEnvironmentPreparedEvent) event);
} }
else if (event instanceof ContextClosedEvent) {
onContextClosedEvent();
}
} }
private void onApplicationStartedEvent(ApplicationStartedEvent event) { private void onApplicationStartedEvent(ApplicationStartedEvent event) {
@ -140,6 +160,12 @@ public class LoggingApplicationListener implements SmartApplicationListener {
initialize(event.getEnvironment(), event.getSpringApplication().getClassLoader()); initialize(event.getEnvironment(), event.getSpringApplication().getClassLoader());
} }
private void onContextClosedEvent() {
if (this.loggingSystem != null) {
this.loggingSystem.cleanUp();
}
}
/** /**
* Initialize the logging system according to preferences expressed through the * Initialize the logging system according to preferences expressed through the
* {@link Environment} and the classpath. * {@link Environment} and the classpath.

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -28,6 +28,7 @@ import org.springframework.util.StringUtils;
* *
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer * @author Dave Syer
* @author Andy Wilkinson
*/ */
public abstract class LoggingSystem { public abstract class LoggingSystem {
@ -66,6 +67,14 @@ public abstract class LoggingSystem {
*/ */
public abstract void initialize(String configLocation, LogFile logFile); public abstract void initialize(String configLocation, LogFile logFile);
/**
* Clean up the logging system. The default implementation does nothing. Subclasses
* should override this method to perform any logging system-specific cleanup.
*/
public void cleanUp() {
}
/** /**
* Sets the logging level for a given logger. * Sets the logging level for a given logger.
* @param loggerName the name of the logger to set * @param loggerName the name of the logger to set

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -36,15 +36,18 @@ public abstract class Slf4JLoggingSystem extends AbstractLoggingSystem {
@Override @Override
public void beforeInitialize() { public void beforeInitialize() {
super.beforeInitialize(); super.beforeInitialize();
configureJdkLoggingBridgeHandler();
}
@Override
public void cleanUp() {
removeJdkLoggingBridgeHandler();
}
private void configureJdkLoggingBridgeHandler() {
try { try {
if (ClassUtils.isPresent(BRIDGE_HANDLER, getClassLoader())) { if (bridgeHandlerIsAvailable()) {
try { removeJdkLoggingBridgeHandler();
SLF4JBridgeHandler.removeHandlersForRootLogger();
}
catch (NoSuchMethodError ex) {
// Method missing in older versions of SLF4J like in JBoss AS 7.1
SLF4JBridgeHandler.uninstall();
}
SLF4JBridgeHandler.install(); SLF4JBridgeHandler.install();
} }
} }
@ -53,4 +56,25 @@ public abstract class Slf4JLoggingSystem extends AbstractLoggingSystem {
} }
} }
private boolean bridgeHandlerIsAvailable() {
return ClassUtils.isPresent(BRIDGE_HANDLER, getClassLoader());
}
private void removeJdkLoggingBridgeHandler() {
try {
if (bridgeHandlerIsAvailable()) {
try {
SLF4JBridgeHandler.removeHandlersForRootLogger();
}
catch (NoSuchMethodError ex) {
// Method missing in older versions of SLF4J like in JBoss AS 7.1
SLF4JBridgeHandler.uninstall();
}
}
}
catch (Throwable ex) {
// Ignore and continue
}
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2013 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -36,6 +36,7 @@ import org.springframework.util.StringUtils;
* *
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer * @author Dave Syer
* @author Andy Wilkinson
*/ */
public class Log4JLoggingSystem extends Slf4JLoggingSystem { public class Log4JLoggingSystem extends Slf4JLoggingSystem {

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -42,7 +42,7 @@ import ch.qos.logback.classic.util.ContextInitializer;
import ch.qos.logback.core.spi.FilterReply; import ch.qos.logback.core.spi.FilterReply;
/** /**
* {@link LoggingSystem} for for <a href="http://logback.qos.ch">logback</a>. * {@link LoggingSystem} for <a href="http://logback.qos.ch">logback</a>.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Dave Syer * @author Dave Syer

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -18,7 +18,9 @@ package org.springframework.boot.logging;
import java.io.File; import java.io.File;
import java.io.IOException; import java.io.IOException;
import java.util.logging.Handler;
import java.util.logging.LogManager; import java.util.logging.LogManager;
import java.util.logging.Logger;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory; import org.apache.commons.logging.LogFactory;
@ -28,11 +30,13 @@ import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.junit.rules.TemporaryFolder; import org.junit.rules.TemporaryFolder;
import org.slf4j.bridge.SLF4JBridgeHandler;
import org.springframework.boot.SpringApplication; import org.springframework.boot.SpringApplication;
import org.springframework.boot.context.event.ApplicationStartedEvent; import org.springframework.boot.context.event.ApplicationStartedEvent;
import org.springframework.boot.logging.java.JavaLoggingSystem; import org.springframework.boot.logging.java.JavaLoggingSystem;
import org.springframework.boot.test.EnvironmentTestUtils; import org.springframework.boot.test.EnvironmentTestUtils;
import org.springframework.boot.test.OutputCapture; import org.springframework.boot.test.OutputCapture;
import org.springframework.context.event.ContextClosedEvent;
import org.springframework.context.support.GenericApplicationContext; import org.springframework.context.support.GenericApplicationContext;
import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.containsString;
@ -46,6 +50,7 @@ import static org.junit.Assert.assertTrue;
* *
* @author Dave Syer * @author Dave Syer
* @author Phillip Webb * @author Phillip Webb
* @author Andy Wilkinson
*/ */
public class LoggingApplicationListenerTests { public class LoggingApplicationListenerTests {
@ -262,4 +267,22 @@ public class LoggingApplicationListenerTests {
this.logger.debug("testatdebug"); this.logger.debug("testatdebug");
assertThat(this.outputCapture.toString(), not(containsString("testatdebug"))); assertThat(this.outputCapture.toString(), not(containsString("testatdebug")));
} }
@Test
public void bridgeHandlerLifecycle() throws Exception {
assertTrue(bridgeHandlerInstalled());
this.initializer.onApplicationEvent(new ContextClosedEvent(this.context));
assertFalse(bridgeHandlerInstalled());
}
private boolean bridgeHandlerInstalled() {
Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
for (Handler handler : handlers) {
if (handler instanceof SLF4JBridgeHandler) {
return true;
}
}
return false;
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,12 +17,16 @@
package org.springframework.boot.logging.log4j; package org.springframework.boot.logging.log4j;
import java.io.File; import java.io.File;
import java.util.logging.Handler;
import java.util.logging.LogManager;
import org.apache.commons.logging.impl.Log4JLogger; import org.apache.commons.logging.impl.Log4JLogger;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Ignore; import org.junit.Ignore;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.slf4j.bridge.SLF4JBridgeHandler;
import org.springframework.boot.logging.AbstractLoggingSystemTests; import org.springframework.boot.logging.AbstractLoggingSystemTests;
import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LogLevel;
import org.springframework.boot.test.OutputCapture; import org.springframework.boot.test.OutputCapture;
@ -37,6 +41,7 @@ import static org.junit.Assert.assertTrue;
* Tests for {@link Log4JLoggingSystem}. * Tests for {@link Log4JLoggingSystem}.
* *
* @author Phillip Webb * @author Phillip Webb
* @author Andy Wilkinson
*/ */
public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests { public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests {
@ -53,6 +58,12 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests {
this.logger = new Log4JLogger(getClass().getName()); this.logger = new Log4JLogger(getClass().getName());
} }
@Override
@After
public void clear() {
this.loggingSystem.cleanUp();
}
@Test @Test
public void noFile() throws Exception { public void noFile() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
@ -118,4 +129,24 @@ public class Log4JLoggingSystemTests extends AbstractLoggingSystemTests {
assertTrue("Wrong output:\n" + output, output.contains("Hello world")); assertTrue("Wrong output:\n" + output, output.contains("Hello world"));
} }
@Test
public void bridgeHandlerLifecycle() {
assertFalse(bridgeHandlerInstalled());
this.loggingSystem.beforeInitialize();
assertTrue(bridgeHandlerInstalled());
this.loggingSystem.cleanUp();
assertFalse(bridgeHandlerInstalled());
}
private boolean bridgeHandlerInstalled() {
java.util.logging.Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
for (Handler handler : handlers) {
if (handler instanceof SLF4JBridgeHandler) {
return true;
}
}
return false;
}
} }

View File

@ -1,5 +1,5 @@
/* /*
* Copyright 2012-2014 the original author or authors. * Copyright 2012-2015 the original author or authors.
* *
* Licensed under the Apache License, Version 2.0 (the "License"); * Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License. * you may not use this file except in compliance with the License.
@ -17,13 +17,17 @@
package org.springframework.boot.logging.logback; package org.springframework.boot.logging.logback;
import java.io.File; import java.io.File;
import java.util.logging.Handler;
import java.util.logging.LogManager;
import org.apache.commons.logging.Log; import org.apache.commons.logging.Log;
import org.apache.commons.logging.impl.SLF4JLogFactory; import org.apache.commons.logging.impl.SLF4JLogFactory;
import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Rule; import org.junit.Rule;
import org.junit.Test; import org.junit.Test;
import org.slf4j.ILoggerFactory; import org.slf4j.ILoggerFactory;
import org.slf4j.bridge.SLF4JBridgeHandler;
import org.slf4j.impl.StaticLoggerBinder; import org.slf4j.impl.StaticLoggerBinder;
import org.springframework.boot.logging.AbstractLoggingSystemTests; import org.springframework.boot.logging.AbstractLoggingSystemTests;
import org.springframework.boot.logging.LogLevel; import org.springframework.boot.logging.LogLevel;
@ -62,6 +66,12 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
this.logger = new SLF4JLogFactory().getInstance(getClass().getName()); this.logger = new SLF4JLogFactory().getInstance(getClass().getName());
} }
@Override
@After
public void clear() {
this.loggingSystem.cleanUp();
}
@Test @Test
public void noFile() throws Exception { public void noFile() throws Exception {
this.loggingSystem.beforeInitialize(); this.loggingSystem.beforeInitialize();
@ -142,4 +152,24 @@ public class LogbackLoggingSystemTests extends AbstractLoggingSystemTests {
assertEquals("slf4j", System.getProperty("org.jboss.logging.provider")); assertEquals("slf4j", System.getProperty("org.jboss.logging.provider"));
} }
@Test
public void bridgeHandlerLifecycle() {
assertFalse(bridgeHandlerInstalled());
this.loggingSystem.beforeInitialize();
assertTrue(bridgeHandlerInstalled());
this.loggingSystem.cleanUp();
assertFalse(bridgeHandlerInstalled());
}
private boolean bridgeHandlerInstalled() {
java.util.logging.Logger rootLogger = LogManager.getLogManager().getLogger("");
Handler[] handlers = rootLogger.getHandlers();
for (Handler handler : handlers) {
if (handler instanceof SLF4JBridgeHandler) {
return true;
}
}
return false;
}
} }