1 /* 2 * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. 8 * 9 * This code is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 12 * version 2 for more details (a copy is included in the LICENSE file that 13 * accompanied this code). 14 * 15 * You should have received a copy of the GNU General Public License version 16 * 2 along with this work; if not, write to the Free Software Foundation, 17 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 18 * 19 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 20 * or visit www.oracle.com if you need additional information or have any 21 * questions. 22 */ 23 import java.security.AccessControlException; 24 import java.security.CodeSource; 25 import java.security.Permission; 26 import java.security.PermissionCollection; 27 import java.security.Permissions; 28 import java.security.Policy; 29 import java.security.ProtectionDomain; 30 import java.util.Arrays; 31 import java.util.Collections; 32 import java.util.Enumeration; 33 import java.util.HashMap; 34 import java.util.Map; 35 import java.util.Objects; 36 import java.util.Queue; 37 import java.util.ResourceBundle; 38 import java.util.concurrent.ArrayBlockingQueue; 39 import java.util.concurrent.ConcurrentHashMap; 40 import java.util.concurrent.atomic.AtomicBoolean; 41 import java.util.concurrent.atomic.AtomicLong; 42 import java.util.function.Supplier; 43 import java.util.logging.Handler; 44 import java.util.logging.LogManager; 45 import java.util.logging.LogRecord; 46 import java.lang.System.LoggerFinder; 47 import java.lang.System.Logger; 48 import java.lang.System.Logger.Level; 49 import java.util.stream.Stream; 50 51 /** 52 * @test 53 * @bug 8046565 54 * @summary Tests the default implementation of System.Logger, when 55 * JUL is the default backend. 56 * @build AccessSystemLogger DefaultLoggerFinderTest 57 * @run driver AccessSystemLogger 58 * @run main/othervm -Xbootclasspath/a:boot DefaultLoggerFinderTest NOSECURITY 59 * @run main/othervm -Xbootclasspath/a:boot DefaultLoggerFinderTest NOPERMISSIONS 60 * @run main/othervm -Xbootclasspath/a:boot DefaultLoggerFinderTest WITHPERMISSIONS 61 * @author danielfuchs 62 */ 63 public class DefaultLoggerFinderTest { 64 65 final static AtomicLong sequencer = new AtomicLong(); 66 final static boolean VERBOSE = false; 67 static final ThreadLocal<AtomicBoolean> allowControl = new ThreadLocal<AtomicBoolean>() { 68 @Override 69 protected AtomicBoolean initialValue() { 70 return new AtomicBoolean(false); 71 } 72 }; 73 static final ThreadLocal<AtomicBoolean> allowAll = new ThreadLocal<AtomicBoolean>() { 74 @Override 75 protected AtomicBoolean initialValue() { 76 return new AtomicBoolean(false); 77 } 78 }; 79 80 static final AccessSystemLogger accessSystemLogger = new AccessSystemLogger(); 81 82 public static final Queue<LogEvent> eventQueue = new ArrayBlockingQueue<>(128); 83 84 public static final class LogEvent { 85 86 public LogEvent() { 87 this(sequencer.getAndIncrement()); 88 } 89 90 LogEvent(long sequenceNumber) { 91 this.sequenceNumber = sequenceNumber; 92 } 93 94 long sequenceNumber; 95 boolean isLoggable; 96 String loggerName; 97 java.util.logging.Level level; 98 ResourceBundle bundle; 99 Throwable thrown; 100 Object[] args; 101 String msg; 102 String className; 103 String methodName; 104 105 Object[] toArray() { 106 return new Object[] { 107 sequenceNumber, 108 isLoggable, 109 loggerName, 110 level, 111 bundle, 112 thrown, 113 args, 114 msg, 115 className, 116 methodName, 117 }; 118 } 119 120 @Override 121 public String toString() { 122 return Arrays.deepToString(toArray()); 123 } 124 125 @Override 126 public boolean equals(Object obj) { 127 return obj instanceof LogEvent 128 && Objects.deepEquals(this.toArray(), ((LogEvent)obj).toArray()); 129 } 130 131 @Override 132 public int hashCode() { 133 return Objects.hash(toArray()); 134 } 135 public static LogEvent of(long sequenceNumber, 136 boolean isLoggable, String name, 137 java.util.logging.Level level, ResourceBundle bundle, 138 String key, Throwable thrown, Object... params) { 139 return LogEvent.of(sequenceNumber, isLoggable, name, 140 DefaultLoggerFinderTest.class.getName(), 141 "testLogger", level, bundle, key, 142 thrown, params); 143 } 144 public static LogEvent of(long sequenceNumber, 145 boolean isLoggable, String name, 146 String className, String methodName, 147 java.util.logging.Level level, ResourceBundle bundle, 148 String key, Throwable thrown, Object... params) { 149 LogEvent evt = new LogEvent(sequenceNumber); 150 evt.loggerName = name; 151 evt.level = level; 152 evt.args = params; 153 evt.bundle = bundle; 154 evt.thrown = thrown; 155 evt.msg = key; 156 evt.isLoggable = isLoggable; 157 evt.className = className; 158 evt.methodName = methodName; 159 return evt; 160 } 161 162 } 163 164 static java.util.logging.Level mapToJul(Level level) { 165 switch (level) { 166 case ALL: return java.util.logging.Level.ALL; 167 case TRACE: return java.util.logging.Level.FINER; 168 case DEBUG: return java.util.logging.Level.FINE; 169 case INFO: return java.util.logging.Level.INFO; 170 case WARNING: return java.util.logging.Level.WARNING; 171 case ERROR: return java.util.logging.Level.SEVERE; 172 case OFF: return java.util.logging.Level.OFF; 173 } 174 throw new InternalError("No such level: " + level); 175 } 176 177 static final java.util.logging.Level[] julLevels = { 178 java.util.logging.Level.ALL, 179 new java.util.logging.Level("FINER_THAN_FINEST", java.util.logging.Level.FINEST.intValue() - 10) {}, 180 java.util.logging.Level.FINEST, 181 new java.util.logging.Level("FINER_THAN_FINER", java.util.logging.Level.FINER.intValue() - 10) {}, 182 java.util.logging.Level.FINER, 183 new java.util.logging.Level("FINER_THAN_FINE", java.util.logging.Level.FINE.intValue() - 10) {}, 184 java.util.logging.Level.FINE, 185 new java.util.logging.Level("FINER_THAN_CONFIG", java.util.logging.Level.FINE.intValue() + 10) {}, 186 java.util.logging.Level.CONFIG, 187 new java.util.logging.Level("FINER_THAN_INFO", java.util.logging.Level.INFO.intValue() - 10) {}, 188 java.util.logging.Level.INFO, 189 new java.util.logging.Level("FINER_THAN_WARNING", java.util.logging.Level.INFO.intValue() + 10) {}, 190 java.util.logging.Level.WARNING, 191 new java.util.logging.Level("FINER_THAN_SEVERE", java.util.logging.Level.SEVERE.intValue() - 10) {}, 192 java.util.logging.Level.SEVERE, 193 new java.util.logging.Level("FATAL", java.util.logging.Level.SEVERE.intValue() + 10) {}, 194 java.util.logging.Level.OFF, 195 }; 196 197 static final Level[] mappedLevels = { 198 Level.ALL, // ALL 199 Level.DEBUG, // FINER_THAN_FINEST 200 Level.DEBUG, // FINEST 201 Level.DEBUG, // FINER_THAN_FINER 202 Level.TRACE, // FINER 203 Level.TRACE, // FINER_THAN_FINE 204 Level.DEBUG, // FINE 205 Level.DEBUG, // FINER_THAN_CONFIG 206 Level.DEBUG, // CONFIG 207 Level.DEBUG, // FINER_THAN_INFO 208 Level.INFO, // INFO 209 Level.INFO, // FINER_THAN_WARNING 210 Level.WARNING, // WARNING 211 Level.WARNING, // FINER_THAN_SEVERE 212 Level.ERROR, // SEVERE 213 Level.ERROR, // FATAL 214 Level.OFF, // OFF 215 }; 216 217 final static Map<java.util.logging.Level, Level> julToSpiMap; 218 static { 219 Map<java.util.logging.Level, Level> map = new HashMap<>(); 220 if (mappedLevels.length != julLevels.length) { 221 throw new ExceptionInInitializerError("Array lengths differ" 222 + "\n\tjulLevels=" + Arrays.deepToString(julLevels) 223 + "\n\tmappedLevels=" + Arrays.deepToString(mappedLevels)); 224 } 225 for (int i=0; i<julLevels.length; i++) { 226 map.put(julLevels[i], mappedLevels[i]); 227 } 228 julToSpiMap = Collections.unmodifiableMap(map); 229 } 230 231 public static class MyBundle extends ResourceBundle { 232 233 final ConcurrentHashMap<String,String> map = new ConcurrentHashMap<>(); 234 235 @Override 236 protected Object handleGetObject(String key) { 237 if (key.contains(" (translated)")) { 238 throw new RuntimeException("Unexpected key: " + key); 239 } 240 return map.computeIfAbsent(key, k -> k + " (translated)"); 241 } 242 243 @Override 244 public Enumeration<String> getKeys() { 245 return Collections.enumeration(map.keySet()); 246 } 247 248 } 249 250 public static class MyHandler extends Handler { 251 252 @Override 253 public java.util.logging.Level getLevel() { 254 return java.util.logging.Level.ALL; 255 } 256 257 @Override 258 public void publish(LogRecord record) { 259 eventQueue.add(LogEvent.of(sequencer.getAndIncrement(), 260 true, record.getLoggerName(), 261 record.getSourceClassName(), 262 record.getSourceMethodName(), 263 record.getLevel(), 264 record.getResourceBundle(), record.getMessage(), 265 record.getThrown(), record.getParameters())); 266 } 267 @Override 268 public void flush() { 269 } 270 @Override 271 public void close() throws SecurityException { 272 } 273 274 } 275 276 public static class MyLoggerBundle extends MyBundle { 277 278 } 279 280 281 static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS}; 282 283 static void setSecurityManager() { 284 if (System.getSecurityManager() == null) { 285 Policy.setPolicy(new SimplePolicy(allowAll, allowControl)); 286 System.setSecurityManager(new SecurityManager()); 287 } 288 } 289 290 public static void main(String[] args) { 291 if (args.length == 0) 292 args = new String[] { 293 "NOSECURITY", 294 "NOPERMISSIONS", 295 "WITHPERMISSIONS" 296 }; 297 298 final java.util.logging.Logger appSink = LogManager.demandLoggerFor("foo", DefaultLoggerFinderTest.class); 299 final java.util.logging.Logger sysSink = LogManager.demandLoggerFor("foo", Thread.class); 300 appSink.addHandler(new MyHandler()); 301 sysSink.addHandler(new MyHandler()); 302 appSink.setUseParentHandlers(VERBOSE); 303 sysSink.setUseParentHandlers(VERBOSE); 304 305 Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> { 306 LoggerFinder provider; 307 switch (testCase) { 308 case NOSECURITY: 309 System.out.println("\n*** Without Security Manager\n"); 310 provider = LoggerFinder.getLoggerFinder(); 311 test(provider, true, appSink, sysSink); 312 System.out.println("Tetscase count: " + sequencer.get()); 313 break; 314 case NOPERMISSIONS: 315 System.out.println("\n*** With Security Manager, without permissions\n"); 316 setSecurityManager(); 317 try { 318 provider = LoggerFinder.getLoggerFinder(); 319 throw new RuntimeException("Expected exception not raised"); 320 } catch (AccessControlException x) { 321 if (!LoggerFinder.LOGGERFINDER_PERMISSION.equals(x.getPermission())) { 322 throw new RuntimeException("Unexpected permission check", x); 323 } 324 final boolean control = allowControl.get().get(); 325 try { 326 allowControl.get().set(true); 327 provider = LoggerFinder.getLoggerFinder(); 328 } finally { 329 allowControl.get().set(control); 330 } 331 } 332 test(provider, false, appSink, sysSink); 333 System.out.println("Tetscase count: " + sequencer.get()); 334 break; 335 case WITHPERMISSIONS: 336 System.out.println("\n*** With Security Manager, with control permission\n"); 337 setSecurityManager(); 338 final boolean control = allowControl.get().get(); 339 try { 340 allowControl.get().set(true); 341 provider = LoggerFinder.getLoggerFinder(); 342 test(provider, true, appSink, sysSink); 343 } finally { 344 allowControl.get().set(control); 345 } 346 break; 347 default: 348 throw new RuntimeException("Unknown test case: " + testCase); 349 } 350 }); 351 System.out.println("\nPASSED: Tested " + sequencer.get() + " cases."); 352 } 353 354 public static void test(LoggerFinder provider, 355 boolean hasRequiredPermissions, 356 java.util.logging.Logger appSink, 357 java.util.logging.Logger sysSink) { 358 359 ResourceBundle loggerBundle = ResourceBundle.getBundle(MyLoggerBundle.class.getName()); 360 final Map<Logger, String> loggerDescMap = new HashMap<>(); 361 362 363 Logger appLogger1 = null; 364 try { 365 appLogger1 = provider.getLogger("foo", DefaultLoggerFinderTest.class); 366 loggerDescMap.put(appLogger1, "provider.getApplicationLogger(\"foo\")"); 367 if (!hasRequiredPermissions) { 368 throw new RuntimeException("Managed to obtain a logger without permission"); 369 } 370 } catch (AccessControlException acx) { 371 if (hasRequiredPermissions) { 372 throw new RuntimeException("Unexpected security exception: ", acx); 373 } 374 if (!acx.getPermission().equals(LoggerFinder.LOGGERFINDER_PERMISSION)) { 375 throw new RuntimeException("Unexpected permission in exception: " + acx, acx); 376 } 377 System.out.println("Got expected exception for logger: " + acx); 378 boolean old = allowControl.get().get(); 379 allowControl.get().set(true); 380 try { 381 appLogger1 =provider.getLogger("foo", DefaultLoggerFinderTest.class); 382 loggerDescMap.put(appLogger1, "provider.getApplicationLogger(\"foo\")"); 383 } finally { 384 allowControl.get().set(old); 385 } 386 } 387 388 Logger sysLogger1 = null; 389 try { 390 sysLogger1 = provider.getLogger("foo", Thread.class); 391 loggerDescMap.put(sysLogger1, "provider.getSystemLogger(\"foo\")"); 392 if (!hasRequiredPermissions) { 393 throw new RuntimeException("Managed to obtain a system logger without permission"); 394 } 395 } catch (AccessControlException acx) { 396 if (hasRequiredPermissions) { 397 throw new RuntimeException("Unexpected security exception: ", acx); 398 } 399 if (!acx.getPermission().equals(LoggerFinder.LOGGERFINDER_PERMISSION)) { 400 throw new RuntimeException("Unexpected permission in exception: " + acx, acx); 401 } 402 System.out.println("Got expected exception for system logger: " + acx); 403 boolean old = allowControl.get().get(); 404 allowControl.get().set(true); 405 try { 406 sysLogger1 = provider.getLogger("foo", Thread.class); 407 loggerDescMap.put(sysLogger1, "provider.getSystemLogger(\"foo\")"); 408 } finally { 409 allowControl.get().set(old); 410 } 411 } 412 if (appLogger1 == sysLogger1) { 413 throw new RuntimeException("identical loggers"); 414 } 415 416 Logger appLogger2 = null; 417 try { 418 appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class); 419 loggerDescMap.put(appLogger2, "provider.getLocalizedApplicationLogger(\"foo\", loggerBundle)"); 420 if (!hasRequiredPermissions) { 421 throw new RuntimeException("Managed to obtain a logger without permission"); 422 } 423 } catch (AccessControlException acx) { 424 if (hasRequiredPermissions) { 425 throw new RuntimeException("Unexpected security exception: ", acx); 426 } 427 if (!acx.getPermission().equals(LoggerFinder.LOGGERFINDER_PERMISSION)) { 428 throw new RuntimeException("Unexpected permission in exception: " + acx, acx); 429 } 430 System.out.println("Got expected exception for logger: " + acx); 431 boolean old = allowControl.get().get(); 432 allowControl.get().set(true); 433 try { 434 appLogger2 = provider.getLocalizedLogger("foo", loggerBundle, DefaultLoggerFinderTest.class); 435 loggerDescMap.put(appLogger2, "provider.getLocalizedApplicationLogger(\"foo\", loggerBundle)"); 436 } finally { 437 allowControl.get().set(old); 438 } 439 } 440 441 Logger sysLogger2 = null; 442 try { 443 sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); 444 loggerDescMap.put(sysLogger2, "provider.getLocalizedSystemLogger(\"foo\", loggerBundle)"); 445 if (!hasRequiredPermissions) { 446 throw new RuntimeException("Managed to obtain a system logger without permission"); 447 } 448 } catch (AccessControlException acx) { 449 if (hasRequiredPermissions) { 450 throw new RuntimeException("Unexpected security exception: ", acx); 451 } 452 if (!acx.getPermission().equals(LoggerFinder.LOGGERFINDER_PERMISSION)) { 453 throw new RuntimeException("Unexpected permission in exception: " + acx, acx); 454 } 455 System.out.println("Got expected exception for localized system logger: " + acx); 456 boolean old = allowControl.get().get(); 457 allowControl.get().set(true); 458 try { 459 sysLogger2 = provider.getLocalizedLogger("foo", loggerBundle, Thread.class); 460 loggerDescMap.put(sysLogger2, "provider.getLocalizedSystemLogger(\"foo\", loggerBundle)"); 461 } finally { 462 allowControl.get().set(old); 463 } 464 } 465 if (appLogger2 == sysLogger2) { 466 throw new RuntimeException("identical loggers"); 467 } 468 if (appLogger2 == appLogger1) { 469 throw new RuntimeException("identical loggers"); 470 } 471 if (sysLogger2 == sysLogger1) { 472 throw new RuntimeException("identical loggers"); 473 } 474 475 476 testLogger(provider, loggerDescMap, "foo", null, appLogger1, appSink); 477 testLogger(provider, loggerDescMap, "foo", null, sysLogger1, sysSink); 478 testLogger(provider, loggerDescMap, "foo", loggerBundle, appLogger2, appSink); 479 testLogger(provider, loggerDescMap, "foo", loggerBundle, sysLogger2, sysSink); 480 481 482 Logger appLogger3 = System.getLogger("foo"); 483 loggerDescMap.put(appLogger3, "System.getLogger(\"foo\")"); 484 485 testLogger(provider, loggerDescMap, "foo", null, appLogger3, appSink); 486 487 Logger appLogger4 = 488 System.getLogger("foo", loggerBundle); 489 loggerDescMap.put(appLogger4, "System.getLogger(\"foo\", loggerBundle)"); 490 491 if (appLogger4 == appLogger1) { 492 throw new RuntimeException("identical loggers"); 493 } 494 495 testLogger(provider, loggerDescMap, "foo", loggerBundle, appLogger4, appSink); 496 497 Logger sysLogger3 = accessSystemLogger.getLogger("foo"); 498 loggerDescMap.put(sysLogger3, "AccessSystemLogger.getLogger(\"foo\")"); 499 500 testLogger(provider, loggerDescMap, "foo", null, sysLogger3, sysSink); 501 502 Logger sysLogger4 = 503 accessSystemLogger.getLogger("foo", loggerBundle); 504 loggerDescMap.put(appLogger4, "AccessSystemLogger.getLogger(\"foo\", loggerBundle)"); 505 506 if (sysLogger4 == sysLogger1) { 507 throw new RuntimeException("identical loggers"); 508 } 509 510 testLogger(provider, loggerDescMap, "foo", loggerBundle, sysLogger4, sysSink); 511 512 } 513 514 public static class Foo { 515 516 } 517 518 static void verbose(String msg) { 519 if (VERBOSE) { 520 System.out.println(msg); 521 } 522 } 523 524 static void setLevel(java.util.logging.Logger sink, java.util.logging.Level loggerLevel) { 525 boolean before = allowAll.get().get(); 526 try { 527 allowAll.get().set(true); 528 sink.setLevel(loggerLevel); 529 } finally { 530 allowAll.get().set(before); 531 } 532 } 533 534 535 // Calls the 8 methods defined on Logger and verify the 536 // parameters received by the underlying Logger Impl 537 // logger. 538 private static void testLogger(LoggerFinder provider, 539 Map<Logger, String> loggerDescMap, 540 String name, 541 ResourceBundle loggerBundle, 542 Logger logger, 543 java.util.logging.Logger sink) { 544 545 System.out.println("Testing " + loggerDescMap.get(logger) + " [" + logger + "]"); 546 final java.util.logging.Level OFF = java.util.logging.Level.OFF; 547 548 Foo foo = new Foo(); 549 String fooMsg = foo.toString(); 550 for (java.util.logging.Level loggerLevel : julLevels) { 551 setLevel(sink, loggerLevel); 552 for (Level messageLevel : Level.values()) { 553 java.util.logging.Level julLevel = mapToJul(messageLevel); 554 String desc = "logger.log(messageLevel, foo): loggerLevel=" 555 + loggerLevel+", messageLevel="+messageLevel; 556 LogEvent expected = 557 LogEvent.of( 558 sequencer.get(), 559 julLevel.intValue() >= loggerLevel.intValue(), 560 name, julLevel, (ResourceBundle)null, 561 fooMsg, (Throwable)null, (Object[])null); 562 logger.log(messageLevel, foo); 563 if (loggerLevel == OFF || julLevel.intValue() < loggerLevel.intValue()) { 564 if (eventQueue.poll() != null) { 565 throw new RuntimeException("unexpected event in queue for " + desc); 566 } 567 } else { 568 LogEvent actual = eventQueue.poll(); 569 if (!expected.equals(actual)) { 570 throw new RuntimeException("mismatch for " + desc 571 + "\n\texpected=" + expected 572 + "\n\t actual=" + actual); 573 } else { 574 verbose("Got expected results for " 575 + desc + "\n\t" + expected); 576 } 577 } 578 } 579 } 580 581 String msg = "blah"; 582 for (java.util.logging.Level loggerLevel : julLevels) { 583 setLevel(sink, loggerLevel); 584 for (Level messageLevel : Level.values()) { 585 java.util.logging.Level julLevel = mapToJul(messageLevel); 586 String desc = "logger.log(messageLevel, \"blah\"): loggerLevel=" 587 + loggerLevel+", messageLevel="+messageLevel; 588 LogEvent expected = 589 LogEvent.of( 590 sequencer.get(), 591 julLevel.intValue() >= loggerLevel.intValue(), 592 name, julLevel, loggerBundle, 593 msg, (Throwable)null, (Object[])null); 594 logger.log(messageLevel, msg); 595 if (loggerLevel == OFF || julLevel.intValue() < loggerLevel.intValue()) { 596 if (eventQueue.poll() != null) { 597 throw new RuntimeException("unexpected event in queue for " + desc); 598 } 599 } else { 600 LogEvent actual = eventQueue.poll(); 601 if (!expected.equals(actual)) { 602 throw new RuntimeException("mismatch for " + desc 603 + "\n\texpected=" + expected 604 + "\n\t actual=" + actual); 605 } else { 606 verbose("Got expected results for " 607 + desc + "\n\t" + expected); 608 } 609 } 610 } 611 } 612 613 Supplier<String> fooSupplier = new Supplier<String>() { 614 @Override 615 public String get() { 616 return this.toString(); 617 } 618 }; 619 620 for (java.util.logging.Level loggerLevel : julLevels) { 621 setLevel(sink, loggerLevel); 622 for (Level messageLevel : Level.values()) { 623 java.util.logging.Level julLevel = mapToJul(messageLevel); 624 String desc = "logger.log(messageLevel, fooSupplier): loggerLevel=" 625 + loggerLevel+", messageLevel="+messageLevel; 626 LogEvent expected = 627 LogEvent.of( 628 sequencer.get(), 629 julLevel.intValue() >= loggerLevel.intValue(), 630 name, julLevel, (ResourceBundle)null, 631 fooSupplier.get(), 632 (Throwable)null, (Object[])null); 633 logger.log(messageLevel, fooSupplier); 634 if (loggerLevel == OFF || julLevel.intValue() < loggerLevel.intValue()) { 635 if (eventQueue.poll() != null) { 636 throw new RuntimeException("unexpected event in queue for " + desc); 637 } 638 } else { 639 LogEvent actual = eventQueue.poll(); 640 if (!expected.equals(actual)) { 641 throw new RuntimeException("mismatch for " + desc 642 + "\n\texpected=" + expected 643 + "\n\t actual=" + actual); 644 } else { 645 verbose("Got expected results for " 646 + desc + "\n\t" + expected); 647 } 648 } 649 } 650 } 651 652 String format = "two params [{1} {2}]"; 653 Object arg1 = foo; 654 Object arg2 = msg; 655 for (java.util.logging.Level loggerLevel : julLevels) { 656 setLevel(sink, loggerLevel); 657 for (Level messageLevel : Level.values()) { 658 java.util.logging.Level julLevel = mapToJul(messageLevel); 659 String desc = "logger.log(messageLevel, format, params...): loggerLevel=" 660 + loggerLevel+", messageLevel="+messageLevel; 661 LogEvent expected = 662 LogEvent.of( 663 sequencer.get(), 664 julLevel.intValue() >= loggerLevel.intValue(), 665 name, julLevel, loggerBundle, 666 format, (Throwable)null, new Object[] {arg1, arg2}); 667 logger.log(messageLevel, format, arg1, arg2); 668 if (loggerLevel == OFF || julLevel.intValue() < loggerLevel.intValue()) { 669 if (eventQueue.poll() != null) { 670 throw new RuntimeException("unexpected event in queue for " + desc); 671 } 672 } else { 673 LogEvent actual = eventQueue.poll(); 674 if (!expected.equals(actual)) { 675 throw new RuntimeException("mismatch for " + desc 676 + "\n\texpected=" + expected 677 + "\n\t actual=" + actual); 678 } else { 679 verbose("Got expected results for " 680 + desc + "\n\t" + expected); 681 } 682 } 683 } 684 } 685 686 Throwable thrown = new Exception("OK: log me!"); 687 for (java.util.logging.Level loggerLevel : julLevels) { 688 setLevel(sink, loggerLevel); 689 for (Level messageLevel : Level.values()) { 690 java.util.logging.Level julLevel = mapToJul(messageLevel); 691 String desc = "logger.log(messageLevel, \"blah\", thrown): loggerLevel=" 692 + loggerLevel+", messageLevel="+messageLevel; 693 LogEvent expected = 694 LogEvent.of( 695 sequencer.get(), 696 julLevel.intValue() >= loggerLevel.intValue(), 697 name, julLevel, loggerBundle, 698 msg, thrown, (Object[]) null); 699 logger.log(messageLevel, msg, thrown); 700 if (loggerLevel == OFF || julLevel.intValue() < loggerLevel.intValue()) { 701 if (eventQueue.poll() != null) { 702 throw new RuntimeException("unexpected event in queue for " + desc); 703 } 704 } else { 705 LogEvent actual = eventQueue.poll(); 706 if (!expected.equals(actual)) { 707 throw new RuntimeException("mismatch for " + desc 708 + "\n\texpected=" + expected 709 + "\n\t actual=" + actual); 710 } else { 711 verbose("Got expected results for " 712 + desc + "\n\t" + expected); 713 } 714 } 715 } 716 } 717 718 719 for (java.util.logging.Level loggerLevel : julLevels) { 720 setLevel(sink, loggerLevel); 721 for (Level messageLevel : Level.values()) { 722 java.util.logging.Level julLevel = mapToJul(messageLevel); 723 String desc = "logger.log(messageLevel, thrown, fooSupplier): loggerLevel=" 724 + loggerLevel+", messageLevel="+messageLevel; 725 LogEvent expected = 726 LogEvent.of( 727 sequencer.get(), 728 julLevel.intValue() >= loggerLevel.intValue(), 729 name, julLevel, (ResourceBundle)null, 730 fooSupplier.get(), 731 (Throwable)thrown, (Object[])null); 732 logger.log(messageLevel, fooSupplier, thrown); 733 if (loggerLevel == OFF || julLevel.intValue() < loggerLevel.intValue()) { 734 if (eventQueue.poll() != null) { 735 throw new RuntimeException("unexpected event in queue for " + desc); 736 } 737 } else { 738 LogEvent actual = eventQueue.poll(); 739 if (!expected.equals(actual)) { 740 throw new RuntimeException("mismatch for " + desc 741 + "\n\texpected=" + expected 742 + "\n\t actual=" + actual); 743 } else { 744 verbose("Got expected results for " 745 + desc + "\n\t" + expected); 746 } 747 } 748 } 749 } 750 751 ResourceBundle bundle = ResourceBundle.getBundle(MyBundle.class.getName()); 752 for (java.util.logging.Level loggerLevel : julLevels) { 753 setLevel(sink, loggerLevel); 754 for (Level messageLevel : Level.values()) { 755 java.util.logging.Level julLevel = mapToJul(messageLevel); 756 String desc = "logger.log(messageLevel, bundle, format, params...): loggerLevel=" 757 + loggerLevel+", messageLevel="+messageLevel; 758 LogEvent expected = 759 LogEvent.of( 760 sequencer.get(), 761 julLevel.intValue() >= loggerLevel.intValue(), 762 name, julLevel, bundle, 763 format, (Throwable)null, new Object[] {foo, msg}); 764 logger.log(messageLevel, bundle, format, foo, msg); 765 if (loggerLevel == OFF || julLevel.intValue() < loggerLevel.intValue()) { 766 if (eventQueue.poll() != null) { 767 throw new RuntimeException("unexpected event in queue for " + desc); 768 } 769 } else { 770 LogEvent actual = eventQueue.poll(); 771 if (!expected.equals(actual)) { 772 throw new RuntimeException("mismatch for " + desc 773 + "\n\texpected=" + expected 774 + "\n\t actual=" + actual); 775 } else { 776 verbose("Got expected results for " 777 + desc + "\n\t" + expected); 778 } 779 } 780 } 781 } 782 783 for (java.util.logging.Level loggerLevel : julLevels) { 784 setLevel(sink, loggerLevel); 785 for (Level messageLevel : Level.values()) { 786 java.util.logging.Level julLevel = mapToJul(messageLevel); 787 String desc = "logger.log(messageLevel, bundle, \"blah\", thrown): loggerLevel=" 788 + loggerLevel+", messageLevel="+messageLevel; 789 LogEvent expected = 790 LogEvent.of( 791 sequencer.get(), 792 julLevel.intValue() >= loggerLevel.intValue(), 793 name, julLevel, bundle, 794 msg, thrown, (Object[]) null); 795 logger.log(messageLevel, bundle, msg, thrown); 796 if (loggerLevel == OFF || julLevel.intValue() < loggerLevel.intValue()) { 797 if (eventQueue.poll() != null) { 798 throw new RuntimeException("unexpected event in queue for " + desc); 799 } 800 } else { 801 LogEvent actual = eventQueue.poll(); 802 if (!expected.equals(actual)) { 803 throw new RuntimeException("mismatch for " + desc 804 + "\n\texpected=" + expected 805 + "\n\t actual=" + actual); 806 } else { 807 verbose("Got expected results for " 808 + desc + "\n\t" + expected); 809 } 810 } 811 } 812 } 813 } 814 815 final static class PermissionsBuilder { 816 final Permissions perms; 817 public PermissionsBuilder() { 818 this(new Permissions()); 819 } 820 public PermissionsBuilder(Permissions perms) { 821 this.perms = perms; 822 } 823 public PermissionsBuilder add(Permission p) { 824 perms.add(p); 825 return this; 826 } 827 public PermissionsBuilder addAll(PermissionCollection col) { 828 if (col != null) { 829 for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) { 830 perms.add(e.nextElement()); 831 } 832 } 833 return this; 834 } 835 public Permissions toPermissions() { 836 final PermissionsBuilder builder = new PermissionsBuilder(); 837 builder.addAll(perms); 838 return builder.perms; 839 } 840 } 841 842 public static class SimplePolicy extends Policy { 843 844 final Permissions permissions; 845 final Permissions withControlPermissions; 846 final Permissions allPermissions; 847 final ThreadLocal<AtomicBoolean> allowAll; 848 final ThreadLocal<AtomicBoolean> allowControl; 849 public SimplePolicy(ThreadLocal<AtomicBoolean> allowAll, 850 ThreadLocal<AtomicBoolean> allowControl) { 851 this.allowAll = allowAll; 852 this.allowControl = allowControl; 853 permissions = new Permissions(); 854 855 withControlPermissions = new Permissions(); 856 withControlPermissions.add(LoggerFinder.LOGGERFINDER_PERMISSION); 857 858 // these are used for configuring the test itself... 859 allPermissions = new Permissions(); 860 allPermissions.add(new java.security.AllPermission()); 861 } 862 863 @Override 864 public boolean implies(ProtectionDomain domain, Permission permission) { 865 if (allowAll.get().get()) return allPermissions.implies(permission); 866 if (allowControl.get().get()) return withControlPermissions.implies(permission); 867 return permissions.implies(permission); 868 } 869 870 @Override 871 public PermissionCollection getPermissions(CodeSource codesource) { 872 return new PermissionsBuilder().addAll( 873 allowAll.get().get() ? allPermissions : 874 allowControl.get().get() 875 ? withControlPermissions : permissions).toPermissions(); 876 } 877 878 @Override 879 public PermissionCollection getPermissions(ProtectionDomain domain) { 880 return new PermissionsBuilder().addAll( 881 allowAll.get().get() ? allPermissions : 882 allowControl.get().get() 883 ? withControlPermissions : permissions).toPermissions(); 884 } 885 } 886 }