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, Class<?> caller); 331 } 332 333 public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder { 334 @Override 335 public Logger getLogger(String name, Class<?> 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)); 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(provider.getLogger("foo", Thread.class)); 446 } finally { 447 allowControl.get().set(before); 448 } 449 450 if (hasRequiredPermissions && appSink == sysSink) { 451 throw new RuntimeException("identical loggers"); 452 } 453 454 if (provider.system.contains(appSink)) { 455 throw new RuntimeException("app logger in system map"); 456 } 457 if (!provider.user.contains(appSink)) { 458 throw new RuntimeException("app logger not in appplication map"); 459 } 460 if (hasRequiredPermissions && provider.user.contains(sysSink)) { 461 throw new RuntimeException("sys logger in appplication map"); 462 } 463 if (hasRequiredPermissions && !provider.system.contains(sysSink)) { 464 throw new RuntimeException("sys logger not in system map"); 465 } 466 467 PlatformLogger platform = getPlatformLogger("foo"); 468 loggerDescMap.put(platform, "PlatformLogger.getLogger(\"foo\")"); 469 470 testLogger(provider, loggerDescMap, "foo", null, platform, sysSink); 471 } 472 473 public static class Foo { 474 475 } 476 477 static void verbose(String msg) { 478 if (VERBOSE) { 479 System.out.println(msg); 480 } 481 } 482 483 static void checkLogEvent(TestLoggerFinder provider, String desc, 484 TestLoggerFinder.LogEvent expected) { 485 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 486 if (!expected.equals(actual)) { 487 throw new RuntimeException("mismatch for " + desc 488 + "\n\texpected=" + expected 489 + "\n\t actual=" + actual); 490 } else { 491 verbose("Got expected results for " 492 + desc + "\n\t" + expected); 493 } 494 } 495 496 static void checkLogEvent(TestLoggerFinder provider, String desc, 497 TestLoggerFinder.LogEvent expected, boolean expectNotNull) { 498 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 499 if (actual == null && !expectNotNull) return; 500 if (actual != null && !expectNotNull) { 501 throw new RuntimeException("Unexpected log event found for " + desc 502 + "\n\tgot: " + actual); 503 } 504 if (!expected.equals(actual)) { 505 throw new RuntimeException("mismatch for " + desc 506 + "\n\texpected=" + expected 507 + "\n\t actual=" + actual); 508 } else { 509 verbose("Got expected results for " 510 + desc + "\n\t" + expected); 511 } 512 } 513 514 // Calls the methods defined on LogProducer and verify the 515 // parameters received by the underlying TestLoggerFinder.LoggerImpl 516 // logger. 517 private static void testLogger(TestLoggerFinder provider, 518 Map<PlatformLogger, String> loggerDescMap, 519 String name, 520 ResourceBundle loggerBundle, 521 PlatformLogger logger, 522 TestLoggerFinder.LoggerImpl sink) { 523 524 System.out.println("Testing " + loggerDescMap.get(logger)); 525 526 Foo foo = new Foo(); 527 String fooMsg = foo.toString(); 528 System.out.println("\tlogger.<level>(fooMsg)"); 529 for (Level loggerLevel : Level.values()) { 530 sink.level = loggerLevel; 531 for (PlatformLogger.Level messageLevel :julLevels) { 532 Level expectedMessageLevel = julToSpiMap.get(messageLevel); 533 TestLoggerFinder.LogEvent expected = 534 TestLoggerFinder.LogEvent.of( 535 sequencer.get(), 536 loggerLevel != Level.OFF && expectedMessageLevel.compareTo(loggerLevel) >= 0, 537 name, expectedMessageLevel, loggerBundle, 538 fooMsg, null, (Throwable)null, (Object[])null); 539 String desc2 = "logger." + messageLevel.toString().toLowerCase() 540 + "(fooMsg): loggerLevel=" 541 + loggerLevel+", messageLevel="+messageLevel; 542 if (messageLevel == PlatformLogger.Level.FINEST) { 543 logger.finest(fooMsg); 544 checkLogEvent(provider, desc2, expected); 545 } else if (messageLevel == PlatformLogger.Level.FINER) { 546 logger.finer(fooMsg); 547 checkLogEvent(provider, desc2, expected); 548 } else if (messageLevel == PlatformLogger.Level.FINE) { 549 logger.fine(fooMsg); 550 checkLogEvent(provider, desc2, expected); 551 } else if (messageLevel == PlatformLogger.Level.CONFIG) { 552 logger.config(fooMsg); 553 checkLogEvent(provider, desc2, expected); 554 } else if (messageLevel == PlatformLogger.Level.INFO) { 555 logger.info(fooMsg); 556 checkLogEvent(provider, desc2, expected); 557 } else if (messageLevel == PlatformLogger.Level.WARNING) { 558 logger.warning(fooMsg); 559 checkLogEvent(provider, desc2, expected); 560 } else if (messageLevel == PlatformLogger.Level.SEVERE) { 561 logger.severe(fooMsg); 562 checkLogEvent(provider, desc2, expected); 563 } 564 } 565 } 566 567 Throwable thrown = new Exception("OK: log me!"); 568 System.out.println("\tlogger.<level>(msg, thrown)"); 569 for (Level loggerLevel : Level.values()) { 570 sink.level = loggerLevel; 571 for (PlatformLogger.Level messageLevel :julLevels) { 572 Level expectedMessageLevel = julToSpiMap.get(messageLevel); 573 TestLoggerFinder.LogEvent expected = 574 TestLoggerFinder.LogEvent.of( 575 sequencer.get(), 576 loggerLevel != Level.OFF && expectedMessageLevel.compareTo(loggerLevel) >= 0, 577 name, expectedMessageLevel, (ResourceBundle) null, 578 fooMsg, null, (Throwable)thrown, (Object[])null); 579 String desc2 = "logger." + messageLevel.toString().toLowerCase() 580 + "(msg, thrown): loggerLevel=" 581 + loggerLevel+", messageLevel="+messageLevel; 582 if (messageLevel == PlatformLogger.Level.FINEST) { 583 logger.finest(fooMsg, thrown); 584 checkLogEvent(provider, desc2, expected); 585 } else if (messageLevel == PlatformLogger.Level.FINER) { 586 logger.finer(fooMsg, thrown); 587 checkLogEvent(provider, desc2, expected); 588 } else if (messageLevel == PlatformLogger.Level.FINE) { 589 logger.fine(fooMsg, thrown); 590 checkLogEvent(provider, desc2, expected); 591 } else if (messageLevel == PlatformLogger.Level.CONFIG) { 592 logger.config(fooMsg, thrown); 593 checkLogEvent(provider, desc2, expected); 594 } else if (messageLevel == PlatformLogger.Level.INFO) { 595 logger.info(fooMsg, thrown); 596 checkLogEvent(provider, desc2, expected); 597 } else if (messageLevel == PlatformLogger.Level.WARNING) { 598 logger.warning(fooMsg, thrown); 599 checkLogEvent(provider, desc2, expected); 600 } else if (messageLevel == PlatformLogger.Level.SEVERE) { 601 logger.severe(fooMsg, thrown); 602 checkLogEvent(provider, desc2, expected); 603 } 604 } 605 } 606 607 String format = "two params [{1} {2}]"; 608 Object arg1 = foo; 609 Object arg2 = fooMsg; 610 System.out.println("\tlogger.<level>(format, arg1, arg2)"); 611 for (Level loggerLevel : Level.values()) { 612 sink.level = loggerLevel; 613 for (PlatformLogger.Level messageLevel :julLevels) { 614 Level expectedMessageLevel = julToSpiMap.get(messageLevel); 615 TestLoggerFinder.LogEvent expected = 616 TestLoggerFinder.LogEvent.of( 617 sequencer.get(), 618 loggerLevel != Level.OFF && expectedMessageLevel.compareTo(loggerLevel) >= 0, 619 name, expectedMessageLevel, (ResourceBundle) null, 620 format, null, (Throwable)null, foo, fooMsg); 621 String desc2 = "logger." + messageLevel.toString().toLowerCase() 622 + "(format, foo, fooMsg): loggerLevel=" 623 + loggerLevel+", messageLevel="+messageLevel; 624 if (messageLevel == PlatformLogger.Level.FINEST) { 625 logger.finest(format, foo, fooMsg); 626 checkLogEvent(provider, desc2, expected); 627 } else if (messageLevel == PlatformLogger.Level.FINER) { 628 logger.finer(format, foo, fooMsg); 629 checkLogEvent(provider, desc2, expected); 630 } else if (messageLevel == PlatformLogger.Level.FINE) { 631 logger.fine(format, foo, fooMsg); 632 checkLogEvent(provider, desc2, expected); 633 } else if (messageLevel == PlatformLogger.Level.CONFIG) { 634 logger.config(format, foo, fooMsg); 635 checkLogEvent(provider, desc2, expected); 636 } else if (messageLevel == PlatformLogger.Level.INFO) { 637 logger.info(format, foo, fooMsg); 638 checkLogEvent(provider, desc2, expected); 639 } else if (messageLevel == PlatformLogger.Level.WARNING) { 640 logger.warning(format, foo, fooMsg); 641 checkLogEvent(provider, desc2, expected); 642 } else if (messageLevel == PlatformLogger.Level.SEVERE) { 643 logger.severe(format, foo, fooMsg); 644 checkLogEvent(provider, desc2, expected); 645 } 646 } 647 } 648 649 } 650 651 final static class PermissionsBuilder { 652 final Permissions perms; 653 public PermissionsBuilder() { 654 this(new Permissions()); 655 } 656 public PermissionsBuilder(Permissions perms) { 657 this.perms = perms; 658 } 659 public PermissionsBuilder add(Permission p) { 660 perms.add(p); 661 return this; 662 } 663 public PermissionsBuilder addAll(PermissionCollection col) { 664 if (col != null) { 665 for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) { 666 perms.add(e.nextElement()); 667 } 668 } 669 return this; 670 } 671 public Permissions toPermissions() { 672 final PermissionsBuilder builder = new PermissionsBuilder(); 673 builder.addAll(perms); 674 return builder.perms; 675 } 676 } 677 678 public static class SimplePolicy extends Policy { 679 final static RuntimePermission CONTROL = LOGGERFINDER_PERMISSION; 680 final static RuntimePermission ACCESS_LOGGING = new RuntimePermission("accessClassInPackage.sun.util.logging"); 681 682 final Permissions permissions; 683 final Permissions allPermissions; 684 final ThreadLocal<AtomicBoolean> allowControl; 685 final ThreadLocal<AtomicBoolean> allowAccess; 686 final ThreadLocal<AtomicBoolean> allowAll; 687 public SimplePolicy(ThreadLocal<AtomicBoolean> allowControl, 688 ThreadLocal<AtomicBoolean> allowAccess, 689 ThreadLocal<AtomicBoolean> allowAll) { 690 this.allowControl = allowControl; 691 this.allowAccess = allowAccess; 692 this.allowAll = allowAll; 693 permissions = new Permissions(); 694 allPermissions = new PermissionsBuilder() 695 .add(new java.security.AllPermission()) 696 .toPermissions(); 697 } 698 699 Permissions getPermissions() { 700 if (allowControl.get().get() || allowAccess.get().get() || allowAll.get().get()) { 701 PermissionsBuilder builder = new PermissionsBuilder() 702 .addAll(permissions); 703 if (allowControl.get().get()) { 704 builder.add(CONTROL); 705 } 706 if (allowAccess.get().get()) { 707 builder.add(ACCESS_LOGGING); 708 } 709 if (allowAll.get().get()) { 710 builder.addAll(allPermissions); 711 } 712 return builder.toPermissions(); 713 } 714 return permissions; 715 } 716 717 @Override 718 public boolean implies(ProtectionDomain domain, Permission permission) { 719 return getPermissions().implies(permission); 720 } 721 722 @Override 723 public PermissionCollection getPermissions(CodeSource codesource) { 724 return new PermissionsBuilder().addAll(getPermissions()).toPermissions(); 725 } 726 727 @Override 728 public PermissionCollection getPermissions(ProtectionDomain domain) { 729 return new PermissionsBuilder().addAll(getPermissions()).toPermissions(); 730 } 731 } 732 }