1 /* 2 * Copyright (c) 2015, 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 import java.security.AccessControlException; 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.Collections; 31 import java.util.Enumeration; 32 import java.util.HashMap; 33 import java.util.Map; 34 import java.util.ResourceBundle; 35 import java.util.stream.Stream; 36 import java.util.concurrent.ConcurrentHashMap; 37 import java.util.concurrent.atomic.AtomicBoolean; 38 import java.util.concurrent.atomic.AtomicLong; 39 import java.util.function.Supplier; 40 import java.lang.System.LoggerFinder; 41 import java.lang.System.Logger; 42 import java.lang.System.Logger.Level; 43 44 /** 45 * @test 46 * @bug 8140364 47 * @summary Tests a naive implementation of LoggerFinder, and in particular 48 * the default body of System.Logger methods. 49 * @build AccessSystemLogger BaseLoggerFinderTest CustomSystemClassLoader BaseLoggerFinder TestLoggerFinder 50 * @run driver AccessSystemLogger 51 * @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader BaseLoggerFinderTest NOSECURITY 52 * @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader BaseLoggerFinderTest NOPERMISSIONS 53 * @run main/othervm -Xbootclasspath/a:boot -Djava.system.class.loader=CustomSystemClassLoader BaseLoggerFinderTest WITHPERMISSIONS 54 * @author danielfuchs 55 */ 56 public class BaseLoggerFinderTest { 57 58 static final RuntimePermission LOGGERFINDER_PERMISSION = 59 new RuntimePermission("loggerFinder"); 60 final static boolean VERBOSE = false; 61 static final ThreadLocal<AtomicBoolean> allowControl = new ThreadLocal<AtomicBoolean>() { 62 @Override 63 protected AtomicBoolean initialValue() { 64 return new AtomicBoolean(false); 65 } 66 }; 67 static final ThreadLocal<AtomicBoolean> allowAccess = new ThreadLocal<AtomicBoolean>() { 68 @Override 69 protected AtomicBoolean initialValue() { 70 return new AtomicBoolean(false); 71 } 72 }; 73 74 final static AccessSystemLogger accessSystemLogger = new AccessSystemLogger(); 75 static final Class<?> providerClass; 76 static { 77 try { 78 providerClass = ClassLoader.getSystemClassLoader().loadClass("BaseLoggerFinder"); 79 } catch (ClassNotFoundException ex) { 80 throw new ExceptionInInitializerError(ex); 81 } 82 } 83 84 public static class MyBundle extends ResourceBundle { 85 86 final ConcurrentHashMap<String,String> map = new ConcurrentHashMap<>(); 87 88 @Override 89 protected Object handleGetObject(String key) { 90 if (key.contains(" (translated)")) { 91 throw new RuntimeException("Unexpected key: " + key); 92 } 93 return map.computeIfAbsent(key, k -> k + " (translated)"); 94 } 95 96 @Override 97 public Enumeration<String> getKeys() { 98 return Collections.enumeration(map.keySet()); 99 } 100 101 } 102 public static class MyLoggerBundle extends MyBundle { 103 104 } 105 106 static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS}; 107 108 static void setSecurityManager() { 109 if (System.getSecurityManager() == null) { 110 Policy.setPolicy(new SimplePolicy(allowControl, allowAccess)); 111 System.setSecurityManager(new SecurityManager()); 112 } 113 } 114 115 public static void main(String[] args) { 116 if (args.length == 0) 117 args = new String[] { 118 //"NOSECURITY", 119 "NOPERMISSIONS", 120 "WITHPERMISSIONS" 121 }; 122 123 System.out.println("Using provider class: " + providerClass + "[" + providerClass.getClassLoader() + "]"); 124 125 Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> { 126 TestLoggerFinder provider; 127 switch (testCase) { 128 case NOSECURITY: 129 System.out.println("\n*** Without Security Manager\n"); 130 provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder()); 131 test(provider, true); 132 System.out.println("Tetscase count: " + TestLoggerFinder.sequencer.get()); 133 break; 134 case NOPERMISSIONS: 135 System.out.println("\n*** With Security Manager, without permissions\n"); 136 setSecurityManager(); 137 try { 138 provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder()); 139 throw new RuntimeException("Expected exception not raised"); 140 } catch (AccessControlException x) { 141 if (!LOGGERFINDER_PERMISSION.equals(x.getPermission())) { 142 throw new RuntimeException("Unexpected permission check", x); 143 } 144 final boolean control = allowControl.get().get(); 145 try { 146 allowControl.get().set(true); 147 provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder()); 148 } finally { 149 allowControl.get().set(control); 150 } 151 } 152 test(provider, false); 153 System.out.println("Tetscase count: " + TestLoggerFinder.sequencer.get()); 154 break; 155 case WITHPERMISSIONS: 156 System.out.println("\n*** With Security Manager, with control permission\n"); 157 setSecurityManager(); 158 final boolean control = allowControl.get().get(); 159 try { 160 allowControl.get().set(true); 161 provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder()); 162 test(provider, true); 163 } finally { 164 allowControl.get().set(control); 165 } 166 break; 167 default: 168 throw new RuntimeException("Unknown test case: " + testCase); 169 } 170 }); 171 System.out.println("\nPASSED: Tested " + TestLoggerFinder.sequencer.get() + " cases."); 172 } 173 174 public static void test(TestLoggerFinder provider, boolean hasRequiredPermissions) { 175 176 ResourceBundle loggerBundle = ResourceBundle.getBundle(MyLoggerBundle.class.getName()); 177 final Map<Logger, String> loggerDescMap = new HashMap<>(); 178 179 180 // 1. Test loggers returned by LoggerFinder, both for system callers 181 // and not system callers. 182 TestLoggerFinder.LoggerImpl appLogger1 = null; 183 try { 184 appLogger1 = 185 TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class)); 186 loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class)"); 187 if (!hasRequiredPermissions) { 188 throw new RuntimeException("Managed to obtain a logger without permission"); 189 } 190 } catch (AccessControlException acx) { 191 if (hasRequiredPermissions) { 192 throw new RuntimeException("Unexpected security exception: ", acx); 193 } 194 if (!acx.getPermission().equals(LOGGERFINDER_PERMISSION)) { 195 throw new RuntimeException("Unexpected permission in exception: " + acx, acx); 196 } 197 System.out.println("Got expected exception for logger: " + acx); 198 final boolean old = allowControl.get().get(); 199 allowControl.get().set(true); 200 try { 201 appLogger1 = 202 TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", BaseLoggerFinderTest.class)); 203 loggerDescMap.put(appLogger1, "provider.getLogger(\"foo\", BaseLoggerFinderTest.class)"); 204 } finally { 205 allowControl.get().set(old); 206 } 207 } 208 209 TestLoggerFinder.LoggerImpl sysLogger1 = null; 210 try { 211 sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); 212 loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class)"); 213 if (!hasRequiredPermissions) { 214 throw new RuntimeException("Managed to obtain a system logger without permission"); 215 } 216 } catch (AccessControlException acx) { 217 if (hasRequiredPermissions) { 218 throw new RuntimeException("Unexpected security exception: ", acx); 219 } 220 if (!acx.getPermission().equals(LOGGERFINDER_PERMISSION)) { 221 throw new RuntimeException("Unexpected permission in exception: " + acx, acx); 222 } 223 System.out.println("Got expected exception for system logger: " + acx); 224 final boolean old = allowControl.get().get(); 225 allowControl.get().set(true); 226 try { 227 sysLogger1 = TestLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class)); 228 loggerDescMap.put(sysLogger1, "provider.getLogger(\"foo\", Thread.class)"); 229 } finally { 230 allowControl.get().set(old); 231 } 232 } 233 if (appLogger1 == sysLogger1) { 234 throw new RuntimeException("identical loggers"); 235 } 236 237 if (provider.system.contains(appLogger1)) { 238 throw new RuntimeException("app logger in system map"); 239 } 240 if (!provider.user.contains(appLogger1)) { 241 throw new RuntimeException("app logger not in appplication map"); 242 } 243 if (provider.user.contains(sysLogger1)) { 244 throw new RuntimeException("sys logger in appplication map"); 245 } 246 if (!provider.system.contains(sysLogger1)) { 247 throw new RuntimeException("sys logger not in system map"); 248 } 249 250 testLogger(provider, loggerDescMap, "foo", null, appLogger1, appLogger1); 251 testLogger(provider, loggerDescMap, "foo", null, sysLogger1, sysLogger1); 252 253 // 2. Test localized loggers returned LoggerFinder, both for system 254 // callers and non system callers 255 Logger appLogger2 = null; 256 try { 257 appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class); 258 loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class)"); 259 if (!hasRequiredPermissions) { 260 throw new RuntimeException("Managed to obtain a logger without permission"); 261 } 262 } catch (AccessControlException acx) { 263 if (hasRequiredPermissions) { 264 throw new RuntimeException("Unexpected security exception: ", acx); 265 } 266 if (!acx.getPermission().equals(LOGGERFINDER_PERMISSION)) { 267 throw new RuntimeException("Unexpected permission in exception: " + acx, acx); 268 } 269 System.out.println("Got expected exception for logger: " + acx); 270 final boolean old = allowControl.get().get(); 271 allowControl.get().set(true); 272 try { 273 appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, BaseLoggerFinderTest.class); 274 loggerDescMap.put(appLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, BaseLoggerFinderTest.class)"); 275 } finally { 276 allowControl.get().set(old); 277 } 278 } 279 280 Logger sysLogger2 = null; 281 try { 282 sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); 283 loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class)"); 284 if (!hasRequiredPermissions) { 285 throw new RuntimeException("Managed to obtain a system logger without permission"); 286 } 287 } catch (AccessControlException acx) { 288 if (hasRequiredPermissions) { 289 throw new RuntimeException("Unexpected security exception: ", acx); 290 } 291 if (!acx.getPermission().equals(LOGGERFINDER_PERMISSION)) { 292 throw new RuntimeException("Unexpected permission in exception: " + acx, acx); 293 } 294 System.out.println("Got expected exception for localized system logger: " + acx); 295 final boolean old = allowControl.get().get(); 296 allowControl.get().set(true); 297 try { 298 sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); 299 loggerDescMap.put(sysLogger2, "provider.getLocalizedLogger(\"foo\", loggerBundle, Thread.class))"); 300 } finally { 301 allowControl.get().set(old); 302 } 303 } 304 if (appLogger2 == sysLogger2) { 305 throw new RuntimeException("identical loggers"); 306 } 307 if (appLogger2 == appLogger1) { 308 throw new RuntimeException("identical loggers"); 309 } 310 if (sysLogger2 == sysLogger1) { 311 throw new RuntimeException("identical loggers"); 312 } 313 314 if (provider.system.contains(appLogger2)) { 315 throw new RuntimeException("localized app logger in system map"); 316 } 317 if (provider.user.contains(appLogger2)) { 318 throw new RuntimeException("localized app logger in appplication map"); 319 } 320 if (provider.user.contains(sysLogger2)) { 321 throw new RuntimeException("localized sys logger in appplication map"); 322 } 323 if (provider.system.contains(sysLogger2)) { 324 throw new RuntimeException("localized sys logger not in system map"); 325 } 326 327 testLogger(provider, loggerDescMap, "foo", loggerBundle, appLogger2, appLogger1); 328 testLogger(provider, loggerDescMap, "foo", loggerBundle, sysLogger2, sysLogger1); 329 330 // 3 Test loggers returned by: 331 // 3.1: System.getLogger("foo") 332 Logger appLogger3 = System.getLogger("foo"); 333 loggerDescMap.put(appLogger3, "System.getLogger(\"foo\")"); 334 testLogger(provider, loggerDescMap, "foo", null, appLogger3, appLogger1); 335 336 // 3.2: System.getLogger("foo") 337 // Emulate what System.getLogger() does when the caller is a 338 // platform classes 339 Logger sysLogger3 = accessSystemLogger.getLogger("foo"); 340 loggerDescMap.put(sysLogger3, "AccessSystemLogger.getLogger(\"foo\")"); 341 342 if (appLogger3 == sysLogger3) { 343 throw new RuntimeException("identical loggers"); 344 } 345 346 testLogger(provider, loggerDescMap, "foo", null, sysLogger3, sysLogger1); 347 348 // 4. Test loggers returned by: 349 // 4.1 System.getLogger("foo", loggerBundle) 350 Logger appLogger4 = 351 System.getLogger("foo", loggerBundle); 352 loggerDescMap.put(appLogger4, "System.getLogger(\"foo\", loggerBundle)"); 353 if (appLogger4 == appLogger1) { 354 throw new RuntimeException("identical loggers"); 355 } 356 357 testLogger(provider, loggerDescMap, "foo", loggerBundle, appLogger4, appLogger1); 358 359 // 4.2: System.getLogger("foo", loggerBundle) 360 // Emulate what System.getLogger() does when the caller is a 361 // platform classes 362 Logger sysLogger4 = accessSystemLogger.getLogger("foo", loggerBundle); 363 loggerDescMap.put(sysLogger4, "AccessSystemLogger.getLogger(\"foo\", loggerBundle)"); 364 if (appLogger4 == sysLogger4) { 365 throw new RuntimeException("identical loggers"); 366 } 367 368 testLogger(provider, loggerDescMap, "foo", loggerBundle, sysLogger4, sysLogger1); 369 370 } 371 372 public static class Foo { 373 374 } 375 376 static void verbose(String msg) { 377 if (VERBOSE) { 378 System.out.println(msg); 379 } 380 } 381 382 // Calls the 8 methods defined on Logger and verify the 383 // parameters received by the underlying TestProvider.LoggerImpl 384 // logger. 385 private static void testLogger(TestLoggerFinder provider, 386 Map<Logger, String> loggerDescMap, 387 String name, 388 ResourceBundle loggerBundle, 389 Logger logger, 390 TestLoggerFinder.LoggerImpl sink) { 391 392 System.out.println("Testing " + loggerDescMap.get(logger) + " [" + logger +"]"); 393 AtomicLong sequencer = TestLoggerFinder.sequencer; 394 395 Foo foo = new Foo(); 396 String fooMsg = foo.toString(); 397 for (Level loggerLevel : Level.values()) { 398 sink.level = loggerLevel; 399 for (Level messageLevel : Level.values()) { 400 String desc = "logger.log(messageLevel, foo): loggerLevel=" 401 + loggerLevel+", messageLevel="+messageLevel; 402 TestLoggerFinder.LogEvent expected = 403 TestLoggerFinder.LogEvent.of( 404 sequencer.get(), 405 messageLevel.compareTo(loggerLevel) >= 0, 406 name, messageLevel, (ResourceBundle)null, 407 fooMsg, null, (Throwable)null, (Object[])null); 408 logger.log(messageLevel, foo); 409 if (loggerLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) { 410 if (provider.eventQueue.poll() != null) { 411 throw new RuntimeException("unexpected event in queue for " + desc); 412 } 413 } else { 414 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 415 if (!expected.equals(actual)) { 416 throw new RuntimeException("mismatch for " + desc 417 + "\n\texpected=" + expected 418 + "\n\t actual=" + actual); 419 } else { 420 verbose("Got expected results for " 421 + desc + "\n\t" + expected); 422 } 423 } 424 } 425 } 426 427 String msg = "blah"; 428 for (Level loggerLevel : Level.values()) { 429 sink.level = loggerLevel; 430 for (Level messageLevel : Level.values()) { 431 String desc = "logger.log(messageLevel, \"blah\"): loggerLevel=" 432 + loggerLevel+", messageLevel="+messageLevel; 433 TestLoggerFinder.LogEvent expected = 434 TestLoggerFinder.LogEvent.of( 435 sequencer.get(), 436 messageLevel.compareTo(loggerLevel) >= 0 && loggerLevel != Level.OFF, 437 name, messageLevel, loggerBundle, 438 msg, null, (Throwable)null, (Object[])null); 439 logger.log(messageLevel, msg); 440 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 441 if (!expected.equals(actual)) { 442 throw new RuntimeException("mismatch for " + desc 443 + "\n\texpected=" + expected 444 + "\n\t actual=" + actual); 445 } else { 446 verbose("Got expected results for " 447 + desc + "\n\t" + expected); 448 } 449 } 450 } 451 452 Supplier<String> fooSupplier = new Supplier<String>() { 453 @Override 454 public String get() { 455 return this.toString(); 456 } 457 }; 458 459 for (Level loggerLevel : Level.values()) { 460 sink.level = loggerLevel; 461 for (Level messageLevel : Level.values()) { 462 String desc = "logger.log(messageLevel, fooSupplier): loggerLevel=" 463 + loggerLevel+", messageLevel="+messageLevel; 464 TestLoggerFinder.LogEvent expected = 465 TestLoggerFinder.LogEvent.of( 466 sequencer.get(), 467 messageLevel.compareTo(loggerLevel) >= 0, 468 name, messageLevel, (ResourceBundle)null, 469 fooSupplier.get(), null, 470 (Throwable)null, (Object[])null); 471 logger.log(messageLevel, fooSupplier); 472 if (loggerLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) { 473 if (provider.eventQueue.poll() != null) { 474 throw new RuntimeException("unexpected event in queue for " + desc); 475 } 476 } else { 477 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 478 if (!expected.equals(actual)) { 479 throw new RuntimeException("mismatch for " + desc 480 + "\n\texpected=" + expected 481 + "\n\t actual=" + actual); 482 } else { 483 verbose("Got expected results for " 484 + desc + "\n\t" + expected); 485 } 486 } 487 } 488 } 489 490 String format = "two params [{1} {2}]"; 491 Object arg1 = foo; 492 Object arg2 = msg; 493 for (Level loggerLevel : Level.values()) { 494 sink.level = loggerLevel; 495 for (Level messageLevel : Level.values()) { 496 String desc = "logger.log(messageLevel, format, params...): loggerLevel=" 497 + loggerLevel+", messageLevel="+messageLevel; 498 TestLoggerFinder.LogEvent expected = 499 TestLoggerFinder.LogEvent.of( 500 sequencer.get(), 501 messageLevel.compareTo(loggerLevel) >= 0 && loggerLevel != Level.OFF, 502 name, messageLevel, loggerBundle, 503 format, null, (Throwable)null, new Object[] {foo, msg}); 504 logger.log(messageLevel, format, foo, msg); 505 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 506 if (!expected.equals(actual)) { 507 throw new RuntimeException("mismatch for " + desc 508 + "\n\texpected=" + expected 509 + "\n\t actual=" + actual); 510 } else { 511 verbose("Got expected results for " 512 + desc + "\n\t" + expected); 513 } 514 } 515 } 516 517 Throwable thrown = new Exception("OK: log me!"); 518 for (Level loggerLevel : Level.values()) { 519 sink.level = loggerLevel; 520 for (Level messageLevel : Level.values()) { 521 String desc = "logger.log(messageLevel, \"blah\", thrown): loggerLevel=" 522 + loggerLevel+", messageLevel="+messageLevel; 523 TestLoggerFinder.LogEvent expected = 524 TestLoggerFinder.LogEvent.of( 525 sequencer.get(), 526 messageLevel.compareTo(loggerLevel) >= 0 && loggerLevel != Level.OFF, 527 name, messageLevel, loggerBundle, 528 msg, null, thrown, (Object[]) null); 529 logger.log(messageLevel, msg, thrown); 530 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 531 if (!expected.equals(actual)) { 532 throw new RuntimeException("mismatch for " + desc 533 + "\n\texpected=" + expected 534 + "\n\t actual=" + actual); 535 } else { 536 verbose("Got expected results for " 537 + desc + "\n\t" + expected); 538 } 539 } 540 } 541 542 543 for (Level loggerLevel : Level.values()) { 544 sink.level = loggerLevel; 545 for (Level messageLevel : Level.values()) { 546 String desc = "logger.log(messageLevel, thrown, fooSupplier): loggerLevel=" 547 + loggerLevel+", messageLevel="+messageLevel; 548 TestLoggerFinder.LogEvent expected = 549 TestLoggerFinder.LogEvent.of( 550 sequencer.get(), 551 messageLevel.compareTo(loggerLevel) >= 0, 552 name, messageLevel, (ResourceBundle)null, 553 fooSupplier.get(), null, 554 (Throwable)thrown, (Object[])null); 555 logger.log(messageLevel, fooSupplier, thrown); 556 if (loggerLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) { 557 if (provider.eventQueue.poll() != null) { 558 throw new RuntimeException("unexpected event in queue for " + desc); 559 } 560 } else { 561 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 562 if (!expected.equals(actual)) { 563 throw new RuntimeException("mismatch for " + desc 564 + "\n\texpected=" + expected 565 + "\n\t actual=" + actual); 566 } else { 567 verbose("Got expected results for " 568 + desc + "\n\t" + expected); 569 } 570 } 571 } 572 } 573 574 ResourceBundle bundle = ResourceBundle.getBundle(MyBundle.class.getName()); 575 for (Level loggerLevel : Level.values()) { 576 sink.level = loggerLevel; 577 for (Level messageLevel : Level.values()) { 578 String desc = "logger.log(messageLevel, bundle, format, params...): loggerLevel=" 579 + loggerLevel+", messageLevel="+messageLevel; 580 TestLoggerFinder.LogEvent expected = 581 TestLoggerFinder.LogEvent.of( 582 sequencer.get(), 583 messageLevel.compareTo(loggerLevel) >= 0 && loggerLevel != Level.OFF, 584 name, messageLevel, bundle, 585 format, null, (Throwable)null, new Object[] {foo, msg}); 586 logger.log(messageLevel, bundle, format, foo, msg); 587 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 588 if (!expected.equals(actual)) { 589 throw new RuntimeException("mismatch for " + desc 590 + "\n\texpected=" + expected 591 + "\n\t actual=" + actual); 592 } else { 593 verbose("Got expected results for " 594 + desc + "\n\t" + expected); 595 } 596 } 597 } 598 599 for (Level loggerLevel : Level.values()) { 600 sink.level = loggerLevel; 601 for (Level messageLevel : Level.values()) { 602 String desc = "logger.log(messageLevel, bundle, \"blah\", thrown): loggerLevel=" 603 + loggerLevel+", messageLevel="+messageLevel; 604 TestLoggerFinder.LogEvent expected = 605 TestLoggerFinder.LogEvent.of( 606 sequencer.get(), 607 messageLevel.compareTo(loggerLevel) >= 0 && loggerLevel != Level.OFF, 608 name, messageLevel, bundle, 609 msg, null, thrown, (Object[]) null); 610 logger.log(messageLevel, bundle, msg, thrown); 611 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 612 if (!expected.equals(actual)) { 613 throw new RuntimeException("mismatch for " + desc 614 + "\n\texpected=" + expected 615 + "\n\t actual=" + actual); 616 } else { 617 verbose("Got expected results for " 618 + desc + "\n\t" + expected); 619 } 620 } 621 } 622 } 623 624 final static class PermissionsBuilder { 625 final Permissions perms; 626 public PermissionsBuilder() { 627 this(new Permissions()); 628 } 629 public PermissionsBuilder(Permissions perms) { 630 this.perms = perms; 631 } 632 public PermissionsBuilder add(Permission p) { 633 perms.add(p); 634 return this; 635 } 636 public PermissionsBuilder addAll(PermissionCollection col) { 637 if (col != null) { 638 for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) { 639 perms.add(e.nextElement()); 640 } 641 } 642 return this; 643 } 644 public Permissions toPermissions() { 645 final PermissionsBuilder builder = new PermissionsBuilder(); 646 builder.addAll(perms); 647 return builder.perms; 648 } 649 } 650 651 public static class SimplePolicy extends Policy { 652 final static RuntimePermission CONTROL = LOGGERFINDER_PERMISSION; 653 final static RuntimePermission ACCESS = new RuntimePermission("accessClassInPackage.jdk.internal.logger"); 654 655 final Permissions permissions; 656 final ThreadLocal<AtomicBoolean> allowControl; 657 final ThreadLocal<AtomicBoolean> allowAccess; 658 public SimplePolicy(ThreadLocal<AtomicBoolean> allowControl, ThreadLocal<AtomicBoolean> allowAccess) { 659 this.allowControl = allowControl; 660 this.allowAccess = allowAccess; 661 permissions = new Permissions(); 662 } 663 664 Permissions getPermissions() { 665 if (allowControl.get().get() || allowAccess.get().get()) { 666 PermissionsBuilder builder = new PermissionsBuilder() 667 .addAll(permissions); 668 if (allowControl.get().get()) { 669 builder.add(CONTROL); 670 } 671 if (allowAccess.get().get()) { 672 builder.add(ACCESS); 673 } 674 return builder.toPermissions(); 675 } 676 return permissions; 677 } 678 679 @Override 680 public boolean implies(ProtectionDomain domain, Permission permission) { 681 return getPermissions().implies(permission); 682 } 683 684 @Override 685 public PermissionCollection getPermissions(CodeSource codesource) { 686 return new PermissionsBuilder().addAll(getPermissions()).toPermissions(); 687 } 688 689 @Override 690 public PermissionCollection getPermissions(ProtectionDomain domain) { 691 return new PermissionsBuilder().addAll(getPermissions()).toPermissions(); 692 } 693 } 694 }