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( 132 TestCase.PERMISSION.toString()); 133 if (System.getSecurityManager() != null) { 134 throw new Error("Security manager is already set"); 135 } 136 Policy.setPolicy(new SimplePolicy(TestCase.PERMISSION)); 137 System.setSecurityManager(new SecurityManager()); 138 139 try { 140 run = new TestConfigurationListener("[Should Be Denied]"); 141 throw new RuntimeException("ConfigurationListener constructor: Permission not checked!"); 142 } catch (AccessControlException x) { 143 boolean ok = false; 144 if (x.getPermission() instanceof LoggingPermission) { 145 if ("control".equals(x.getPermission().getName())) { 146 System.out.println("ConfigurationListener constructor: Got expected exception: " + x); 147 ok = true; 148 } 149 } 150 if (!ok) { 151 throw new RuntimeException("ConfigurationListener constructor: Unexpected exception: "+x, x); 152 } 153 } 154 try { 155 LogManager.getLogManager().addConfigurationListener(run); 156 throw new RuntimeException("addConfigurationListener: Permission not checked!"); 157 } catch (AccessControlException x) { 158 boolean ok = false; 159 if (x.getPermission() instanceof LoggingPermission) { 160 if ("control".equals(x.getPermission().getName())) { 161 System.out.println("addConfigurationListener: Got expected exception: " + x); 162 ok = true; 163 } 164 } 165 if (!ok) { 166 throw new RuntimeException("addConfigurationListener: Unexpected exception: "+x, x); 167 } 168 } 169 170 try { 171 LogManager.getLogManager().removeConfigurationListener(run); 172 throw new RuntimeException("removeConfigurationListener: Permission not checked!"); 173 } catch (AccessControlException x) { 174 boolean ok = false; 175 if (x.getPermission() instanceof LoggingPermission) { 176 if ("control".equals(x.getPermission().getName())) { 177 System.out.println("removeConfigurationListener: Got expected exception: " + x); 178 ok = true; 179 } 180 } 181 if (!ok) { 182 throw new RuntimeException("removeConfigurationListener: Unexpected exception: "+x, x); 183 } 184 } 185 try { 186 LogManager.getLogManager().addConfigurationListener(null); 187 throw new RuntimeException( 188 "addConfigurationListener(null): Expected NPE not thrown."); 189 } catch (NullPointerException npe) { 190 System.out.println("Got expected NPE: "+npe); 191 } 192 193 try { 194 LogManager.getLogManager().removeConfigurationListener(null); 195 throw new RuntimeException( 196 "removeConfigurationListener(null): Expected NPE not thrown."); 197 } catch (NullPointerException npe) { 198 System.out.println("Got expected NPE: "+npe); 199 } 200 201 202 } 203 204 205 static class TestConfigurationListener implements Runnable { 206 final AtomicLong count = new AtomicLong(0); 207 final String name; 208 TestConfigurationListener(String name) { 209 this.name = name; 210 } 211 @Override 212 public void run() { 213 final long times = count.incrementAndGet(); 214 System.out.println("Configured \"" + name + "\": " + times); 215 } 216 } 217 218 private static void expect(TestConfigurationListener listener, long value) { 219 final long got = listener.count.longValue(); 220 if (got != value) { 221 throw new RuntimeException(listener.name + " expected " + value +", got " + got); 222 } 223 224 } 225 226 public interface ThrowingConsumer<T, I extends Exception> { 227 public void accept(T t) throws I; 228 } 229 230 public static class ReadConfiguration implements ThrowingConsumer<LogManager, IOException> { 231 232 @Override 233 public void accept(LogManager t) throws IOException { 234 t.readConfiguration(); 235 } 236 237 } 238 239 public static void test(String loggerName) throws Exception { 240 System.out.println("Starting test for " + loggerName); 241 test("m.readConfiguration()", (m) -> m.readConfiguration()); 242 test("m.readConfiguration(new ByteArrayInputStream(new byte[0]))", 243 (m) -> m.readConfiguration(new ByteArrayInputStream(new byte[0]))); 244 System.out.println("Test passed for " + loggerName); 245 } 246 247 public static void test(String testName, 248 ThrowingConsumer<LogManager, IOException> readConfiguration) throws Exception { 249 250 251 System.out.println("\nBEGIN " + testName); 252 LogManager m = LogManager.getLogManager(); 253 254 final TestConfigurationListener l1 = new TestConfigurationListener("l#1"); 255 final TestConfigurationListener l2 = new TestConfigurationListener("l#2"); 256 m.addConfigurationListener(l1); 257 m.addConfigurationListener(l2); 258 expect(l1, 0); 259 expect(l2, 0); 260 261 readConfiguration.accept(m); 262 expect(l1, 1); 263 expect(l2, 1); 264 m.addConfigurationListener(l1); 265 expect(l1, 1); 266 expect(l2, 1); 267 readConfiguration.accept(m); 268 expect(l1, 2); 269 expect(l2, 2); 270 m.removeConfigurationListener(l1); 271 expect(l1, 2); 272 expect(l2, 2); 273 readConfiguration.accept(m); 274 expect(l1, 2); 275 expect(l2, 3); 276 m.removeConfigurationListener(l1); 277 expect(l1, 2); 278 expect(l2, 3); 279 readConfiguration.accept(m); 280 expect(l1, 2); 281 expect(l2, 4); 282 m.removeConfigurationListener(l2); 283 expect(l1, 2); 284 expect(l2, 4); 285 readConfiguration.accept(m); 286 expect(l1, 2); 287 expect(l2, 4); 288 289 // l1 and l2 should no longer be present: this should not fail... 290 m.removeConfigurationListener(l1); 291 m.removeConfigurationListener(l1); 292 m.removeConfigurationListener(l2); 293 m.removeConfigurationListener(l2); 294 expect(l1, 2); 295 expect(l2, 4); 296 297 readConfiguration.accept(m); 298 expect(l1, 2); 299 expect(l2, 4); 300 301 // add back l1 and l2 302 m.addConfigurationListener(l1); 303 m.addConfigurationListener(l2); 304 expect(l1, 2); 305 expect(l2, 4); 306 307 readConfiguration.accept(m); 308 expect(l1, 3); 309 expect(l2, 5); 310 311 m.removeConfigurationListener(l1); 312 m.removeConfigurationListener(l2); 313 expect(l1, 3); 314 expect(l2, 5); 315 316 readConfiguration.accept(m); 317 expect(l1, 3); 318 expect(l2, 5); 319 320 try { 321 m.addConfigurationListener(null); 322 throw new RuntimeException( 323 "addConfigurationListener(null): Expected NPE not thrown."); 324 } catch (NullPointerException npe) { 325 System.out.println("Got expected NPE: "+npe); 326 } 327 328 try { 329 m.removeConfigurationListener(null); 330 throw new RuntimeException( 331 "removeConfigurationListener(null): Expected NPE not thrown."); 332 } catch (NullPointerException npe) { 333 System.out.println("Got expected NPE: "+npe); 334 } 335 336 System.out.println("END " + testName+"\n"); 337 338 } 339 340 341 final static class PermissionsBuilder { 342 final Permissions perms; 343 public PermissionsBuilder() { 344 this(new Permissions()); 345 } 346 public PermissionsBuilder(Permissions perms) { 347 this.perms = perms; 348 } 349 public PermissionsBuilder add(Permission p) { 350 perms.add(p); 351 return this; 352 } 353 public PermissionsBuilder addAll(PermissionCollection col) { 354 if (col != null) { 355 for (Enumeration<Permission> e = col.elements(); e.hasMoreElements(); ) { 356 perms.add(e.nextElement()); 357 } 358 } 359 return this; 360 } 361 public Permissions toPermissions() { 362 final PermissionsBuilder builder = new PermissionsBuilder(); 363 builder.addAll(perms); 364 return builder.perms; 365 } 366 } 367 368 public static class SimplePolicy extends Policy { 369 370 final Permissions permissions; 371 public SimplePolicy(TestCase test) { 372 permissions = new Permissions(); 373 if (test != TestCase.PERMISSION) { 374 permissions.add(new LoggingPermission("control", null)); 375 permissions.add(new PropertyPermission("java.util.logging.config.class", "read")); 376 permissions.add(new PropertyPermission("java.util.logging.config.file", "read")); 377 permissions.add(new PropertyPermission("java.home", "read")); 378 permissions.add(new FilePermission("<<ALL FILES>>", "read")); 379 } 380 } 381 382 @Override 383 public boolean implies(ProtectionDomain domain, Permission permission) { 384 return permissions.implies(permission); 385 } 386 387 @Override 388 public PermissionCollection getPermissions(CodeSource codesource) { 389 return new PermissionsBuilder().addAll(permissions).toPermissions(); 390 } 391 392 @Override 393 public PermissionCollection getPermissions(ProtectionDomain domain) { 394 return new PermissionsBuilder().addAll(permissions).toPermissions(); 395 } 396 } 397 398 }