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