1 /* 2 * Copyright (c) 2013, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 24 import java.security.CodeSource; 25 import java.security.Permission; 26 import java.security.PermissionCollection; 27 import java.security.Permissions; 28 import java.security.Policy; 29 import java.security.ProtectionDomain; 30 import java.util.EnumSet; 31 import java.util.HashMap; 32 import java.util.Map; 33 import java.util.logging.LogManager; 34 import java.util.logging.Logger; 35 import java.util.logging.LoggingPermission; 36 import sun.misc.JavaAWTAccess; 37 import sun.misc.SharedSecrets; 38 39 /* 40 * @test 41 * @bug 8017174 8010727 8019945 42 * @summary NPE when using Logger.getAnonymousLogger or 43 * LogManager.getLogManager().getLogger 44 * 45 * @modules java.base/sun.misc 46 * @run main/othervm -Dtest.security=off TestAppletLoggerContext LoadingApplet 47 * @run main/othervm -Dtest.security=on TestAppletLoggerContext LoadingApplet 48 * @run main/othervm -Dtest.security=off TestAppletLoggerContext LoadingMain 49 * @run main/othervm -Dtest.security=on TestAppletLoggerContext LoadingMain 50 * @run main/othervm -Dtest.security=off TestAppletLoggerContext One 51 * @run main/othervm -Dtest.security=on TestAppletLoggerContext One 52 * @run main/othervm -Dtest.security=off TestAppletLoggerContext Two 53 * @run main/othervm -Dtest.security=on TestAppletLoggerContext Two 54 * @run main/othervm -Dtest.security=off TestAppletLoggerContext Three 55 * @run main/othervm -Dtest.security=on TestAppletLoggerContext Three 56 * @run main/othervm -Dtest.security=off TestAppletLoggerContext Four 57 * @run main/othervm -Dtest.security=on TestAppletLoggerContext Four 58 * @run main/othervm -Dtest.security=off TestAppletLoggerContext Five 59 * @run main/othervm -Dtest.security=on TestAppletLoggerContext Five 60 * @run main/othervm -Dtest.security=off TestAppletLoggerContext Six 61 * @run main/othervm -Dtest.security=on TestAppletLoggerContext Six 62 * @run main/othervm -Dtest.security=off TestAppletLoggerContext Seven 63 * @run main/othervm -Dtest.security=on TestAppletLoggerContext Seven 64 * @run main/othervm -Dtest.security=off TestAppletLoggerContext 65 * @run main/othervm -Dtest.security=on TestAppletLoggerContext 66 */ 67 68 // NOTE: We run in other VM in order to 1. switch security manager and 2. cause 69 // LogManager class to be loaded anew. 70 public class TestAppletLoggerContext { 71 72 // Avoids the hassle of dealing with files and system props... 73 static class SimplePolicy extends Policy { 74 private final Permissions perms; 75 public SimplePolicy(Permission... permissions) { 76 perms = new Permissions(); 77 for (Permission permission : permissions) { 78 perms.add(permission); 79 } 80 } 81 @Override 82 public PermissionCollection getPermissions(CodeSource cs) { 83 return perms; 84 } 85 @Override 86 public PermissionCollection getPermissions(ProtectionDomain pd) { 87 return perms; 88 } 89 @Override 90 public boolean implies(ProtectionDomain pd, Permission p) { 91 return perms.implies(p); 92 } 93 } 94 95 // The bridge class initializes the logging system. 96 // It stubs the applet context in order to simulate context changes. 97 // 98 public static class Bridge { 99 100 private static class JavaAWTAccessStub implements JavaAWTAccess { 101 boolean active = true; 102 103 private static class TestExc { 104 private final Map<Object, Object> map = new HashMap<>(); 105 void put(Object key, Object v) { map.put(key, v); } 106 Object get(Object key) { return map.get(key); } 107 void remove(Object o) { map.remove(o); } 108 public static TestExc exc(Object o) { 109 return TestExc.class.cast(o); 110 } 111 } 112 113 TestExc exc; 114 115 @Override 116 public Object getAppletContext() { return active ? exc : null; } 117 } 118 119 final static JavaAWTAccessStub javaAwtAccess = new JavaAWTAccessStub(); 120 public static void init() { 121 SharedSecrets.setJavaAWTAccess(javaAwtAccess); 122 if (System.getProperty("test.security", "on").equals("on")) { 123 Policy p = new SimplePolicy(new LoggingPermission("control", null), 124 new RuntimePermission("setContextClassLoader"), 125 new RuntimePermission("shutdownHooks")); 126 Policy.setPolicy(p); 127 System.setSecurityManager(new SecurityManager()); 128 } 129 } 130 131 public static void changeContext() { 132 System.out.println("... Switching to a new applet context ..."); 133 javaAwtAccess.active = true; 134 javaAwtAccess.exc = new JavaAWTAccessStub.TestExc(); 135 } 136 137 public static void desactivate() { 138 System.out.println("... Running with no applet context ..."); 139 javaAwtAccess.exc = null; 140 javaAwtAccess.active = false; 141 } 142 143 public static class CustomAnonymousLogger extends Logger { 144 public CustomAnonymousLogger() { 145 this(""); 146 } 147 public CustomAnonymousLogger(String name) { 148 super(null, null); 149 System.out.println( " LogManager: " +LogManager.getLogManager()); 150 System.out.println( " getLogger: " +LogManager.getLogManager().getLogger(name)); 151 setParent(LogManager.getLogManager().getLogger(name)); 152 } 153 } 154 155 public static class CustomLogger extends Logger { 156 CustomLogger(String name) { 157 super(name, null); 158 } 159 } 160 } 161 162 public static enum TestCase { 163 LoadingApplet, LoadingMain, One, Two, Three, Four, Five, Six, Seven; 164 public void test() { 165 switch(this) { 166 // When run - each of these two tests must be 167 // run before any other tests and before each other. 168 case LoadingApplet: testLoadingApplet(); break; 169 case LoadingMain: testLoadingMain(); break; 170 case One: testOne(); break; 171 case Two: testTwo(); break; 172 case Three: testThree(); break; 173 case Four: testFour(); break; 174 case Five: testFive(); break; 175 case Six: testSix(); break; 176 case Seven: testSeven(); break; 177 } 178 } 179 public String describe() { 180 switch(this) { 181 case LoadingApplet: 182 return "Test that when the LogManager class is" 183 + " loaded in an applet thread first," 184 + "\n all LoggerContexts are correctly initialized"; 185 case LoadingMain: 186 return "Test that when the LogManager class is" 187 + " loaded in the main thread first," 188 + "\n all LoggerContexts are correctly initialized"; 189 case One: 190 return "Test that Logger.getAnonymousLogger()" 191 + " and new CustomAnonymousLogger() don't throw NPE"; 192 case Two: 193 return "Test that Logger.getLogger(\"\")" 194 + " does not return null nor throws NPE"; 195 case Three: 196 return "Test that LogManager.getLogManager().getLogger(\"\")" 197 + " does not return null nor throws NPE"; 198 case Four: 199 return "Test that Logger.getLogger(Logger.GLOBAL_LOGGER_NAME)" 200 + " does not return null,\n and that" 201 + " new CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME)" 202 + " does not throw NPE"; 203 case Five: 204 return "Test that LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME)" 205 + "\n does not return null nor throws NPE"; 206 case Six: 207 return "Test that manager.getLogger(Logger.GLOBAL_LOGGER_NAME)" 208 + " returns null\n when manager is not the default" 209 + " LogManager instance.\n" 210 + "Test adding a new logger named \"global\" in that" 211 + " non default instance."; 212 case Seven: return "Test that manager.getLogger(\"\")" 213 + " returns null\n when manager is not the default" 214 + " LogManager instance.\n" 215 + "Test adding a new logger named \"\" in that" 216 + " non default instance."; 217 default: return "Undefined"; 218 } 219 } 220 }; 221 222 /** 223 * @param args the command line arguments 224 */ 225 public static void main(String[] args) { 226 Bridge.init(); 227 EnumSet<TestCase> tests = EnumSet.noneOf(TestCase.class); 228 for (String arg : args) { 229 tests.add(TestCase.valueOf(arg)); 230 } 231 if (args.length == 0) { 232 tests = EnumSet.complementOf(EnumSet.of(TestCase.LoadingMain)); 233 } 234 final EnumSet<TestCase> loadingTests = 235 EnumSet.of(TestCase.LoadingApplet, TestCase.LoadingMain); 236 int testrun = 0; 237 for (TestCase test : tests) { 238 if (loadingTests.contains(test)) { 239 if (testrun > 0) { 240 throw new UnsupportedOperationException("Test case " 241 + test + " must be executed first!"); 242 } 243 } 244 System.out.println("Testing "+ test+": "); 245 System.out.println(test.describe()); 246 try { 247 test.test(); 248 } catch (Exception x) { 249 throw new Error(String.valueOf(test) 250 + (System.getSecurityManager() == null ? " without " : " with ") 251 + "security failed: "+x+"\n "+"FAILED: "+test.describe()+"\n", x); 252 } finally { 253 testrun++; 254 } 255 Bridge.changeContext(); 256 System.out.println("PASSED: "+ test); 257 } 258 } 259 260 public static void testLoadingApplet() { 261 Bridge.changeContext(); 262 263 Logger bar = new Bridge.CustomLogger("com.foo.Bar"); 264 LogManager.getLogManager().addLogger(bar); 265 assertNotNull(bar.getParent()); 266 testParent(bar); 267 testParent(LogManager.getLogManager().getLogger("global")); 268 testParent(LogManager.getLogManager().getLogger(bar.getName())); 269 270 Bridge.desactivate(); 271 272 Logger foo = new Bridge.CustomLogger("com.foo.Foo"); 273 boolean b = LogManager.getLogManager().addLogger(foo); 274 assertEquals(Boolean.TRUE, Boolean.valueOf(b)); 275 assertNotNull(foo.getParent()); 276 testParent(foo); 277 testParent(LogManager.getLogManager().getLogger("global")); 278 testParent(LogManager.getLogManager().getLogger(foo.getName())); 279 } 280 281 public static void testLoadingMain() { 282 Bridge.desactivate(); 283 284 Logger bar = new Bridge.CustomLogger("com.foo.Bar"); 285 LogManager.getLogManager().addLogger(bar); 286 assertNotNull(bar.getParent()); 287 testParent(bar); 288 testParent(LogManager.getLogManager().getLogger("global")); 289 testParent(LogManager.getLogManager().getLogger(bar.getName())); 290 291 Bridge.changeContext(); 292 293 Logger foo = new Bridge.CustomLogger("com.foo.Foo"); 294 boolean b = LogManager.getLogManager().addLogger(foo); 295 assertEquals(Boolean.TRUE, Boolean.valueOf(b)); 296 assertNotNull(foo.getParent()); 297 testParent(foo); 298 testParent(LogManager.getLogManager().getLogger("global")); 299 testParent(LogManager.getLogManager().getLogger(foo.getName())); 300 301 } 302 303 public static void testOne() { 304 for (int i=0; i<3 ; i++) { 305 Logger logger1 = Logger.getAnonymousLogger(); 306 Logger logger1b = Logger.getAnonymousLogger(); 307 Bridge.changeContext(); 308 Logger logger2 = Logger.getAnonymousLogger(); 309 Logger logger2b = Logger.getAnonymousLogger(); 310 Bridge.changeContext(); 311 Logger logger3 = new Bridge.CustomAnonymousLogger(); 312 Logger logger3b = new Bridge.CustomAnonymousLogger(); 313 Bridge.changeContext(); 314 Logger logger4 = new Bridge.CustomAnonymousLogger(); 315 Logger logger4b = new Bridge.CustomAnonymousLogger(); 316 } 317 } 318 319 320 public static void testTwo() { 321 for (int i=0; i<3 ; i++) { 322 Logger logger1 = Logger.getLogger(""); 323 Logger logger1b = Logger.getLogger(""); 324 assertNotNull(logger1); 325 assertNotNull(logger1b); 326 assertEquals(logger1, logger1b); 327 Bridge.changeContext(); 328 Logger logger2 = Logger.getLogger(""); 329 Logger logger2b = Logger.getLogger(""); 330 assertNotNull(logger2); 331 assertNotNull(logger2b); 332 assertEquals(logger2, logger2b); 333 assertEquals(logger1, logger2); 334 } 335 } 336 337 public static void testThree() { 338 for (int i=0; i<3 ; i++) { 339 Logger logger1 = LogManager.getLogManager().getLogger(""); 340 Logger logger1b = LogManager.getLogManager().getLogger(""); 341 assertNotNull(logger1); 342 assertNotNull(logger1b); 343 assertEquals(logger1, logger1b); 344 Bridge.changeContext(); 345 Logger logger2 = LogManager.getLogManager().getLogger(""); 346 Logger logger2b = LogManager.getLogManager().getLogger(""); 347 assertNotNull(logger2); 348 assertNotNull(logger2b); 349 assertEquals(logger2, logger2b); 350 assertEquals(logger1, logger2); 351 } 352 } 353 354 public static void testFour() { 355 for (int i=0; i<3 ; i++) { 356 Logger logger1 = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); 357 Logger logger1b = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); 358 assertNotNull(logger1); 359 assertNotNull(logger1b); 360 assertEquals(logger1, logger1b); 361 Bridge.changeContext(); 362 363 Logger logger2 = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); 364 Logger logger2b = Logger.getLogger(Logger.GLOBAL_LOGGER_NAME); 365 assertNotNull(logger2); 366 assertNotNull(logger2b); 367 assertEquals(logger2, logger2b); 368 369 assertEquals(logger1, logger2); 370 371 Bridge.changeContext(); 372 Logger logger3 = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME); 373 Logger logger3b = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME); 374 Bridge.changeContext(); 375 Logger logger4 = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME); 376 Logger logger4b = new Bridge.CustomAnonymousLogger(Logger.GLOBAL_LOGGER_NAME); 377 } 378 } 379 380 public static void testFive() { 381 for (int i=0; i<3 ; i++) { 382 Logger logger1 = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME); 383 Logger logger1b = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME); 384 assertNotNull(logger1); 385 assertNotNull(logger1b); 386 assertEquals(logger1, logger1b); 387 388 Bridge.changeContext(); 389 390 Logger logger2 = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME); 391 Logger logger2b = LogManager.getLogManager().getLogger(Logger.GLOBAL_LOGGER_NAME); 392 assertNotNull(logger2); 393 assertNotNull(logger2b); 394 assertEquals(logger2, logger2b); 395 396 assertEquals(logger1, logger2); 397 } 398 } 399 400 /** 401 * This test is designed to test the behavior of additional LogManager instances. 402 * It must be noted that if the security manager is off, then calling 403 * Bridge.changeContext() has actually no effect - which explains why we have 404 * some differences between the cases security manager on & security manager 405 * off. 406 **/ 407 public static void testSix() { 408 for (int i=0; i<3 ; i++) { 409 Bridge.desactivate(); 410 LogManager manager = new LogManager() {}; 411 Logger logger1 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 412 Logger logger1b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 413 assertNull(logger1); 414 assertNull(logger1b); 415 Logger global = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME); 416 manager.addLogger(global); 417 Logger logger2 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 418 Logger logger2b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 419 assertNotNull(logger2); 420 assertNotNull(logger2b); 421 assertEquals(logger2, global); 422 assertEquals(logger2b, global); 423 assertNull(manager.getLogger("")); 424 assertNull(manager.getLogger("")); 425 426 for (int j = 0; j<3; j++) { 427 Bridge.changeContext(); 428 429 // this is not a supported configuration: 430 // We are in an applet context with several log managers. 431 // We however need to check our assumptions... 432 433 // Applet context => root logger and global logger should also be null. 434 435 Logger expected = (System.getSecurityManager() == null ? global : null); 436 Logger logger3 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 437 Logger logger3b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 438 assertEquals(expected, logger3); 439 assertEquals(expected, logger3b); 440 Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME); 441 manager.addLogger(global2); 442 Logger logger4 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 443 Logger logger4b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 444 assertNotNull(logger4); 445 assertNotNull(logger4b); 446 expected = (System.getSecurityManager() == null ? global : global2);; 447 assertEquals(logger4, expected); 448 assertEquals(logger4b, expected); 449 450 Logger logger5 = manager.getLogger(""); 451 Logger logger5b = manager.getLogger(""); 452 Logger expectedRoot = null; 453 assertEquals(logger5, expectedRoot); 454 assertEquals(logger5b, expectedRoot); 455 } 456 457 } 458 } 459 460 /** 461 * This test is designed to test the behavior of additional LogManager instances. 462 * It must be noted that if the security manager is off, then calling 463 * Bridge.changeContext() has actually no effect - which explains why we have 464 * some differences between the cases security manager on & security manager 465 * off. 466 **/ 467 public static void testSeven() { 468 for (int i=0; i<3 ; i++) { 469 Bridge.desactivate(); 470 LogManager manager = new LogManager() {}; 471 Logger logger1 = manager.getLogger(""); 472 Logger logger1b = manager.getLogger(""); 473 assertNull(logger1); 474 assertNull(logger1b); 475 Logger global = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME); 476 manager.addLogger(global); 477 Logger logger2 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 478 Logger logger2b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 479 assertNotNull(logger2); 480 assertNotNull(logger2b); 481 assertEquals(logger2, global); 482 assertEquals(logger2b, global); 483 Logger logger3 = manager.getLogger(""); 484 Logger logger3b = manager.getLogger(""); 485 assertNull(logger3); 486 assertNull(logger3b); 487 Logger root = new Bridge.CustomLogger(""); 488 manager.addLogger(root); 489 Logger logger4 = manager.getLogger(""); 490 Logger logger4b = manager.getLogger(""); 491 assertNotNull(logger4); 492 assertNotNull(logger4b); 493 assertEquals(logger4, root); 494 assertEquals(logger4b, root); 495 496 for (int j = 0 ; j < 3 ; j++) { 497 Bridge.changeContext(); 498 499 // this is not a supported configuration: 500 // We are in an applet context with several log managers. 501 // We however need to check our assumptions... 502 503 // Applet context => root logger and global logger should also be null. 504 505 Logger logger5 = manager.getLogger(""); 506 Logger logger5b = manager.getLogger(""); 507 Logger expectedRoot = (System.getSecurityManager() == null ? root : null); 508 assertEquals(logger5, expectedRoot); 509 assertEquals(logger5b, expectedRoot); 510 511 if (System.getSecurityManager() != null) { 512 assertNull(manager.getLogger(Logger.GLOBAL_LOGGER_NAME)); 513 } else { 514 assertEquals(global, manager.getLogger(Logger.GLOBAL_LOGGER_NAME)); 515 } 516 517 Logger global2 = new Bridge.CustomLogger(Logger.GLOBAL_LOGGER_NAME); 518 manager.addLogger(global2); 519 Logger logger6 = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 520 Logger logger6b = manager.getLogger(Logger.GLOBAL_LOGGER_NAME); 521 Logger expectedGlobal = (System.getSecurityManager() == null ? global : global2); 522 523 assertNotNull(logger6); 524 assertNotNull(logger6b); 525 assertEquals(logger6, expectedGlobal); 526 assertEquals(logger6b, expectedGlobal); 527 if (System.getSecurityManager() != null) { 528 assertNull(manager.getLogger("")); 529 } else { 530 assertEquals(root, manager.getLogger("")); 531 } 532 533 Logger root2 = new Bridge.CustomLogger(""); 534 manager.addLogger(root2); 535 expectedRoot = (System.getSecurityManager() == null ? root : root2); 536 Logger logger7 = manager.getLogger(""); 537 Logger logger7b = manager.getLogger(""); 538 assertNotNull(logger7); 539 assertNotNull(logger7b); 540 assertEquals(logger7, expectedRoot); 541 assertEquals(logger7b, expectedRoot); 542 } 543 } 544 } 545 546 public static void testParent(Logger logger) { 547 Logger l = logger; 548 while (l.getParent() != null) { 549 l = l.getParent(); 550 } 551 assertEquals("", l.getName()); 552 } 553 554 public static class TestError extends RuntimeException { 555 public TestError(String msg) { 556 super(msg); 557 } 558 } 559 560 public static void assertNotNull(Object obj) { 561 if (obj == null) throw new NullPointerException(); 562 } 563 564 public static void assertNull(Object obj) { 565 if (obj != null) throw new TestError("Null expected, got "+obj); 566 } 567 568 public static void assertEquals(Object o1, Object o2) { 569 if (o1 != o2) { 570 throw new TestError(o1 + " != " + o2); 571 } 572 } 573 574 public static void assertNotEquals(Object o1, Object o2) { 575 if (o1 == o2) { 576 throw new TestError(o1 + " == " + o2); 577 } 578 } 579 }