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