/* * Copyright (c) 2009, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License version 2 only, as * published by the Free Software Foundation. Oracle designates this * particular file as subject to the "Classpath" exception as provided * by Oracle in the LICENSE file that accompanied this code. * * This code is distributed in the hope that it will be useful, but WITHOUT * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License * version 2 for more details (a copy is included in the LICENSE file that * accompanied this code). * * You should have received a copy of the GNU General Public License version * 2 along with this work; if not, write to the Free Software Foundation, * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. * * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA * or visit www.oracle.com if you need additional information or have any * questions. */ package sun.util.logging; import java.lang.ref.WeakReference; import java.util.Arrays; import java.util.HashMap; import java.util.Map; import sun.util.logger.LazyLoggers; import sun.util.logging.ConfigurableLoggerBridge.LoggerConfiguration; /** * Platform logger provides an API for the JRE components to log * messages. This enables the runtime components to eliminate the * static dependency of the logging facility and also defers the * java.util.logging initialization until it is enabled. * In addition, the PlatformLogger API can be used if the logging * module does not exist. * * If the logging facility is not enabled, the platform loggers * will output log messages per the default logging configuration * (see below). In this implementation, it does not log the * the stack frame information issuing the log message. * * When the logging facility is enabled (at startup or runtime), * the backend logger will be created for each platform * logger and all log messages will be forwarded to the Logger * to handle. * * The PlatformLogger uses an underlying PlatformLoggerBridge instance * obtained by calling {@link PlatformLoggerBridge#convert PlatformLoggerBridge.convert(} * {@link sun.util.logger.LazyLoggers#getLazyLogger(java.lang.String, java.lang.Class) * sun.util.logger.LazyLoggers#getLazyLogger(name, PlatformLogger.class))}. * * Logging facility is "enabled" when one of the following * conditions is met: * 1) ServiceLoader.load({@link java.lang.System.LoggerFinder LoggerFinder.class}, * ClassLoader.getSystemClassLoader()).iterator().hasNext(). * 2) ServiceLoader.loadInstalled({@link sun.util.logger.JdkLoggerProvider}).iterator().hasNext(), * and 2.1) a system property "java.util.logging.config.class" or * "java.util.logging.config.file" is set * or 2.2) java.util.logging.LogManager or java.util.logging.Logger * is referenced that will trigger the logging initialization. * * Default logging configuration: * * No LoggerFinder service implementation declared * global logging level = INFO * handlers = java.util.logging.ConsoleHandler * java.util.logging.ConsoleHandler.level = INFO * java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter * * Limitation: * {@code /conf/logging.properties} is the system-wide logging * configuration defined in the specification and read in the * default case to configure any java.util.logging.Logger instances. * Platform loggers will not detect if {@code /conf/logging.properties} * is modified. In other words, unless the java.util.logging API * is used at runtime or the logging system properties is set, * the platform loggers will use the default setting described above. * The platform loggers are designed for JDK developers use and * this limitation can be workaround with setting * -Djava.util.logging.config.file system property. *
* Calling PlatformLogger.setLevel will not work when there is a custom * LoggerFinder installed - and as a consequence {@link #setLevel setLevel} * is now deprecated. * * @since 1.7 */ public class PlatformLogger { /** * PlatformLogger logging levels. */ public static enum Level { // The name and value must match that of {@code java.util.logging.Level}s. // Declare in ascending order of the given value for binary search. ALL(System.Logger.Level.ALL), FINEST(System.Logger.Level.TRACE), FINER(System.Logger.Level.TRACE), FINE(System.Logger.Level.DEBUG), CONFIG(System.Logger.Level.DEBUG), INFO(System.Logger.Level.INFO), WARNING(System.Logger.Level.WARNING), SEVERE(System.Logger.Level.ERROR), OFF(System.Logger.Level.OFF); final System.Logger.Level systemLevel; Level(System.Logger.Level systemLevel) { this.systemLevel = systemLevel; } // The integer values must match that of {@code java.util.logging.Level} // objects. private static final int SEVERITY_OFF = Integer.MAX_VALUE; private static final int SEVERITY_SEVERE = 1000; private static final int SEVERITY_WARNING = 900; private static final int SEVERITY_INFO = 800; private static final int SEVERITY_CONFIG = 700; private static final int SEVERITY_FINE = 500; private static final int SEVERITY_FINER = 400; private static final int SEVERITY_FINEST = 300; private static final int SEVERITY_ALL = Integer.MIN_VALUE; // ascending order for binary search matching the list of enum constants private static final int[] LEVEL_VALUES = new int[] { SEVERITY_ALL, SEVERITY_FINEST, SEVERITY_FINER, SEVERITY_FINE, SEVERITY_CONFIG, SEVERITY_INFO, SEVERITY_WARNING, SEVERITY_SEVERE, SEVERITY_OFF }; public System.Logger.Level systemLevel() { return systemLevel; } public int intValue() { return LEVEL_VALUES[this.ordinal()]; } /** * Maps a severity value to an effective logger level. * @param level The severity of the messages that should be * logged with a logger set to the returned level. * @return The effective logger level, which is the nearest Level value * whose severity is greater or equal to the given level. * For level > SEVERE (OFF excluded), return SEVERE. */ public static Level valueOf(int level) { switch (level) { // ordering per the highest occurrences in the jdk source // finest, fine, finer, info first case SEVERITY_FINEST : return Level.FINEST; case SEVERITY_FINE : return Level.FINE; case SEVERITY_FINER : return Level.FINER; case SEVERITY_INFO : return Level.INFO; case SEVERITY_WARNING : return Level.WARNING; case SEVERITY_CONFIG : return Level.CONFIG; case SEVERITY_SEVERE : return Level.SEVERE; case SEVERITY_OFF : return Level.OFF; case SEVERITY_ALL : return Level.ALL; } // return the nearest Level value >= the given level, // for level > SEVERE, return SEVERE and exclude OFF int i = Arrays.binarySearch(LEVEL_VALUES, 0, LEVEL_VALUES.length-2, level); return values()[i >= 0 ? i : (-i-1)]; } } // Table of known loggers. Maps names to PlatformLoggers. private static final Map> loggers = new HashMap<>(); /** * Returns a PlatformLogger of a given name. * @param name the name of the logger * @return a PlatformLogger */ public static synchronized PlatformLogger getLogger(String name) { PlatformLogger log = null; WeakReference ref = loggers.get(name); if (ref != null) { log = ref.get(); } if (log == null) { log = new PlatformLogger(PlatformLoggerBridge.convert( // We pass PlatformLogger.class rather than the actual caller // because we want PlatformLoggers to be system loggers: we // won't need to resolve any resource bundles anyway. // Note: Many unit tests depend on the fact that // PlatformLogger.getLoggerFromFinder is not caller sensitive. LazyLoggers.getLazyLogger(name, PlatformLogger.class))); loggers.put(name, new WeakReference<>(log)); } return log; } // The system loggerProxy returned by LazyLoggers // This may be a lazy logger - see sun.util.logger.LazyLoggers, // or may be a Logger instance (or a wrapper thereof). // private final PlatformLoggerBridge loggerProxy; private PlatformLogger(PlatformLoggerBridge loggerProxy) { this.loggerProxy = loggerProxy; } /** * A convenience method to test if the logger is turned off. * (i.e. its level is OFF). * @return whether the logger is turned off. */ public boolean isEnabled() { return loggerProxy.isEnabled(); } /** * Gets the name for this platform logger. * @return the name of the platform logger. */ public String getName() { return loggerProxy.getName(); } /** * Returns true if a message of the given level would actually * be logged by this logger. * @param level the level * @return whether a message of that level would be logged */ public boolean isLoggable(Level level) { if (level == null) { throw new NullPointerException(); } return loggerProxy.isLoggable(level); } /** * Get the log level that has been specified for this PlatformLogger. * The result may be null, which means that this logger's * effective level will be inherited from its parent. * * @return this PlatformLogger's level */ public Level level() { final LoggerConfiguration spi = ConfigurableLoggerBridge.getLoggerConfiguration(loggerProxy); return spi == null ? null : spi.getPlatformLevel(); } /** * Set the log level specifying which message levels will be * logged by this logger. Message levels lower than this * value will be discarded. The level value {@link Level#OFF} * can be used to turn off logging. *

* If the new level is null, it means that this node should * inherit its level from its nearest ancestor with a specific * (non-null) level value. * * @param newLevel the new value for the log level (may be null) * @deprecated Platform Loggers should not be configured programmatically. * This method will not work if a custom {@link * java.lang.System.LoggerFinder} is installed. */ @Deprecated public void setLevel(Level newLevel) { final LoggerConfiguration spi = ConfigurableLoggerBridge.getLoggerConfiguration(loggerProxy);; if (spi != null) { spi.setPlatformLevel(newLevel); } } /** * Logs a SEVERE message. * @param msg the message */ public void severe(String msg) { loggerProxy.log(Level.SEVERE, msg, (Object[])null); } public void severe(String msg, Throwable t) { loggerProxy.log(Level.SEVERE, msg, t); } public void severe(String msg, Object... params) { loggerProxy.log(Level.SEVERE, msg, params); } /** * Logs a WARNING message. * @param msg the message */ public void warning(String msg) { loggerProxy.log(Level.WARNING, msg, (Object[])null); } public void warning(String msg, Throwable t) { loggerProxy.log(Level.WARNING, msg, t); } public void warning(String msg, Object... params) { loggerProxy.log(Level.WARNING, msg, params); } /** * Logs an INFO message. * @param msg the message */ public void info(String msg) { loggerProxy.log(Level.INFO, msg, (Object[])null); } public void info(String msg, Throwable t) { loggerProxy.log(Level.INFO, msg, t); } public void info(String msg, Object... params) { loggerProxy.log(Level.INFO, msg, params); } /** * Logs a CONFIG message. * @param msg the message */ public void config(String msg) { loggerProxy.log(Level.CONFIG, msg, (Object[])null); } public void config(String msg, Throwable t) { loggerProxy.log(Level.CONFIG, msg, t); } public void config(String msg, Object... params) { loggerProxy.log(Level.CONFIG, msg, params); } /** * Logs a FINE message. * @param msg the message */ public void fine(String msg) { loggerProxy.log(Level.FINE, msg, (Object[])null); } public void fine(String msg, Throwable t) { loggerProxy.log(Level.FINE, msg, t); } public void fine(String msg, Object... params) { loggerProxy.log(Level.FINE, msg, params); } /** * Logs a FINER message. * @param msg the message */ public void finer(String msg) { loggerProxy.log(Level.FINER, msg, (Object[])null); } public void finer(String msg, Throwable t) { loggerProxy.log(Level.FINER, msg, t); } public void finer(String msg, Object... params) { loggerProxy.log(Level.FINER, msg, params); } /** * Logs a FINEST message. * @param msg the message */ public void finest(String msg) { loggerProxy.log(Level.FINEST, msg, (Object[])null); } public void finest(String msg, Throwable t) { loggerProxy.log(Level.FINEST, msg, t); } public void finest(String msg, Object... params) { loggerProxy.log(Level.FINEST, msg, params); } // ------------------------------------ // Maps used for Level conversion // ------------------------------------ // This map is indexed by java.util.spi.Logger.Level.ordinal() and returns // a PlatformLogger.Level // // ALL, TRACE, DEBUG, INFO, WARNING, ERROR, OFF private static final Level[] spi2platformLevelMapping = { Level.ALL, // mapped from ALL Level.FINER, // mapped from TRACE Level.FINE, // mapped from DEBUG Level.INFO, // mapped from INFO Level.WARNING, // mapped from WARNING Level.SEVERE, // mapped from ERROR Level.OFF // mapped from OFF }; public static Level toPlatformLevel(java.lang.System.Logger.Level level) { if (level == null) return null; assert level.ordinal() < spi2platformLevelMapping.length; return spi2platformLevelMapping[level.ordinal()]; } }