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