1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23 import java.io.ByteArrayOutputStream;
24 import java.io.IOException;
25 import java.io.PrintStream;
26 import java.io.UncheckedIOException;
27 import java.security.AccessControlException;
28 import java.security.CodeSource;
29 import java.security.Permission;
30 import java.security.PermissionCollection;
31 import java.security.Permissions;
32 import java.security.Policy;
33 import java.security.ProtectionDomain;
34 import java.util.Collections;
35 import java.util.Enumeration;
36 import java.util.HashMap;
37 import java.util.Map;
38 import java.util.ResourceBundle;
39 import java.util.stream.Stream;
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.AccessController;
48 import java.security.PrivilegedAction;
49 import java.util.EnumSet;
50 import java.util.Iterator;
51 import java.util.Locale;
52 import java.util.ServiceConfigurationError;
53 import java.util.ServiceLoader;
54 import java.util.concurrent.atomic.AtomicReference;
55 import jdk.internal.logger.SimpleConsoleLogger;
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97 public class LoggerFinderLoaderTest {
98
99 static final RuntimePermission LOGGERFINDER_PERMISSION =
100 new RuntimePermission("loggerFinder");
101 final static boolean VERBOSE = false;
102 static final ThreadLocal<AtomicBoolean> allowControl = new ThreadLocal<AtomicBoolean>() {
103 @Override
104 protected AtomicBoolean initialValue() {
105 return new AtomicBoolean(false);
106 }
107 };
108 static final ThreadLocal<AtomicBoolean> allowAccess = new ThreadLocal<AtomicBoolean>() {
109 @Override
110 protected AtomicBoolean initialValue() {
111 return new AtomicBoolean(false);
112 }
113 };
114
115 final static AccessSystemLogger accessSystemLogger = new AccessSystemLogger();
116 static final Class<?>[] providerClass;
117 static {
118 try {
119 providerClass = new Class<?>[] {
120 ClassLoader.getSystemClassLoader().loadClass("LoggerFinderLoaderTest$BaseLoggerFinder"),
121 ClassLoader.getSystemClassLoader().loadClass("LoggerFinderLoaderTest$BaseLoggerFinder2")
122 };
123 } catch (ClassNotFoundException ex) {
124 throw new ExceptionInInitializerError(ex);
125 }
126 }
127
128
129
130
131 public static interface TestLoggerFinder {
132 public final static AtomicBoolean fails = new AtomicBoolean();
133 public final static AtomicReference<String> conf = new AtomicReference<>("");
134 public final static AtomicLong sequencer = new AtomicLong();
135 public final ConcurrentHashMap<String, LoggerImpl> system = new ConcurrentHashMap<>();
136 public final ConcurrentHashMap<String, LoggerImpl> user = new ConcurrentHashMap<>();
137
138 public class LoggerImpl implements System.Logger {
139 final String name;
140 final Logger logger;
141
142 public LoggerImpl(String name, Logger logger) {
143 this.name = name;
144 this.logger = logger;
145 }
146
147 @Override
148 public String getName() {
149 return name;
150 }
151
152 @Override
153 public boolean isLoggable(Logger.Level level) {
154 return logger.isLoggable(level);
155 }
156
157 @Override
158 public void log(Logger.Level level, ResourceBundle bundle, String key, Throwable thrown) {
159 logger.log(level, bundle, key, thrown);
160 }
161
162 @Override
163 public void log(Logger.Level level, ResourceBundle bundle, String format, Object... params) {
164 logger.log(level, bundle, format, params);
165 }
166
167 }
168
169 public Logger getLogger(String name, Module caller);
170 public Logger getLocalizedLogger(String name, ResourceBundle bundle, Module caller);
171 }
172
173 public static class BaseLoggerFinder extends LoggerFinder implements TestLoggerFinder {
174
175 static final RuntimePermission LOGGERFINDER_PERMISSION =
176 new RuntimePermission("loggerFinder");
177 public BaseLoggerFinder() {
178 if (fails.get()) {
179 throw new RuntimeException("Simulate exception while loading provider");
180 }
181 }
182
183 System.Logger createSimpleLogger(String name) {
184 PrivilegedAction<System.Logger> pa = () -> SimpleConsoleLogger.makeSimpleLogger(name);
185 return AccessController.doPrivileged(pa);
186 }
187
188
189 @Override
190 public Logger getLogger(String name, Module caller) {
191 SecurityManager sm = System.getSecurityManager();
192 if (sm != null) {
193 sm.checkPermission(LOGGERFINDER_PERMISSION);
194 }
195 PrivilegedAction<ClassLoader> pa = () -> caller.getClassLoader();
196 ClassLoader callerLoader = AccessController.doPrivileged(pa);
197 if (callerLoader == null) {
198 return system.computeIfAbsent(name, (n) -> new LoggerImpl(n, createSimpleLogger(name)));
199 } else {
200 return user.computeIfAbsent(name, (n) -> new LoggerImpl(n, createSimpleLogger(name)));
201 }
202 }
203 }
204
205 public static class BaseLoggerFinder2 extends LoggerFinder implements TestLoggerFinder {
206
207 static final RuntimePermission LOGGERFINDER_PERMISSION =
208 new RuntimePermission("loggerFinder");
209 public BaseLoggerFinder2() {
210 throw new ServiceConfigurationError("Should not come here");
211 }
212 @Override
213 public Logger getLogger(String name, Module caller) {
214 throw new ServiceConfigurationError("Should not come here");
215 }
216 }
217
218 public static class MyBundle extends ResourceBundle {
219
220 final ConcurrentHashMap<String,String> map = new ConcurrentHashMap<>();
221
222 @Override
223 protected Object handleGetObject(String key) {
224 if (key.contains(" (translated)")) {
225 throw new RuntimeException("Unexpected key: " + key);
226 }
227 return map.computeIfAbsent(key, k -> k.toUpperCase(Locale.ROOT) + " (translated)");
228 }
229
230 @Override
231 public Enumeration<String> getKeys() {
232 return Collections.enumeration(map.keySet());
233 }
234
235 }
236 public static class MyLoggerBundle extends MyBundle {
237
238 }
239
240 static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS};
241
242 static void setSecurityManager() {
243 if (System.getSecurityManager() == null) {
244 Policy.setPolicy(new SimplePolicy(allowControl, allowAccess));
245 System.setSecurityManager(new SecurityManager());
246 }
247 }
248
249 static LoggerFinder getLoggerFinder(Class<?> expectedClass,
250 String errorPolicy, boolean singleton) {
251 LoggerFinder provider = null;
252 try {
253 TestLoggerFinder.sequencer.incrementAndGet();
254 provider = LoggerFinder.getLoggerFinder();
255 if (TestLoggerFinder.fails.get() || singleton) {
256 if ("ERROR".equals(errorPolicy.toUpperCase(Locale.ROOT))) {
257 throw new RuntimeException("Expected exception not thrown");
258 } else if ("WARNING".equals(errorPolicy.toUpperCase(Locale.ROOT))) {
259 String warning = ErrorStream.errorStream.peek();
260 if (!warning.contains("WARNING: Failed to instantiate LoggerFinder provider; Using default.")) {
261 throw new RuntimeException("Expected message not found. Error stream contained: " + warning);
262 }
263 } else if ("DEBUG".equals(errorPolicy.toUpperCase(Locale.ROOT))) {
264 String warning = ErrorStream.errorStream.peek();
265 if (!warning.contains("WARNING: Failed to instantiate LoggerFinder provider; Using default.")) {
266 throw new RuntimeException("Expected message not found. Error stream contained: " + warning);
267 }
268 if (!warning.contains("WARNING: Exception raised trying to instantiate LoggerFinder")) {
269 throw new RuntimeException("Expected message not found. Error stream contained: " + warning);
270 }
271 if (TestLoggerFinder.fails.get()) {
272 if (!warning.contains("java.util.ServiceConfigurationError: java.lang.System$LoggerFinder: Provider LoggerFinderLoaderTest$BaseLoggerFinder could not be instantiated")) {
273 throw new RuntimeException("Expected message not found. Error stream contained: " + warning);
274 }
275 } else if (singleton) {
276 if (!warning.contains("java.util.ServiceConfigurationError: More than on LoggerFinder implementation")) {
277 throw new RuntimeException("Expected message not found. Error stream contained: " + warning);
278 }
279 }
280 } else if ("QUIET".equals(errorPolicy.toUpperCase(Locale.ROOT))) {
281 if (!ErrorStream.errorStream.peek().isEmpty()) {
282 throw new RuntimeException("Unexpected error message found: "
283 + ErrorStream.errorStream.peek());
284 }
285 }
286 }
287 } catch(AccessControlException a) {
288 throw a;
289 } catch(Throwable t) {
290 if (TestLoggerFinder.fails.get() || singleton) {
291
292 if ("ERROR".equals(errorPolicy.toUpperCase(Locale.ROOT))) {
293 provider = LoggerFinder.getLoggerFinder();
294 } else {
295 Throwable orig = t.getCause();
296 while (orig != null && orig.getCause() != null) orig = orig.getCause();
297 if (orig != null) orig.printStackTrace(ErrorStream.err);
298 throw new RuntimeException("Unexpected exception: " + t, t);
299 }
300 } else {
301 throw new RuntimeException("Unexpected exception: " + t, t);
302 }
303 }
304 expectedClass.cast(provider);
305 ErrorStream.errorStream.store();
306 System.out.println("*** Actual LoggerFinder class is: " + provider.getClass().getName());
307 return provider;
308 }
309
310
311 static class ErrorStream extends PrintStream {
312
313 static AtomicBoolean forward = new AtomicBoolean();
314 ByteArrayOutputStream out;
315 String saved = "";
316 public ErrorStream(ByteArrayOutputStream out) {
317 super(out);
318 this.out = out;
319 }
320
321 @Override
322 public void write(int b) {
323 super.write(b);
324 if (forward.get()) err.write(b);
325 }
326
327 @Override
328 public void write(byte[] b) throws IOException {
329 super.write(b);
330 if (forward.get()) err.write(b);
331 }
332
333 @Override
334 public void write(byte[] buf, int off, int len) {
335 super.write(buf, off, len);
336 if (forward.get()) err.write(buf, off, len);
337 }
338
339 public String peek() {
340 flush();
341 return out.toString();
342 }
343
344 public String drain() {
345 flush();
346 String res = out.toString();
347 out.reset();
348 return res;
349 }
350
351 public void store() {
352 flush();
353 saved = out.toString();
354 out.reset();
355 }
356
357 public void restore() {
358 out.reset();
359 try {
360 out.write(saved.getBytes());
361 } catch(IOException io) {
362 throw new UncheckedIOException(io);
363 }
364 }
365
366 static final PrintStream err = System.err;
367 static final ErrorStream errorStream = new ErrorStream(new ByteArrayOutputStream());
368 }
369
370 private static StringBuilder appendProperty(StringBuilder b, String name) {
371 String value = System.getProperty(name);
372 if (value == null) return b;
373 return b.append(name).append("=").append(value).append('\n');
374 }
375
376 public static void main(String[] args) {
377 if (args.length == 0) {
378 args = new String[] {
379 "NOSECURITY",
380 "NOPERMISSIONS",
381 "WITHPERMISSIONS"
382 };
383 }
384 Locale.setDefault(Locale.ENGLISH);
385 System.setErr(ErrorStream.errorStream);
386 System.setProperty("jdk.logger.packages", TestLoggerFinder.LoggerImpl.class.getName());
387
388
389
390 TestLoggerFinder.fails.set(Boolean.getBoolean("test.fails"));
391 StringBuilder c = new StringBuilder();
392 appendProperty(c, "jdk.logger.packages");
393 appendProperty(c, "jdk.logger.finder.error");
394 appendProperty(c, "jdk.logger.finder.singleton");
395 appendProperty(c, "test.fails");
396 TestLoggerFinder.conf.set(c.toString());
397 try {
398 test(args);
399 } finally {
400 try {
401 System.setErr(ErrorStream.err);
402 } catch (Error | RuntimeException x) {
403 x.printStackTrace(ErrorStream.err);
404 }
405 }
406 }
407
408
409 public static void test(String[] args) {
410
411 final String errorPolicy = System.getProperty("jdk.logger.finder.error", "WARNING");
412 final Boolean ensureSingleton = Boolean.getBoolean("jdk.logger.finder.singleton");
413
414 final Class<?> expectedClass =
415 TestLoggerFinder.fails.get() || ensureSingleton
416 ? jdk.internal.logger.DefaultLoggerFinder.class
417 : TestLoggerFinder.class;
418
419 System.out.println("Declared provider class: " + providerClass[0]
420 + "[" + providerClass[0].getClassLoader() + "]");
421
422 if (!TestLoggerFinder.fails.get()) {
423 ServiceLoader<LoggerFinder> serviceLoader =
424 ServiceLoader.load(LoggerFinder.class, ClassLoader.getSystemClassLoader());
425 Iterator<LoggerFinder> iterator = serviceLoader.iterator();
426 Object firstProvider = iterator.next();
427 if (!firstProvider.getClass().getName().equals("LoggerFinderLoaderTest$BaseLoggerFinder")) {
428 throw new RuntimeException("Unexpected provider: " + firstProvider.getClass().getName());
429 }
430 if (!iterator.hasNext()) {
431 throw new RuntimeException("Expected two providers");
432 }
433 }
434
435 Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> {
436 LoggerFinder provider;
437 ErrorStream.errorStream.restore();
438 switch (testCase) {
439 case NOSECURITY:
440 System.out.println("\n*** Without Security Manager\n");
441 System.out.println(TestLoggerFinder.conf.get());
442 provider = getLoggerFinder(expectedClass, errorPolicy, ensureSingleton);
443 test(provider, true);
444 System.out.println("Tetscase count: " + TestLoggerFinder.sequencer.get());
445 break;
446 case NOPERMISSIONS:
447 System.out.println("\n*** With Security Manager, without permissions\n");
448 System.out.println(TestLoggerFinder.conf.get());
449 setSecurityManager();
450 try {
451 provider = getLoggerFinder(expectedClass, errorPolicy, ensureSingleton);
452 throw new RuntimeException("Expected exception not raised");
453 } catch (AccessControlException x) {
454 if (!LOGGERFINDER_PERMISSION.equals(x.getPermission())) {
455 throw new RuntimeException("Unexpected permission check", x);
456 }
457 final boolean control = allowControl.get().get();
458 try {
459 allowControl.get().set(true);
460 provider = getLoggerFinder(expectedClass, errorPolicy, ensureSingleton);
461 } finally {
462 allowControl.get().set(control);
463 }
464 }
465 test(provider, false);
466 System.out.println("Tetscase count: " + TestLoggerFinder.sequencer.get());
467 break;
468 case WITHPERMISSIONS:
469 System.out.println("\n*** With Security Manager, with control permission\n");
470 System.out.println(TestLoggerFinder.conf.get());
471 setSecurityManager();
472 final boolean control = allowControl.get().get();
473 try {
474 allowControl.get().set(true);
475 provider = getLoggerFinder(expectedClass, errorPolicy, ensureSingleton);
476 test(provider, true);
477 } finally {
478 allowControl.get().set(control);
479 }
480 break;
481 default:
482 throw new RuntimeException("Unknown test case: " + testCase);
483 }
484 });
485 System.out.println("\nPASSED: Tested " + TestLoggerFinder.sequencer.get() + " cases.");
486 }
487
488 public static void test(LoggerFinder provider, boolean hasRequiredPermissions) {
489
490 ResourceBundle loggerBundle = ResourceBundle.getBundle(MyLoggerBundle.class.getName());
491 final Map<Logger, String> loggerDescMap = new HashMap<>();
492
493 System.Logger sysLogger = accessSystemLogger.getLogger("foo");
494 loggerDescMap.put(sysLogger, "accessSystemLogger.getLogger(\"foo\")");
495 System.Logger localizedSysLogger = accessSystemLogger.getLogger("fox", loggerBundle);
496 loggerDescMap.put(localizedSysLogger, "accessSystemLogger.getLogger(\"fox\", loggerBundle)");
497 System.Logger appLogger = System.getLogger("bar");
498 loggerDescMap.put(appLogger,"System.getLogger(\"bar\")");
499 System.Logger localizedAppLogger = System.getLogger("baz", loggerBundle);
500 loggerDescMap.put(localizedAppLogger,"System.getLogger(\"baz\", loggerBundle)");
501
502 testLogger(provider, loggerDescMap, "foo", null, sysLogger);
503 testLogger(provider, loggerDescMap, "foo", loggerBundle, localizedSysLogger);
504 testLogger(provider, loggerDescMap, "foo", null, appLogger);
505 testLogger(provider, loggerDescMap, "foo", loggerBundle, localizedAppLogger);
506 }
507
508 public static class Foo {
509
510 }
511
512 static void verbose(String msg) {
513 if (VERBOSE) {
514 System.out.println(msg);
515 }
516 }
517
518
519
520
521 private static void testLogger(LoggerFinder provider,
522 Map<Logger, String> loggerDescMap,
523 String name,
524 ResourceBundle loggerBundle,
525 Logger logger) {
526
527 System.out.println("Testing " + loggerDescMap.get(logger) + " [" + logger +"]");
528 AtomicLong sequencer = TestLoggerFinder.sequencer;
529
530 Foo foo = new Foo();
531 String fooMsg = foo.toString();
532 for (Level loggerLevel : EnumSet.of(Level.INFO)) {
533 for (Level messageLevel : Level.values()) {
534 ErrorStream.errorStream.drain();
535 String desc = "logger.log(messageLevel, foo): loggerLevel="
536 + loggerLevel+", messageLevel="+messageLevel;
537 sequencer.incrementAndGet();
538 logger.log(messageLevel, foo);
539 if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
540 if (!ErrorStream.errorStream.peek().isEmpty()) {
541 throw new RuntimeException("unexpected event in queue for "
542 + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
543 }
544 } else {
545 String logged = ErrorStream.errorStream.drain();
546 if (!logged.contains("LoggerFinderLoaderTest testLogger")
547 || !logged.contains(messageLevel.getName() + ": " + fooMsg)) {
548 throw new RuntimeException("mismatch for " + desc
549 + "\n\texpected:" + "\n<<<<\n"
550 + "[date] LoggerFinderLoaderTest testLogger\n"
551 + messageLevel.getName() + " " + fooMsg
552 + "\n>>>>"
553 + "\n\t actual:"
554 + "\n<<<<\n" + logged + ">>>>\n");
555 } else {
556 verbose("Got expected results for "
557 + desc + "\n<<<<\n" + logged + ">>>>\n");
558 }
559 }
560 }
561 }
562
563 String msg = "blah";
564 for (Level loggerLevel : EnumSet.of(Level.INFO)) {
565 for (Level messageLevel : Level.values()) {
566 String desc = "logger.log(messageLevel, \"blah\"): loggerLevel="
567 + loggerLevel+", messageLevel="+messageLevel;
568 sequencer.incrementAndGet();
569 logger.log(messageLevel, msg);
570 if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
571 if (!ErrorStream.errorStream.peek().isEmpty()) {
572 throw new RuntimeException("unexpected event in queue for "
573 + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
574 }
575 } else {
576 String logged = ErrorStream.errorStream.drain();
577 String msgText = loggerBundle == null ? msg : loggerBundle.getString(msg);
578 if (!logged.contains("LoggerFinderLoaderTest testLogger")
579 || !logged.contains(messageLevel.getName() + ": " + msgText)) {
580 throw new RuntimeException("mismatch for " + desc
581 + "\n\texpected:" + "\n<<<<\n"
582 + "[date] LoggerFinderLoaderTest testLogger\n"
583 + messageLevel.getName() + " " + msgText
584 + "\n>>>>"
585 + "\n\t actual:"
586 + "\n<<<<\n" + logged + ">>>>\n");
587 } else {
588 verbose("Got expected results for "
589 + desc + "\n<<<<\n" + logged + ">>>>\n");
590 }
591 }
592 }
593 }
594
595 Supplier<String> fooSupplier = new Supplier<String>() {
596 @Override
597 public String get() {
598 return this.toString();
599 }
600 };
601
602 for (Level loggerLevel : EnumSet.of(Level.INFO)) {
603 for (Level messageLevel : Level.values()) {
604 String desc = "logger.log(messageLevel, fooSupplier): loggerLevel="
605 + loggerLevel+", messageLevel="+messageLevel;
606 sequencer.incrementAndGet();
607 logger.log(messageLevel, fooSupplier);
608 if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
609 if (!ErrorStream.errorStream.peek().isEmpty()) {
610 throw new RuntimeException("unexpected event in queue for "
611 + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
612 }
613 } else {
614 String logged = ErrorStream.errorStream.drain();
615 if (!logged.contains("LoggerFinderLoaderTest testLogger")
616 || !logged.contains(messageLevel.getName() + ": " + fooSupplier.get())) {
617 throw new RuntimeException("mismatch for " + desc
618 + "\n\texpected:" + "\n<<<<\n"
619 + "[date] LoggerFinderLoaderTest testLogger\n"
620 + messageLevel.getName() + " " + fooSupplier.get()
621 + "\n>>>>"
622 + "\n\t actual:"
623 + "\n<<<<\n" + logged + ">>>>\n");
624 } else {
625 verbose("Got expected results for "
626 + desc + "\n<<<<\n" + logged + ">>>>\n");
627 }
628 }
629 }
630 }
631
632
633 String format = "two params [{1} {2}]";
634 Object arg1 = foo;
635 Object arg2 = msg;
636 for (Level loggerLevel : EnumSet.of(Level.INFO)) {
637 for (Level messageLevel : Level.values()) {
638 String desc = "logger.log(messageLevel, format, params...): loggerLevel="
639 + loggerLevel+", messageLevel="+messageLevel;
640 sequencer.incrementAndGet();
641 logger.log(messageLevel, format, foo, msg);
642 if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
643 if (!ErrorStream.errorStream.peek().isEmpty()) {
644 throw new RuntimeException("unexpected event in queue for "
645 + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
646 }
647 } else {
648 String logged = ErrorStream.errorStream.drain();
649 String msgFormat = loggerBundle == null ? format : loggerBundle.getString(format);
650 String text = java.text.MessageFormat.format(msgFormat, foo, msg);
651 if (!logged.contains("LoggerFinderLoaderTest testLogger")
652 || !logged.contains(messageLevel.getName() + ": " + text)) {
653 throw new RuntimeException("mismatch for " + desc
654 + "\n\texpected:" + "\n<<<<\n"
655 + "[date] LoggerFinderLoaderTest testLogger\n"
656 + messageLevel.getName() + " " + text
657 + "\n>>>>"
658 + "\n\t actual:"
659 + "\n<<<<\n" + logged + ">>>>\n");
660 } else {
661 verbose("Got expected results for "
662 + desc + "\n<<<<\n" + logged + ">>>>\n");
663 }
664 }
665 }
666 }
667
668 Throwable thrown = new Exception("OK: log me!");
669 for (Level loggerLevel : EnumSet.of(Level.INFO)) {
670 for (Level messageLevel : Level.values()) {
671 String desc = "logger.log(messageLevel, \"blah\", thrown): loggerLevel="
672 + loggerLevel+", messageLevel="+messageLevel;
673 sequencer.incrementAndGet();
674 logger.log(messageLevel, msg, thrown);
675 if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
676 if (!ErrorStream.errorStream.peek().isEmpty()) {
677 throw new RuntimeException("unexpected event in queue for "
678 + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
679 }
680 } else {
681 String logged = ErrorStream.errorStream.drain();
682 ByteArrayOutputStream baos = new ByteArrayOutputStream();
683 thrown.printStackTrace(new PrintStream(baos));
684 String text = baos.toString();
685 String msgText = loggerBundle == null ? msg : loggerBundle.getString(msg);
686 if (!logged.contains("LoggerFinderLoaderTest testLogger")
687 || !logged.contains(messageLevel.getName() + ": " + msgText)
688 || !logged.contains(text)) {
689 throw new RuntimeException("mismatch for " + desc
690 + "\n\texpected:" + "\n<<<<\n"
691 + "[date] LoggerFinderLoaderTest testLogger\n"
692 + messageLevel.getName() + " " + msgText +"\n"
693 + text
694 + ">>>>"
695 + "\n\t actual:"
696 + "\n<<<<\n" + logged + ">>>>\n");
697 } else {
698 verbose("Got expected results for "
699 + desc + "\n<<<<\n" + logged + ">>>>\n");
700 }
701 }
702 }
703 }
704
705
706 for (Level loggerLevel : EnumSet.of(Level.INFO)) {
707 for (Level messageLevel : Level.values()) {
708 String desc = "logger.log(messageLevel, thrown, fooSupplier): loggerLevel="
709 + loggerLevel+", messageLevel="+messageLevel;
710 sequencer.incrementAndGet();
711 logger.log(messageLevel, fooSupplier, thrown);
712 if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
713 if (!ErrorStream.errorStream.peek().isEmpty()) {
714 throw new RuntimeException("unexpected event in queue for "
715 + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
716 }
717 } else {
718 String logged = ErrorStream.errorStream.drain();
719 ByteArrayOutputStream baos = new ByteArrayOutputStream();
720 thrown.printStackTrace(new PrintStream(baos));
721 String text = baos.toString();
722 if (!logged.contains("LoggerFinderLoaderTest testLogger")
723 || !logged.contains(messageLevel.getName() + ": " + fooSupplier.get())
724 || !logged.contains(text)) {
725 throw new RuntimeException("mismatch for " + desc
726 + "\n\texpected:" + "\n<<<<\n"
727 + "[date] LoggerFinderLoaderTest testLogger\n"
728 + messageLevel.getName() + " " + fooSupplier.get() +"\n"
729 + text
730 + ">>>>"
731 + "\n\t actual:"
732 + "\n<<<<\n" + logged + ">>>>\n");
733 } else {
734 verbose("Got expected results for "
735 + desc + "\n<<<<\n" + logged + ">>>>\n");
736 }
737 }
738 }
739 }
740
741 ResourceBundle bundle = ResourceBundle.getBundle(MyBundle.class.getName());
742 for (Level loggerLevel : EnumSet.of(Level.INFO)) {
743 for (Level messageLevel : Level.values()) {
744 String desc = "logger.log(messageLevel, bundle, format, params...): loggerLevel="
745 + loggerLevel+", messageLevel="+messageLevel;
746 sequencer.incrementAndGet();
747 logger.log(messageLevel, bundle, format, foo, msg);
748 if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
749 if (!ErrorStream.errorStream.peek().isEmpty()) {
750 throw new RuntimeException("unexpected event in queue for "
751 + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
752 }
753 } else {
754 String logged = ErrorStream.errorStream.drain();
755 String text = java.text.MessageFormat.format(bundle.getString(format), foo, msg);
756 if (!logged.contains("LoggerFinderLoaderTest testLogger")
757 || !logged.contains(messageLevel.getName() + ": " + text)) {
758 throw new RuntimeException("mismatch for " + desc
759 + "\n\texpected:" + "\n<<<<\n"
760 + "[date] LoggerFinderLoaderTest testLogger\n"
761 + messageLevel.getName() + " " + text
762 + "\n>>>>"
763 + "\n\t actual:"
764 + "\n<<<<\n" + logged + ">>>>\n");
765 } else {
766 verbose("Got expected results for "
767 + desc + "\n<<<<\n" + logged + ">>>>\n");
768 }
769 }
770 }
771 }
772
773 for (Level loggerLevel : EnumSet.of(Level.INFO)) {
774 for (Level messageLevel : Level.values()) {
775 String desc = "logger.log(messageLevel, bundle, \"blah\", thrown): loggerLevel="
776 + loggerLevel+", messageLevel="+messageLevel;
777 sequencer.incrementAndGet();
778 logger.log(messageLevel, bundle, msg, thrown);
779 if (loggerLevel == Level.OFF || messageLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
780 if (!ErrorStream.errorStream.peek().isEmpty()) {
781 throw new RuntimeException("unexpected event in queue for "
782 + desc +": " + "\n\t" + ErrorStream.errorStream.drain());
783 }
784 } else {
785 String logged = ErrorStream.errorStream.drain();
786 String textMsg = bundle.getString(msg);
787 ByteArrayOutputStream baos = new ByteArrayOutputStream();
788 thrown.printStackTrace(new PrintStream(baos));
789 String text = baos.toString();
790 if (!logged.contains("LoggerFinderLoaderTest testLogger")
791 || !logged.contains(messageLevel.getName() + ": " + textMsg)
792 || !logged.contains(text)) {
793 throw new RuntimeException("mismatch for " + desc
794 + "\n\texpected:" + "\n<<<<\n"
795 + "[date] LoggerFinderLoaderTest testLogger\n"
796 + messageLevel.getName() + " " + textMsg +"\n"
797 + text
798 + ">>>>"
799 + "\n\t actual:"
800 + "\n<<<<\n" + logged + ">>>>\n");
801 } else {
802 verbose("Got expected results for "
803 + desc + "\n<<<<\n" + logged + ">>>>\n");
804 }
805 }
806 }
807 }
808
809 }
810
811 final static class PermissionsBuilder {
812 final Permissions perms;
813 public PermissionsBuilder() {
814 this(new Permissions());
815 }
816 public PermissionsBuilder(Permissions perms) {
817 this.perms = perms;
818 }
819 public PermissionsBuilder add(Permission p) {
820 perms.add(p);
821 return this;
822 }
823 public PermissionsBuilder addAll(PermissionCollection col) {
824 if (col != null) {
825 for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {
826 perms.add(e.nextElement());
827 }
828 }
829 return this;
830 }
831 public Permissions toPermissions() {
832 final PermissionsBuilder builder = new PermissionsBuilder();
833 builder.addAll(perms);
834 return builder.perms;
835 }
836 }
837
838 public static class SimplePolicy extends Policy {
839 final static RuntimePermission CONTROL = LOGGERFINDER_PERMISSION;
840 final static RuntimePermission ACCESS = new RuntimePermission("accessClassInPackage.jdk.internal.logger");
841
842 final Permissions permissions;
843 final ThreadLocal<AtomicBoolean> allowControl;
844 final ThreadLocal<AtomicBoolean> allowAccess;
845 public SimplePolicy(ThreadLocal<AtomicBoolean> allowControl, ThreadLocal<AtomicBoolean> allowAccess) {
846 this.allowControl = allowControl;
847 this.allowAccess = allowAccess;
848 permissions = new Permissions();
849 permissions.add(new RuntimePermission("setIO"));
850 }
851
852 Permissions getPermissions() {
853 if (allowControl.get().get() || allowAccess.get().get()) {
854 PermissionsBuilder builder = new PermissionsBuilder()
855 .addAll(permissions);
856 if (allowControl.get().get()) {
857 builder.add(CONTROL);
858 }
859 if (allowAccess.get().get()) {
860 builder.add(ACCESS);
861 }
862 return builder.toPermissions();
863 }
864 return permissions;
865 }
866
867 @Override
868 public boolean implies(ProtectionDomain domain, Permission permission) {
869 return getPermissions().implies(permission);
870 }
871
872 @Override
873 public PermissionCollection getPermissions(CodeSource codesource) {
874 return new PermissionsBuilder().addAll(getPermissions()).toPermissions();
875 }
876
877 @Override
878 public PermissionCollection getPermissions(ProtectionDomain domain) {
879 return new PermissionsBuilder().addAll(getPermissions()).toPermissions();
880 }
881 }
882 }