--- a/jdk/src/share/classes/java/util/logging/LogManager.java Mon Jul 01 17:46:12 2013 -0700
+++ b/jdk/src/share/classes/java/util/logging/LogManager.java Tue Jul 02 11:30:31 2013 +0200
@@ -193,13 +193,22 @@
// 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 @@
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 @@
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 @@
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 @@
return logger;
}
- synchronized void ensureRootLogger(Logger logger) {
- if (logger.getName().isEmpty())
- return;
+ // 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.
- // during initialization, rootLogger is null when
- // instantiating itself RootLogger
- if (findLogger("") == null && manager.rootLogger != null) {
- addLocalLogger(manager.rootLogger);
+ // 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 @@
}
synchronized Enumeration<String> getLoggerNames() {
+ // ensure that this context is properly initialized before
+ // returning logger names.
+ ensureInitialized();
return namedLoggers.keys();
}
--- /dev/null Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/util/logging/TestAppletLoggerContext.java Tue Jul 02 11:30:31 2013 +0200
@@ -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);
+ }
+ }
+}