001/* 002 * Copyright 2012-2018 the original author or authors. 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * http://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016 017package org.springframework.boot.logging; 018 019import java.util.logging.ConsoleHandler; 020import java.util.logging.Handler; 021import java.util.logging.LogManager; 022import java.util.logging.Logger; 023 024import org.slf4j.bridge.SLF4JBridgeHandler; 025 026import org.springframework.util.Assert; 027import org.springframework.util.ClassUtils; 028 029/** 030 * Abstract base class for {@link LoggingSystem} implementations that utilize SLF4J. 031 * 032 * @author Andy Wilkinson 033 * @since 1.2.0 034 */ 035public abstract class Slf4JLoggingSystem extends AbstractLoggingSystem { 036 037 private static final String BRIDGE_HANDLER = "org.slf4j.bridge.SLF4JBridgeHandler"; 038 039 public Slf4JLoggingSystem(ClassLoader classLoader) { 040 super(classLoader); 041 } 042 043 @Override 044 public void beforeInitialize() { 045 super.beforeInitialize(); 046 configureJdkLoggingBridgeHandler(); 047 } 048 049 @Override 050 public void cleanUp() { 051 if (isBridgeHandlerAvailable()) { 052 removeJdkLoggingBridgeHandler(); 053 } 054 } 055 056 @Override 057 protected void loadConfiguration(LoggingInitializationContext initializationContext, 058 String location, LogFile logFile) { 059 Assert.notNull(location, "Location must not be null"); 060 if (initializationContext != null) { 061 applySystemProperties(initializationContext.getEnvironment(), logFile); 062 } 063 } 064 065 private void configureJdkLoggingBridgeHandler() { 066 try { 067 if (isBridgeJulIntoSlf4j()) { 068 removeJdkLoggingBridgeHandler(); 069 SLF4JBridgeHandler.install(); 070 } 071 } 072 catch (Throwable ex) { 073 // Ignore. No java.util.logging bridge is installed. 074 } 075 } 076 077 /** 078 * Return whether bridging JUL into SLF4J or not. 079 * @return whether bridging JUL into SLF4J or not 080 * @since 2.0.4 081 */ 082 protected final boolean isBridgeJulIntoSlf4j() { 083 return isBridgeHandlerAvailable() && isJulUsingASingleConsoleHandlerAtMost(); 084 } 085 086 protected final boolean isBridgeHandlerAvailable() { 087 return ClassUtils.isPresent(BRIDGE_HANDLER, getClassLoader()); 088 } 089 090 private boolean isJulUsingASingleConsoleHandlerAtMost() { 091 Logger rootLogger = LogManager.getLogManager().getLogger(""); 092 Handler[] handlers = rootLogger.getHandlers(); 093 return handlers.length == 0 094 || (handlers.length == 1 && handlers[0] instanceof ConsoleHandler); 095 } 096 097 private void removeJdkLoggingBridgeHandler() { 098 try { 099 removeDefaultRootHandler(); 100 SLF4JBridgeHandler.uninstall(); 101 } 102 catch (Throwable ex) { 103 // Ignore and continue 104 } 105 } 106 107 private void removeDefaultRootHandler() { 108 try { 109 Logger rootLogger = LogManager.getLogManager().getLogger(""); 110 Handler[] handlers = rootLogger.getHandlers(); 111 if (handlers.length == 1 && handlers[0] instanceof ConsoleHandler) { 112 rootLogger.removeHandler(handlers[0]); 113 } 114 } 115 catch (Throwable ex) { 116 // Ignore and continue 117 } 118 } 119 120}