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