8017174: NPE when using Logger.getAnonymousLogger or LogManager.getLogManager().getLogger

This patch makes sure that LoggerContext instances created for applets have a root and global logger.

Reviewed-by: mchung
This commit is contained in:
Daniel Fuchs 2013-07-02 11:30:31 +02:00
parent 200428aa69
commit 677643324e
3 changed files with 719 additions and 14 deletions

View File

@ -193,13 +193,22 @@ public class LogManager {
// Create and retain Logger for the root of the namespace.
manager.rootLogger = manager.new RootLogger();
// since by design the global manager's userContext and
// systemContext don't have their requiresDefaultLoggers
// flag set - we make sure to add the root logger to
// the global manager's default contexts here.
manager.addLogger(manager.rootLogger);
manager.systemContext.addLocalLogger(manager.rootLogger);
manager.systemContext.addLocalLogger(manager.rootLogger, false);
manager.userContext.addLocalLogger(manager.rootLogger, false);
// Adding the global Logger. Doing so in the Logger.<clinit>
// would deadlock with the LogManager.<clinit>.
Logger.global.setLogManager(manager);
// Make sure the global logger will be registered in the
// global manager's default contexts.
manager.addLogger(Logger.global);
manager.systemContext.addLocalLogger(Logger.global, false);
manager.userContext.addLocalLogger(Logger.global, false);
// We don't call readConfiguration() here, as we may be running
// very early in the JVM startup sequence. Instead readConfiguration
@ -401,7 +410,11 @@ public class LogManager {
if (javaAwtAccess.isMainAppContext()) {
context = userContext;
} else {
context = new LoggerContext();
// Create a new LoggerContext for the applet.
// The new logger context has its requiresDefaultLoggers
// flag set to true - so that these loggers will be
// lazily added when the context is firt accessed.
context = new LoggerContext(true);
}
javaAwtAccess.put(ecx, LoggerContext.class, context);
}
@ -508,9 +521,13 @@ public class LogManager {
private final Hashtable<String,LoggerWeakRef> namedLoggers = new Hashtable<>();
// Tree of named Loggers
private final LogNode root;
private final boolean requiresDefaultLoggers;
private LoggerContext() {
this(false);
}
private LoggerContext(boolean requiresDefaultLoggers) {
this.root = new LogNode(null, this);
this.requiresDefaultLoggers = requiresDefaultLoggers;
}
Logger demandLogger(String name, String resourceBundleName) {
@ -519,7 +536,27 @@ public class LogManager {
return manager.demandLogger(name, resourceBundleName, null);
}
// Due to subtle deadlock issues getUserContext() no longer
// calls addLocalLogger(rootLogger);
// Therefore - we need to add the default loggers later on.
// Checks that the context is properly initialized
// This is necessary before calling e.g. find(name)
// or getLoggerNames()
//
private void ensureInitialized() {
if (requiresDefaultLoggers) {
// Ensure that the root and global loggers are set.
ensureDefaultLogger(manager.rootLogger);
ensureDefaultLogger(Logger.global);
}
}
synchronized Logger findLogger(String name) {
// ensure that this context is properly initialized before
// looking for loggers.
ensureInitialized();
LoggerWeakRef ref = namedLoggers.get(name);
if (ref == null) {
return null;
@ -533,21 +570,76 @@ public class LogManager {
return logger;
}
synchronized void ensureRootLogger(Logger logger) {
if (logger.getName().isEmpty())
return;
// during initialization, rootLogger is null when
// instantiating itself RootLogger
if (findLogger("") == null && manager.rootLogger != null) {
addLocalLogger(manager.rootLogger);
// This method is called before adding a logger to the
// context.
// 'logger' is the context that will be added.
// This method will ensure that the defaults loggers are added
// before adding 'logger'.
//
private void ensureAllDefaultLoggers(Logger logger) {
if (requiresDefaultLoggers) {
final String name = logger.getName();
if (!name.isEmpty()) {
ensureDefaultLogger(manager.rootLogger);
}
if (!Logger.GLOBAL_LOGGER_NAME.equals(name)) {
ensureDefaultLogger(Logger.global);
}
}
}
private void ensureDefaultLogger(Logger logger) {
// Used for lazy addition of root logger and global logger
// to a LoggerContext.
// This check is simple sanity: we do not want that this
// method be called for anything else than Logger.global
// or owner.rootLogger.
if (!requiresDefaultLoggers || logger == null
|| logger != Logger.global && logger != manager.rootLogger) {
// the case where we have a non null logger which is neither
// Logger.global nor manager.rootLogger indicates a serious
// issue - as ensureDefaultLogger should never be called
// with any other loggers than one of these two (or null - if
// e.g manager.rootLogger is not yet initialized)...
assert logger == null;
return;
}
// Adds the logger if it's not already there.
if (!namedLoggers.containsKey(logger.getName())) {
// It is important to prevent addLocalLogger to
// call ensureAllDefaultLoggers when we're in the process
// off adding one of those default loggers - as this would
// immediately cause a stack overflow.
// Therefore we must pass addDefaultLoggersIfNeeded=false,
// even if requiresDefaultLoggers is true.
addLocalLogger(logger, false);
}
}
boolean addLocalLogger(Logger logger) {
// no need to add default loggers if it's not required
return addLocalLogger(logger, requiresDefaultLoggers);
}
// Add a logger to this context. This method will only set its level
// and process parent loggers. It doesn't set its handlers.
synchronized boolean addLocalLogger(Logger logger) {
ensureRootLogger(logger);
synchronized boolean addLocalLogger(Logger logger, boolean addDefaultLoggersIfNeeded) {
// addDefaultLoggersIfNeeded serves to break recursion when adding
// default loggers. If we're adding one of the default loggers
// (we're being called from ensureDefaultLogger()) then
// addDefaultLoggersIfNeeded will be false: we don't want to
// call ensureAllDefaultLoggers again.
//
// Note: addDefaultLoggersIfNeeded can also be false when
// requiresDefaultLoggers is false - since calling
// ensureAllDefaultLoggers would have no effect in this case.
if (addDefaultLoggersIfNeeded) {
ensureAllDefaultLoggers(logger);
}
final String name = logger.getName();
if (name == null) {
@ -615,6 +707,9 @@ public class LogManager {
}
synchronized Enumeration<String> getLoggerNames() {
// ensure that this context is properly initialized before
// returning logger names.
ensureInitialized();
return namedLoggers.keys();
}

View File

@ -63,7 +63,7 @@ public class LogManagerInstanceTest {
if (!super.addLogger(root))
throw new RuntimeException("Fail to addLogger " + root);
} else {
System.out.println("Root logger already exists");
throw new RuntimeException("Root logger already exists");
}
this.base = root;
}

View File

@ -0,0 +1,610 @@
/*
* Copyright (c) 2013, 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.security.CodeSource;
import java.security.Permission;
import java.security.PermissionCollection;
import java.security.Permissions;
import java.security.Policy;
import java.security.ProtectionDomain;
import java.util.EnumSet;
import java.util.HashMap;
import java.util.Map;
import java.util.logging.LogManager;
import java.util.logging.Logger;
import java.util.logging.LoggingPermission;
import sun.misc.JavaAWTAccess;
import sun.misc.SharedSecrets;
/*
* @test
* @bug 8017174 8010727
* @summary NPE when using Logger.getAnonymousLogger or
* LogManager.getLogManager().getLogger
*
* @run main/othervm -Dtest.security=off TestAppletLoggerContext LoadingApplet
* @run main/othervm -Dtest.security=on TestAppletLoggerContext LoadingApplet
* @run main/othervm -Dtest.security=off TestAppletLoggerContext LoadingMain
* @run main/othervm -Dtest.security=on TestAppletLoggerContext LoadingMain
* @run main/othervm -Dtest.security=off TestAppletLoggerContext One
* @run main/othervm -Dtest.security=on TestAppletLoggerContext One
* @run main/othervm -Dtest.security=off TestAppletLoggerContext Two
* @run main/othervm -Dtest.security=on TestAppletLoggerContext Two
* @run main/othervm -Dtest.security=off TestAppletLoggerContext Three
* @run main/othervm -Dtest.security=on TestAppletLoggerContext Three
* @run main/othervm -Dtest.security=off TestAppletLoggerContext Four
* @run main/othervm -Dtest.security=on TestAppletLoggerContext Four
* @run main/othervm -Dtest.security=off TestAppletLoggerContext Five
* @run main/othervm -Dtest.security=on TestAppletLoggerContext Five
* @run main/othervm -Dtest.security=off TestAppletLoggerContext Six
* @run main/othervm -Dtest.security=on TestAppletLoggerContext Six
* @run main/othervm -Dtest.security=off TestAppletLoggerContext Seven
* @run main/othervm -Dtest.security=on TestAppletLoggerContext Seven
* @run main/othervm -Dtest.security=off TestAppletLoggerContext
* @run main/othervm -Dtest.security=on TestAppletLoggerContext
*/
// NOTE: We run in other VM in order to 1. switch security manager and 2. cause
// LogManager class to be loaded anew.
public class TestAppletLoggerContext {
// Avoids the hassle of dealing with files and system props...
static class SimplePolicy extends Policy {
private final Permissions perms;
public SimplePolicy(Permission... permissions) {
perms = new Permissions();
for (Permission permission : permissions) {
perms.add(permission);
}
}
@Override
public PermissionCollection getPermissions(CodeSource cs) {
return perms;
}
@Override
public PermissionCollection getPermissions(ProtectionDomain pd) {
return perms;
}
@Override
public boolean implies(ProtectionDomain pd, Permission p) {
return perms.implies(p);
}
}
// The bridge class initializes the logging system.
// It stubs the applet context in order to simulate context changes.
//
public static class Bridge {
private static class JavaAWTAccessStub implements JavaAWTAccess {
boolean active = true;
private static class TestExc {
private final Map<Object, Object> map = new HashMap<>();
void put(Object key, Object v) { map.put(key, v); }
Object get(Object key) { return map.get(key); }
void remove(Object o) { map.remove(o); }
public static TestExc exc(Object o) {
return TestExc.class.cast(o);
}
}
TestExc exc;
TestExc global = new TestExc();
@Override
public Object getContext() { return active ? global : null; }
@Override
public Object getExecutionContext() { return active ? exc : null; }
@Override
public Object get(Object o, Object o1) { return TestExc.exc(o).get(o1); }
@Override
public void put(Object o, Object o1, Object o2) { TestExc.exc(o).put(o1, o2); }
@Override
public void remove(Object o, Object o1) { TestExc.exc(o).remove(o1); }
@Override
public Object get(Object o) { return global.get(o); }
@Override
public void put(Object o, Object o1) { global.put(o, o1); }
@Override
public void remove(Object o) { global.remove(o); }
@Override
public boolean isDisposed() { return false; }
@Override
public boolean isMainAppContext() { return exc == null; }
}
final static JavaAWTAccessStub javaAwtAccess = new JavaAWTAccessStub();
public static void init() {
SharedSecrets.setJavaAWTAccess(javaAwtAccess);
if (System.getProperty("test.security", "on").equals("on")) {
Policy p = new SimplePolicy(new LoggingPermission("control", null),
new RuntimePermission("setContextClassLoader"),
new RuntimePermission("shutdownHooks"));
Policy.setPolicy(p);
System.setSecurityManager(new SecurityManager());
}
}
public static void changeContext() {
System.out.println("... Switching to a new applet context ...");
javaAwtAccess.active = true;
javaAwtAccess.exc = new JavaAWTAccessStub.TestExc();
}
public static void desactivate() {
System.out.println("... Running with no applet context ...");
javaAwtAccess.exc = null;
javaAwtAccess.active = false;
}
public static class CustomAnonymousLogger extends Logger {
public CustomAnonymousLogger() {
this("");
}
public CustomAnonymousLogger(String name) {
super(null, null);
System.out.println( " LogManager: " +LogManager.getLogManager());
System.out.println( " getLogger: " +LogManager.getLogManager().getLogger(name));
setParent(LogManager.getLogManager().getLogger(name));
}
}
public static class CustomLogger extends Logger {
CustomLogger(String name) {
super(name, null);
}
}
}
public static enum TestCase {
LoadingApplet, LoadingMain, One, Two, Three, Four, Five, Six, Seven;
public void test() {
switch(this) {
// When run - each of these two tests must be
// run before any other tests and before each other.
case LoadingApplet: testLoadingApplet(); break;
case LoadingMain: testLoadingMain(); break;
case One: testOne(); break;
case Two: testTwo(); break;
case Three: testThree(); break;
case Four: testFour(); break;
case Five: testFive(); break;
case Six: testSix(); break;
case Seven: testSeven(); break;
}
}
public String describe() {
switch(this) {
case LoadingApplet:
return "Test that when the LogManager class is"
+ " loaded in an applet thread first,"
+ "\n all LoggerContexts are correctly initialized";
case LoadingMain:
return "Test that when the LogManager class is"
+ " loaded in the main thread first,"
+ "\n all LoggerContexts are correctly initialized";
case One:
return "Test that Logger.getAnonymousLogger()"
+ " and new CustomAnonymousLogger() don't throw NPE";
case Two:
return "Test that Logger.getLogger(\"\")"
+ " does not return null nor throws NPE";
case Three:
return "Test that LogManager.getLogManager().getLogger(\"\")"
+ " does not return null nor throws NPE";
case Four:
return "Test that Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)"
+ " does not return null,\n and that"
+ " new CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME)"
+ " does not throw NPE";
case Five:
return "Test that LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME)"
+ "\n does not return null nor throws NPE";
case Six:
return "Test that manager.getLogger(Logger.GLOBAL_LOGGER_NAME)"
+ " returns null\n when manager is not the default"
+ " LogManager instance.\n"
+ "Test adding a new logger named \"global\" in that"
+ " non default instance.";
case Seven: return "Test that manager.getLogger(\"\")"
+ " returns null\n when manager is not the default"
+ " LogManager instance.\n"
+ "Test adding a new logger named \"\" in that"
+ " non default instance.";
default: return "Undefined";
}
}
};
/**
* @param args the command line arguments
*/
public static void main(String[] args) {
Bridge.init();
EnumSet<TestCase> tests = EnumSet.noneOf(TestCase.class);
for (String arg : args) {
tests.add(TestCase.valueOf(arg));
}
if (args.length == 0) {
tests = EnumSet.complementOf(EnumSet.of(TestCase.LoadingMain));
}
final EnumSet<TestCase> loadingTests =
EnumSet.of(TestCase.LoadingApplet, TestCase.LoadingMain);
int testrun = 0;
for (TestCase test : tests) {
if (loadingTests.contains(test)) {
if (testrun > 0) {
throw new UnsupportedOperationException("Test case "
+ test + " must be executed first!");
}
}
System.out.println("Testing "+ test+": ");
System.out.println(test.describe());
try {
test.test();
} catch (Exception x) {
throw new Error(String.valueOf(test)
+ (System.getSecurityManager() == null ? " without " : " with ")
+ "security failed: "+x+"\n "+"FAILED: "+test.describe()+"\n", x);
} finally {
testrun++;
}
Bridge.changeContext();
System.out.println("PASSED: "+ test);
}
}
public static void testLoadingApplet() {
Bridge.changeContext();
Logger bar = new Bridge.CustomLogger("com.foo.Bar");
LogManager.getLogManager().addLogger(bar);
assertNotNull(bar.getParent());
testParent(bar);
testParent(LogManager.getLogManager().getLogger("global"));
testParent(LogManager.getLogManager().getLogger(bar.getName()));
Bridge.desactivate();
Logger foo = new Bridge.CustomLogger("com.foo.Foo");
boolean b = LogManager.getLogManager().addLogger(foo);
assertEquals(Boolean.TRUE, Boolean.valueOf(b));
assertNotNull(foo.getParent());
testParent(foo);
testParent(LogManager.getLogManager().getLogger("global"));
testParent(LogManager.getLogManager().getLogger(foo.getName()));
}
public static void testLoadingMain() {
Bridge.desactivate();
Logger bar = new Bridge.CustomLogger("com.foo.Bar");
LogManager.getLogManager().addLogger(bar);
assertNotNull(bar.getParent());
testParent(bar);
testParent(LogManager.getLogManager().getLogger("global"));
testParent(LogManager.getLogManager().getLogger(bar.getName()));
Bridge.changeContext();
Logger foo = new Bridge.CustomLogger("com.foo.Foo");
boolean b = LogManager.getLogManager().addLogger(foo);
assertEquals(Boolean.TRUE, Boolean.valueOf(b));
assertNotNull(foo.getParent());
testParent(foo);
testParent(LogManager.getLogManager().getLogger("global"));
testParent(LogManager.getLogManager().getLogger(foo.getName()));
}
public static void testOne() {
for (int i=0; i<3 ; i++) {
Logger logger1 = Logger.getAnonymousLogger();
Logger logger1b = Logger.getAnonymousLogger();
Bridge.changeContext();
Logger logger2 = Logger.getAnonymousLogger();
Logger logger2b = Logger.getAnonymousLogger();
Bridge.changeContext();
Logger logger3 = new Bridge.CustomAnonymousLogger();
Logger logger3b = new Bridge.CustomAnonymousLogger();
Bridge.changeContext();
Logger logger4 = new Bridge.CustomAnonymousLogger();
Logger logger4b = new Bridge.CustomAnonymousLogger();
}
}
public static void testTwo() {
for (int i=0; i<3 ; i++) {
Logger logger1 = Logger.getLogger("");
Logger logger1b = Logger.getLogger("");
assertNotNull(logger1);
assertNotNull(logger1b);
assertEquals(logger1, logger1b);
Bridge.changeContext();
Logger logger2 = Logger.getLogger("");
Logger logger2b = Logger.getLogger("");
assertNotNull(logger2);
assertNotNull(logger2b);
assertEquals(logger2, logger2b);
assertEquals(logger1, logger2);
}
}
public static void testThree() {
for (int i=0; i<3 ; i++) {
Logger logger1 = LogManager.getLogManager().getLogger("");
Logger logger1b = LogManager.getLogManager().getLogger("");
assertNotNull(logger1);
assertNotNull(logger1b);
assertEquals(logger1, logger1b);
Bridge.changeContext();
Logger logger2 = LogManager.getLogManager().getLogger("");
Logger logger2b = LogManager.getLogManager().getLogger("");
assertNotNull(logger2);
assertNotNull(logger2b);
assertEquals(logger2, logger2b);
assertEquals(logger1, logger2);
}
}
public static void testFour() {
for (int i=0; i<3 ; i++) {
Logger logger1 = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger1b = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
assertNotNull(logger1);
assertNotNull(logger1b);
assertEquals(logger1, logger1b);
Bridge.changeContext();
Logger logger2 = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger2b = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME);
assertNotNull(logger2);
assertNotNull(logger2b);
assertEquals(logger2, logger2b);
assertEquals(logger1, logger2);
Bridge.changeContext();
Logger logger3 = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger3b = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
Bridge.changeContext();
Logger logger4 = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger4b = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME);
}
}
public static void testFive() {
for (int i=0; i<3 ; i++) {
Logger logger1 = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger1b = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
assertNotNull(logger1);
assertNotNull(logger1b);
assertEquals(logger1, logger1b);
Bridge.changeContext();
Logger logger2 = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger2b = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME);
assertNotNull(logger2);
assertNotNull(logger2b);
assertEquals(logger2, logger2b);
assertEquals(logger1, logger2);
}
}
/**
* This test is designed to test the behavior of additional LogManager instances.
* It must be noted that if the security manager is off, then calling
* Bridge.changeContext() has actually no effect - which explains why we have
* some differences between the cases security manager on & security manager
* off.
**/
public static void testSix() {
for (int i=0; i<3 ; i++) {
Bridge.desactivate();
LogManager manager = new LogManager() {};
Logger logger1 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger1b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
assertNull(logger1);
assertNull(logger1b);
Logger global = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
manager.addLogger(global);
Logger logger2 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger2b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
assertNotNull(logger2);
assertNotNull(logger2b);
assertEquals(logger2, global);
assertEquals(logger2b, global);
assertNull(manager.getLogger(""));
assertNull(manager.getLogger(""));
Bridge.changeContext();
// this is not a supported configuration:
// We are in an applet context with several log managers.
// We however need to check our assumptions...
// Applet context => root logger and global logger are not null.
// root == LogManager.getLogManager().rootLogger
// global == Logger.global
Logger logger3 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger3b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
assertNotNull(logger3);
assertNotNull(logger3b);
Logger expected = (System.getSecurityManager() != null
? Logger.getGlobal()
: global);
assertEquals(logger3, expected); // in applet context, we will not see
// the LogManager's custom global logger added above...
assertEquals(logger3b, expected); // in applet context, we will not see
// the LogManager's custom global logger added above...
Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
manager.addLogger(global2); // adding a global logger will not work in applet context
// we will always get back the global logger.
// this could be considered as a bug...
Logger logger4 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger4b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
assertNotNull(logger4);
assertNotNull(logger4b);
assertEquals(logger4, expected); // adding a global logger will not work in applet context
assertEquals(logger4b, expected); // adding a global logger will not work in applet context
Logger logger5 = manager.getLogger("");
Logger logger5b = manager.getLogger("");
Logger expectedRoot = (System.getSecurityManager() != null
? LogManager.getLogManager().getLogger("")
: null);
assertEquals(logger5, expectedRoot);
assertEquals(logger5b, expectedRoot);
}
}
/**
* This test is designed to test the behavior of additional LogManager instances.
* It must be noted that if the security manager is off, then calling
* Bridge.changeContext() has actually no effect - which explains why we have
* some differences between the cases security manager on & security manager
* off.
**/
public static void testSeven() {
for (int i=0; i<3 ; i++) {
Bridge.desactivate();
LogManager manager = new LogManager() {};
Logger logger1 = manager.getLogger("");
Logger logger1b = manager.getLogger("");
assertNull(logger1);
assertNull(logger1b);
Logger global = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
manager.addLogger(global);
Logger logger2 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger2b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
assertNotNull(logger2);
assertNotNull(logger2b);
assertEquals(logger2, global);
assertEquals(logger2b, global);
Logger logger3 = manager.getLogger("");
Logger logger3b = manager.getLogger("");
assertNull(logger3);
assertNull(logger3b);
Logger root = new Bridge.CustomLogger("");
manager.addLogger(root);
Logger logger4 = manager.getLogger("");
Logger logger4b = manager.getLogger("");
assertNotNull(logger4);
assertNotNull(logger4b);
assertEquals(logger4, root);
assertEquals(logger4b, root);
Bridge.changeContext();
// this is not a supported configuration:
// We are in an applet context with several log managers.
// We haowever need to check our assumptions...
// Applet context => root logger and global logger are not null.
// root == LogManager.getLogManager().rootLogger
// global == Logger.global
Logger logger5 = manager.getLogger("");
Logger logger5b = manager.getLogger("");
Logger expectedRoot = (System.getSecurityManager() != null
? LogManager.getLogManager().getLogger("")
: root);
assertNotNull(logger5);
assertNotNull(logger5b);
assertEquals(logger5, expectedRoot);
assertEquals(logger5b, expectedRoot);
if (System.getSecurityManager() != null) {
assertNotEquals(logger5, root);
assertNotEquals(logger5b, root);
}
Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
manager.addLogger(global2); // adding a global logger will not work in applet context
// we will always get back the global logger.
// this could be considered as a bug...
Logger logger6 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
Logger logger6b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
Logger expectedGlobal = (System.getSecurityManager() != null
? Logger.getGlobal()
: global);
assertNotNull(logger6);
assertNotNull(logger6b);
assertEquals(logger6, expectedGlobal); // adding a global logger will not work in applet context
assertEquals(logger6b, expectedGlobal); // adding a global logger will not work in applet context
Logger root2 = new Bridge.CustomLogger("");
manager.addLogger(root2); // adding a root logger will not work in applet context
// we will always get back the default manager's root logger.
// this could be considered as a bug...
Logger logger7 = manager.getLogger("");
Logger logger7b = manager.getLogger("");
assertNotNull(logger7);
assertNotNull(logger7b);
assertEquals(logger7, expectedRoot); // adding a global logger will not work in applet context
assertEquals(logger7b, expectedRoot); // adding a global logger will not work in applet context
assertNotEquals(logger7, root2);
assertNotEquals(logger7b, root2);
}
}
public static void testParent(Logger logger) {
Logger l = logger;
while (l.getParent() != null) {
l = l.getParent();
}
assertEquals("", l.getName());
}
public static class TestError extends RuntimeException {
public TestError(String msg) {
super(msg);
}
}
public static void assertNotNull(Object obj) {
if (obj == null) throw new NullPointerException();
}
public static void assertNull(Object obj) {
if (obj != null) throw new TestError("Null expected, got "+obj);
}
public static void assertEquals(Object o1, Object o2) {
if (o1 != o2) {
throw new TestError(o1 + " != " + o2);
}
}
public static void assertNotEquals(Object o1, Object o2) {
if (o1 == o2) {
throw new TestError(o1 + " == " + o2);
}
}
}