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