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