/*
 * 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 8019945
 * @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;

            @Override
            public Object getAppletContext() { return active ? 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(""));

            for (int j = 0; j<3; j++) {
                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 should also be null.

                Logger expected = (System.getSecurityManager() == null ? global : null);
                Logger logger3 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
                Logger logger3b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
                assertEquals(expected, logger3);
                assertEquals(expected, logger3b);
                Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
                manager.addLogger(global2);
                Logger logger4 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
                Logger logger4b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
                assertNotNull(logger4);
                assertNotNull(logger4b);
                expected = (System.getSecurityManager() == null ? global : global2);;
                assertEquals(logger4,  expected);
                assertEquals(logger4b, expected);

                Logger logger5 = manager.getLogger("");
                Logger logger5b = manager.getLogger("");
                Logger expectedRoot = 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);

            for (int j = 0 ; j < 3 ; j++) {
                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 should also be null.

                Logger logger5 = manager.getLogger("");
                Logger logger5b = manager.getLogger("");
                Logger expectedRoot = (System.getSecurityManager() == null ? root : null);
                assertEquals(logger5, expectedRoot);
                assertEquals(logger5b, expectedRoot);

                if (System.getSecurityManager() != null) {
                    assertNull(manager.getLogger(Logger.GLOBAL_LOGGER_NAME));
                } else {
                    assertEquals(global, manager.getLogger(Logger.GLOBAL_LOGGER_NAME));
                }

                Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME);
                manager.addLogger(global2);
                Logger logger6 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
                Logger logger6b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME);
                Logger expectedGlobal = (System.getSecurityManager() == null ? global : global2);

                assertNotNull(logger6);
                assertNotNull(logger6b);
                assertEquals(logger6, expectedGlobal);
                assertEquals(logger6b, expectedGlobal);
                if (System.getSecurityManager() != null) {
                    assertNull(manager.getLogger(""));
                } else {
                    assertEquals(root, manager.getLogger(""));
                }

                Logger root2 = new Bridge.CustomLogger("");
                manager.addLogger(root2);
                expectedRoot = (System.getSecurityManager() == null ? root : root2);
                Logger logger7 = manager.getLogger("");
                Logger logger7b = manager.getLogger("");
                assertNotNull(logger7);
                assertNotNull(logger7b);
                assertEquals(logger7, expectedRoot);
                assertEquals(logger7b, expectedRoot);
            }
        }
    }

    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);
        }
    }
}
