1 /*
2  * Copyright (c) 2015, 2019, Oracle and/or its affiliates. All rights reserved.
3  * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4  *
5  * This code is free software; you can redistribute it and/or modify it
6  * under the terms of the GNU General Public License version 2 only, as
7  * published by the Free Software Foundation.
8  *
9  * This code is distributed in the hope that it will be useful, but WITHOUT
10  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
12  * version 2 for more details (a copy is included in the LICENSE file that
13  * accompanied this code).
14  *
15  * You should have received a copy of the GNU General Public License version
16  * 2 along with this work; if not, write to the Free Software Foundation,
17  * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
18  *
19  * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
20  * or visit www.oracle.com if you need additional information or have any
21  * questions.
22  */
23 import java.security.AccessController;
24 import java.security.CodeSource;
25 import java.security.Permission;
26 import java.security.PermissionCollection;
27 import java.security.Permissions;
28 import java.security.Policy;
29 import java.security.PrivilegedAction;
30 import java.security.ProtectionDomain;
31 import java.util.Arrays;
32 import java.util.Collections;
33 import java.util.Enumeration;
34 import java.util.HashMap;
35 import java.util.Map;
36 import java.util.Objects;
37 import java.util.Queue;
38 import java.util.ResourceBundle;
39 import java.util.concurrent.ArrayBlockingQueue;
40 import java.util.concurrent.ConcurrentHashMap;
41 import java.util.concurrent.atomic.AtomicBoolean;
42 import java.util.concurrent.atomic.AtomicLong;
43 import java.util.function.Supplier;
44 import java.lang.System.LoggerFinder;
45 import java.lang.System.Logger;
46 import java.lang.System.Logger.Level;
47 import java.security.AccessControlException;
48 import java.util.stream.Stream;
49 import sun.util.logging.PlatformLogger;
50 
51 /**
52  * @test
53  * @bug     8140364
54  * @summary JDK implementation specific unit test for JDK internal API.
55  *   Tests a naive implementation of System.Logger, and in particular
56  *   the default mapping provided by PlatformLogger.
57  * @modules java.base/sun.util.logging
58  * @build CustomSystemClassLoader BaseLoggerFinder BasePlatformLoggerTest
59  * @run  main/othervm -Djava.system.class.loader=CustomSystemClassLoader BasePlatformLoggerTest NOSECURITY
60  * @run  main/othervm -Djava.system.class.loader=CustomSystemClassLoader BasePlatformLoggerTest NOPERMISSIONS
61  * @run  main/othervm -Djava.system.class.loader=CustomSystemClassLoader BasePlatformLoggerTest WITHPERMISSIONS
62  * @author danielfuchs
63  */
64 public class BasePlatformLoggerTest {
65 
66     public static final RuntimePermission LOGGERFINDER_PERMISSION =
67                 new RuntimePermission("loggerFinder");
68 
69     final static AtomicLong sequencer = new AtomicLong();
70     final static boolean VERBOSE = false;
71     static final ThreadLocal<AtomicBoolean> allowControl = new ThreadLocal<AtomicBoolean>() {
72         @Override
73         protected AtomicBoolean initialValue() {
74             return  new AtomicBoolean(false);
75         }
76     };
77     static final ThreadLocal<AtomicBoolean> allowAccess = new ThreadLocal<AtomicBoolean>() {
78         @Override
79         protected AtomicBoolean initialValue() {
80             return  new AtomicBoolean(false);
81         }
82     };
83     static final ThreadLocal<AtomicBoolean> allowAll = new ThreadLocal<AtomicBoolean>() {
84         @Override
85         protected AtomicBoolean initialValue() {
86             return  new AtomicBoolean(false);
87         }
88     };
89 
90     static final Class<?> providerClass;
91     static {
92         try {
93             providerClass = ClassLoader.getSystemClassLoader().loadClass("BaseLoggerFinder");
94         } catch (ClassNotFoundException ex) {
95             throw new ExceptionInInitializerError(ex);
96         }
97     }
98 
99     static final PlatformLogger.Level[] julLevels = {
100         PlatformLogger.Level.ALL,
101         PlatformLogger.Level.FINEST,
102         PlatformLogger.Level.FINER,
103         PlatformLogger.Level.FINE,
104         PlatformLogger.Level.CONFIG,
105         PlatformLogger.Level.INFO,
106         PlatformLogger.Level.WARNING,
107         PlatformLogger.Level.SEVERE,
108         PlatformLogger.Level.OFF,
109     };
110 
111     static final Level[] mappedLevels = {
112         Level.ALL,     // ALL
113         Level.TRACE,   // FINEST
114         Level.TRACE,   // FINER
115         Level.DEBUG,   // FINE
116         Level.DEBUG,   // CONFIG
117         Level.INFO,    // INFO
118         Level.WARNING, // WARNING
119         Level.ERROR,   // SEVERE
120         Level.OFF,     // OFF
121     };
122 
123     final static Map<PlatformLogger.Level, Level> julToSpiMap;
124     static {
125         Map<PlatformLogger.Level, Level> map = new HashMap<>();
126         if (mappedLevels.length != julLevels.length) {
127             throw new ExceptionInInitializerError("Array lengths differ"
128                 + "\n\tjulLevels=" + Arrays.deepToString(julLevels)
129                 + "\n\tmappedLevels=" + Arrays.deepToString(mappedLevels));
130         }
131         for (int i=0; i<julLevels.length; i++) {
map.put(julLevels[i], mappedLevels[i])132             map.put(julLevels[i], mappedLevels[i]);
133         }
134         julToSpiMap = Collections.unmodifiableMap(map);
135     }
136 
137     public static class MyBundle extends ResourceBundle {
138 
139         final ConcurrentHashMap<String,String> map = new ConcurrentHashMap<>();
140 
141         @Override
handleGetObject(String key)142         protected Object handleGetObject(String key) {
143             if (key.contains(" (translated)")) {
144                 throw new RuntimeException("Unexpected key: " + key);
145             }
146             return map.computeIfAbsent(key, k -> k + " (translated)");
147         }
148 
149         @Override
getKeys()150         public Enumeration<String> getKeys() {
151             return Collections.enumeration(map.keySet());
152         }
153 
154     }
155     public static class MyLoggerBundle extends MyBundle {
156 
157     }
158 
159 
160     public static interface TestLoggerFinder  {
161         final ConcurrentHashMap<String, LoggerImpl> system = new ConcurrentHashMap<>();
162         final ConcurrentHashMap<String, LoggerImpl> user = new ConcurrentHashMap<>();
163         public Queue<LogEvent> eventQueue = new ArrayBlockingQueue<>(128);
164 
165         public static final class LogEvent implements Cloneable {
166 
LogEvent()167             public LogEvent() {
168                 this(sequencer.getAndIncrement());
169             }
170 
LogEvent(long sequenceNumber)171             LogEvent(long sequenceNumber) {
172                 this.sequenceNumber = sequenceNumber;
173             }
174 
175             long sequenceNumber;
176             boolean isLoggable;
177             String loggerName;
178             Level level;
179             ResourceBundle bundle;
180             Throwable thrown;
181             Object[] args;
182             Supplier<String> supplier;
183             String msg;
184 
toArray()185             Object[] toArray() {
186                 return new Object[] {
187                     sequenceNumber,
188                     isLoggable,
189                     loggerName,
190                     level,
191                     bundle,
192                     thrown,
193                     args,
194                     supplier,
195                     msg,
196                 };
197             }
198 
199             @Override
toString()200             public String toString() {
201                 return Arrays.deepToString(toArray());
202             }
203 
204 
205 
206             @Override
equals(Object obj)207             public boolean equals(Object obj) {
208                 return obj instanceof LogEvent
209                         && Objects.deepEquals(this.toArray(), ((LogEvent)obj).toArray());
210             }
211 
212             @Override
hashCode()213             public int hashCode() {
214                 return Objects.hash(toArray());
215             }
216 
cloneWith(long sequenceNumber)217             public LogEvent cloneWith(long sequenceNumber)
218                     throws CloneNotSupportedException {
219                 LogEvent cloned = (LogEvent)super.clone();
220                 cloned.sequenceNumber = sequenceNumber;
221                 return cloned;
222             }
223 
of(boolean isLoggable, String name, Level level, ResourceBundle bundle, String key, Throwable thrown)224             public static LogEvent of(boolean isLoggable, String name,
225                     Level level, ResourceBundle bundle,
226                     String key, Throwable thrown) {
227                 LogEvent evt = new LogEvent();
228                 evt.isLoggable = isLoggable;
229                 evt.loggerName = name;
230                 evt.level = level;
231                 evt.args = null;
232                 evt.bundle = bundle;
233                 evt.thrown = thrown;
234                 evt.supplier = null;
235                 evt.msg = key;
236                 return evt;
237             }
238 
of(boolean isLoggable, String name, Level level, Throwable thrown, Supplier<String> supplier)239             public static LogEvent of(boolean isLoggable, String name,
240                     Level level, Throwable thrown, Supplier<String> supplier) {
241                 LogEvent evt = new LogEvent();
242                 evt.isLoggable = isLoggable;
243                 evt.loggerName = name;
244                 evt.level = level;
245                 evt.args = null;
246                 evt.bundle = null;
247                 evt.thrown = thrown;
248                 evt.supplier = supplier;
249                 evt.msg = null;
250                 return evt;
251             }
252 
of(boolean isLoggable, String name, Level level, ResourceBundle bundle, String key, Object... params)253             public static LogEvent of(boolean isLoggable, String name,
254                     Level level, ResourceBundle bundle,
255                     String key, Object... params) {
256                 LogEvent evt = new LogEvent();
257                 evt.isLoggable = isLoggable;
258                 evt.loggerName = name;
259                 evt.level = level;
260                 evt.args = params;
261                 evt.bundle = bundle;
262                 evt.thrown = null;
263                 evt.supplier = null;
264                 evt.msg = key;
265                 return evt;
266             }
267 
of(long sequenceNumber, boolean isLoggable, String name, Level level, ResourceBundle bundle, String key, Supplier<String> supplier, Throwable thrown, Object... params)268             public static LogEvent of(long sequenceNumber,
269                     boolean isLoggable, String name,
270                     Level level, ResourceBundle bundle,
271                     String key, Supplier<String> supplier,
272                     Throwable thrown, Object... params) {
273                 LogEvent evt = new LogEvent(sequenceNumber);
274                 evt.loggerName = name;
275                 evt.level = level;
276                 evt.args = params;
277                 evt.bundle = bundle;
278                 evt.thrown = thrown;
279                 evt.supplier = supplier;
280                 evt.msg = key;
281                 evt.isLoggable = isLoggable;
282                 return evt;
283             }
284 
285         }
286 
287         public class LoggerImpl implements Logger {
288             private final String name;
289             private Level level = Level.INFO;
290 
LoggerImpl(String name)291             public LoggerImpl(String name) {
292                 this.name = name;
293             }
294 
295             @Override
getName()296             public String getName() {
297                 return name;
298             }
299 
300             @Override
isLoggable(Level level)301             public boolean isLoggable(Level level) {
302                 return this.level != Level.OFF && this.level.getSeverity() <= level.getSeverity();
303             }
304 
305             @Override
log(Level level, ResourceBundle bundle, String key, Throwable thrown)306             public void log(Level level, ResourceBundle bundle, String key, Throwable thrown) {
307                 log(LogEvent.of(isLoggable(level), this.name, level, bundle, key, thrown));
308             }
309 
310             @Override
log(Level level, ResourceBundle bundle, String format, Object... params)311             public void log(Level level, ResourceBundle bundle, String format, Object... params) {
312                 log(LogEvent.of(isLoggable(level), name, level, bundle, format, params));
313             }
314 
log(LogEvent event)315             void log(LogEvent event) {
316                 eventQueue.add(event);
317             }
318 
319             @Override
log(Level level, Supplier<String> msgSupplier)320             public void log(Level level, Supplier<String> msgSupplier) {
321                 log(LogEvent.of(isLoggable(level), name, level, null, msgSupplier));
322             }
323 
324             @Override
log(Level level, Supplier<String> msgSupplier, Throwable thrown)325             public void log(Level level,  Supplier<String> msgSupplier, Throwable thrown) {
326                 log(LogEvent.of(isLoggable(level), name, level, thrown, msgSupplier));
327             }
328         }
329 
getLogger(String name, Module caller)330         public Logger getLogger(String name, Module caller);
331     }
332 
getPlatformLogger(String name)333     static PlatformLogger getPlatformLogger(String name) {
334         boolean old = allowAccess.get().get();
335         allowAccess.get().set(true);
336         try {
337             return PlatformLogger.getLogger(name);
338         } finally {
339             allowAccess.get().set(old);
340         }
341     }
342 
343     static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS};
344 
setSecurityManager()345     static void setSecurityManager() {
346         if (System.getSecurityManager() == null) {
347             Policy.setPolicy(new SimplePolicy(allowControl, allowAccess, allowAll));
348             System.setSecurityManager(new SecurityManager());
349         }
350     }
351 
main(String[] args)352     public static void main(String[] args) {
353         if (args.length == 0)
354             args = new String[] {
355                 "NOSECURITY",
356                 "NOPERMISSIONS",
357                 "WITHPERMISSIONS"
358             };
359 
360 
361         Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> {
362             TestLoggerFinder provider;
363             switch (testCase) {
364                 case NOSECURITY:
365                     System.out.println("\n*** Without Security Manager\n");
366                     provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder());
367                     test(provider, true);
368                     System.out.println("Tetscase count: " + sequencer.get());
369                     break;
370                 case NOPERMISSIONS:
371                     System.out.println("\n*** With Security Manager, without permissions\n");
372                     setSecurityManager();
373                     try {
374                         provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder());
375                         throw new RuntimeException("Expected exception not raised");
376                     } catch (AccessControlException x) {
377                         if (!LOGGERFINDER_PERMISSION.equals(x.getPermission())) {
378                             throw new RuntimeException("Unexpected permission check", x);
379                         }
380                         final boolean control = allowControl.get().get();
381                         try {
382                             allowControl.get().set(true);
383                             provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder());
384                         } finally {
385                             allowControl.get().set(control);
386                         }
387                     }
388                     test(provider, false);
389                     System.out.println("Tetscase count: " + sequencer.get());
390                     break;
391                 case WITHPERMISSIONS:
392                     System.out.println("\n*** With Security Manager, with control permission\n");
393                     setSecurityManager();
394                     final boolean control = allowControl.get().get();
395                     try {
396                         allowControl.get().set(true);
397                         provider = TestLoggerFinder.class.cast(LoggerFinder.getLoggerFinder());
398                         test(provider, true);
399                     } finally {
400                         allowControl.get().set(control);
401                     }
402                     break;
403                 default:
404                     throw new RuntimeException("Unknown test case: " + testCase);
405             }
406         });
407         System.out.println("\nPASSED: Tested " + sequencer.get() + " cases.");
408     }
409 
test(TestLoggerFinder provider, boolean hasRequiredPermissions)410     public static void test(TestLoggerFinder provider, boolean hasRequiredPermissions) {
411 
412         final Map<PlatformLogger, String> loggerDescMap = new HashMap<>();
413 
414         TestLoggerFinder.LoggerImpl appSink;
415         boolean before = allowControl.get().get();
416         try {
417             allowControl.get().set(true);
418             appSink = TestLoggerFinder.LoggerImpl.class.cast(
419                         provider.getLogger("foo", BasePlatformLoggerTest.class.getModule()));
420         } finally {
421             allowControl.get().set(before);
422         }
423 
424         TestLoggerFinder.LoggerImpl sysSink = null;
425         before = allowControl.get().get();
426         try {
427             allowControl.get().set(true);
428             sysSink = TestLoggerFinder.LoggerImpl.class.cast(
429                         provider.getLogger("foo", Thread.class.getModule()));
430         } finally {
431             allowControl.get().set(before);
432         }
433 
434         if (hasRequiredPermissions && appSink == sysSink) {
435             throw new RuntimeException("identical loggers");
436         }
437 
438         if (provider.system.contains(appSink)) {
439             throw new RuntimeException("app logger in system map");
440         }
441         if (!provider.user.contains(appSink)) {
442             throw new RuntimeException("app logger not in appplication map");
443         }
444         if (hasRequiredPermissions && provider.user.contains(sysSink)) {
445             throw new RuntimeException("sys logger in appplication map");
446         }
447         if (hasRequiredPermissions && !provider.system.contains(sysSink)) {
448             throw new RuntimeException("sys logger not in system map");
449         }
450 
451         PlatformLogger platform = getPlatformLogger("foo");
452         loggerDescMap.put(platform, "PlatformLogger.getLogger(\"foo\")");
453 
454         testLogger(provider, loggerDescMap, "foo", null, platform, sysSink);
455     }
456 
457     public static class Foo {
458 
459     }
460 
verbose(String msg)461     static void verbose(String msg) {
462        if (VERBOSE) {
463            System.out.println(msg);
464        }
465     }
466 
checkLogEvent(TestLoggerFinder provider, String desc, TestLoggerFinder.LogEvent expected)467     static void checkLogEvent(TestLoggerFinder provider, String desc,
468             TestLoggerFinder.LogEvent expected) {
469         TestLoggerFinder.LogEvent actual =  provider.eventQueue.poll();
470         if (!expected.equals(actual)) {
471             throw new RuntimeException("mismatch for " + desc
472                     + "\n\texpected=" + expected
473                     + "\n\t  actual=" + actual);
474         } else {
475             verbose("Got expected results for "
476                     + desc + "\n\t" + expected);
477         }
478     }
479 
checkLogEvent(TestLoggerFinder provider, String desc, TestLoggerFinder.LogEvent expected, boolean expectNotNull)480     static void checkLogEvent(TestLoggerFinder provider, String desc,
481             TestLoggerFinder.LogEvent expected, boolean expectNotNull) {
482         TestLoggerFinder.LogEvent actual =  provider.eventQueue.poll();
483         if (actual == null && !expectNotNull) return;
484         if (actual != null && !expectNotNull) {
485             throw new RuntimeException("Unexpected log event found for " + desc
486                 + "\n\tgot: " + actual);
487         }
488         if (!expected.equals(actual)) {
489             throw new RuntimeException("mismatch for " + desc
490                     + "\n\texpected=" + expected
491                     + "\n\t  actual=" + actual);
492         } else {
493             verbose("Got expected results for "
494                     + desc + "\n\t" + expected);
495         }
496     }
497 
498     // Calls the methods defined on LogProducer and verify the
499     // parameters received by the underlying TestLoggerFinder.LoggerImpl
500     // logger.
testLogger(TestLoggerFinder provider, Map<PlatformLogger, String> loggerDescMap, String name, ResourceBundle loggerBundle, PlatformLogger logger, TestLoggerFinder.LoggerImpl sink)501     private static void testLogger(TestLoggerFinder provider,
502             Map<PlatformLogger, String> loggerDescMap,
503             String name,
504             ResourceBundle loggerBundle,
505             PlatformLogger logger,
506             TestLoggerFinder.LoggerImpl sink) {
507 
508         System.out.println("Testing " + loggerDescMap.get(logger));
509 
510         Foo foo = new Foo();
511         String fooMsg = foo.toString();
512         System.out.println("\tlogger.<level>(fooMsg)");
513         for (Level loggerLevel : Level.values()) {
514             sink.level = loggerLevel;
515             for (PlatformLogger.Level messageLevel :julLevels) {
516                 Level expectedMessageLevel = julToSpiMap.get(messageLevel);
517                 TestLoggerFinder.LogEvent expected =
518                         TestLoggerFinder.LogEvent.of(
519                             sequencer.get(),
520                             loggerLevel != Level.OFF && expectedMessageLevel.compareTo(loggerLevel) >= 0,
521                             name, expectedMessageLevel, loggerBundle,
522                             fooMsg, null, (Throwable)null, (Object[])null);
523                 String desc2 = "logger." + messageLevel.toString().toLowerCase()
524                         + "(fooMsg): loggerLevel="
525                         + loggerLevel+", messageLevel="+messageLevel;
526                 if (messageLevel == PlatformLogger.Level.FINEST) {
527                     logger.finest(fooMsg);
528                     checkLogEvent(provider, desc2, expected);
529                 } else if (messageLevel == PlatformLogger.Level.FINER) {
530                     logger.finer(fooMsg);
531                     checkLogEvent(provider, desc2, expected);
532                 } else if (messageLevel == PlatformLogger.Level.FINE) {
533                     logger.fine(fooMsg);
534                     checkLogEvent(provider, desc2, expected);
535                 } else if (messageLevel == PlatformLogger.Level.CONFIG) {
536                     logger.config(fooMsg);
537                     checkLogEvent(provider, desc2, expected);
538                 } else if (messageLevel == PlatformLogger.Level.INFO) {
539                     logger.info(fooMsg);
540                     checkLogEvent(provider, desc2, expected);
541                 } else if (messageLevel == PlatformLogger.Level.WARNING) {
542                     logger.warning(fooMsg);
543                     checkLogEvent(provider, desc2, expected);
544                 } else if (messageLevel == PlatformLogger.Level.SEVERE) {
545                     logger.severe(fooMsg);
546                     checkLogEvent(provider, desc2, expected);
547                 }
548             }
549         }
550 
551         Throwable thrown = new Exception("OK: log me!");
552         System.out.println("\tlogger.<level>(msg, thrown)");
553         for (Level loggerLevel : Level.values()) {
554             sink.level = loggerLevel;
555             for (PlatformLogger.Level messageLevel :julLevels) {
556                 Level expectedMessageLevel = julToSpiMap.get(messageLevel);
557                 TestLoggerFinder.LogEvent expected =
558                         TestLoggerFinder.LogEvent.of(
559                             sequencer.get(),
560                             loggerLevel != Level.OFF && expectedMessageLevel.compareTo(loggerLevel) >= 0,
561                             name, expectedMessageLevel, (ResourceBundle) null,
562                             fooMsg, null, (Throwable)thrown, (Object[])null);
563                 String desc2 = "logger." + messageLevel.toString().toLowerCase()
564                         + "(msg, thrown): loggerLevel="
565                         + loggerLevel+", messageLevel="+messageLevel;
566                 if (messageLevel == PlatformLogger.Level.FINEST) {
567                     logger.finest(fooMsg, thrown);
568                     checkLogEvent(provider, desc2, expected);
569                 } else if (messageLevel == PlatformLogger.Level.FINER) {
570                     logger.finer(fooMsg, thrown);
571                     checkLogEvent(provider, desc2, expected);
572                 } else if (messageLevel == PlatformLogger.Level.FINE) {
573                     logger.fine(fooMsg, thrown);
574                     checkLogEvent(provider, desc2, expected);
575                 } else if (messageLevel == PlatformLogger.Level.CONFIG) {
576                     logger.config(fooMsg, thrown);
577                     checkLogEvent(provider, desc2, expected);
578                 } else if (messageLevel == PlatformLogger.Level.INFO) {
579                     logger.info(fooMsg, thrown);
580                     checkLogEvent(provider, desc2, expected);
581                 } else if (messageLevel == PlatformLogger.Level.WARNING) {
582                     logger.warning(fooMsg, thrown);
583                     checkLogEvent(provider, desc2, expected);
584                 } else if (messageLevel == PlatformLogger.Level.SEVERE) {
585                     logger.severe(fooMsg, thrown);
586                     checkLogEvent(provider, desc2, expected);
587                 }
588             }
589         }
590 
591         String format = "two params [{1} {2}]";
592         Object arg1 = foo;
593         Object arg2 = fooMsg;
594         System.out.println("\tlogger.<level>(format, arg1, arg2)");
595         for (Level loggerLevel : Level.values()) {
596             sink.level = loggerLevel;
597             for (PlatformLogger.Level messageLevel :julLevels) {
598                 Level expectedMessageLevel = julToSpiMap.get(messageLevel);
599                 TestLoggerFinder.LogEvent expected =
600                         TestLoggerFinder.LogEvent.of(
601                             sequencer.get(),
602                             loggerLevel != Level.OFF && expectedMessageLevel.compareTo(loggerLevel) >= 0,
603                             name, expectedMessageLevel, (ResourceBundle) null,
604                             format, null, (Throwable)null, foo, fooMsg);
605                 String desc2 = "logger." + messageLevel.toString().toLowerCase()
606                         + "(format, foo, fooMsg): loggerLevel="
607                         + loggerLevel+", messageLevel="+messageLevel;
608                 if (messageLevel == PlatformLogger.Level.FINEST) {
609                     logger.finest(format, foo, fooMsg);
610                     checkLogEvent(provider, desc2, expected);
611                 } else if (messageLevel == PlatformLogger.Level.FINER) {
612                     logger.finer(format, foo, fooMsg);
613                     checkLogEvent(provider, desc2, expected);
614                 } else if (messageLevel == PlatformLogger.Level.FINE) {
615                     logger.fine(format, foo, fooMsg);
616                     checkLogEvent(provider, desc2, expected);
617                 } else if (messageLevel == PlatformLogger.Level.CONFIG) {
618                     logger.config(format, foo, fooMsg);
619                     checkLogEvent(provider, desc2, expected);
620                 } else if (messageLevel == PlatformLogger.Level.INFO) {
621                     logger.info(format, foo, fooMsg);
622                     checkLogEvent(provider, desc2, expected);
623                 } else if (messageLevel == PlatformLogger.Level.WARNING) {
624                     logger.warning(format, foo, fooMsg);
625                     checkLogEvent(provider, desc2, expected);
626                 } else if (messageLevel == PlatformLogger.Level.SEVERE) {
627                     logger.severe(format, foo, fooMsg);
628                     checkLogEvent(provider, desc2, expected);
629                 }
630             }
631         }
632 
633     }
634 
635     final static class PermissionsBuilder {
636         final Permissions perms;
PermissionsBuilder()637         public PermissionsBuilder() {
638             this(new Permissions());
639         }
PermissionsBuilder(Permissions perms)640         public PermissionsBuilder(Permissions perms) {
641             this.perms = perms;
642         }
add(Permission p)643         public PermissionsBuilder add(Permission p) {
644             perms.add(p);
645             return this;
646         }
addAll(PermissionCollection col)647         public PermissionsBuilder addAll(PermissionCollection col) {
648             if (col != null) {
649                 for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {
650                     perms.add(e.nextElement());
651                 }
652             }
653             return this;
654         }
toPermissions()655         public Permissions toPermissions() {
656             final PermissionsBuilder builder = new PermissionsBuilder();
657             builder.addAll(perms);
658             return builder.perms;
659         }
660     }
661 
662     public static class SimplePolicy extends Policy {
663         final static RuntimePermission CONTROL = LOGGERFINDER_PERMISSION;
664         final static RuntimePermission ACCESS_LOGGING = new RuntimePermission("accessClassInPackage.sun.util.logging");
665 
666         static final Policy DEFAULT_POLICY = Policy.getPolicy();
667 
668         final Permissions permissions;
669         final Permissions allPermissions;
670         final ThreadLocal<AtomicBoolean> allowControl;
671         final ThreadLocal<AtomicBoolean> allowAccess;
672         final ThreadLocal<AtomicBoolean> allowAll;
SimplePolicy(ThreadLocal<AtomicBoolean> allowControl, ThreadLocal<AtomicBoolean> allowAccess, ThreadLocal<AtomicBoolean> allowAll)673         public SimplePolicy(ThreadLocal<AtomicBoolean> allowControl,
674                 ThreadLocal<AtomicBoolean> allowAccess,
675                 ThreadLocal<AtomicBoolean> allowAll) {
676             this.allowControl = allowControl;
677             this.allowAccess = allowAccess;
678             this.allowAll = allowAll;
679             permissions = new Permissions();
680             allPermissions = new PermissionsBuilder()
681                     .add(new java.security.AllPermission())
682                     .toPermissions();
683         }
684 
getPermissions()685         Permissions getPermissions() {
686             if (allowControl.get().get() || allowAccess.get().get() || allowAll.get().get()) {
687                 PermissionsBuilder builder =  new PermissionsBuilder()
688                         .addAll(permissions);
689                 if (allowControl.get().get()) {
690                     builder.add(CONTROL);
691                 }
692                 if (allowAccess.get().get()) {
693                     builder.add(ACCESS_LOGGING);
694                 }
695                 if (allowAll.get().get()) {
696                     builder.addAll(allPermissions);
697                 }
698                 return builder.toPermissions();
699             }
700             return permissions;
701         }
702 
703         @Override
implies(ProtectionDomain domain, Permission permission)704         public boolean implies(ProtectionDomain domain, Permission permission) {
705             return getPermissions().implies(permission) || DEFAULT_POLICY.implies(domain, permission);
706         }
707 
708         @Override
getPermissions(CodeSource codesource)709         public PermissionCollection getPermissions(CodeSource codesource) {
710             return new PermissionsBuilder().addAll(getPermissions()).toPermissions();
711         }
712 
713         @Override
getPermissions(ProtectionDomain domain)714         public PermissionCollection getPermissions(ProtectionDomain domain) {
715             return new PermissionsBuilder().addAll(getPermissions()).toPermissions();
716         }
717     }
718 }
719