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