1 /* 2 * Copyright (c) 2015, 2019, 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 BaseLoggerFinder 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("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++) { map.put(julLevels[i], mappedLevels[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 handleGetObject(String key)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 getKeys()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 LogEvent()167 public LogEvent() { 168 this(sequencer.getAndIncrement()); 169 } 170 LogEvent(long sequenceNumber)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 toArray()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 toString()200 public String toString() { 201 return Arrays.deepToString(toArray()); 202 } 203 204 205 206 @Override equals(Object obj)207 public boolean equals(Object obj) { 208 return obj instanceof LogEvent 209 && Objects.deepEquals(this.toArray(), ((LogEvent)obj).toArray()); 210 } 211 212 @Override hashCode()213 public int hashCode() { 214 return Objects.hash(toArray()); 215 } 216 cloneWith(long sequenceNumber)217 public LogEvent cloneWith(long sequenceNumber) 218 throws CloneNotSupportedException { 219 LogEvent cloned = (LogEvent)super.clone(); 220 cloned.sequenceNumber = sequenceNumber; 221 return cloned; 222 } 223 of(boolean isLoggable, String name, Level level, ResourceBundle bundle, String key, Throwable thrown)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 of(boolean isLoggable, String name, Level level, Throwable thrown, Supplier<String> supplier)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 of(boolean isLoggable, String name, Level level, ResourceBundle bundle, String key, Object... params)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 of(long sequenceNumber, boolean isLoggable, String name, Level level, ResourceBundle bundle, String key, Supplier<String> supplier, Throwable thrown, Object... params)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 LoggerImpl(String name)291 public LoggerImpl(String name) { 292 this.name = name; 293 } 294 295 @Override getName()296 public String getName() { 297 return name; 298 } 299 300 @Override isLoggable(Level level)301 public boolean isLoggable(Level level) { 302 return this.level != Level.OFF && this.level.getSeverity() <= level.getSeverity(); 303 } 304 305 @Override log(Level level, ResourceBundle bundle, String key, Throwable thrown)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 log(Level level, ResourceBundle bundle, String format, Object... params)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 log(LogEvent event)315 void log(LogEvent event) { 316 eventQueue.add(event); 317 } 318 319 @Override log(Level level, Supplier<String> msgSupplier)320 public void log(Level level, Supplier<String> msgSupplier) { 321 log(LogEvent.of(isLoggable(level), name, level, null, msgSupplier)); 322 } 323 324 @Override log(Level level, Supplier<String> msgSupplier, Throwable thrown)325 public void log(Level level, Supplier<String> msgSupplier, Throwable thrown) { 326 log(LogEvent.of(isLoggable(level), name, level, thrown, msgSupplier)); 327 } 328 } 329 getLogger(String name, Module caller)330 public Logger getLogger(String name, Module caller); 331 } 332 getPlatformLogger(String name)333 static PlatformLogger getPlatformLogger(String name) { 334 boolean old = allowAccess.get().get(); 335 allowAccess.get().set(true); 336 try { 337 return PlatformLogger.getLogger(name); 338 } finally { 339 allowAccess.get().set(old); 340 } 341 } 342 343 static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS}; 344 setSecurityManager()345 static void setSecurityManager() { 346 if (System.getSecurityManager() == null) { 347 Policy.setPolicy(new SimplePolicy(allowControl, allowAccess, allowAll)); 348 System.setSecurityManager(new SecurityManager()); 349 } 350 } 351 main(String[] args)352 public static void main(String[] args) { 353 if (args.length == 0) 354 args = new String[] { 355 "NOSECURITY", 356 "NOPERMISSIONS", 357 "WITHPERMISSIONS" 358 }; 359 360 361 Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> { 362 TestLoggerFinder provider; 363 switch (testCase) { 364 case NOSECURITY: 365 System.out.println("\n*** Without Security Manager\n"); 366 provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder()); 367 test(provider, true); 368 System.out.println("Tetscase count: " + sequencer.get()); 369 break; 370 case NOPERMISSIONS: 371 System.out.println("\n*** With Security Manager, without permissions\n"); 372 setSecurityManager(); 373 try { 374 provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder()); 375 throw new RuntimeException("Expected exception not raised"); 376 } catch (AccessControlException x) { 377 if (!LOGGERFINDER_PERMISSION.equals(x.getPermission())) { 378 throw new RuntimeException("Unexpected permission check", x); 379 } 380 final boolean control = allowControl.get().get(); 381 try { 382 allowControl.get().set(true); 383 provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder()); 384 } finally { 385 allowControl.get().set(control); 386 } 387 } 388 test(provider, false); 389 System.out.println("Tetscase count: " + sequencer.get()); 390 break; 391 case WITHPERMISSIONS: 392 System.out.println("\n*** With Security Manager, with control permission\n"); 393 setSecurityManager(); 394 final boolean control = allowControl.get().get(); 395 try { 396 allowControl.get().set(true); 397 provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder()); 398 test(provider, true); 399 } finally { 400 allowControl.get().set(control); 401 } 402 break; 403 default: 404 throw new RuntimeException("Unknown test case: " + testCase); 405 } 406 }); 407 System.out.println("\nPASSED: Tested " + sequencer.get() + " cases."); 408 } 409 test(TestLoggerFinder provider, boolean hasRequiredPermissions)410 public static void test(TestLoggerFinder provider, boolean hasRequiredPermissions) { 411 412 final Map<PlatformLogger, String> loggerDescMap = new HashMap<>(); 413 414 TestLoggerFinder.LoggerImpl appSink; 415 boolean before = allowControl.get().get(); 416 try { 417 allowControl.get().set(true); 418 appSink = TestLoggerFinder.LoggerImpl.class.cast( 419 provider.getLogger("foo", BasePlatformLoggerTest.class.getModule())); 420 } finally { 421 allowControl.get().set(before); 422 } 423 424 TestLoggerFinder.LoggerImpl sysSink = null; 425 before = allowControl.get().get(); 426 try { 427 allowControl.get().set(true); 428 sysSink = TestLoggerFinder.LoggerImpl.class.cast( 429 provider.getLogger("foo", Thread.class.getModule())); 430 } finally { 431 allowControl.get().set(before); 432 } 433 434 if (hasRequiredPermissions && appSink == sysSink) { 435 throw new RuntimeException("identical loggers"); 436 } 437 438 if (provider.system.contains(appSink)) { 439 throw new RuntimeException("app logger in system map"); 440 } 441 if (!provider.user.contains(appSink)) { 442 throw new RuntimeException("app logger not in appplication map"); 443 } 444 if (hasRequiredPermissions && provider.user.contains(sysSink)) { 445 throw new RuntimeException("sys logger in appplication map"); 446 } 447 if (hasRequiredPermissions && !provider.system.contains(sysSink)) { 448 throw new RuntimeException("sys logger not in system map"); 449 } 450 451 PlatformLogger platform = getPlatformLogger("foo"); 452 loggerDescMap.put(platform, "PlatformLogger.getLogger(\"foo\")"); 453 454 testLogger(provider, loggerDescMap, "foo", null, platform, sysSink); 455 } 456 457 public static class Foo { 458 459 } 460 verbose(String msg)461 static void verbose(String msg) { 462 if (VERBOSE) { 463 System.out.println(msg); 464 } 465 } 466 checkLogEvent(TestLoggerFinder provider, String desc, TestLoggerFinder.LogEvent expected)467 static void checkLogEvent(TestLoggerFinder provider, String desc, 468 TestLoggerFinder.LogEvent expected) { 469 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 470 if (!expected.equals(actual)) { 471 throw new RuntimeException("mismatch for " + desc 472 + "\n\texpected=" + expected 473 + "\n\t actual=" + actual); 474 } else { 475 verbose("Got expected results for " 476 + desc + "\n\t" + expected); 477 } 478 } 479 checkLogEvent(TestLoggerFinder provider, String desc, TestLoggerFinder.LogEvent expected, boolean expectNotNull)480 static void checkLogEvent(TestLoggerFinder provider, String desc, 481 TestLoggerFinder.LogEvent expected, boolean expectNotNull) { 482 TestLoggerFinder.LogEvent actual = provider.eventQueue.poll(); 483 if (actual == null && !expectNotNull) return; 484 if (actual != null && !expectNotNull) { 485 throw new RuntimeException("Unexpected log event found for " + desc 486 + "\n\tgot: " + actual); 487 } 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 // Calls the methods defined on LogProducer and verify the 499 // parameters received by the underlying TestLoggerFinder.LoggerImpl 500 // logger. testLogger(TestLoggerFinder provider, Map<PlatformLogger, String> loggerDescMap, String name, ResourceBundle loggerBundle, PlatformLogger logger, TestLoggerFinder.LoggerImpl sink)501 private static void testLogger(TestLoggerFinder provider, 502 Map<PlatformLogger, String> loggerDescMap, 503 String name, 504 ResourceBundle loggerBundle, 505 PlatformLogger logger, 506 TestLoggerFinder.LoggerImpl sink) { 507 508 System.out.println("Testing " + loggerDescMap.get(logger)); 509 510 Foo foo = new Foo(); 511 String fooMsg = foo.toString(); 512 System.out.println("\tlogger.<level>(fooMsg)"); 513 for (Level loggerLevel : Level.values()) { 514 sink.level = loggerLevel; 515 for (PlatformLogger.Level messageLevel :julLevels) { 516 Level expectedMessageLevel = julToSpiMap.get(messageLevel); 517 TestLoggerFinder.LogEvent expected = 518 TestLoggerFinder.LogEvent.of( 519 sequencer.get(), 520 loggerLevel != Level.OFF && expectedMessageLevel.compareTo(loggerLevel) >= 0, 521 name, expectedMessageLevel, loggerBundle, 522 fooMsg, null, (Throwable)null, (Object[])null); 523 String desc2 = "logger." + messageLevel.toString().toLowerCase() 524 + "(fooMsg): loggerLevel=" 525 + loggerLevel+", messageLevel="+messageLevel; 526 if (messageLevel == PlatformLogger.Level.FINEST) { 527 logger.finest(fooMsg); 528 checkLogEvent(provider, desc2, expected); 529 } else if (messageLevel == PlatformLogger.Level.FINER) { 530 logger.finer(fooMsg); 531 checkLogEvent(provider, desc2, expected); 532 } else if (messageLevel == PlatformLogger.Level.FINE) { 533 logger.fine(fooMsg); 534 checkLogEvent(provider, desc2, expected); 535 } else if (messageLevel == PlatformLogger.Level.CONFIG) { 536 logger.config(fooMsg); 537 checkLogEvent(provider, desc2, expected); 538 } else if (messageLevel == PlatformLogger.Level.INFO) { 539 logger.info(fooMsg); 540 checkLogEvent(provider, desc2, expected); 541 } else if (messageLevel == PlatformLogger.Level.WARNING) { 542 logger.warning(fooMsg); 543 checkLogEvent(provider, desc2, expected); 544 } else if (messageLevel == PlatformLogger.Level.SEVERE) { 545 logger.severe(fooMsg); 546 checkLogEvent(provider, desc2, expected); 547 } 548 } 549 } 550 551 Throwable thrown = new Exception("OK: log me!"); 552 System.out.println("\tlogger.<level>(msg, thrown)"); 553 for (Level loggerLevel : Level.values()) { 554 sink.level = loggerLevel; 555 for (PlatformLogger.Level messageLevel :julLevels) { 556 Level expectedMessageLevel = julToSpiMap.get(messageLevel); 557 TestLoggerFinder.LogEvent expected = 558 TestLoggerFinder.LogEvent.of( 559 sequencer.get(), 560 loggerLevel != Level.OFF && expectedMessageLevel.compareTo(loggerLevel) >= 0, 561 name, expectedMessageLevel, (ResourceBundle) null, 562 fooMsg, null, (Throwable)thrown, (Object[])null); 563 String desc2 = "logger." + messageLevel.toString().toLowerCase() 564 + "(msg, thrown): loggerLevel=" 565 + loggerLevel+", messageLevel="+messageLevel; 566 if (messageLevel == PlatformLogger.Level.FINEST) { 567 logger.finest(fooMsg, thrown); 568 checkLogEvent(provider, desc2, expected); 569 } else if (messageLevel == PlatformLogger.Level.FINER) { 570 logger.finer(fooMsg, thrown); 571 checkLogEvent(provider, desc2, expected); 572 } else if (messageLevel == PlatformLogger.Level.FINE) { 573 logger.fine(fooMsg, thrown); 574 checkLogEvent(provider, desc2, expected); 575 } else if (messageLevel == PlatformLogger.Level.CONFIG) { 576 logger.config(fooMsg, thrown); 577 checkLogEvent(provider, desc2, expected); 578 } else if (messageLevel == PlatformLogger.Level.INFO) { 579 logger.info(fooMsg, thrown); 580 checkLogEvent(provider, desc2, expected); 581 } else if (messageLevel == PlatformLogger.Level.WARNING) { 582 logger.warning(fooMsg, thrown); 583 checkLogEvent(provider, desc2, expected); 584 } else if (messageLevel == PlatformLogger.Level.SEVERE) { 585 logger.severe(fooMsg, thrown); 586 checkLogEvent(provider, desc2, expected); 587 } 588 } 589 } 590 591 String format = "two params [{1} {2}]"; 592 Object arg1 = foo; 593 Object arg2 = fooMsg; 594 System.out.println("\tlogger.<level>(format, arg1, arg2)"); 595 for (Level loggerLevel : Level.values()) { 596 sink.level = loggerLevel; 597 for (PlatformLogger.Level messageLevel :julLevels) { 598 Level expectedMessageLevel = julToSpiMap.get(messageLevel); 599 TestLoggerFinder.LogEvent expected = 600 TestLoggerFinder.LogEvent.of( 601 sequencer.get(), 602 loggerLevel != Level.OFF && expectedMessageLevel.compareTo(loggerLevel) >= 0, 603 name, expectedMessageLevel, (ResourceBundle) null, 604 format, null, (Throwable)null, foo, fooMsg); 605 String desc2 = "logger." + messageLevel.toString().toLowerCase() 606 + "(format, foo, fooMsg): loggerLevel=" 607 + loggerLevel+", messageLevel="+messageLevel; 608 if (messageLevel == PlatformLogger.Level.FINEST) { 609 logger.finest(format, foo, fooMsg); 610 checkLogEvent(provider, desc2, expected); 611 } else if (messageLevel == PlatformLogger.Level.FINER) { 612 logger.finer(format, foo, fooMsg); 613 checkLogEvent(provider, desc2, expected); 614 } else if (messageLevel == PlatformLogger.Level.FINE) { 615 logger.fine(format, foo, fooMsg); 616 checkLogEvent(provider, desc2, expected); 617 } else if (messageLevel == PlatformLogger.Level.CONFIG) { 618 logger.config(format, foo, fooMsg); 619 checkLogEvent(provider, desc2, expected); 620 } else if (messageLevel == PlatformLogger.Level.INFO) { 621 logger.info(format, foo, fooMsg); 622 checkLogEvent(provider, desc2, expected); 623 } else if (messageLevel == PlatformLogger.Level.WARNING) { 624 logger.warning(format, foo, fooMsg); 625 checkLogEvent(provider, desc2, expected); 626 } else if (messageLevel == PlatformLogger.Level.SEVERE) { 627 logger.severe(format, foo, fooMsg); 628 checkLogEvent(provider, desc2, expected); 629 } 630 } 631 } 632 633 } 634 635 final static class PermissionsBuilder { 636 final Permissions perms; PermissionsBuilder()637 public PermissionsBuilder() { 638 this(new Permissions()); 639 } PermissionsBuilder(Permissions perms)640 public PermissionsBuilder(Permissions perms) { 641 this.perms = perms; 642 } add(Permission p)643 public PermissionsBuilder add(Permission p) { 644 perms.add(p); 645 return this; 646 } addAll(PermissionCollection col)647 public PermissionsBuilder addAll(PermissionCollection col) { 648 if (col != null) { 649 for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) { 650 perms.add(e.nextElement()); 651 } 652 } 653 return this; 654 } toPermissions()655 public Permissions toPermissions() { 656 final PermissionsBuilder builder = new PermissionsBuilder(); 657 builder.addAll(perms); 658 return builder.perms; 659 } 660 } 661 662 public static class SimplePolicy extends Policy { 663 final static RuntimePermission CONTROL = LOGGERFINDER_PERMISSION; 664 final static RuntimePermission ACCESS_LOGGING = new RuntimePermission("accessClassInPackage.sun.util.logging"); 665 666 static final Policy DEFAULT_POLICY = Policy.getPolicy(); 667 668 final Permissions permissions; 669 final Permissions allPermissions; 670 final ThreadLocal<AtomicBoolean> allowControl; 671 final ThreadLocal<AtomicBoolean> allowAccess; 672 final ThreadLocal<AtomicBoolean> allowAll; SimplePolicy(ThreadLocal<AtomicBoolean> allowControl, ThreadLocal<AtomicBoolean> allowAccess, ThreadLocal<AtomicBoolean> allowAll)673 public SimplePolicy(ThreadLocal<AtomicBoolean> allowControl, 674 ThreadLocal<AtomicBoolean> allowAccess, 675 ThreadLocal<AtomicBoolean> allowAll) { 676 this.allowControl = allowControl; 677 this.allowAccess = allowAccess; 678 this.allowAll = allowAll; 679 permissions = new Permissions(); 680 allPermissions = new PermissionsBuilder() 681 .add(new java.security.AllPermission()) 682 .toPermissions(); 683 } 684 getPermissions()685 Permissions getPermissions() { 686 if (allowControl.get().get() || allowAccess.get().get() || allowAll.get().get()) { 687 PermissionsBuilder builder = new PermissionsBuilder() 688 .addAll(permissions); 689 if (allowControl.get().get()) { 690 builder.add(CONTROL); 691 } 692 if (allowAccess.get().get()) { 693 builder.add(ACCESS_LOGGING); 694 } 695 if (allowAll.get().get()) { 696 builder.addAll(allPermissions); 697 } 698 return builder.toPermissions(); 699 } 700 return permissions; 701 } 702 703 @Override implies(ProtectionDomain domain, Permission permission)704 public boolean implies(ProtectionDomain domain, Permission permission) { 705 return getPermissions().implies(permission) || DEFAULT_POLICY.implies(domain, permission); 706 } 707 708 @Override getPermissions(CodeSource codesource)709 public PermissionCollection getPermissions(CodeSource codesource) { 710 return new PermissionsBuilder().addAll(getPermissions()).toPermissions(); 711 } 712 713 @Override getPermissions(ProtectionDomain domain)714 public PermissionCollection getPermissions(ProtectionDomain domain) { 715 return new PermissionsBuilder().addAll(getPermissions()).toPermissions(); 716 } 717 } 718 } 719