< prev index next >
jdk/src/java.base/share/classes/sun/util/logging/PlatformLogger.java
Print this page
*** 25,48 ****
package sun.util.logging;
import java.lang.ref.WeakReference;
- import java.io.PrintStream;
- import java.io.PrintWriter;
- import java.io.StringWriter;
- import java.security.AccessController;
- import java.security.PrivilegedAction;
- import java.time.Clock;
- import java.time.Instant;
- import java.time.ZoneId;
- import java.time.ZonedDateTime;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
! import jdk.internal.misc.JavaLangAccess;
! import jdk.internal.misc.SharedSecrets;
/**
* 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
--- 25,41 ----
package sun.util.logging;
import java.lang.ref.WeakReference;
import java.util.Arrays;
import java.util.HashMap;
import java.util.Map;
! import java.util.ResourceBundle;
! import java.util.function.Supplier;
! import jdk.internal.logger.LazyLoggers;
! import jdk.internal.logger.LoggerWrapper;
/**
* 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
*** 54,75 ****
* 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 java.util.logging.Logger will be created for each platform
* logger and all log messages will be forwarded to the Logger
* to handle.
*
* Logging facility is "enabled" when one of the following
* conditions is met:
! * 1) a system property "java.util.logging.config.class" or
* "java.util.logging.config.file" is set
! * 2) java.util.logging.LogManager or java.util.logging.Logger
* is referenced that will trigger the logging initialization.
*
* Default logging configuration:
* global logging level = INFO
* handlers = java.util.logging.ConsoleHandler
* java.util.logging.ConsoleHandler.level = INFO
* java.util.logging.ConsoleHandler.formatter = java.util.logging.SimpleFormatter
*
--- 47,78 ----
* 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 PlatformLogger.Bridge instance
+ * obtained by calling {@link PlatformLogger.Bridge#convert PlatformLogger.Bridge.convert(}
+ * {@link jdk.internal.logger.LazyLoggers#getLazyLogger(java.lang.String, java.lang.Class)
+ * jdk.internal.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 jdk.internal.logger.DefaultLoggerFinder}).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
*
*** 82,660 ****
* 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.
*
* @since 1.7
*/
public class PlatformLogger {
- // The integer values must match that of {@code java.util.logging.Level}
- // objects.
- private static final int OFF = Integer.MAX_VALUE;
- private static final int SEVERE = 1000;
- private static final int WARNING = 900;
- private static final int INFO = 800;
- private static final int CONFIG = 700;
- private static final int FINE = 500;
- private static final int FINER = 400;
- private static final int FINEST = 300;
- private static final int ALL = Integer.MIN_VALUE;
-
/**
* 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,
! FINEST,
! FINER,
! FINE,
! CONFIG,
! INFO,
! WARNING,
! SEVERE,
! OFF;
!
! /**
! * Associated java.util.logging.Level lazily initialized in
! * JavaLoggerProxy's static initializer only once
! * when java.util.logging is available and enabled.
! * Only accessed by JavaLoggerProxy.
! */
! /* java.util.logging.Level */ Object javaLevel;
// ascending order for binary search matching the list of enum constants
private static final int[] LEVEL_VALUES = new int[] {
! PlatformLogger.ALL, PlatformLogger.FINEST, PlatformLogger.FINER,
! PlatformLogger.FINE, PlatformLogger.CONFIG, PlatformLogger.INFO,
! PlatformLogger.WARNING, PlatformLogger.SEVERE, PlatformLogger.OFF
};
public int intValue() {
return LEVEL_VALUES[this.ordinal()];
}
! static Level valueOf(int level) {
switch (level) {
// ordering per the highest occurrences in the jdk source
// finest, fine, finer, info first
! case PlatformLogger.FINEST : return Level.FINEST;
! case PlatformLogger.FINE : return Level.FINE;
! case PlatformLogger.FINER : return Level.FINER;
! case PlatformLogger.INFO : return Level.INFO;
! case PlatformLogger.WARNING : return Level.WARNING;
! case PlatformLogger.CONFIG : return Level.CONFIG;
! case PlatformLogger.SEVERE : return Level.SEVERE;
! case PlatformLogger.OFF : return Level.OFF;
! case PlatformLogger.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)];
}
}
! private static final Level DEFAULT_LEVEL = Level.INFO;
! private static boolean loggingEnabled;
! static {
! loggingEnabled = AccessController.doPrivileged(
! new PrivilegedAction<>() {
! public Boolean run() {
! String cname = System.getProperty("java.util.logging.config.class");
! String fname = System.getProperty("java.util.logging.config.file");
! return (cname != null || fname != null);
! }
! });
!
! // force loading of all JavaLoggerProxy (sub)classes to make JIT de-optimizations
! // less probable. Don't initialize JavaLoggerProxy class since
! // java.util.logging may not be enabled.
! try {
! Class.forName("sun.util.logging.PlatformLogger$DefaultLoggerProxy",
! false,
! PlatformLogger.class.getClassLoader());
! Class.forName("sun.util.logging.PlatformLogger$JavaLoggerProxy",
! false, // do not invoke class initializer
! PlatformLogger.class.getClassLoader());
! } catch (ClassNotFoundException ex) {
! throw new InternalError(ex);
}
}
// Table of known loggers. Maps names to PlatformLoggers.
! private static Map<String,WeakReference<PlatformLogger>> loggers =
new HashMap<>();
/**
* Returns a PlatformLogger of a given name.
*/
public static synchronized PlatformLogger getLogger(String name) {
PlatformLogger log = null;
WeakReference<PlatformLogger> ref = loggers.get(name);
if (ref != null) {
log = ref.get();
}
if (log == null) {
! log = new PlatformLogger(name);
loggers.put(name, new WeakReference<>(log));
}
return log;
}
! /**
! * Initialize java.util.logging.Logger objects for all platform loggers.
! * This method is called from LogManager.readPrimordialConfiguration().
! */
! public static synchronized void redirectPlatformLoggers() {
! if (loggingEnabled || !LoggingSupport.isAvailable()) return;
!
! loggingEnabled = true;
! for (Map.Entry<String, WeakReference<PlatformLogger>> entry : loggers.entrySet()) {
! WeakReference<PlatformLogger> ref = entry.getValue();
! PlatformLogger plog = ref.get();
! if (plog != null) {
! plog.redirectToJavaLoggerProxy();
! }
! }
! }
!
! /**
! * Creates a new JavaLoggerProxy and redirects the platform logger to it
! */
! private void redirectToJavaLoggerProxy() {
! DefaultLoggerProxy lp = DefaultLoggerProxy.class.cast(this.loggerProxy);
! JavaLoggerProxy jlp = new JavaLoggerProxy(lp.name, lp.level);
! // the order of assignments is important
! this.javaLoggerProxy = jlp; // isLoggable checks javaLoggerProxy if set
! this.loggerProxy = jlp;
! }
!
! // DefaultLoggerProxy may be replaced with a JavaLoggerProxy object
! // when the java.util.logging facility is enabled
! private volatile LoggerProxy loggerProxy;
! // javaLoggerProxy is only set when the java.util.logging facility is enabled
! private volatile JavaLoggerProxy javaLoggerProxy;
! private PlatformLogger(String name) {
! if (loggingEnabled) {
! this.loggerProxy = this.javaLoggerProxy = new JavaLoggerProxy(name);
! } else {
! this.loggerProxy = new DefaultLoggerProxy(name);
! }
}
/**
* A convenience method to test if the logger is turned off.
* (i.e. its level is OFF).
*/
public boolean isEnabled() {
return loggerProxy.isEnabled();
}
/**
* Gets the name for this platform logger.
*/
public String getName() {
! return loggerProxy.name;
}
/**
* Returns true if a message of the given level would actually
* be logged by this logger.
*/
public boolean isLoggable(Level level) {
if (level == null) {
throw new NullPointerException();
}
! // performance-sensitive method: use two monomorphic call-sites
! JavaLoggerProxy jlp = javaLoggerProxy;
! return jlp != null ? jlp.isLoggable(level) : 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() {
! return loggerProxy.getLevel();
}
/**
* 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 #OFF}
* can be used to turn off logging.
* <p>
* 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)
*/
public void setLevel(Level newLevel) {
! loggerProxy.setLevel(newLevel);
}
/**
* Logs a SEVERE message.
*/
public void severe(String msg) {
! loggerProxy.doLog(Level.SEVERE, msg);
}
public void severe(String msg, Throwable t) {
! loggerProxy.doLog(Level.SEVERE, msg, t);
}
public void severe(String msg, Object... params) {
! loggerProxy.doLog(Level.SEVERE, msg, params);
}
/**
* Logs a WARNING message.
*/
public void warning(String msg) {
! loggerProxy.doLog(Level.WARNING, msg);
}
public void warning(String msg, Throwable t) {
! loggerProxy.doLog(Level.WARNING, msg, t);
}
public void warning(String msg, Object... params) {
! loggerProxy.doLog(Level.WARNING, msg, params);
}
/**
* Logs an INFO message.
*/
public void info(String msg) {
! loggerProxy.doLog(Level.INFO, msg);
}
public void info(String msg, Throwable t) {
! loggerProxy.doLog(Level.INFO, msg, t);
}
public void info(String msg, Object... params) {
! loggerProxy.doLog(Level.INFO, msg, params);
}
/**
* Logs a CONFIG message.
*/
public void config(String msg) {
! loggerProxy.doLog(Level.CONFIG, msg);
}
public void config(String msg, Throwable t) {
! loggerProxy.doLog(Level.CONFIG, msg, t);
}
public void config(String msg, Object... params) {
! loggerProxy.doLog(Level.CONFIG, msg, params);
}
/**
* Logs a FINE message.
*/
public void fine(String msg) {
! loggerProxy.doLog(Level.FINE, msg);
}
public void fine(String msg, Throwable t) {
! loggerProxy.doLog(Level.FINE, msg, t);
}
public void fine(String msg, Object... params) {
! loggerProxy.doLog(Level.FINE, msg, params);
}
/**
* Logs a FINER message.
*/
public void finer(String msg) {
! loggerProxy.doLog(Level.FINER, msg);
}
public void finer(String msg, Throwable t) {
! loggerProxy.doLog(Level.FINER, msg, t);
}
public void finer(String msg, Object... params) {
! loggerProxy.doLog(Level.FINER, msg, params);
}
/**
* Logs a FINEST message.
*/
public void finest(String msg) {
! loggerProxy.doLog(Level.FINEST, msg);
}
public void finest(String msg, Throwable t) {
! loggerProxy.doLog(Level.FINEST, msg, t);
}
public void finest(String msg, Object... params) {
! loggerProxy.doLog(Level.FINEST, msg, params);
! }
!
! /**
! * Abstract base class for logging support, defining the API and common field.
! */
! private abstract static class LoggerProxy {
! final String name;
!
! protected LoggerProxy(String name) {
! this.name = name;
}
! abstract boolean isEnabled();
!
! abstract Level getLevel();
! abstract void setLevel(Level newLevel);
!
! abstract void doLog(Level level, String msg);
! abstract void doLog(Level level, String msg, Throwable thrown);
! abstract void doLog(Level level, String msg, Object... params);
!
! abstract boolean isLoggable(Level level);
! }
!
!
! private static final class DefaultLoggerProxy extends LoggerProxy {
! /**
! * Default platform logging support - output messages to System.err -
! * equivalent to ConsoleHandler with SimpleFormatter.
! */
! private static PrintStream outputStream() {
! return System.err;
! }
!
! volatile Level effectiveLevel; // effective level (never null)
! volatile Level level; // current level set for this node (may be null)
!
! DefaultLoggerProxy(String name) {
! super(name);
! this.effectiveLevel = deriveEffectiveLevel(null);
! this.level = null;
! }
!
! boolean isEnabled() {
! return effectiveLevel != Level.OFF;
! }
!
! Level getLevel() {
! return level;
! }
!
! void setLevel(Level newLevel) {
! Level oldLevel = level;
! if (oldLevel != newLevel) {
! level = newLevel;
! effectiveLevel = deriveEffectiveLevel(newLevel);
! }
! }
!
! void doLog(Level level, String msg) {
! if (isLoggable(level)) {
! outputStream().print(format(level, msg, null));
! }
! }
!
! void doLog(Level level, String msg, Throwable thrown) {
! if (isLoggable(level)) {
! outputStream().print(format(level, msg, thrown));
! }
! }
!
! void doLog(Level level, String msg, Object... params) {
! if (isLoggable(level)) {
! String newMsg = formatMessage(msg, params);
! outputStream().print(format(level, newMsg, null));
! }
! }
!
! boolean isLoggable(Level level) {
! Level effectiveLevel = this.effectiveLevel;
! return level.intValue() >= effectiveLevel.intValue() && effectiveLevel != Level.OFF;
! }
!
! // derive effective level (could do inheritance search like j.u.l.Logger)
! private Level deriveEffectiveLevel(Level level) {
! return level == null ? DEFAULT_LEVEL : level;
! }
!
! // Copied from java.util.logging.Formatter.formatMessage
! private String formatMessage(String format, Object... parameters) {
! // Do the formatting.
! try {
! if (parameters == null || parameters.length == 0) {
! // No parameters. Just return format string.
! return format;
! }
! // Is it a java.text style format?
! // Ideally we could match with
! // Pattern.compile("\\{\\d").matcher(format).find())
! // However the cost is 14% higher, so we cheaply check for
! // 1 of the first 4 parameters
! if (format.indexOf("{0") >= 0 || format.indexOf("{1") >=0 ||
! format.indexOf("{2") >=0|| format.indexOf("{3") >=0) {
! return java.text.MessageFormat.format(format, parameters);
! }
! return format;
! } catch (Exception ex) {
! // Formatting failed: use format string.
! return format;
! }
! }
!
! private static final String formatString =
! LoggingSupport.getSimpleFormat(false); // don't check logging.properties
! private final ZoneId zoneId = ZoneId.systemDefault();
! private synchronized String format(Level level, String msg, Throwable thrown) {
! ZonedDateTime zdt = ZonedDateTime.now(zoneId);
! String throwable = "";
! if (thrown != null) {
! StringWriter sw = new StringWriter();
! PrintWriter pw = new PrintWriter(sw);
! pw.println();
! thrown.printStackTrace(pw);
! pw.close();
! throwable = sw.toString();
! }
!
! return String.format(formatString,
! zdt,
! getCallerInfo(),
! name,
! level.name(),
! msg,
! throwable);
! }
!
! // Returns the caller's class and method's name; best effort
! // if cannot infer, return the logger's name.
! private String getCallerInfo() {
! String sourceClassName = null;
! String sourceMethodName = null;
!
! JavaLangAccess access = SharedSecrets.getJavaLangAccess();
! Throwable throwable = new Throwable();
! int depth = access.getStackTraceDepth(throwable);
!
! String logClassName = "sun.util.logging.PlatformLogger";
! boolean lookingForLogger = true;
! for (int ix = 0; ix < depth; ix++) {
! // Calling getStackTraceElement directly prevents the VM
! // from paying the cost of building the entire stack frame.
! StackTraceElement frame =
! access.getStackTraceElement(throwable, ix);
! String cname = frame.getClassName();
! if (lookingForLogger) {
! // Skip all frames until we have found the first logger frame.
! if (cname.equals(logClassName)) {
! lookingForLogger = false;
! }
! } else {
! if (!cname.equals(logClassName)) {
! // We've found the relevant frame.
! sourceClassName = cname;
! sourceMethodName = frame.getMethodName();
! break;
! }
! }
! }
!
! if (sourceClassName != null) {
! return sourceClassName + " " + sourceMethodName;
! } else {
! return name;
! }
! }
! }
!
! /**
! * JavaLoggerProxy forwards all the calls to its corresponding
! * java.util.logging.Logger object.
! */
! private static final class JavaLoggerProxy extends LoggerProxy {
! // initialize javaLevel fields for mapping from Level enum -> j.u.l.Level object
! static {
! for (Level level : Level.values()) {
! level.javaLevel = LoggingSupport.parseLevel(level.name());
! }
! }
!
! private final /* java.util.logging.Logger */ Object javaLogger;
!
! JavaLoggerProxy(String name) {
! this(name, null);
! }
!
! JavaLoggerProxy(String name, Level level) {
! super(name);
! this.javaLogger = LoggingSupport.getLogger(name);
! if (level != null) {
! // level has been updated and so set the Logger's level
! LoggingSupport.setLevel(javaLogger, level.javaLevel);
! }
! }
!
! void doLog(Level level, String msg) {
! LoggingSupport.log(javaLogger, level.javaLevel, msg);
! }
!
! void doLog(Level level, String msg, Throwable t) {
! LoggingSupport.log(javaLogger, level.javaLevel, msg, t);
! }
!
! void doLog(Level level, String msg, Object... params) {
! if (!isLoggable(level)) {
! return;
! }
! // only pass String objects to the j.u.l.Logger which may
! // be created by untrusted code
! int len = (params != null) ? params.length : 0;
! Object[] sparams = new String[len];
! for (int i = 0; i < len; i++) {
! sparams [i] = String.valueOf(params[i]);
! }
! LoggingSupport.log(javaLogger, level.javaLevel, msg, sparams);
! }
!
! boolean isEnabled() {
! return LoggingSupport.isLoggable(javaLogger, Level.OFF.javaLevel);
! }
!
! /**
! * Returns the PlatformLogger.Level mapped from j.u.l.Level
! * set in the logger. If the j.u.l.Logger is set to a custom Level,
! * this method will return the nearest Level.
! */
! Level getLevel() {
! Object javaLevel = LoggingSupport.getLevel(javaLogger);
! if (javaLevel == null) return null;
!
! try {
! return Level.valueOf(LoggingSupport.getLevelName(javaLevel));
! } catch (IllegalArgumentException e) {
! return Level.valueOf(LoggingSupport.getLevelValue(javaLevel));
! }
! }
! void setLevel(Level level) {
! LoggingSupport.setLevel(javaLogger, level == null ? null : level.javaLevel);
}
- boolean isLoggable(Level level) {
- return LoggingSupport.isLoggable(javaLogger, level.javaLevel);
- }
- }
}
--- 85,513 ----
* 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.
+ * <br>
+ * 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)];
}
}
! /**
! *
! * The PlatformLogger.Bridge interface is implemented by the System.Logger
! * objects returned by our default JUL provider - so that JRE classes using
! * PlatformLogger see no difference when JUL is the actual backend.
! *
! * PlatformLogger is now only a thin adaptation layer over the same
! * loggers than returned by java.lang.System.getLogger(String name).
! *
! * The recommendation for JRE classes going forward is to use
! * java.lang.System.getLogger(String name), which will
! * use Lazy Loggers when possible and necessary.
! *
! */
! public static interface Bridge {
!
! /**
! * Gets the name for this platform logger.
! * @return the name of the platform logger.
! */
! public String 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);
! public boolean isEnabled();
!
! public void log(Level level, String msg);
! public void log(Level level, String msg, Throwable thrown);
! public void log(Level level, String msg, Object... params);
! public void log(Level level, Supplier<String> msgSupplier);
! public void log(Level level, Throwable thrown, Supplier<String> msgSupplier);
! public void logp(Level level, String sourceClass, String sourceMethod, String msg);
! public void logp(Level level, String sourceClass, String sourceMethod,
! Supplier<String> msgSupplier);
! public void logp(Level level, String sourceClass, String sourceMethod,
! String msg, Object... params);
! public void logp(Level level, String sourceClass, String sourceMethod,
! String msg, Throwable thrown);
! public void logp(Level level, String sourceClass, String sourceMethod,
! Throwable thrown, Supplier<String> msgSupplier);
! public void logrb(Level level, String sourceClass, String sourceMethod,
! ResourceBundle bundle, String msg, Object... params);
! public void logrb(Level level, String sourceClass, String sourceMethod,
! ResourceBundle bundle, String msg, Throwable thrown);
! public void logrb(Level level, ResourceBundle bundle, String msg,
! Object... params);
! public void logrb(Level level, ResourceBundle bundle, String msg,
! Throwable thrown);
!
!
! public static Bridge convert(System.Logger logger) {
! if (logger instanceof PlatformLogger.Bridge) {
! return (Bridge) logger;
! } else {
! return new LoggerWrapper<>(logger);
! }
! }
! }
!
! /**
! * The {@code PlatformLogger.ConfigurableBridge} interface is used to
! * implement the deprecated {@link PlatformLogger#setLevel} method.
! *
! * PlatformLogger is now only a thin adaptation layer over the same
! * loggers than returned by java.lang.System.getLogger(String name).
! *
! * The recommendation for JRE classes going forward is to use
! * java.lang.System.getLogger(String name), which will
! * use Lazy Loggers when possible and necessary.
! *
! */
! public static interface ConfigurableBridge {
!
! public abstract class LoggerConfiguration {
! public abstract Level getPlatformLevel();
! public abstract void setPlatformLevel(Level level);
! }
!
! public default LoggerConfiguration getLoggerConfiguration() {
! return null;
! }
!
! public static LoggerConfiguration getLoggerConfiguration(PlatformLogger.Bridge logger) {
! if (logger instanceof PlatformLogger.ConfigurableBridge) {
! return ((ConfigurableBridge) logger).getLoggerConfiguration();
! } else {
! return null;
! }
}
}
// Table of known loggers. Maps names to PlatformLoggers.
! private static final Map<String,WeakReference<PlatformLogger>> 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<PlatformLogger> ref = loggers.get(name);
if (ref != null) {
log = ref.get();
}
if (log == null) {
! log = new PlatformLogger(PlatformLogger.Bridge.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 jdk.internal.logger.LazyLoggers,
! // or may be a Logger instance (or a wrapper thereof).
! //
! private final PlatformLogger.Bridge loggerProxy;
! private PlatformLogger(PlatformLogger.Bridge 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 ConfigurableBridge.LoggerConfiguration spi =
! PlatformLogger.ConfigurableBridge.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.
* <p>
* 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 ConfigurableBridge.LoggerConfiguration spi =
! PlatformLogger.ConfigurableBridge.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()];
}
}
< prev index next >