001/* 002 * Copyright 2012-2017 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.java; 018 019import java.io.ByteArrayInputStream; 020import java.io.InputStreamReader; 021import java.util.ArrayList; 022import java.util.Collections; 023import java.util.Enumeration; 024import java.util.List; 025import java.util.Set; 026import java.util.logging.Level; 027import java.util.logging.LogManager; 028import java.util.logging.Logger; 029 030import org.springframework.boot.logging.AbstractLoggingSystem; 031import org.springframework.boot.logging.LogFile; 032import org.springframework.boot.logging.LogLevel; 033import org.springframework.boot.logging.LoggerConfiguration; 034import org.springframework.boot.logging.LoggingInitializationContext; 035import org.springframework.boot.logging.LoggingSystem; 036import org.springframework.util.Assert; 037import org.springframework.util.FileCopyUtils; 038import org.springframework.util.ResourceUtils; 039import org.springframework.util.StringUtils; 040 041/** 042 * {@link LoggingSystem} for {@link Logger java.util.logging}. 043 * 044 * @author Phillip Webb 045 * @author Dave Syer 046 * @author Andy Wilkinson 047 * @author Ben Hale 048 */ 049public class JavaLoggingSystem extends AbstractLoggingSystem { 050 051 private static final LogLevels<Level> LEVELS = new LogLevels<>(); 052 053 static { 054 LEVELS.map(LogLevel.TRACE, Level.FINEST); 055 LEVELS.map(LogLevel.DEBUG, Level.FINE); 056 LEVELS.map(LogLevel.INFO, Level.INFO); 057 LEVELS.map(LogLevel.WARN, Level.WARNING); 058 LEVELS.map(LogLevel.ERROR, Level.SEVERE); 059 LEVELS.map(LogLevel.FATAL, Level.SEVERE); 060 LEVELS.map(LogLevel.OFF, Level.OFF); 061 } 062 063 public JavaLoggingSystem(ClassLoader classLoader) { 064 super(classLoader); 065 } 066 067 @Override 068 protected String[] getStandardConfigLocations() { 069 return new String[] { "logging.properties" }; 070 } 071 072 @Override 073 public void beforeInitialize() { 074 super.beforeInitialize(); 075 Logger.getLogger("").setLevel(Level.SEVERE); 076 } 077 078 @Override 079 protected void loadDefaults(LoggingInitializationContext initializationContext, 080 LogFile logFile) { 081 if (logFile != null) { 082 loadConfiguration(getPackagedConfigFile("logging-file.properties"), logFile); 083 } 084 else { 085 loadConfiguration(getPackagedConfigFile("logging.properties"), logFile); 086 } 087 } 088 089 @Override 090 protected void loadConfiguration(LoggingInitializationContext initializationContext, 091 String location, LogFile logFile) { 092 loadConfiguration(location, logFile); 093 } 094 095 protected void loadConfiguration(String location, LogFile logFile) { 096 Assert.notNull(location, "Location must not be null"); 097 try { 098 String configuration = FileCopyUtils.copyToString( 099 new InputStreamReader(ResourceUtils.getURL(location).openStream())); 100 if (logFile != null) { 101 configuration = configuration.replace("${LOG_FILE}", 102 StringUtils.cleanPath(logFile.toString())); 103 } 104 LogManager.getLogManager().readConfiguration( 105 new ByteArrayInputStream(configuration.getBytes())); 106 } 107 catch (Exception ex) { 108 throw new IllegalStateException( 109 "Could not initialize Java logging from " + location, ex); 110 } 111 } 112 113 @Override 114 public Set<LogLevel> getSupportedLogLevels() { 115 return LEVELS.getSupported(); 116 } 117 118 @Override 119 public void setLogLevel(String loggerName, LogLevel level) { 120 if (loggerName == null || ROOT_LOGGER_NAME.equals(loggerName)) { 121 loggerName = ""; 122 } 123 Logger logger = Logger.getLogger(loggerName); 124 if (logger != null) { 125 logger.setLevel(LEVELS.convertSystemToNative(level)); 126 } 127 } 128 129 @Override 130 public List<LoggerConfiguration> getLoggerConfigurations() { 131 List<LoggerConfiguration> result = new ArrayList<>(); 132 Enumeration<String> names = LogManager.getLogManager().getLoggerNames(); 133 while (names.hasMoreElements()) { 134 result.add(getLoggerConfiguration(names.nextElement())); 135 } 136 result.sort(CONFIGURATION_COMPARATOR); 137 return Collections.unmodifiableList(result); 138 } 139 140 @Override 141 public LoggerConfiguration getLoggerConfiguration(String loggerName) { 142 Logger logger = Logger.getLogger(loggerName); 143 if (logger == null) { 144 return null; 145 } 146 LogLevel level = LEVELS.convertNativeToSystem(logger.getLevel()); 147 LogLevel effectiveLevel = LEVELS.convertNativeToSystem(getEffectiveLevel(logger)); 148 String name = (StringUtils.hasLength(logger.getName()) ? logger.getName() 149 : ROOT_LOGGER_NAME); 150 return new LoggerConfiguration(name, level, effectiveLevel); 151 } 152 153 private Level getEffectiveLevel(Logger root) { 154 Logger logger = root; 155 while (logger.getLevel() == null) { 156 logger = logger.getParent(); 157 } 158 return logger.getLevel(); 159 } 160 161 @Override 162 public Runnable getShutdownHandler() { 163 return new ShutdownHandler(); 164 } 165 166 private final class ShutdownHandler implements Runnable { 167 168 @Override 169 public void run() { 170 LogManager.getLogManager().reset(); 171 } 172 173 } 174 175}