1 /*
2  * Copyright (c) 2015, 2017, 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.io.ByteArrayInputStream;
24 import java.io.ByteArrayOutputStream;
25 import java.io.FileOutputStream;
26 import java.io.IOException;
27 import java.nio.file.Path;
28 import java.nio.file.Paths;
29 import java.security.CodeSource;
30 import java.security.Permission;
31 import java.security.PermissionCollection;
32 import java.security.Permissions;
33 import java.security.Policy;
34 import java.security.ProtectionDomain;
35 import java.util.Arrays;
36 import java.util.Enumeration;
37 import java.util.Objects;
38 import java.util.Properties;
39 import java.util.concurrent.Callable;
40 import java.util.concurrent.atomic.AtomicBoolean;
41 import java.util.concurrent.atomic.AtomicLong;
42 import java.util.function.BiFunction;
43 import java.util.function.Function;
44 import java.util.logging.Handler;
45 import java.util.logging.Level;
46 import java.util.logging.LogManager;
47 import java.util.logging.LogRecord;
48 import java.util.logging.Logger;
49 import java.util.logging.LoggingPermission;
50 
51 /**
52  * @test
53  * @bug 8033661 8189291
54  * @summary tests LogManager.updateConfiguration(InputStream, Function) method
55  * @run main/othervm SimpleUpdateConfigWithInputStreamTest UNSECURE
56  * @run main/othervm SimpleUpdateConfigWithInputStreamTest SECURE
57  * @author danielfuchs
58  */
59 public class SimpleUpdateConfigWithInputStreamTest {
60     static final Policy DEFAULT_POLICY = Policy.getPolicy();
61 
62     /**
63      * We will test updateConfiguration in
64      * two configurations:
65      * UNSECURE: No security manager.
66      * SECURE: With the security manager present - and the required
67      *         permissions granted.
68      */
69     public static enum TestCase {
70         UNSECURE, SECURE;
execute(Runnable run)71         public void execute(Runnable run) {
72             System.out.println("Running test case: " + name());
73             try {
74                Configure.setUp(this);
75                Configure.doPrivileged(run, SimplePolicy.allowControl);
76             } finally {
77                Configure.doPrivileged(() -> {
78                    try {
79                        setSystemProperty("java.util.logging.config.file", null);
80                        LogManager.getLogManager().readConfiguration();
81                        System.gc();
82                    } catch (Exception x) {
83                        throw new RuntimeException(x);
84                    }
85                }, SimplePolicy.allowAll);
86             }
87         }
88     }
89 
90     public static class MyHandler extends Handler {
91         static final AtomicLong seq = new AtomicLong();
92         long count = seq.incrementAndGet();
93 
94         @Override
publish(LogRecord record)95         public void publish(LogRecord record) {
96         }
97 
98         @Override
flush()99         public void flush() {
100         }
101 
102         @Override
close()103         public void close() throws SecurityException {
104         }
105 
106         @Override
toString()107         public String toString() {
108             return super.toString() + "("+count+")";
109         }
110 
111     }
112 
storePropertyToFile(String name, Properties props)113     static String storePropertyToFile(String name, Properties props)
114         throws Exception {
115         return Configure.callPrivileged(() -> {
116             String scratch = System.getProperty("user.dir", ".");
117             Path p = Paths.get(scratch, name);
118             try (FileOutputStream fos = new FileOutputStream(p.toFile())) {
119                 props.store(fos, name);
120             }
121             return p.toString();
122         }, SimplePolicy.allowAll);
123     }
124 
setSystemProperty(String name, String value)125     static void setSystemProperty(String name, String value)
126         throws Exception {
127         Configure.doPrivileged(() -> {
128             if (value == null)
129                 System.clearProperty(name);
130             else
131                 System.setProperty(name, value);
132         }, SimplePolicy.allowAll);
133     }
134 
trim(String value)135     static String trim(String value) {
136         return value == null ? null : value.trim();
137     }
138 
139 
140     /**
141      * Tests one of the configuration defined above.
142      * <p>
143      * This is the main test method (the rest is infrastructure).
144      */
testUpdateConfiguration()145     static void testUpdateConfiguration() {
146         try {
147             // manager initialized with default configuration.
148             LogManager manager = LogManager.getLogManager();
149 
150             // Test default configuration. It should not have
151             // any value for "com.foo.level" and "com.foo.handlers"
152             assertEquals(null, manager.getProperty("com.foo.level"),
153                 "com.foo.level in default configuration");
154             assertEquals(null, manager.getProperty("com.foo.handlers"),
155                 "com.foo.handlers in default configuration");
156 
157             // Create a logging configuration file that contains
158             // com.foo.level=FINEST
159             // and set "java.util.logging.config.file" to this file.
160             Properties props = new Properties();
161             props.setProperty("com.foo.level", "FINEST");
162 
163             // Update configuration with props
164             // then test that the new configuration has
165             // com.foo.level=FINEST
166             // and nothing for com.foo.handlers
167             Configure.updateConfigurationWith(props, null);
168             assertEquals("FINEST", manager.getProperty("com.foo.level"),
169                 "com.foo.level in " + props);
170             assertEquals(null, manager.getProperty("com.foo.handlers"),
171                 "com.foo.handlers in " + props);
172 
173             // call updateConfiguration with an empty stream.
174             // check that the new configuration no longer has
175             // any value for com.foo.level, and still no value
176             // for com.foo.handlers
177             Configure.updateConfigurationWith(new Properties(), null);
178             assertEquals(null, manager.getProperty("com.foo.level"),
179                     "com.foo.level in default configuration");
180             assertEquals(null, manager.getProperty("com.foo.handlers"),
181                 "com.foo.handlers in default configuration");
182 
183             // creates the com.foo logger, check it has
184             // the default config: no level, and no handlers
185             final Logger logger = Logger.getLogger("com.foo");
186             assertEquals(null, logger.getLevel(),
187                 "Logger.getLogger(\"com.foo\").getLevel()");
188             assertDeepEquals(new Handler[0], logger.getHandlers(),
189                     "Logger.getLogger(\"com.foo\").getHandlers()");
190 
191             // call updateConfiguration with 'props'
192             // check that the configuration has
193             // com.foo.level=FINEST
194             // and nothing for com.foo.handlers
195             // check that the logger has now a FINEST level and still
196             // no handlers
197             Configure.updateConfigurationWith(props, null);
198             assertEquals("FINEST", manager.getProperty("com.foo.level"),
199                 "com.foo.level in " + props);
200             assertEquals(Level.FINEST, logger.getLevel(),
201                 "Logger.getLogger(\"com.foo\").getLevel()");
202             assertDeepEquals(new Handler[0], logger.getHandlers(),
203                     "Logger.getLogger(\"com.foo\").getHandlers()");
204             assertEquals(null, manager.getProperty("com.foo.handlers"),
205                 "com.foo.handlers in " + props);
206 
207             // Calls updateConfiguration with a lambda whose effect should
208             // be to set the FINER level on the "com.foo" logger.
209             // Check that the new configuration has
210             // com.foo.level=FINER
211             // and nothing for com.foo.handlers
212             // check that the logger has now a FINER level and still
213             // no handlers
214             Configure.updateConfigurationWith(props,
215                     (k) -> ("com.foo.level".equals(k) ? (o, n) -> "FINER" : (o, n) -> n));
216             assertEquals("FINER", manager.getProperty("com.foo.level"),
217                 "com.foo.level set to FINER by updateConfiguration");
218             assertEquals(Level.FINER, logger.getLevel(),
219                 "Logger.getLogger(\"com.foo\").getLevel()");
220             assertDeepEquals(new Handler[0], logger.getHandlers(),
221                     "Logger.getLogger(\"com.foo\").getHandlers()");
222             assertEquals(null, manager.getProperty("com.foo.handlers"),
223                 "com.foo.handlers in " + props);
224 
225             // Calls updateConfiguration with a lambda whose effect is a noop.
226             // This should not change the configuration, so
227             // check that the new configuration still has
228             // com.foo.level=FINER
229             // and nothing for com.foo.handlers
230             // check that the logger still has FINER level and still
231             // no handlers
232             Configure.updateConfigurationWith(props,
233                     (k) -> ((o, n) -> o));
234             assertEquals("FINER", manager.getProperty("com.foo.level"),
235                 "com.foo.level preserved by updateConfiguration");
236             assertEquals(Level.FINER, logger.getLevel(),
237                 "Logger.getLogger(\"com.foo\").getLevel()");
238             assertDeepEquals(new Handler[0], logger.getHandlers(),
239                     "Logger.getLogger(\"com.foo\").getHandlers()");
240             assertEquals(null, manager.getProperty("com.foo.handlers"),
241                 "com.foo.handlers in " + props);
242 
243             // Calls updateConfiguration with a lambda whose effect is to
244             // take all values from the new configuration.
245             // This should update the configuration to what is in props, so
246             // check that the new configuration has
247             // com.foo.level=FINEST
248             // and nothing for com.foo.handlers
249             // check that the logger now has FINEST level and still
250             // no handlers
251             Configure.updateConfigurationWith(props,
252                     (k) -> ((o, n) -> n));
253             assertEquals("FINEST", manager.getProperty("com.foo.level"),
254                 "com.foo.level updated by updateConfiguration");
255             assertEquals(Level.FINEST, logger.getLevel(),
256                 "Logger.getLogger(\"com.foo\").getLevel()");
257             assertDeepEquals(new Handler[0], logger.getHandlers(),
258                     "Logger.getLogger(\"com.foo\").getHandlers()");
259             assertEquals(null, manager.getProperty("com.foo.handlers"),
260                 "com.foo.handlers in " + props);
261 
262             // now set a handler on the com.foo logger.
263             MyHandler h = new MyHandler();
264             logger.addHandler(h);
265             assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
266                     "Logger.getLogger(\"com.foo\").getHandlers()");
267 
268             // Calls updateConfiguration with a lambda whose effect should
269             // be to set the FINER level on the "com.foo" logger, and
270             // take the value from props for everything else.
271             // Check that the new configuration has
272             // com.foo.level=FINER
273             // and nothing for com.foo.handlers
274             // check that the logger has now a FINER level, but that its
275             // handlers are still present and have not been reset
276             // since neither the old nor new configuration defined them.
277             Configure.updateConfigurationWith(props,
278                     (k) -> ("com.foo.level".equals(k) ? (o, n) -> "FINER" : (o, n) -> n));
279             assertEquals("FINER", manager.getProperty("com.foo.level"),
280                 "com.foo.level set to FINER by updateConfiguration");
281             assertEquals(Level.FINER, logger.getLevel(),
282                 "Logger.getLogger(\"com.foo\").getLevel()");
283             assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
284                     "Logger.getLogger(\"com.foo\").getHandlers()");
285             assertEquals(null, manager.getProperty("com.foo.handlers"),
286                 "com.foo.handlers in " + props);
287 
288             // now add some configuration for com.foo.handlers
289             props.setProperty("com.foo.handlers", MyHandler.class.getName());
290 
291             // we didn't call updateConfiguration, so just changing the
292             // content of props should have had no effect.
293             assertEquals("FINER", manager.getProperty("com.foo.level"),
294                 "com.foo.level set to FINER by updateConfiguration");
295             assertEquals(Level.FINER, logger.getLevel(),
296                 "Logger.getLogger(\"com.foo\").getLevel()");
297             assertEquals(null,
298                     manager.getProperty("com.foo.handlers"),
299                     "manager.getProperty(\"com.foo.handlers\")");
300             assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
301                     "Logger.getLogger(\"com.foo\").getHandlers()");
302 
303             // Calls updateConfiguration with a lambda whose effect is a noop.
304             // This should not change the current configuration, so
305             // check that the new configuration still has
306             // com.foo.level=FINER
307             // and nothing for com.foo.handlers
308             // check that the logger still has FINER level and still
309             // has its handlers and that they haven't been reset.
310             Configure.updateConfigurationWith(props, (k) -> ((o, n) -> o));
311             assertEquals("FINER", manager.getProperty("com.foo.level"),
312                 "com.foo.level set to FINER by updateConfiguration");
313             assertEquals(Level.FINER, logger.getLevel(),
314                 "Logger.getLogger(\"com.foo\").getLevel()");
315             assertEquals(null,
316                     manager.getProperty("com.foo.handlers"),
317                     "manager.getProperty(\"com.foo.handlers\")");
318             assertDeepEquals(new Handler[] {h}, logger.getHandlers(),
319                     "Logger.getLogger(\"com.foo\").getHandlers()");
320 
321             // Calls updateConfiguration with a lambda whose effect is to
322             // take all values from the new configuration.
323             // This should update the configuration to what is in props, so
324             // check that the new configuration has
325             // com.foo.level=FINEST
326             // com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
327             // check that the logger now has FINEST level
328             // and a new handler instance, since the old config
329             // had no handlers for com.foo and the new config has one.
330             Configure.updateConfigurationWith(props, (k) -> ((o, n) -> n));
331             assertEquals("FINEST", manager.getProperty("com.foo.level"),
332                 "com.foo.level updated by updateConfiguration");
333             assertEquals(Level.FINEST, logger.getLevel(),
334                 "Logger.getLogger(\"com.foo\").getLevel()");
335             assertEquals(MyHandler.class.getName(),
336                     manager.getProperty("com.foo.handlers"),
337                     "manager.getProperty(\"com.foo.handlers\")");
338             Handler[] loggerHandlers = logger.getHandlers().clone();
339             assertEquals(1, loggerHandlers.length,
340                     "Logger.getLogger(\"com.foo\").getHandlers().length");
341             assertEquals(MyHandler.class, loggerHandlers[0].getClass(),
342                     "Logger.getLogger(\"com.foo\").getHandlers()[0].getClass()");
343             assertEquals(h.count + 1, ((MyHandler)logger.getHandlers()[0]).count,
344                     "Logger.getLogger(\"com.foo\").getHandlers()[0].count");
345 
346             // Calls updateConfiguration with a lambda whose effect is a noop.
347             // This should not change the current configuration, so
348             // check that the new configuration still has
349             // com.foo.level=FINEST
350             // com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
351             // check that the logger still has FINEST level and still
352             // has its handlers and that they haven't been reset.
353             Configure.updateConfigurationWith(props, (k) -> ((o, n) -> o));
354             assertDeepEquals(loggerHandlers, logger.getHandlers(),
355                     "Logger.getLogger(\"com.foo\").getHandlers()");
356             assertEquals("FINEST", manager.getProperty("com.foo.level"),
357                 "com.foo.level updated by updateConfiguration");
358             assertEquals(Level.FINEST, logger.getLevel(),
359                 "Logger.getLogger(\"com.foo\").getLevel()");
360             assertEquals(MyHandler.class.getName(),
361                     manager.getProperty("com.foo.handlers"),
362                     "manager.getProperty(\"com.foo.handlers\")");
363 
364             // Calls updateConfiguration with a lambda whose effect is to
365             // take all values from the new configuration.
366             // Because the content of the props hasn't changed, then
367             // it should also be a noop.
368             // check that the new configuration still has
369             // com.foo.level=FINEST
370             // com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
371             // check that the logger still has FINEST level and still
372             // has its handlers and that they haven't been reset.
373             Configure.updateConfigurationWith(props, (k) -> ((o, n) -> n));
374             assertDeepEquals(loggerHandlers, logger.getHandlers(),
375                     "Logger.getLogger(\"com.foo\").getHandlers()");
376             assertEquals("FINEST", manager.getProperty("com.foo.level"),
377                 "com.foo.level updated by updateConfiguration");
378             assertEquals(Level.FINEST, logger.getLevel(),
379                 "Logger.getLogger(\"com.foo\").getLevel()");
380             assertEquals(MyHandler.class.getName(),
381                     manager.getProperty("com.foo.handlers"),
382                     "manager.getProperty(\"com.foo.handlers\")");
383 
384             // Calls updateConfiguration with a null lambda, whose effect is to
385             // take all values from the new configuration.
386             // Because the content of the props hasn't changed, then
387             // it should also be a noop.
388             // check that the new configuration still has
389             // com.foo.level=FINEST
390             // com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
391             // check that the logger still has FINEST level and still
392             // has its handlers and that they haven't been reset.
393             Configure.updateConfigurationWith(props, (k) -> ((o, n) -> n));
394             assertDeepEquals(loggerHandlers, logger.getHandlers(),
395                     "Logger.getLogger(\"com.foo\").getHandlers()");
396             assertEquals("FINEST", manager.getProperty("com.foo.level"),
397                 "com.foo.level updated by updateConfiguration");
398             assertEquals(Level.FINEST, logger.getLevel(),
399                 "Logger.getLogger(\"com.foo\").getLevel()");
400             assertEquals(MyHandler.class.getName(),
401                     manager.getProperty("com.foo.handlers"),
402                     "manager.getProperty(\"com.foo.handlers\")");
403 
404             // now remove com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
405             // from the configuration file.
406             props.remove("com.foo.handlers");
407 
408             // Calls updateConfiguration with a lambda whose effect is a noop.
409             // This should not change the current configuration, so
410             // check that the new configuration still has
411             // com.foo.level=FINEST
412             // com.foo.handlers=SimpleUpdateConfigWithInputStreamTest$MyHandler
413             // check that the logger still has FINEST level and still
414             // has its handlers and that they haven't been reset.
415             Configure.updateConfigurationWith(props, (k) -> ((o, n) -> o));
416             assertDeepEquals(loggerHandlers, logger.getHandlers(),
417                     "Logger.getLogger(\"com.foo\").getHandlers()");
418             assertEquals("FINEST", manager.getProperty("com.foo.level"),
419                 "com.foo.level updated by updateConfiguration");
420             assertEquals(Level.FINEST, logger.getLevel(),
421                 "Logger.getLogger(\"com.foo\").getLevel()");
422             assertEquals(MyHandler.class.getName(),
423                     manager.getProperty("com.foo.handlers"),
424                     "manager.getProperty(\"com.foo.handlers\")");
425 
426             // Calls updateConfiguration with a lambda whose effect is to
427             // take all values from the new configuration.
428             // This should update the configuration to what is in props, so
429             // check that the new configuration has
430             // com.foo.level=FINEST
431             // and nothing for com.foo.handlers
432             // check that the logger still has FINEST level
433             // and no handlers, since the old config
434             // had an handler for com.foo and the new config doesn't.
435             Configure.updateConfigurationWith(props, (k) -> ((o, n) -> n));
436             assertDeepEquals(new Handler[0], logger.getHandlers(),
437                     "Logger.getLogger(\"com.foo\").getHandlers()");
438             assertEquals("FINEST", manager.getProperty("com.foo.level"),
439                 "com.foo.level updated by updateConfiguration");
440             assertEquals(Level.FINEST, logger.getLevel(),
441                 "Logger.getLogger(\"com.foo\").getLevel()");
442             assertEquals(null,
443                     manager.getProperty("com.foo.handlers"),
444                     "manager.getProperty(\"com.foo.handlers\")");
445 
446 
447         } catch (RuntimeException | Error r) {
448             throw r;
449         } catch (Exception x) {
450             throw new RuntimeException(x);
451         }
452     }
453 
main(String[] args)454     public static void main(String[] args) throws Exception {
455         if (args == null || args.length == 0) {
456             args = new String[] { "UNSECURE", "SECURE" };
457         }
458         for (String test : args) {
459             TestCase.valueOf(test).execute(SimpleUpdateConfigWithInputStreamTest::testUpdateConfiguration);
460         }
461     }
462 
463     static class Configure {
464         static Policy policy = null;
setUp(TestCase test)465         static void setUp(TestCase test) {
466             switch (test) {
467                 case SECURE:
468                     if (policy == null && System.getSecurityManager() != null) {
469                         throw new IllegalStateException("SecurityManager already set");
470                     } else if (policy == null) {
471                         policy = new SimplePolicy(TestCase.SECURE);
472                         Policy.setPolicy(policy);
473                         System.setSecurityManager(new SecurityManager());
474                     }
475                     if (System.getSecurityManager() == null) {
476                         throw new IllegalStateException("No SecurityManager.");
477                     }
478                     if (policy == null) {
479                         throw new IllegalStateException("policy not configured");
480                     }
481                     break;
482                 case UNSECURE:
483                     if (System.getSecurityManager() != null) {
484                         throw new IllegalStateException("SecurityManager already set");
485                     }
486                     break;
487                 default:
488                     throw new InternalError("No such testcase: " + test);
489             }
490         }
491 
updateConfigurationWith(Properties propertyFile, Function<String,BiFunction<String,String,String>> remapper)492         static void updateConfigurationWith(Properties propertyFile,
493                 Function<String,BiFunction<String,String,String>> remapper) {
494             try {
495                 ByteArrayOutputStream bytes = new ByteArrayOutputStream();
496                 propertyFile.store(bytes, propertyFile.getProperty("test.name"));
497                 ByteArrayInputStream bais = new ByteArrayInputStream(bytes.toByteArray());
498                 LogManager.getLogManager().updateConfiguration(bais, remapper);
499             } catch (IOException ex) {
500                 throw new RuntimeException(ex);
501             }
502         }
503 
doPrivileged(Runnable run, ThreadLocal<AtomicBoolean> granter)504         static void doPrivileged(Runnable run, ThreadLocal<AtomicBoolean> granter) {
505             final boolean old = granter.get().getAndSet(true);
506             try {
507                 run.run();
508             } finally {
509                 granter.get().set(old);
510             }
511         }
callPrivileged(Callable<T> call, ThreadLocal<AtomicBoolean> granter)512         static <T> T callPrivileged(Callable<T> call,
513                 ThreadLocal<AtomicBoolean> granter) throws Exception {
514             final boolean old = granter.get().getAndSet(true);
515             try {
516                 return call.call();
517             } finally {
518                 granter.get().set(old);
519             }
520         }
521     }
522 
523     static final class TestAssertException extends RuntimeException {
TestAssertException(String msg)524         TestAssertException(String msg) {
525             super(msg);
526         }
527     }
528 
assertEquals(long expected, long received, String msg)529     private static void assertEquals(long expected, long received, String msg) {
530         if (expected != received) {
531             throw new TestAssertException("Unexpected result for " + msg
532                     + ".\n\texpected: " + expected
533                     +  "\n\tactual:   " + received);
534         } else {
535             System.out.println("Got expected " + msg + ": " + received);
536         }
537     }
538 
assertEquals(String expected, String received, String msg)539     private static void assertEquals(String expected, String received, String msg) {
540         if (!Objects.equals(expected, received)) {
541             throw new TestAssertException("Unexpected result for " + msg
542                     + ".\n\texpected: " + expected
543                     +  "\n\tactual:   " + received);
544         } else {
545             System.out.println("Got expected " + msg + ": " + received);
546         }
547     }
548 
assertEquals(Object expected, Object received, String msg)549     private static void assertEquals(Object expected, Object received, String msg) {
550         if (!Objects.equals(expected, received)) {
551             throw new TestAssertException("Unexpected result for " + msg
552                     + ".\n\texpected: " + expected
553                     +  "\n\tactual:   " + received);
554         } else {
555             System.out.println("Got expected " + msg + ": " + received);
556         }
557     }
558 
deepToString(Object o)559     public static String deepToString(Object o) {
560         if (o == null) {
561             return "null";
562         } else if (o.getClass().isArray()) {
563             String s;
564             if (o instanceof Object[])
565                 s = Arrays.deepToString((Object[]) o);
566             else if (o instanceof byte[])
567                 s = Arrays.toString((byte[]) o);
568             else if (o instanceof short[])
569                 s = Arrays.toString((short[]) o);
570             else if (o instanceof int[])
571                 s = Arrays.toString((int[]) o);
572             else if (o instanceof long[])
573                 s = Arrays.toString((long[]) o);
574             else if (o instanceof char[])
575                 s = Arrays.toString((char[]) o);
576             else if (o instanceof float[])
577                 s = Arrays.toString((float[]) o);
578             else if (o instanceof double[])
579                 s = Arrays.toString((double[]) o);
580             else if (o instanceof boolean[])
581                 s = Arrays.toString((boolean[]) o);
582             else
583                 s = o.toString();
584             return s;
585         } else {
586             return o.toString();
587         }
588     }
589 
assertDeepEquals(Object expected, Object received, String msg)590     private static void assertDeepEquals(Object expected, Object received, String msg) {
591         if (!Objects.deepEquals(expected, received)) {
592             throw new TestAssertException("Unexpected result for " + msg
593                     + ".\n\texpected: " + deepToString(expected)
594                     +  "\n\tactual:   " + deepToString(received));
595         } else {
596             System.out.println("Got expected " + msg + ": " + deepToString(received));
597         }
598     }
599 
600     final static class PermissionsBuilder {
601         final Permissions perms;
PermissionsBuilder()602         public PermissionsBuilder() {
603             this(new Permissions());
604         }
PermissionsBuilder(Permissions perms)605         public PermissionsBuilder(Permissions perms) {
606             this.perms = perms;
607         }
add(Permission p)608         public PermissionsBuilder add(Permission p) {
609             perms.add(p);
610             return this;
611         }
addAll(PermissionCollection col)612         public PermissionsBuilder addAll(PermissionCollection col) {
613             if (col != null) {
614                 for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) {
615                     perms.add(e.nextElement());
616                 }
617             }
618             return this;
619         }
toPermissions()620         public Permissions toPermissions() {
621             final PermissionsBuilder builder = new PermissionsBuilder();
622             builder.addAll(perms);
623             return builder.perms;
624         }
625     }
626 
627     public static class SimplePolicy extends Policy {
628 
629         final Permissions basic;
630         final Permissions control;
631         final Permissions all;
632         public final static ThreadLocal<AtomicBoolean> allowAll =
633                 new ThreadLocal<AtomicBoolean>() {
634             @Override
635             protected AtomicBoolean initialValue() {
636                 return new AtomicBoolean();
637             }
638         };
639         public final static ThreadLocal<AtomicBoolean> allowControl =
640                 new ThreadLocal<AtomicBoolean>() {
641             @Override
642             protected AtomicBoolean initialValue() {
643                 return new AtomicBoolean();
644             }
645         };
SimplePolicy(TestCase test)646         public SimplePolicy(TestCase test) {
647             basic = new Permissions();
648             control = new Permissions();
649             control.add(new LoggingPermission("control", null));
650 
651             // these are used for configuring the test itself...
652             all = new Permissions();
653             all.add(new java.security.AllPermission());
654 
655         }
656 
657         @Override
implies(ProtectionDomain domain, Permission permission)658         public boolean implies(ProtectionDomain domain, Permission permission) {
659             return getPermissions(domain).implies(permission) ||
660                    DEFAULT_POLICY.implies(domain, permission);
661         }
662 
permissions()663         public PermissionCollection permissions() {
664             PermissionsBuilder builder = new PermissionsBuilder();
665             if (allowAll.get().get()) {
666                 builder.addAll(all);
667             } else {
668                 builder.addAll(basic);
669                 if (allowControl.get().get()) {
670                     builder.addAll(control);
671                 }
672             }
673             return builder.toPermissions();
674         }
675 
676         @Override
getPermissions(CodeSource codesource)677         public PermissionCollection getPermissions(CodeSource codesource) {
678             return permissions();
679         }
680 
681         @Override
getPermissions(ProtectionDomain domain)682         public PermissionCollection getPermissions(ProtectionDomain domain) {
683             return permissions();
684         }
685     }
686 
687 }
688