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