Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
PojavLauncherTeam
GitHub Repository: PojavLauncherTeam/mobile
Path: blob/master/test/jdk/java/lang/System/Logger/custom/CustomLoggerTest.java
41154 views
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.AccessControlException;
24
import java.security.AccessController;
25
import java.security.CodeSource;
26
import java.security.Permission;
27
import java.security.PermissionCollection;
28
import java.security.Permissions;
29
import java.security.Policy;
30
import java.security.PrivilegedAction;
31
import java.security.ProtectionDomain;
32
import java.util.Arrays;
33
import java.util.Collections;
34
import java.util.Enumeration;
35
import java.util.HashMap;
36
import java.util.Map;
37
import java.util.Objects;
38
import java.util.Queue;
39
import java.util.ResourceBundle;
40
import java.util.concurrent.ArrayBlockingQueue;
41
import java.util.concurrent.ConcurrentHashMap;
42
import java.util.concurrent.atomic.AtomicBoolean;
43
import java.util.concurrent.atomic.AtomicLong;
44
import java.util.function.Supplier;
45
import java.lang.System.LoggerFinder;
46
import java.lang.System.Logger;
47
import java.lang.System.Logger.Level;
48
import java.util.stream.Stream;
49
import java.security.AllPermission;
50
51
/**
52
* @test
53
* @bug 8140364
54
* @summary Tests loggers returned by System.getLogger with a naive implementation
55
* of LoggerFinder, and in particular the default body of
56
* System.Logger methods.
57
* @build CustomLoggerTest AccessSystemLogger
58
* @run driver AccessSystemLogger
59
* @run main/othervm -Xbootclasspath/a:boot CustomLoggerTest NOSECURITY
60
* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow CustomLoggerTest NOPERMISSIONS
61
* @run main/othervm -Xbootclasspath/a:boot -Djava.security.manager=allow CustomLoggerTest WITHPERMISSIONS
62
* @author danielfuchs
63
*/
64
public class CustomLoggerTest {
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> allowAll = new ThreadLocal<AtomicBoolean>() {
75
@Override
76
protected AtomicBoolean initialValue() {
77
return new AtomicBoolean(false);
78
}
79
};
80
81
public static class MyBundle extends ResourceBundle {
82
83
final ConcurrentHashMap<String,String> map = new ConcurrentHashMap<>();
84
85
@Override
86
protected Object handleGetObject(String key) {
87
if (key.contains(" (translated)")) {
88
throw new RuntimeException("Unexpected key: " + key);
89
}
90
return map.computeIfAbsent(key, k -> k + " (translated)");
91
}
92
93
@Override
94
public Enumeration<String> getKeys() {
95
return Collections.enumeration(map.keySet());
96
}
97
98
}
99
public static class MyLoggerBundle extends MyBundle {
100
101
}
102
103
104
public static class BaseLoggerFinder extends LoggerFinder {
105
final ConcurrentHashMap<String, LoggerImpl> system = new ConcurrentHashMap<>();
106
final ConcurrentHashMap<String, LoggerImpl> user = new ConcurrentHashMap<>();
107
public Queue<LogEvent> eventQueue = new ArrayBlockingQueue<>(128);
108
109
// changing this to true requires changing the logic in the
110
// test in order to load this class with a protection domain
111
// that has the CONTROL_PERMISSION (e.g. by using a custom
112
// system class loader.
113
final boolean doChecks = false;
114
115
public static final class LogEvent {
116
117
public LogEvent() {
118
this(sequencer.getAndIncrement());
119
}
120
121
LogEvent(long sequenceNumber) {
122
this.sequenceNumber = sequenceNumber;
123
}
124
125
long sequenceNumber;
126
boolean isLoggable;
127
String loggerName;
128
Level level;
129
ResourceBundle bundle;
130
Throwable thrown;
131
Object[] args;
132
Supplier<String> supplier;
133
String msg;
134
135
Object[] toArray() {
136
return new Object[] {
137
sequenceNumber,
138
isLoggable,
139
loggerName,
140
level,
141
bundle,
142
thrown,
143
args,
144
supplier,
145
msg,
146
};
147
}
148
149
@Override
150
public String toString() {
151
return Arrays.deepToString(toArray());
152
}
153
154
155
156
@Override
157
public boolean equals(Object obj) {
158
return obj instanceof LogEvent
159
&& Objects.deepEquals(this.toArray(), ((LogEvent)obj).toArray());
160
}
161
162
@Override
163
public int hashCode() {
164
return Objects.hash(toArray());
165
}
166
167
168
public static LogEvent of(boolean isLoggable, String name,
169
Level level, ResourceBundle bundle,
170
String key, Throwable thrown) {
171
LogEvent evt = new LogEvent();
172
evt.isLoggable = isLoggable;
173
evt.loggerName = name;
174
evt.level = level;
175
evt.args = null;
176
evt.bundle = bundle;
177
evt.thrown = thrown;
178
evt.supplier = null;
179
evt.msg = key;
180
return evt;
181
}
182
183
public static LogEvent of(boolean isLoggable, String name,
184
Level level, ResourceBundle bundle,
185
String key, Object... params) {
186
LogEvent evt = new LogEvent();
187
evt.isLoggable = isLoggable;
188
evt.loggerName = name;
189
evt.level = level;
190
evt.args = params;
191
evt.bundle = bundle;
192
evt.thrown = null;
193
evt.supplier = null;
194
evt.msg = key;
195
return evt;
196
}
197
198
public static LogEvent of(long sequenceNumber,
199
boolean isLoggable, String name,
200
Level level, ResourceBundle bundle,
201
String key, Supplier<String> supplier,
202
Throwable thrown, Object... params) {
203
LogEvent evt = new LogEvent(sequenceNumber);
204
evt.loggerName = name;
205
evt.level = level;
206
evt.args = params;
207
evt.bundle = bundle;
208
evt.thrown = thrown;
209
evt.supplier = supplier;
210
evt.msg = key;
211
evt.isLoggable = isLoggable;
212
return evt;
213
}
214
215
}
216
217
public class LoggerImpl implements Logger {
218
private final String name;
219
private Level level = Level.INFO;
220
221
public LoggerImpl(String name) {
222
this.name = name;
223
}
224
225
@Override
226
public String getName() {
227
return name;
228
}
229
230
@Override
231
public boolean isLoggable(Level level) {
232
return this.level != Level.OFF && this.level.getSeverity() <= level.getSeverity();
233
}
234
235
@Override
236
public void log(Level level, ResourceBundle bundle, String key, Throwable thrown) {
237
log(LogEvent.of(isLoggable(level), this.name, level, bundle, key, thrown));
238
}
239
240
@Override
241
public void log(Level level, ResourceBundle bundle, String format, Object... params) {
242
log(LogEvent.of(isLoggable(level), name, level, bundle, format, params));
243
}
244
245
void log(LogEvent event) {
246
eventQueue.add(event);
247
}
248
}
249
250
@Override
251
public Logger getLogger(String name, Module caller) {
252
// We should check the permission to obey the API contract, but
253
// what happens if we don't?
254
// This is the main difference compared with what we test in
255
// java/lang/System/LoggerFinder/BaseLoggerFinderTest
256
SecurityManager sm = System.getSecurityManager();
257
if (sm != null && doChecks) {
258
sm.checkPermission(SimplePolicy.LOGGERFINDER_PERMISSION);
259
}
260
261
final boolean before = allowAll.get().getAndSet(true);
262
final ClassLoader callerLoader;
263
try {
264
callerLoader = caller.getClassLoader();
265
} finally {
266
allowAll.get().set(before);
267
}
268
if (callerLoader == null) {
269
return system.computeIfAbsent(name, (n) -> new LoggerImpl(n));
270
} else {
271
return user.computeIfAbsent(name, (n) -> new LoggerImpl(n));
272
}
273
}
274
}
275
276
static final AccessSystemLogger accessSystemLogger = new AccessSystemLogger();
277
278
static enum TestCases {NOSECURITY, NOPERMISSIONS, WITHPERMISSIONS};
279
280
static void setSecurityManager() {
281
if (System.getSecurityManager() == null) {
282
Policy.setPolicy(new SimplePolicy(allowControl, allowAll));
283
System.setSecurityManager(new SecurityManager());
284
}
285
}
286
public static void main(String[] args) {
287
if (args.length == 0)
288
args = new String[] {
289
"NOSECURITY",
290
"NOPERMISSIONS",
291
"WITHPERMISSIONS"
292
};
293
294
// 1. Obtain destination loggers directly from the LoggerFinder
295
// - LoggerFinder.getLogger("foo", type)
296
BaseLoggerFinder provider =
297
BaseLoggerFinder.class.cast(LoggerFinder.getLoggerFinder());
298
BaseLoggerFinder.LoggerImpl appSink =
299
BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", CustomLoggerTest.class.getModule()));
300
BaseLoggerFinder.LoggerImpl sysSink =
301
BaseLoggerFinder.LoggerImpl.class.cast(provider.getLogger("foo", Thread.class.getModule()));
302
303
304
Stream.of(args).map(TestCases::valueOf).forEach((testCase) -> {
305
switch (testCase) {
306
case NOSECURITY:
307
System.out.println("\n*** Without Security Manager\n");
308
test(provider, true, appSink, sysSink);
309
System.out.println("Tetscase count: " + sequencer.get());
310
break;
311
case NOPERMISSIONS:
312
System.out.println("\n*** With Security Manager, without permissions\n");
313
setSecurityManager();
314
test(provider, false, appSink, sysSink);
315
System.out.println("Tetscase count: " + sequencer.get());
316
break;
317
case WITHPERMISSIONS:
318
System.out.println("\n*** With Security Manager, with control permission\n");
319
setSecurityManager();
320
final boolean control = allowControl.get().get();
321
try {
322
allowControl.get().set(true);
323
test(provider, true, appSink, sysSink);
324
} finally {
325
allowControl.get().set(control);
326
}
327
break;
328
default:
329
throw new RuntimeException("Unknown test case: " + testCase);
330
}
331
});
332
System.out.println("\nPASSED: Tested " + sequencer.get() + " cases.");
333
}
334
335
public static void test(BaseLoggerFinder provider, boolean hasRequiredPermissions,
336
BaseLoggerFinder.LoggerImpl appSink, BaseLoggerFinder.LoggerImpl sysSink) {
337
338
ResourceBundle loggerBundle = ResourceBundle.getBundle(MyLoggerBundle.class.getName());
339
final Map<Logger, String> loggerDescMap = new HashMap<>();
340
341
342
// 1. Test loggers returned by:
343
// - System.getLogger("foo")
344
// - and AccessSystemLogger.getLogger("foo")
345
Logger appLogger1 = System.getLogger("foo");
346
loggerDescMap.put(appLogger1, "System.getLogger(\"foo\");");
347
348
Logger sysLogger1 = null;
349
try {
350
sysLogger1 = accessSystemLogger.getLogger("foo");
351
loggerDescMap.put(sysLogger1, "AccessSystemLogger.getLogger(\"foo\")");
352
} catch (AccessControlException acx) {
353
if (hasRequiredPermissions) {
354
throw new RuntimeException("Unexpected security exception: ", acx);
355
}
356
if (!acx.getPermission().equals(SimplePolicy.LOGGERFINDER_PERMISSION)) {
357
throw new RuntimeException("Unexpected permission in exception: " + acx, acx);
358
}
359
throw new RuntimeException("unexpected exception: " + acx, acx);
360
}
361
362
if (appLogger1 == sysLogger1) {
363
throw new RuntimeException("identical loggers");
364
}
365
366
if (provider.system.contains(appLogger1)) {
367
throw new RuntimeException("app logger in system map");
368
}
369
if (provider.user.contains(sysLogger1)) {
370
throw new RuntimeException("sys logger in appplication map");
371
}
372
if (provider.system.contains(sysLogger1)) {
373
// sysLogger should be a a LazyLoggerWrapper
374
throw new RuntimeException("sys logger is in system map (should be wrapped)");
375
}
376
377
378
// 2. Test loggers returned by:
379
// - System.getLogger(\"foo\", loggerBundle)
380
// - and AccessSystemLogger.getLogger(\"foo\", loggerBundle)
381
Logger appLogger2 =
382
System.getLogger("foo", loggerBundle);
383
loggerDescMap.put(appLogger2, "System.getLogger(\"foo\", loggerBundle)");
384
385
Logger sysLogger2 = null;
386
try {
387
sysLogger2 = accessSystemLogger.getLogger("foo", loggerBundle);
388
loggerDescMap.put(sysLogger2, "AccessSystemLogger.getLogger(\"foo\", loggerBundle)");
389
} catch (AccessControlException acx) {
390
if (hasRequiredPermissions) {
391
throw new RuntimeException("Unexpected security exception: ", acx);
392
}
393
if (!acx.getPermission().equals(SimplePolicy.LOGGERFINDER_PERMISSION)) {
394
throw new RuntimeException("Unexpected permission in exception: " + acx, acx);
395
}
396
throw new RuntimeException("unexpected exception: " + acx, acx);
397
}
398
if (appLogger2 == sysLogger2) {
399
throw new RuntimeException("identical loggers");
400
}
401
if (appLogger2 == appSink) {
402
throw new RuntimeException("identical loggers");
403
}
404
if (sysLogger2 == sysSink) {
405
throw new RuntimeException("identical loggers");
406
}
407
408
if (provider.system.contains(appLogger2)) {
409
throw new RuntimeException("localized app logger in system map");
410
}
411
if (provider.user.contains(appLogger2)) {
412
throw new RuntimeException("localized app logger in appplication map");
413
}
414
if (provider.user.contains(sysLogger2)) {
415
throw new RuntimeException("localized sys logger in appplication map");
416
}
417
if (provider.system.contains(sysLogger2)) {
418
throw new RuntimeException("localized sys logger not in system map");
419
}
420
421
testLogger(provider, loggerDescMap, "foo", null, appLogger1, appSink);
422
testLogger(provider, loggerDescMap, "foo", null, sysLogger1, sysSink);
423
testLogger(provider, loggerDescMap, "foo", loggerBundle, appLogger2, appSink);
424
testLogger(provider, loggerDescMap, "foo", loggerBundle, sysLogger2, sysSink);
425
}
426
427
public static class Foo {
428
429
}
430
431
static void verbose(String msg) {
432
if (VERBOSE) {
433
System.out.println(msg);
434
}
435
}
436
437
// Calls the 8 methods defined on Logger and verify the
438
// parameters received by the underlying BaseLoggerFinder.LoggerImpl
439
// logger.
440
private static void testLogger(BaseLoggerFinder provider,
441
Map<Logger, String> loggerDescMap,
442
String name,
443
ResourceBundle loggerBundle,
444
Logger logger,
445
BaseLoggerFinder.LoggerImpl sink) {
446
447
System.out.println("Testing " + loggerDescMap.get(logger));
448
449
Foo foo = new Foo();
450
String fooMsg = foo.toString();
451
for (Level loggerLevel : Level.values()) {
452
sink.level = loggerLevel;
453
for (Level messageLevel : Level.values()) {
454
String desc = "logger.log(messageLevel, foo): loggerLevel="
455
+ loggerLevel+", messageLevel="+messageLevel;
456
BaseLoggerFinder.LogEvent expected =
457
BaseLoggerFinder.LogEvent.of(
458
sequencer.get(),
459
messageLevel.compareTo(loggerLevel) >= 0,
460
name, messageLevel, (ResourceBundle)null,
461
fooMsg, null, (Throwable)null, (Object[])null);
462
logger.log(messageLevel, foo);
463
if (loggerLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
464
if (provider.eventQueue.poll() != null) {
465
throw new RuntimeException("unexpected event in queue for " + desc);
466
}
467
} else {
468
BaseLoggerFinder.LogEvent actual = provider.eventQueue.poll();
469
if (!expected.equals(actual)) {
470
throw new RuntimeException("mismatch for " + desc
471
+ "\n\texpected=" + expected
472
+ "\n\t actual=" + actual);
473
} else {
474
verbose("Got expected results for "
475
+ desc + "\n\t" + expected);
476
}
477
}
478
}
479
}
480
481
String msg = "blah";
482
for (Level loggerLevel : Level.values()) {
483
sink.level = loggerLevel;
484
for (Level messageLevel : Level.values()) {
485
String desc = "logger.log(messageLevel, \"blah\"): loggerLevel="
486
+ loggerLevel+", messageLevel="+messageLevel;
487
BaseLoggerFinder.LogEvent expected =
488
BaseLoggerFinder.LogEvent.of(
489
sequencer.get(),
490
messageLevel.compareTo(loggerLevel) >= 0 && loggerLevel != Level.OFF,
491
name, messageLevel, loggerBundle,
492
msg, null, (Throwable)null, (Object[])null);
493
logger.log(messageLevel, msg);
494
BaseLoggerFinder.LogEvent actual = provider.eventQueue.poll();
495
if (!expected.equals(actual)) {
496
throw new RuntimeException("mismatch for " + desc
497
+ "\n\texpected=" + expected
498
+ "\n\t actual=" + actual);
499
} else {
500
verbose("Got expected results for "
501
+ desc + "\n\t" + expected);
502
}
503
}
504
}
505
506
Supplier<String> fooSupplier = new Supplier<String>() {
507
@Override
508
public String get() {
509
return this.toString();
510
}
511
};
512
513
for (Level loggerLevel : Level.values()) {
514
sink.level = loggerLevel;
515
for (Level messageLevel : Level.values()) {
516
String desc = "logger.log(messageLevel, fooSupplier): loggerLevel="
517
+ loggerLevel+", messageLevel="+messageLevel;
518
BaseLoggerFinder.LogEvent expected =
519
BaseLoggerFinder.LogEvent.of(
520
sequencer.get(),
521
messageLevel.compareTo(loggerLevel) >= 0,
522
name, messageLevel, (ResourceBundle)null,
523
fooSupplier.get(), null,
524
(Throwable)null, (Object[])null);
525
logger.log(messageLevel, fooSupplier);
526
if (loggerLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
527
if (provider.eventQueue.poll() != null) {
528
throw new RuntimeException("unexpected event in queue for " + desc);
529
}
530
} else {
531
BaseLoggerFinder.LogEvent actual = provider.eventQueue.poll();
532
if (!expected.equals(actual)) {
533
throw new RuntimeException("mismatch for " + desc
534
+ "\n\texpected=" + expected
535
+ "\n\t actual=" + actual);
536
} else {
537
verbose("Got expected results for "
538
+ desc + "\n\t" + expected);
539
}
540
}
541
}
542
}
543
544
String format = "two params [{1} {2}]";
545
Object arg1 = foo;
546
Object arg2 = msg;
547
for (Level loggerLevel : Level.values()) {
548
sink.level = loggerLevel;
549
for (Level messageLevel : Level.values()) {
550
String desc = "logger.log(messageLevel, format, params...): loggerLevel="
551
+ loggerLevel+", messageLevel="+messageLevel;
552
BaseLoggerFinder.LogEvent expected =
553
BaseLoggerFinder.LogEvent.of(
554
sequencer.get(),
555
messageLevel.compareTo(loggerLevel) >= 0 && loggerLevel != Level.OFF,
556
name, messageLevel, loggerBundle,
557
format, null, (Throwable)null, new Object[] {arg1, arg2});
558
logger.log(messageLevel, format, arg1, arg2);
559
BaseLoggerFinder.LogEvent actual = provider.eventQueue.poll();
560
if (!expected.equals(actual)) {
561
throw new RuntimeException("mismatch for " + desc
562
+ "\n\texpected=" + expected
563
+ "\n\t actual=" + actual);
564
} else {
565
verbose("Got expected results for "
566
+ desc + "\n\t" + expected);
567
}
568
}
569
}
570
571
Throwable thrown = new Exception("OK: log me!");
572
for (Level loggerLevel : Level.values()) {
573
sink.level = loggerLevel;
574
for (Level messageLevel : Level.values()) {
575
String desc = "logger.log(messageLevel, \"blah\", thrown): loggerLevel="
576
+ loggerLevel+", messageLevel="+messageLevel;
577
BaseLoggerFinder.LogEvent expected =
578
BaseLoggerFinder.LogEvent.of(
579
sequencer.get(),
580
messageLevel.compareTo(loggerLevel) >= 0 && loggerLevel != Level.OFF,
581
name, messageLevel, loggerBundle,
582
msg, null, thrown, (Object[]) null);
583
logger.log(messageLevel, msg, thrown);
584
BaseLoggerFinder.LogEvent actual = provider.eventQueue.poll();
585
if (!expected.equals(actual)) {
586
throw new RuntimeException("mismatch for " + desc
587
+ "\n\texpected=" + expected
588
+ "\n\t actual=" + actual);
589
} else {
590
verbose("Got expected results for "
591
+ desc + "\n\t" + expected);
592
}
593
}
594
}
595
596
597
for (Level loggerLevel : Level.values()) {
598
sink.level = loggerLevel;
599
for (Level messageLevel : Level.values()) {
600
String desc = "logger.log(messageLevel, thrown, fooSupplier): loggerLevel="
601
+ loggerLevel+", messageLevel="+messageLevel;
602
BaseLoggerFinder.LogEvent expected =
603
BaseLoggerFinder.LogEvent.of(
604
sequencer.get(),
605
messageLevel.compareTo(loggerLevel) >= 0,
606
name, messageLevel, (ResourceBundle)null,
607
fooSupplier.get(), null,
608
(Throwable)thrown, (Object[])null);
609
logger.log(messageLevel, fooSupplier, thrown);
610
if (loggerLevel == Level.OFF || messageLevel.compareTo(loggerLevel) < 0) {
611
if (provider.eventQueue.poll() != null) {
612
throw new RuntimeException("unexpected event in queue for " + desc);
613
}
614
} else {
615
BaseLoggerFinder.LogEvent actual = provider.eventQueue.poll();
616
if (!expected.equals(actual)) {
617
throw new RuntimeException("mismatch for " + desc
618
+ "\n\texpected=" + expected
619
+ "\n\t actual=" + actual);
620
} else {
621
verbose("Got expected results for "
622
+ desc + "\n\t" + expected);
623
}
624
}
625
}
626
}
627
628
ResourceBundle bundle = ResourceBundle.getBundle(MyBundle.class.getName());
629
for (Level loggerLevel : Level.values()) {
630
sink.level = loggerLevel;
631
for (Level messageLevel : Level.values()) {
632
String desc = "logger.log(messageLevel, bundle, format, params...): loggerLevel="
633
+ loggerLevel+", messageLevel="+messageLevel;
634
BaseLoggerFinder.LogEvent expected =
635
BaseLoggerFinder.LogEvent.of(
636
sequencer.get(),
637
messageLevel.compareTo(loggerLevel) >= 0 && loggerLevel != Level.OFF,
638
name, messageLevel, bundle,
639
format, null, (Throwable)null, new Object[] {foo, msg});
640
logger.log(messageLevel, bundle, format, foo, msg);
641
BaseLoggerFinder.LogEvent actual = provider.eventQueue.poll();
642
if (!expected.equals(actual)) {
643
throw new RuntimeException("mismatch for " + desc
644
+ "\n\texpected=" + expected
645
+ "\n\t actual=" + actual);
646
} else {
647
verbose("Got expected results for "
648
+ desc + "\n\t" + expected);
649
}
650
}
651
}
652
653
for (Level loggerLevel : Level.values()) {
654
sink.level = loggerLevel;
655
for (Level messageLevel : Level.values()) {
656
String desc = "logger.log(messageLevel, bundle, \"blah\", thrown): loggerLevel="
657
+ loggerLevel+", messageLevel="+messageLevel;
658
BaseLoggerFinder.LogEvent expected =
659
BaseLoggerFinder.LogEvent.of(
660
sequencer.get(),
661
messageLevel.compareTo(loggerLevel) >= 0 && loggerLevel != Level.OFF,
662
name, messageLevel, bundle,
663
msg, null, thrown, (Object[]) null);
664
logger.log(messageLevel, bundle, msg, thrown);
665
BaseLoggerFinder.LogEvent actual = provider.eventQueue.poll();
666
if (!expected.equals(actual)) {
667
throw new RuntimeException("mismatch for " + desc
668
+ "\n\texpected=" + expected
669
+ "\n\t actual=" + actual);
670
} else {
671
verbose("Got expected results for "
672
+ desc + "\n\t" + expected);
673
}
674
}
675
}
676
}
677
678
final static class PermissionsBuilder {
679
final Permissions perms;
680
public PermissionsBuilder() {
681
this(new Permissions());
682
}
683
public PermissionsBuilder(Permissions perms) {
684
this.perms = perms;
685
}
686
public PermissionsBuilder add(Permission p) {
687
perms.add(p);
688
return this;
689
}
690
public PermissionsBuilder addAll(PermissionCollection col) {
691
if (col != null) {
692
for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {
693
perms.add(e.nextElement());
694
}
695
}
696
return this;
697
}
698
public Permissions toPermissions() {
699
final PermissionsBuilder builder = new PermissionsBuilder();
700
builder.addAll(perms);
701
return builder.perms;
702
}
703
}
704
705
public static class SimplePolicy extends Policy {
706
707
static final Policy DEFAULT_POLICY = Policy.getPolicy();
708
709
static final RuntimePermission LOGGERFINDER_PERMISSION =
710
new RuntimePermission("loggerFinder");
711
final Permissions permissions;
712
final Permissions controlPermissions;
713
final Permissions allPermissions;
714
final ThreadLocal<AtomicBoolean> allowControl;
715
final ThreadLocal<AtomicBoolean> allowAll;
716
public SimplePolicy(ThreadLocal<AtomicBoolean> allowControl, ThreadLocal<AtomicBoolean> allowAll) {
717
this.allowControl = allowControl;
718
this.allowAll = allowAll;
719
permissions = new Permissions();
720
721
// these are used for configuring the test itself...
722
controlPermissions = new Permissions();
723
controlPermissions.add(LOGGERFINDER_PERMISSION);
724
725
// these are used for simulating a doPrivileged call from
726
// a class in the BCL
727
allPermissions = new Permissions();
728
allPermissions.add(new AllPermission());
729
730
}
731
732
Permissions permissions() {
733
if (allowAll.get().get()) return allPermissions;
734
if (allowControl.get().get()) return controlPermissions;
735
return permissions;
736
737
}
738
739
@Override
740
public boolean implies(ProtectionDomain domain, Permission permission) {
741
return permissions().implies(permission) || DEFAULT_POLICY.implies(domain, permission);
742
}
743
744
@Override
745
public PermissionCollection getPermissions(CodeSource codesource) {
746
return new PermissionsBuilder().addAll(permissions()).toPermissions();
747
}
748
749
@Override
750
public PermissionCollection getPermissions(ProtectionDomain domain) {
751
return new PermissionsBuilder().addAll(permissions()).toPermissions();
752
}
753
}
754
}
755
756