8150840: Add an internal system property to control the default level of System.Logger when java.logging is not present.
Reviewed-by: mchung, rriggs
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/BootstrapLogger.java Fri Mar 25 19:46:48 2016 +0800
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/BootstrapLogger.java Fri Mar 25 17:12:18 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -904,7 +904,7 @@
? LoggingBackend.JUL_WITH_CONFIG
: LoggingBackend.JUL_DEFAULT;
} else {
- // SimpleLogger is used
+ // SimpleConsoleLogger is used
return LoggingBackend.NONE;
}
}
@@ -913,10 +913,10 @@
}
}
- // We will use temporary SimpleConsoleLoggers if
+ // We will use a temporary SurrogateLogger if
// the logging backend is JUL, there is no custom config,
// and the LogManager has not been initialized yet.
- private static boolean useTemporaryLoggers() {
+ private static boolean useSurrogateLoggers() {
// being paranoid: this should already have been checked
if (!isBooted()) return true;
return DetectBackend.detectedBackend == LoggingBackend.JUL_DEFAULT
@@ -931,25 +931,24 @@
public static synchronized boolean useLazyLoggers() {
return !BootstrapLogger.isBooted()
|| DetectBackend.detectedBackend == LoggingBackend.CUSTOM
- || useTemporaryLoggers();
+ || useSurrogateLoggers();
}
// Called by LazyLoggerAccessor. This method will determine whether
// to create a BootstrapLogger (if the VM is not yet booted),
- // a SimpleConsoleLogger (if JUL is the default backend and there
+ // a SurrogateLogger (if JUL is the default backend and there
// is no custom JUL configuration and LogManager is not yet initialized),
// or a logger returned by the loaded LoggerFinder (all other cases).
static Logger getLogger(LazyLoggerAccessor accessor) {
if (!BootstrapLogger.isBooted()) {
return new BootstrapLogger(accessor);
} else {
- boolean temporary = useTemporaryLoggers();
- if (temporary) {
+ if (useSurrogateLoggers()) {
// JUL is the default backend, there is no custom configuration,
// LogManager has not been used.
synchronized(BootstrapLogger.class) {
- if (useTemporaryLoggers()) {
- return makeTemporaryLogger(accessor);
+ if (useSurrogateLoggers()) {
+ return createSurrogateLogger(accessor);
}
}
}
@@ -961,46 +960,46 @@
// If the backend is JUL, and there is no custom configuration, and
// nobody has attempted to call LogManager.getLogManager() yet, then
- // we can temporarily substitute JUL Logger with SimpleConsoleLoggers,
+ // we can temporarily substitute JUL Logger with SurrogateLoggers,
// which avoids the cost of actually loading up the LogManager...
- // The TemporaryLoggers class has the logic to create such temporary
+ // The RedirectedLoggers class has the logic to create such surrogate
// loggers, and to possibly replace them with real JUL loggers if
// someone calls LogManager.getLogManager().
- static final class TemporaryLoggers implements
- Function<LazyLoggerAccessor, SimpleConsoleLogger> {
+ static final class RedirectedLoggers implements
+ Function<LazyLoggerAccessor, SurrogateLogger> {
// all accesses must be synchronized on the outer BootstrapLogger.class
- final Map<LazyLoggerAccessor, SimpleConsoleLogger> temporaryLoggers =
+ final Map<LazyLoggerAccessor, SurrogateLogger> redirectedLoggers =
new HashMap<>();
// all accesses must be synchronized on the outer BootstrapLogger.class
- // The temporaryLoggers map will be cleared when LogManager is initialized.
+ // The redirectLoggers map will be cleared when LogManager is initialized.
boolean cleared;
@Override
// all accesses must be synchronized on the outer BootstrapLogger.class
- public SimpleConsoleLogger apply(LazyLoggerAccessor t) {
+ public SurrogateLogger apply(LazyLoggerAccessor t) {
if (cleared) throw new IllegalStateException("LoggerFinder already initialized");
- return SimpleConsoleLogger.makeSimpleLogger(t.getLoggerName(), true);
+ return SurrogateLogger.makeSurrogateLogger(t.getLoggerName());
}
// all accesses must be synchronized on the outer BootstrapLogger.class
- SimpleConsoleLogger get(LazyLoggerAccessor a) {
+ SurrogateLogger get(LazyLoggerAccessor a) {
if (cleared) throw new IllegalStateException("LoggerFinder already initialized");
- return temporaryLoggers.computeIfAbsent(a, this);
+ return redirectedLoggers.computeIfAbsent(a, this);
}
// all accesses must be synchronized on the outer BootstrapLogger.class
- Map<LazyLoggerAccessor, SimpleConsoleLogger> drainTemporaryLoggers() {
- if (temporaryLoggers.isEmpty()) return null;
+ Map<LazyLoggerAccessor, SurrogateLogger> drainLoggersMap() {
+ if (redirectedLoggers.isEmpty()) return null;
if (cleared) throw new IllegalStateException("LoggerFinder already initialized");
- final Map<LazyLoggerAccessor, SimpleConsoleLogger> accessors = new HashMap<>(temporaryLoggers);
- temporaryLoggers.clear();
+ final Map<LazyLoggerAccessor, SurrogateLogger> accessors = new HashMap<>(redirectedLoggers);
+ redirectedLoggers.clear();
cleared = true;
return accessors;
}
- static void resetTemporaryLoggers(Map<LazyLoggerAccessor, SimpleConsoleLogger> accessors) {
+ static void replaceSurrogateLoggers(Map<LazyLoggerAccessor, SurrogateLogger> accessors) {
// When the backend is JUL we want to force the creation of
// JUL loggers here: some tests are expecting that the
// PlatformLogger will create JUL loggers as soon as the
@@ -1012,36 +1011,38 @@
final LoggingBackend detectedBackend = DetectBackend.detectedBackend;
final boolean lazy = detectedBackend != LoggingBackend.JUL_DEFAULT
&& detectedBackend != LoggingBackend.JUL_WITH_CONFIG;
- for (Map.Entry<LazyLoggerAccessor, SimpleConsoleLogger> a : accessors.entrySet()) {
+ for (Map.Entry<LazyLoggerAccessor, SurrogateLogger> a : accessors.entrySet()) {
a.getKey().release(a.getValue(), !lazy);
}
}
// all accesses must be synchronized on the outer BootstrapLogger.class
- static final TemporaryLoggers INSTANCE = new TemporaryLoggers();
+ static final RedirectedLoggers INSTANCE = new RedirectedLoggers();
}
- static synchronized Logger makeTemporaryLogger(LazyLoggerAccessor a) {
- // accesses to TemporaryLoggers is synchronized on BootstrapLogger.class
- return TemporaryLoggers.INSTANCE.get(a);
+ static synchronized Logger createSurrogateLogger(LazyLoggerAccessor a) {
+ // accesses to RedirectedLoggers is synchronized on BootstrapLogger.class
+ return RedirectedLoggers.INSTANCE.get(a);
}
private static volatile boolean logManagerConfigured;
- private static synchronized Map<LazyLoggerAccessor, SimpleConsoleLogger>
- releaseTemporaryLoggers() {
+ private static synchronized Map<LazyLoggerAccessor, SurrogateLogger>
+ releaseSurrogateLoggers() {
// first check whether there's a chance that we have used
- // temporary loggers; Will be false if logManagerConfigured is already
+ // surrogate loggers; Will be false if logManagerConfigured is already
// true.
- final boolean clearTemporaryLoggers = useTemporaryLoggers();
+ final boolean releaseSurrogateLoggers = useSurrogateLoggers();
// then sets the flag that tells that the log manager is configured
logManagerConfigured = true;
- // finally replace all temporary loggers by real JUL loggers
- if (clearTemporaryLoggers) {
- // accesses to TemporaryLoggers is synchronized on BootstrapLogger.class
- return TemporaryLoggers.INSTANCE.drainTemporaryLoggers();
+ // finally retrieves all surrogate loggers that should be replaced
+ // by real JUL loggers, and return them in the form of a redirected
+ // loggers map.
+ if (releaseSurrogateLoggers) {
+ // accesses to RedirectedLoggers is synchronized on BootstrapLogger.class
+ return RedirectedLoggers.INSTANCE.drainLoggersMap();
} else {
return null;
}
@@ -1049,14 +1050,14 @@
public static void redirectTemporaryLoggers() {
// This call is synchronized on BootstrapLogger.class.
- final Map<LazyLoggerAccessor, SimpleConsoleLogger> accessors =
- releaseTemporaryLoggers();
+ final Map<LazyLoggerAccessor, SurrogateLogger> accessors =
+ releaseSurrogateLoggers();
// We will now reset the logger accessors, triggering the
- // (possibly lazy) replacement of any temporary logger by the
+ // (possibly lazy) replacement of any temporary surrogate logger by the
// real logger returned from the loaded LoggerFinder.
if (accessors != null) {
- TemporaryLoggers.resetTemporaryLoggers(accessors);
+ RedirectedLoggers.replaceSurrogateLoggers(accessors);
}
BootstrapExecutors.flush();
--- a/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Fri Mar 25 19:46:48 2016 +0800
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/SimpleConsoleLogger.java Fri Mar 25 17:12:18 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2015, 2016, 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
@@ -38,6 +38,7 @@
import java.lang.System.Logger;
import java.util.function.Predicate;
import java.util.function.Supplier;
+import sun.security.action.GetPropertyAction;
import sun.util.logging.PlatformLogger;
import sun.util.logging.PlatformLogger.ConfigurableBridge.LoggerConfiguration;
@@ -49,7 +50,19 @@
public class SimpleConsoleLogger extends LoggerConfiguration
implements Logger, PlatformLogger.Bridge, PlatformLogger.ConfigurableBridge {
- static final PlatformLogger.Level DEFAULT_LEVEL = PlatformLogger.Level.INFO;
+ static final Level DEFAULT_LEVEL = getDefaultLevel();
+ static final PlatformLogger.Level DEFAULT_PLATFORM_LEVEL =
+ PlatformLogger.toPlatformLevel(DEFAULT_LEVEL);
+
+ static Level getDefaultLevel() {
+ String levelName = AccessController.doPrivileged(
+ new GetPropertyAction("jdk.system.logger.level", "INFO"));
+ try {
+ return Level.valueOf(levelName);
+ } catch (IllegalArgumentException iae) {
+ return Level.INFO;
+ }
+ }
final String name;
volatile PlatformLogger.Level level;
@@ -59,8 +72,16 @@
this.usePlatformLevel = usePlatformLevel;
}
+ String getSimpleFormatString() {
+ return Formatting.SIMPLE_CONSOLE_LOGGER_FORMAT;
+ }
+
+ PlatformLogger.Level defaultPlatformLevel() {
+ return DEFAULT_PLATFORM_LEVEL;
+ }
+
@Override
- public String getName() {
+ public final String getName() {
return name;
}
@@ -77,12 +98,12 @@
// ---------------------------------------------------
@Override
- public boolean isLoggable(Level level) {
+ public final boolean isLoggable(Level level) {
return isLoggable(PlatformLogger.toPlatformLevel(level));
}
@Override
- public void log(Level level, ResourceBundle bundle, String key, Throwable thrown) {
+ public final void log(Level level, ResourceBundle bundle, String key, Throwable thrown) {
if (isLoggable(level)) {
if (bundle != null) {
key = bundle.getString(key);
@@ -92,7 +113,7 @@
}
@Override
- public void log(Level level, ResourceBundle bundle, String format, Object... params) {
+ public final void log(Level level, ResourceBundle bundle, String format, Object... params) {
if (isLoggable(level)) {
if (bundle != null) {
format = bundle.getString(format);
@@ -106,55 +127,55 @@
// ---------------------------------------------------
@Override
- public boolean isLoggable(PlatformLogger.Level level) {
+ public final boolean isLoggable(PlatformLogger.Level level) {
final PlatformLogger.Level effectiveLevel = effectiveLevel();
return level != PlatformLogger.Level.OFF
&& level.ordinal() >= effectiveLevel.ordinal();
}
@Override
- public boolean isEnabled() {
+ public final boolean isEnabled() {
return level != PlatformLogger.Level.OFF;
}
@Override
- public void log(PlatformLogger.Level level, String msg) {
+ public final void log(PlatformLogger.Level level, String msg) {
if (isLoggable(level)) {
publish(getCallerInfo(), logLevel(level), msg);
}
}
@Override
- public void log(PlatformLogger.Level level, String msg, Throwable thrown) {
+ public final void log(PlatformLogger.Level level, String msg, Throwable thrown) {
if (isLoggable(level)) {
publish(getCallerInfo(), logLevel(level), msg, thrown);
}
}
@Override
- public void log(PlatformLogger.Level level, String msg, Object... params) {
+ public final void log(PlatformLogger.Level level, String msg, Object... params) {
if (isLoggable(level)) {
publish(getCallerInfo(), logLevel(level), msg, params);
}
}
private PlatformLogger.Level effectiveLevel() {
- if (level == null) return DEFAULT_LEVEL;
+ if (level == null) return defaultPlatformLevel();
return level;
}
@Override
- public PlatformLogger.Level getPlatformLevel() {
+ public final PlatformLogger.Level getPlatformLevel() {
return level;
}
@Override
- public void setPlatformLevel(PlatformLogger.Level newLevel) {
+ public final void setPlatformLevel(PlatformLogger.Level newLevel) {
level = newLevel;
}
@Override
- public LoggerConfiguration getLoggerConfiguration() {
+ public final LoggerConfiguration getLoggerConfiguration() {
return this;
}
@@ -222,7 +243,7 @@
}
// Continue walking until we've found the relevant calling frame.
// Skips logging/logger infrastructure.
- return !isFilteredFrame(t);
+ return !Formatting.isFilteredFrame(t);
}
private boolean isLoggerImplFrame(String cname) {
@@ -256,7 +277,7 @@
ZonedDateTime zdt = ZonedDateTime.now();
String throwable = toString(thrown);
- return String.format(Formatting.formatString,
+ return String.format(getSimpleFormatString(),
zdt,
callerInfo,
name,
@@ -280,31 +301,19 @@
outputStream().print(format(level, msg, null, callerInfo));
}
- public static SimpleConsoleLogger makeSimpleLogger(String name, boolean usePlatformLevel) {
- return new SimpleConsoleLogger(name, usePlatformLevel);
- }
-
public static SimpleConsoleLogger makeSimpleLogger(String name) {
return new SimpleConsoleLogger(name, false);
}
- public static String getSimpleFormat(Function<String, String> defaultPropertyGetter) {
- return Formatting.getSimpleFormat(defaultPropertyGetter);
- }
-
- public static boolean isFilteredFrame(StackFrame st) {
- return Formatting.isFilteredFrame(st);
- }
-
@Override
- public void log(PlatformLogger.Level level, Supplier<String> msgSupplier) {
+ public final void log(PlatformLogger.Level level, Supplier<String> msgSupplier) {
if (isLoggable(level)) {
publish(getCallerInfo(), logLevel(level), msgSupplier.get());
}
}
@Override
- public void log(PlatformLogger.Level level, Throwable thrown,
+ public final void log(PlatformLogger.Level level, Throwable thrown,
Supplier<String> msgSupplier) {
if (isLoggable(level)) {
publish(getCallerInfo(), logLevel(level), msgSupplier.get(), thrown);
@@ -312,7 +321,7 @@
}
@Override
- public void logp(PlatformLogger.Level level, String sourceClass,
+ public final void logp(PlatformLogger.Level level, String sourceClass,
String sourceMethod, String msg) {
if (isLoggable(level)) {
publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg);
@@ -320,7 +329,7 @@
}
@Override
- public void logp(PlatformLogger.Level level, String sourceClass,
+ public final void logp(PlatformLogger.Level level, String sourceClass,
String sourceMethod, Supplier<String> msgSupplier) {
if (isLoggable(level)) {
publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msgSupplier.get());
@@ -328,7 +337,7 @@
}
@Override
- public void logp(PlatformLogger.Level level, String sourceClass, String sourceMethod,
+ public final void logp(PlatformLogger.Level level, String sourceClass, String sourceMethod,
String msg, Object... params) {
if (isLoggable(level)) {
publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg, params);
@@ -336,7 +345,7 @@
}
@Override
- public void logp(PlatformLogger.Level level, String sourceClass,
+ public final void logp(PlatformLogger.Level level, String sourceClass,
String sourceMethod, String msg, Throwable thrown) {
if (isLoggable(level)) {
publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msg, thrown);
@@ -344,7 +353,7 @@
}
@Override
- public void logp(PlatformLogger.Level level, String sourceClass,
+ public final void logp(PlatformLogger.Level level, String sourceClass,
String sourceMethod, Throwable thrown, Supplier<String> msgSupplier) {
if (isLoggable(level)) {
publish(getCallerInfo(sourceClass, sourceMethod), logLevel(level), msgSupplier.get(), thrown);
@@ -352,7 +361,7 @@
}
@Override
- public void logrb(PlatformLogger.Level level, String sourceClass,
+ public final void logrb(PlatformLogger.Level level, String sourceClass,
String sourceMethod, ResourceBundle bundle, String key, Object... params) {
if (isLoggable(level)) {
String msg = bundle == null ? key : bundle.getString(key);
@@ -361,7 +370,7 @@
}
@Override
- public void logrb(PlatformLogger.Level level, String sourceClass,
+ public final void logrb(PlatformLogger.Level level, String sourceClass,
String sourceMethod, ResourceBundle bundle, String key, Throwable thrown) {
if (isLoggable(level)) {
String msg = bundle == null ? key : bundle.getString(key);
@@ -370,7 +379,7 @@
}
@Override
- public void logrb(PlatformLogger.Level level, ResourceBundle bundle,
+ public final void logrb(PlatformLogger.Level level, ResourceBundle bundle,
String key, Object... params) {
if (isLoggable(level)) {
String msg = bundle == null ? key : bundle.getString(key);
@@ -379,7 +388,7 @@
}
@Override
- public void logrb(PlatformLogger.Level level, ResourceBundle bundle,
+ public final void logrb(PlatformLogger.Level level, ResourceBundle bundle,
String key, Throwable thrown) {
if (isLoggable(level)) {
String msg = bundle == null ? key : bundle.getString(key);
@@ -387,21 +396,38 @@
}
}
- private static final class Formatting {
+ static final class Formatting {
+ // The default simple log format string.
+ // Used both by SimpleConsoleLogger when java.logging is not present,
+ // and by SurrogateLogger and java.util.logging.SimpleFormatter when
+ // java.logging is present.
static final String DEFAULT_FORMAT =
"%1$tb %1$td, %1$tY %1$tl:%1$tM:%1$tS %1$Tp %2$s%n%4$s: %5$s%6$s%n";
- static final String FORMAT_PROP_KEY =
+
+ // The system property key that allows to change the default log format
+ // when java.logging is not present. This is used to control the formatting
+ // of the SimpleConsoleLogger.
+ static final String DEFAULT_FORMAT_PROP_KEY =
+ "jdk.system.logger.format";
+
+ // The system property key that allows to change the default log format
+ // when java.logging is present. This is used to control the formatting
+ // of the SurrogateLogger (used before java.util.logging.LogManager is
+ // initialized) and the java.util.logging.SimpleFormatter (used after
+ // java.util.logging.LogManager is initialized).
+ static final String JUL_FORMAT_PROP_KEY =
"java.util.logging.SimpleFormatter.format";
- static final String formatString = getSimpleFormat(null);
+
+ // The simple console logger format string
+ static final String SIMPLE_CONSOLE_LOGGER_FORMAT =
+ getSimpleFormat(DEFAULT_FORMAT_PROP_KEY, null);
// Make it easier to wrap Logger...
static private final String[] skips;
static {
String additionalPkgs = AccessController.doPrivileged(
- (PrivilegedAction<String>)
- () -> System.getProperty("jdk.logger.packages"));
+ new GetPropertyAction("jdk.logger.packages"));
skips = additionalPkgs == null ? new String[0] : additionalPkgs.split(",");
-
}
static boolean isFilteredFrame(StackFrame st) {
@@ -440,21 +466,29 @@
return false;
}
- static String getSimpleFormat(Function<String, String> defaultPropertyGetter) {
- // Using a lambda here causes
+ static String getSimpleFormat(String key, Function<String, String> defaultPropertyGetter) {
+ // Double check that 'key' is one of the expected property names:
+ // - DEFAULT_FORMAT_PROP_KEY is used to control the
+ // SimpleConsoleLogger format when java.logging is
+ // not present.
+ // - JUL_FORMAT_PROP_KEY is used when this method is called
+ // from the SurrogateLogger subclass. It is used to control the
+ // SurrogateLogger format and java.util.logging.SimpleFormatter
+ // format when java.logging is present.
+ // This method should not be called with any other key.
+ if (!DEFAULT_FORMAT_PROP_KEY.equals(key)
+ && !JUL_FORMAT_PROP_KEY.equals(key)) {
+ throw new IllegalArgumentException("Invalid property name: " + key);
+ }
+
+ // Do not use any lambda in this method. Using a lambda here causes
// jdk/test/java/lang/invoke/lambda/LogGeneratedClassesTest.java
// to fail - because that test has a testcase which somehow references
- // PlatformLogger and counts the number of generated lambda classes
- // So we explicitely use new PrivilegedAction<String> here.
- String format =
- AccessController.doPrivileged(new PrivilegedAction<String>() {
- @Override
- public String run() {
- return System.getProperty(FORMAT_PROP_KEY);
- }
- });
+ // PlatformLogger and counts the number of generated lambda classes.
+ String format = AccessController.doPrivileged(new GetPropertyAction(key));
+
if (format == null && defaultPropertyGetter != null) {
- format = defaultPropertyGetter.apply(FORMAT_PROP_KEY);
+ format = defaultPropertyGetter.apply(key);
}
if (format != null) {
try {
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/java.base/share/classes/jdk/internal/logger/SurrogateLogger.java Fri Mar 25 17:12:18 2016 +0100
@@ -0,0 +1,72 @@
+/*
+ * Copyright (c) 2016, 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 jdk.internal.logger;
+
+import java.util.function.Function;
+import sun.util.logging.PlatformLogger;
+
+/**
+ * A simple console logger used to emulate the behavior of JUL loggers when
+ * java.util.logging has no custom configuration.
+ * Surrogate loggers are usually only used temporarily, until the LogManager
+ * is initialized. At this point, the surrogates are replaced by an actual
+ * logger obtained from LogManager.
+ */
+public final class SurrogateLogger extends SimpleConsoleLogger {
+
+ private static final PlatformLogger.Level JUL_DEFAULT_LEVEL =
+ PlatformLogger.Level.INFO;
+ private static volatile String simpleFormatString;
+
+ SurrogateLogger(String name) {
+ super(name, true);
+ }
+
+ @Override
+ PlatformLogger.Level defaultPlatformLevel() {
+ return JUL_DEFAULT_LEVEL;
+ }
+
+ @Override
+ String getSimpleFormatString() {
+ if (simpleFormatString == null) {
+ simpleFormatString = getSimpleFormat(null);
+ }
+ return simpleFormatString;
+ }
+
+ public static String getSimpleFormat(Function<String, String> defaultPropertyGetter) {
+ return Formatting.getSimpleFormat(Formatting.JUL_FORMAT_PROP_KEY, defaultPropertyGetter);
+ }
+
+ public static SurrogateLogger makeSurrogateLogger(String name) {
+ return new SurrogateLogger(name);
+ }
+
+ public static boolean isFilteredFrame(StackWalker.StackFrame st) {
+ return Formatting.isFilteredFrame(st);
+ }
+}
--- a/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java Fri Mar 25 19:46:48 2016 +0800
+++ b/jdk/src/java.logging/share/classes/java/util/logging/LogRecord.java Fri Mar 25 17:12:18 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -33,8 +33,7 @@
import java.security.PrivilegedAction;
import java.time.Clock;
import java.util.function.Predicate;
-
-import static jdk.internal.logger.SimpleConsoleLogger.isFilteredFrame;
+import static jdk.internal.logger.SurrogateLogger.isFilteredFrame;
/**
* LogRecord objects are used to pass logging requests between
--- a/jdk/src/java.logging/share/classes/java/util/logging/SimpleFormatter.java Fri Mar 25 19:46:48 2016 +0800
+++ b/jdk/src/java.logging/share/classes/java/util/logging/SimpleFormatter.java Fri Mar 25 17:12:18 2016 +0100
@@ -1,5 +1,5 @@
/*
- * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2016, 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
@@ -29,7 +29,7 @@
import java.io.*;
import java.time.ZoneId;
import java.time.ZonedDateTime;
-import jdk.internal.logger.SimpleConsoleLogger;
+import jdk.internal.logger.SurrogateLogger;
/**
* Print a brief summary of the {@code LogRecord} in a human readable
@@ -64,7 +64,7 @@
}
private final String format =
- SimpleConsoleLogger.getSimpleFormat(SimpleFormatter::getLoggingProperty);
+ SurrogateLogger.getSimpleFormat(SimpleFormatter::getLoggingProperty);
/**
* Format the given LogRecord.
--- a/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java Fri Mar 25 19:46:48 2016 +0800
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/LoggerFinderLoaderTest/LoggerFinderLoaderTest.java Fri Mar 25 17:12:18 2016 +0100
@@ -181,7 +181,7 @@
}
System.Logger createSimpleLogger(String name) {
- PrivilegedAction<System.Logger> pa = () -> SimpleConsoleLogger.makeSimpleLogger(name, false);
+ PrivilegedAction<System.Logger> pa = () -> SimpleConsoleLogger.makeSimpleLogger(name);
return AccessController.doPrivileged(pa);
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/lang/System/LoggerFinder/internal/SimpleConsoleLoggerTest/SimpleConsoleLoggerTest.java Fri Mar 25 17:12:18 2016 +0100
@@ -0,0 +1,561 @@
+/*
+ * Copyright (c) 2016, 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.
+ *
+ * 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.
+ */
+import java.io.ByteArrayOutputStream;
+import java.io.IOException;
+import java.io.PrintStream;
+import java.io.UncheckedIOException;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.ResourceBundle;
+import java.util.concurrent.ConcurrentHashMap;
+import java.util.concurrent.atomic.AtomicBoolean;
+import java.util.concurrent.atomic.AtomicLong;
+import java.util.function.Supplier;
+import java.lang.System.Logger;
+import java.lang.System.Logger.Level;
+import java.util.EnumSet;
+import java.util.HashMap;
+import java.util.Locale;
+import java.util.Map;
+import jdk.internal.logger.SimpleConsoleLogger;
+import jdk.internal.logger.SurrogateLogger;
+import sun.util.logging.PlatformLogger;
+
+/**
+ * @test
+ * @bug 8140364
+ * @summary JDK implementation specific unit test for SimpleConsoleLogger.
+ * Tests the behavior of SimpleConsoleLogger.
+ * @modules java.base/sun.util.logging
+ * java.base/jdk.internal.logger
+ * @build SimpleConsoleLoggerTest
+ * @run main/othervm SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level=OFF SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level=ERROR SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level=WARNING SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level=INFO SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level=DEBUG SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level=TRACE SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level=ALL SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level=WOMBAT SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level=FINEST SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level=DEBUG -Djava.util.logging.SimpleFormatter.format=++++_%2$s%n%4$s:_%5$s%6$s%n SimpleConsoleLoggerTest
+ * @run main/othervm -Djdk.system.logger.level=DEBUG -Djdk.system.logger.format=++++_%2$s%n%4$s:_%5$s%6$s%n SimpleConsoleLoggerTest
+ *
+ * @author danielfuchs
+ */
+public class SimpleConsoleLoggerTest {
+
+ static final RuntimePermission LOGGERFINDER_PERMISSION =
+ new RuntimePermission("loggerFinder");
+ final static boolean VERBOSE = false;
+
+ public static class MyBundle extends ResourceBundle {
+
+ final ConcurrentHashMap<String,String> map = new ConcurrentHashMap<>();
+
+ @Override
+ protected Object handleGetObject(String key) {
+ if (key.contains(" (translated)")) {
+ throw new RuntimeException("Unexpected key: " + key);
+ }
+ return map.computeIfAbsent(key, k -> k.toUpperCase(Locale.ROOT) + " (translated)");
+ }
+
+ @Override
+ public Enumeration<String> getKeys() {
+ return Collections.enumeration(map.keySet());
+ }
+
+ }
+ public static class MyLoggerBundle extends MyBundle {
+
+ }
+
+
+ static class ErrorStream extends PrintStream {
+
+ static AtomicBoolean forward = new AtomicBoolean();
+ ByteArrayOutputStream out;
+ String saved = "";
+ public ErrorStream(ByteArrayOutputStream out) {
+ super(out);
+ this.out = out;
+ }
+
+ @Override
+ public void write(int b) {
+ super.write(b);
+ if (forward.get()) err.write(b);
+ }
+
+ @Override
+ public void write(byte[] b) throws IOException {
+ super.write(b);
+ if (forward.get()) err.write(b);
+ }
+
+ @Override
+ public void write(byte[] buf, int off, int len) {
+ super.write(buf, off, len);
+ if (forward.get()) err.write(buf, off, len);
+ }
+
+ public String peek() {
+ flush();
+ return out.toString();
+ }
+
+ public String drain() {
+ flush();
+ String res = out.toString();
+ out.reset();
+ return res;
+ }
+
+ public void store() {
+ flush();
+ saved = out.toString();
+ out.reset();
+ }
+
+ public void restore() {
+ out.reset();
+ try {
+ out.write(saved.getBytes());
+ } catch(IOException io) {
+ throw new UncheckedIOException(io);
+ }
+ }
+
+ static final PrintStream err = System.err;
+ static final ErrorStream errorStream = new ErrorStream(new ByteArrayOutputStream());
+ }
+
+ private static StringBuilder appendProperty(StringBuilder b, String name) {
+ String value = System.getProperty(name);
+ if (value == null) return b;
+ return b.append(name).append("=").append(value).append('\n');
+ }
+
+ public static void main(String[] args) {
+ Locale.setDefault(Locale.ENGLISH);
+ System.setErr(ErrorStream.errorStream);
+ try {
+ test(args);
+ } finally {
+ try {
+ System.setErr(ErrorStream.err);
+ } catch (Error | RuntimeException x) {
+ x.printStackTrace(ErrorStream.err);
+ }
+ }
+ }
+
+
+ public static void test(String[] args) {
+
+ ErrorStream.errorStream.restore();
+ String l = System.getProperty("jdk.system.logger.level");
+ String f = System.getProperty("jdk.system.logger.format");
+ String jf = System.getProperty("java.util.logging.SimpleFormatter.format");
+ System.out.println("Running test: "
+ + "\n\tjdk.system.logger.level=\"" + l + "\""
+ + "\n\tjdk.system.logger.format=\"" + f + "\""
+ + "\n\tjava.util.logging.SimpleFormatter.format=\"" + jf + "\"");
+
+ test(l,f,jf);
+ System.out.println("\nPASSED: tested " + SEQUENCER.get() + " test cases");
+ }
+
+ static final AtomicLong SEQUENCER = new AtomicLong();
+ public static void test(String defaultLevel, String defaultFormat, String julFormat) {
+
+ final Map<Logger, String> loggerDescMap = new HashMap<>();
+
+ SimpleConsoleLogger simple = SimpleConsoleLogger.makeSimpleLogger("test.logger");
+ loggerDescMap.put(simple, "SimpleConsoleLogger.makeSimpleLogger(\"test.logger\")");
+ SimpleConsoleLogger temporary = SurrogateLogger.makeSurrogateLogger("test.logger");
+ loggerDescMap.put(temporary, "SurrogateLogger.makeSimpleLogger(\"test.logger\")");
+
+ Level level;
+ try {
+ level = defaultLevel == null ? null : Level.valueOf(defaultLevel);
+ } catch (IllegalArgumentException ex) {
+ level = null;
+ }
+ testLogger(loggerDescMap, simple, level, false, defaultFormat);
+ testLogger(loggerDescMap, temporary, null, true, julFormat);
+ }
+
+ public static class Foo {
+
+ }
+
+ static void verbose(String msg) {
+ if (VERBOSE) {
+ System.out.println(msg);
+ }
+ }
+
+ static String getName(Level level, boolean usePlatformLevel) {
+ if (usePlatformLevel) {
+ return PlatformLogger.toPlatformLevel(level).name();
+ } else {
+ return level.getName();
+ }
+ }
+
+ // Calls the 8 methods defined on Logger and verify the
+ // parameters received by the underlying TestProvider.LoggerImpl
+ // logger.
+ private static void testLogger(Map<Logger, String> loggerDescMap,
+ SimpleConsoleLogger simple,
+ Level defaultLevel,
+ boolean usePlatformLevel,
+ String defaultFormat) {
+
+ System.out.println("Testing " + loggerDescMap.get(simple) + " [" + simple +"]");
+
+ String formatStrMarker = defaultFormat == null ? ""
+ : defaultFormat.startsWith("++++") ? "++++" : "";
+ String unexpectedMarker = defaultFormat == null ? "++++"
+ : defaultFormat.startsWith("++++") ? "????" : "++++";
+ String formatStrSpec = defaultFormat == null ? "[date]"
+ : defaultFormat.startsWith("++++") ? "++++" : "????";
+ String sep = defaultFormat == null ? ": " : ":_";
+ String sepw = defaultFormat == null ? " " : "_";
+
+ Foo foo = new Foo();
+ String fooMsg = foo.toString();
+ for (Level loggerLevel : defaultLevel == null
+ ? EnumSet.of(Level.INFO) : EnumSet.of(defaultLevel)) {
+ for (Level messageLevel : Level.values()) {
+ ErrorStream.errorStream.drain();
+ String desc = "logger.log(messageLevel, foo): loggerLevel="
+ + loggerLevel+", messageLevel="+messageLevel;
+ SEQUENCER.incrementAndGet();
+ simple.log(messageLevel, foo);
+ if (loggerLevel == Level.OFF || messageLevel == Level.OFF
+ || messageLevel.compareTo(loggerLevel) < 0) {
+ if (!ErrorStream.errorStream.peek().isEmpty()) {
+ throw new RuntimeException("unexpected event in queue for "
+ + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
+ }
+ } else {
+ String logged = ErrorStream.errorStream.drain();
+ String expected = getName(messageLevel, usePlatformLevel) + sep + fooMsg;
+ if (!logged.contains("SimpleConsoleLoggerTest testLogger")
+ || !logged.contains(formatStrMarker)
+ || logged.contains(unexpectedMarker)
+ || !logged.contains(expected)) {
+ throw new RuntimeException("mismatch for " + desc
+ + "\n\texpected:" + "\n<<<<\n"
+ + formatStrSpec + sepw + "SimpleConsoleLoggerTest testLogger\n"
+ + expected
+ + "\n>>>>"
+ + "\n\t actual:"
+ + "\n<<<<\n" + logged + ">>>>\n");
+ } else {
+ verbose("Got expected results for "
+ + desc + "\n<<<<\n" + logged + ">>>>\n");
+ }
+ }
+ }
+ }
+
+ String msg = "blah";
+ for (Level loggerLevel : defaultLevel == null
+ ? EnumSet.of(Level.INFO) : EnumSet.of(defaultLevel)) {
+ for (Level messageLevel : Level.values()) {
+ String desc = "logger.log(messageLevel, \"blah\"): loggerLevel="
+ + loggerLevel+", messageLevel="+messageLevel;
+ SEQUENCER.incrementAndGet();
+ simple.log(messageLevel, msg);
+ if (loggerLevel == Level.OFF || messageLevel == Level.OFF
+ || messageLevel.compareTo(loggerLevel) < 0) {
+ if (!ErrorStream.errorStream.peek().isEmpty()) {
+ throw new RuntimeException("unexpected event in queue for "
+ + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
+ }
+ } else {
+ String logged = ErrorStream.errorStream.drain();
+ String expected = getName(messageLevel, usePlatformLevel) + sep + msg;
+ if (!logged.contains("SimpleConsoleLoggerTest testLogger")
+ || !logged.contains(formatStrMarker)
+ || logged.contains(unexpectedMarker)
+ || !logged.contains(expected)) {
+ throw new RuntimeException("mismatch for " + desc
+ + "\n\texpected:" + "\n<<<<\n"
+ + formatStrSpec + sepw + "SimpleConsoleLoggerTest testLogger\n"
+ + expected
+ + "\n>>>>"
+ + "\n\t actual:"
+ + "\n<<<<\n" + logged + ">>>>\n");
+ } else {
+ verbose("Got expected results for "
+ + desc + "\n<<<<\n" + logged + ">>>>\n");
+ }
+ }
+ }
+ }
+
+ Supplier<String> fooSupplier = new Supplier<String>() {
+ @Override
+ public String get() {
+ return this.toString();
+ }
+ };
+
+ for (Level loggerLevel : defaultLevel == null
+ ? EnumSet.of(Level.INFO) : EnumSet.of(defaultLevel)) {
+ for (Level messageLevel : Level.values()) {
+ String desc = "logger.log(messageLevel, fooSupplier): loggerLevel="
+ + loggerLevel+", messageLevel="+messageLevel;
+ SEQUENCER.incrementAndGet();
+ simple.log(messageLevel, fooSupplier);
+ if (loggerLevel == Level.OFF || messageLevel == Level.OFF
+ || messageLevel.compareTo(loggerLevel) < 0) {
+ if (!ErrorStream.errorStream.peek().isEmpty()) {
+ throw new RuntimeException("unexpected event in queue for "
+ + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
+ }
+ } else {
+ String logged = ErrorStream.errorStream.drain();
+ String expected = getName(messageLevel, usePlatformLevel) + sep + fooSupplier.get();
+ if (!logged.contains("SimpleConsoleLoggerTest testLogger")
+ || !logged.contains(formatStrMarker)
+ || logged.contains(unexpectedMarker)
+ || !logged.contains(expected)) {
+ throw new RuntimeException("mismatch for " + desc
+ + "\n\texpected:" + "\n<<<<\n"
+ + formatStrSpec + sepw + "SimpleConsoleLoggerTest testLogger\n"
+ + expected
+ + "\n>>>>"
+ + "\n\t actual:"
+ + "\n<<<<\n" + logged + ">>>>\n");
+ } else {
+ verbose("Got expected results for "
+ + desc + "\n<<<<\n" + logged + ">>>>\n");
+ }
+ }
+ }
+ }
+
+
+ String format = "two params [{1} {2}]";
+ Object arg1 = foo;
+ Object arg2 = msg;
+ for (Level loggerLevel : defaultLevel == null
+ ? EnumSet.of(Level.INFO) : EnumSet.of(defaultLevel)) {
+ for (Level messageLevel : Level.values()) {
+ String desc = "logger.log(messageLevel, format, params...): loggerLevel="
+ + loggerLevel+", messageLevel="+messageLevel;
+ SEQUENCER.incrementAndGet();
+ simple.log(messageLevel, format, foo, msg);
+ if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
+ if (!ErrorStream.errorStream.peek().isEmpty()) {
+ throw new RuntimeException("unexpected event in queue for "
+ + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
+ }
+ } else {
+ String logged = ErrorStream.errorStream.drain();
+ String msgFormat = format;
+ String text = java.text.MessageFormat.format(msgFormat, foo, msg);
+ String expected = getName(messageLevel, usePlatformLevel) + sep + text;
+ if (!logged.contains("SimpleConsoleLoggerTest testLogger")
+ || !logged.contains(formatStrMarker)
+ || !logged.contains(expected)) {
+ throw new RuntimeException("mismatch for " + desc
+ + "\n\texpected:" + "\n<<<<\n"
+ + formatStrSpec + sepw + "SimpleConsoleLoggerTest testLogger\n"
+ + expected
+ + "\n>>>>"
+ + "\n\t actual:"
+ + "\n<<<<\n" + logged + ">>>>\n");
+ } else {
+ verbose("Got expected results for "
+ + desc + "\n<<<<\n" + logged + ">>>>\n");
+ }
+ }
+ }
+ }
+
+ Throwable thrown = new Exception("OK: log me!");
+ for (Level loggerLevel : defaultLevel == null
+ ? EnumSet.of(Level.INFO) : EnumSet.of(defaultLevel)) {
+ for (Level messageLevel : Level.values()) {
+ String desc = "logger.log(messageLevel, \"blah\", thrown): loggerLevel="
+ + loggerLevel+", messageLevel="+messageLevel;
+ SEQUENCER.incrementAndGet();
+ simple.log(messageLevel, msg, thrown);
+ if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
+ if (!ErrorStream.errorStream.peek().isEmpty()) {
+ throw new RuntimeException("unexpected event in queue for "
+ + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
+ }
+ } else {
+ String logged = ErrorStream.errorStream.drain();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ thrown.printStackTrace(new PrintStream(baos));
+ String text = baos.toString();
+ String expected = getName(messageLevel, usePlatformLevel) + sep + msg;
+ if (!logged.contains("SimpleConsoleLoggerTest testLogger")
+ || !logged.contains(formatStrMarker)
+ || !logged.contains(expected)
+ || logged.contains(unexpectedMarker)
+ || !logged.contains(text)) {
+ throw new RuntimeException("mismatch for " + desc
+ + "\n\texpected:" + "\n<<<<\n"
+ + formatStrSpec + sepw + "SimpleConsoleLoggerTest testLogger\n"
+ + msg +"\n"
+ + text
+ + ">>>>"
+ + "\n\t actual:"
+ + "\n<<<<\n" + logged + ">>>>\n");
+ } else {
+ verbose("Got expected results for "
+ + desc + "\n<<<<\n" + logged + ">>>>\n");
+ }
+ }
+ }
+ }
+
+
+ for (Level loggerLevel : defaultLevel == null
+ ? EnumSet.of(Level.INFO) : EnumSet.of(defaultLevel)) {
+ for (Level messageLevel : Level.values()) {
+ String desc = "logger.log(messageLevel, thrown, fooSupplier): loggerLevel="
+ + loggerLevel+", messageLevel="+messageLevel;
+ SEQUENCER.incrementAndGet();
+ simple.log(messageLevel, fooSupplier, thrown);
+ if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
+ if (!ErrorStream.errorStream.peek().isEmpty()) {
+ throw new RuntimeException("unexpected event in queue for "
+ + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
+ }
+ } else {
+ String logged = ErrorStream.errorStream.drain();
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ thrown.printStackTrace(new PrintStream(baos));
+ String text = baos.toString();
+ String expected = getName(messageLevel, usePlatformLevel) + sep + fooSupplier.get();
+ if (!logged.contains("SimpleConsoleLoggerTest testLogger")
+ || !logged.contains(formatStrMarker)
+ || !logged.contains(expected)
+ || logged.contains(unexpectedMarker)
+ || !logged.contains(text)) {
+ throw new RuntimeException("mismatch for " + desc
+ + "\n\texpected:" + "\n<<<<\n"
+ + formatStrSpec + sepw + "SimpleConsoleLoggerTest testLogger\n"
+ + expected +"\n"
+ + text
+ + ">>>>"
+ + "\n\t actual:"
+ + "\n<<<<\n" + logged + ">>>>\n");
+ } else {
+ verbose("Got expected results for "
+ + desc + "\n<<<<\n" + logged + ">>>>\n");
+ }
+ }
+ }
+ }
+
+ ResourceBundle bundle = ResourceBundle.getBundle(MyBundle.class.getName());
+ for (Level loggerLevel : defaultLevel == null
+ ? EnumSet.of(Level.INFO) : EnumSet.of(defaultLevel)) {
+ for (Level messageLevel : Level.values()) {
+ String desc = "logger.log(messageLevel, bundle, format, params...): loggerLevel="
+ + loggerLevel+", messageLevel="+messageLevel;
+ SEQUENCER.incrementAndGet();
+ simple.log(messageLevel, bundle, format, foo, msg);
+ if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
+ if (!ErrorStream.errorStream.peek().isEmpty()) {
+ throw new RuntimeException("unexpected event in queue for "
+ + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
+ }
+ } else {
+ String logged = ErrorStream.errorStream.drain();
+ String text = java.text.MessageFormat.format(bundle.getString(format), foo, msg);
+ if (!logged.contains("SimpleConsoleLoggerTest testLogger")
+ || !logged.contains(formatStrMarker)
+ || logged.contains(unexpectedMarker)
+ || !logged.contains(getName(messageLevel, usePlatformLevel) + sep + text)) {
+ throw new RuntimeException("mismatch for " + desc
+ + "\n\texpected:" + "\n<<<<\n"
+ + formatStrSpec + sepw + "SimpleConsoleLoggerTest testLogger\n"
+ + getName(messageLevel, usePlatformLevel) + " " + text
+ + "\n>>>>"
+ + "\n\t actual:"
+ + "\n<<<<\n" + logged + ">>>>\n");
+ } else {
+ verbose("Got expected results for "
+ + desc + "\n<<<<\n" + logged + ">>>>\n");
+ }
+ }
+ }
+ }
+
+ for (Level loggerLevel : defaultLevel == null
+ ? EnumSet.of(Level.INFO) : EnumSet.of(defaultLevel)) {
+ for (Level messageLevel : Level.values()) {
+ String desc = "logger.log(messageLevel, bundle, \"blah\", thrown): loggerLevel="
+ + loggerLevel+", messageLevel="+messageLevel;
+ SEQUENCER.incrementAndGet();
+ simple.log(messageLevel, bundle, msg, thrown);
+ if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
+ if (!ErrorStream.errorStream.peek().isEmpty()) {
+ throw new RuntimeException("unexpected event in queue for "
+ + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
+ }
+ } else {
+ String logged = ErrorStream.errorStream.drain();
+ String textMsg = bundle.getString(msg);
+ ByteArrayOutputStream baos = new ByteArrayOutputStream();
+ thrown.printStackTrace(new PrintStream(baos));
+ String text = baos.toString();
+ String expected = getName(messageLevel, usePlatformLevel) + sep + textMsg;
+ if (!logged.contains("SimpleConsoleLoggerTest testLogger")
+ || !logged.contains(formatStrMarker)
+ || !logged.contains(expected)
+ || logged.contains(unexpectedMarker)
+ || !logged.contains(text)) {
+ throw new RuntimeException("mismatch for " + desc
+ + "\n\texpected:" + "\n<<<<\n"
+ + formatStrSpec + sepw + "SimpleConsoleLoggerTest testLogger\n"
+ + expected +"\n"
+ + text
+ + ">>>>"
+ + "\n\t actual:"
+ + "\n<<<<\n" + logged + ">>>>\n");
+ } else {
+ verbose("Got expected results for "
+ + desc + "\n<<<<\n" + logged + ">>>>\n");
+ }
+ }
+ }
+ }
+
+ }
+}