1 /* 2 * Copyright (c) 2014, 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.FilePermission; 25 import java.io.IOException; 26 import java.security.AccessControlException; 27 import java.security.CodeSource; 28 import java.security.Permission; 29 import java.security.PermissionCollection; 30 import java.security.Permissions; 31 import java.security.Policy; 32 import java.security.ProtectionDomain; 33 import java.util.Enumeration; 34 import java.util.PropertyPermission; 35 import java.util.concurrent.atomic.AtomicLong; 36 import java.util.logging.LogManager; 37 import java.util.logging.LoggingPermission; 38 39 /** 40 * @test 41 * @bug 8043306 42 * @summary tests LogManager.addConfigurationListener and 43 * LogManager.removeConfigurationListener; 44 * @build TestConfigurationListeners 45 * @run main/othervm TestConfigurationListeners UNSECURE 46 * @run main/othervm TestConfigurationListeners PERMISSION 47 * @run main/othervm TestConfigurationListeners SECURE 48 * @author danielfuchs 49 */ 50 public class TestConfigurationListeners { 51 52 /** 53 * We will test add and remove ConfigurationListeners in 3 configurations. 54 * UNSECURE: No security manager. 55 * SECURE: With the security manager present - and the required 56 * LoggingPermission("control") granted. 57 * PERMISSION: With the security manager present - and the required 58 * LoggingPermission("control") *not* granted. Here we will 59 * test that the expected security permission is thrown. 60 */ 61 public static enum TestCase { 62 UNSECURE, SECURE, PERMISSION; 63 public void run(String name) throws Exception { 64 System.out.println("Running test case: " + name()); 65 switch (this) { 66 case UNSECURE: 67 testUnsecure(name); 68 break; 69 case SECURE: 70 testSecure(name); 71 break; 72 case PERMISSION: 73 testPermission(name); 74 break; 75 default: 76 throw new Error("Unknown test case: "+this); 77 } 78 } 79 public String loggerName(String name) { 80 return name; 81 } 82 } 83 84 public static void main(String... args) throws Exception { 85 86 87 if (args == null || args.length == 0) { 88 args = new String[] { 89 TestCase.UNSECURE.name(), 90 TestCase.SECURE.name(), 91 }; 92 } 93 94 for (String testName : args) { 95 TestCase test = TestCase.valueOf(testName); 96 test.run(test.loggerName("foo.bar")); 97 } 98 } 99 100 /** 101 * Test without security manager. 102 * @param loggerName The logger to use. 103 * @throws Exception if the test fails. 104 */ 105 public static void testUnsecure(String loggerName) throws Exception { 106 if (System.getSecurityManager() != null) { 107 throw new Error("Security manager is set"); 108 } 109 test(loggerName); 110 } 111 112 /** 113 * Test with security manager. 114 * @param loggerName The logger to use. 115 * @throws Exception if the test fails. 116 */ 117 public static void testSecure(String loggerName) throws Exception { 118 if (System.getSecurityManager() != null) { 119 throw new Error("Security manager is already set"); 120 } 121 Policy.setPolicy(new SimplePolicy(TestCase.SECURE)); 122 System.setSecurityManager(new SecurityManager()); 123 test(loggerName); 124 } 125 126 /** 127 * Test the LoggingPermission("control") is required. 128 * @param loggerName The logger to use. 129 */ 130 public static void testPermission(String loggerName) { 131 TestConfigurationListener run = new TestConfigurationListener(TestCase.PERMISSION.toString()); 132 if (System.getSecurityManager() != null) { 133 throw new Error("Security manager is already set"); 134 } 135 Policy.setPolicy(new SimplePolicy(TestCase.PERMISSION)); 136 System.setSecurityManager(new SecurityManager()); 137 138 try { 139 run = new TestConfigurationListener("[Should Be Denied]"); 140 throw new RuntimeException("ConfigurationListener constructor: Permission not checked!"); 141 } catch (AccessControlException x) { 142 boolean ok = false; 143 if (x.getPermission() instanceof LoggingPermission) { 144 if ("control".equals(x.getPermission().getName())) { 145 System.out.println("ConfigurationListener constructor: Got expected exception: " + x); 146 ok = true; 147 } 148 } 149 if (!ok) { 150 throw new RuntimeException("ConfigurationListener constructor: Unexpected exception: "+x, x); 151 } 152 } 153 try { 154 LogManager.getLogManager().addConfigurationListener(run); 155 throw new RuntimeException("addConfigurationListener: Permission not checked!"); 156 } catch (AccessControlException x) { 157 boolean ok = false; 158 if (x.getPermission() instanceof LoggingPermission) { 159 if ("control".equals(x.getPermission().getName())) { 160 System.out.println("addConfigurationListener: Got expected exception: " + x); 161 ok = true; 162 } 163 } 164 if (!ok) { 165 throw new RuntimeException("addConfigurationListener: Unexpected exception: "+x, x); 166 } 167 } 168 169 try { 170 LogManager.getLogManager().removeConfigurationListener(run); 171 throw new RuntimeException("removeConfigurationListener: Permission not checked!"); 172 } catch (AccessControlException x) { 173 boolean ok = false; 174 if (x.getPermission() instanceof LoggingPermission) { 175 if ("control".equals(x.getPermission().getName())) { 176 System.out.println("removeConfigurationListener: Got expected exception: " + x); 177 ok = true; 178 } 179 } 180 if (!ok) { 181 throw new RuntimeException("removeConfigurationListener: Unexpected exception: "+x, x); 182 } 183 } 184 185 } 186 187 188 static class TestConfigurationListener extends LogManager.ConfigurationListener { 189 final AtomicLong count = new AtomicLong(0); 190 final String name; 191 TestConfigurationListener(String name) { 192 this.name = name; 193 } 194 @Override 195 public void configurationLoaded() { 196 final long times = count.incrementAndGet(); 197 System.out.println("Configured \"" + name + "\": " + times); 198 } 199 } 200 201 private static void expect(TestConfigurationListener listener, long value) { 202 final long got = listener.count.longValue(); 203 if (got != value) { 204 throw new RuntimeException(listener.name + " expected " + value +", got " + got); 205 } 206 207 } 208 209 public interface ThrowingConsumer<T, I extends Exception> { 210 public void accept(T t) throws I; 211 } 212 213 public static class ReadConfiguration implements ThrowingConsumer<LogManager, IOException> { 214 215 @Override 216 public void accept(LogManager t) throws IOException { 217 t.readConfiguration(); 218 } 219 220 } 221 222 public static void test(String loggerName) throws Exception { 223 System.out.println("Starting test for " + loggerName); 224 test("m.readConfiguration()", (m) -> m.readConfiguration()); 225 test("m.readConfiguration(new ByteArrayInputStream(new byte[0]))", 226 (m) -> m.readConfiguration(new ByteArrayInputStream(new byte[0]))); 227 System.out.println("Test passed for " + loggerName); 228 } 229 230 public static void test(String testName, 231 ThrowingConsumer<LogManager, IOException> readConfiguration) throws Exception { 232 233 234 System.out.println("\nBEGIN " + testName); 235 LogManager m = LogManager.getLogManager(); 236 237 final TestConfigurationListener l1 = new TestConfigurationListener("l#1"); 238 final TestConfigurationListener l2 = new TestConfigurationListener("l#2"); 239 m.addConfigurationListener(l1); 240 m.addConfigurationListener(l2); 241 expect(l1, 0); 242 expect(l2, 0); 243 244 readConfiguration.accept(m); 245 expect(l1, 1); 246 expect(l2, 1); 247 m.addConfigurationListener(l1); 248 expect(l1, 1); 249 expect(l2, 1); 250 readConfiguration.accept(m); 251 expect(l1, 3); 252 expect(l2, 2); 253 m.removeConfigurationListener(l1); 254 expect(l1, 3); 255 expect(l2, 2); 256 readConfiguration.accept(m); 257 expect(l1, 4); 258 expect(l2, 3); 259 m.removeConfigurationListener(l1); 260 expect(l1, 4); 261 expect(l2, 3); 262 readConfiguration.accept(m); 263 expect(l1, 4); 264 expect(l2, 4); 265 m.removeConfigurationListener(l2); 266 expect(l1, 4); 267 expect(l2, 4); 268 readConfiguration.accept(m); 269 expect(l1, 4); 270 expect(l2, 4); 271 272 // l1 and l2 should no longer be present: this should not fail... 273 m.removeConfigurationListener(l1); 274 m.removeConfigurationListener(l1); 275 m.removeConfigurationListener(l2); 276 m.removeConfigurationListener(l2); 277 expect(l1, 4); 278 expect(l2, 4); 279 280 readConfiguration.accept(m); 281 expect(l1, 4); 282 expect(l2, 4); 283 284 // add back l1 and l2 285 m.addConfigurationListener(l1); 286 m.addConfigurationListener(l2); 287 expect(l1, 4); 288 expect(l2, 4); 289 290 readConfiguration.accept(m); 291 expect(l1, 5); 292 expect(l2, 5); 293 294 m.removeConfigurationListener(l1); 295 m.removeConfigurationListener(l2); 296 expect(l1, 5); 297 expect(l2, 5); 298 299 readConfiguration.accept(m); 300 expect(l1, 5); 301 expect(l2, 5); 302 303 System.out.println("END " + testName+"\n"); 304 305 } 306 307 308 final static class PermissionsBuilder { 309 final Permissions perms; 310 public PermissionsBuilder() { 311 this(new Permissions()); 312 } 313 public PermissionsBuilder(Permissions perms) { 314 this.perms = perms; 315 } 316 public PermissionsBuilder add(Permission p) { 317 perms.add(p); 318 return this; 319 } 320 public PermissionsBuilder addAll(PermissionCollection col) { 321 if (col != null) { 322 for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) { 323 perms.add(e.nextElement()); 324 } 325 } 326 return this; 327 } 328 public Permissions toPermissions() { 329 final PermissionsBuilder builder = new PermissionsBuilder(); 330 builder.addAll(perms); 331 return builder.perms; 332 } 333 } 334 335 public static class SimplePolicy extends Policy { 336 337 final Permissions permissions; 338 public SimplePolicy(TestCase test) { 339 permissions = new Permissions(); 340 if (test != TestCase.PERMISSION) { 341 permissions.add(new LoggingPermission("control", null)); 342 permissions.add(new PropertyPermission("java.util.logging.config.class", "read")); 343 permissions.add(new PropertyPermission("java.util.logging.config.file", "read")); 344 permissions.add(new PropertyPermission("java.home", "read")); 345 permissions.add(new FilePermission("<<ALL FILES>>", "read")); 346 } 347 } 348 349 @Override 350 public boolean implies(ProtectionDomain domain, Permission permission) { 351 return permissions.implies(permission); 352 } 353 354 @Override 355 public PermissionCollection getPermissions(CodeSource codesource) { 356 return new PermissionsBuilder().addAll(permissions).toPermissions(); 357 } 358 359 @Override 360 public PermissionCollection getPermissions(ProtectionDomain domain) { 361 return new PermissionsBuilder().addAll(permissions).toPermissions(); 362 } 363 } 364 365 }