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