# HG changeset patch # User mullan # Date 1433855887 14400 # Node ID 00a25f4c4d4438a8001d9725be749255e01d11d8 # Parent a6b5f444cb68ffd8bbc67def56416db50e32ff04 8056179: Store permissions in concurrent collections in PermissionCollection subclasses 8065942: Store PermissionCollection entries in a ConcurrentHashMap instead of a HashMap in Permissions class Reviewed-by: weijun diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/src/java.base/share/classes/java/io/FilePermission.java --- a/jdk/src/java.base/share/classes/java/io/FilePermission.java Mon Jun 08 16:17:37 2015 +0300 +++ b/jdk/src/java.base/share/classes/java/io/FilePermission.java Tue Jun 09 09:18:07 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -27,11 +27,9 @@ import java.security.*; import java.util.Enumeration; -import java.util.List; -import java.util.ArrayList; +import java.util.StringJoiner; import java.util.Vector; -import java.util.Collections; -import java.util.StringJoiner; +import java.util.concurrent.ConcurrentHashMap; import sun.security.util.SecurityConstants; /** @@ -288,7 +286,6 @@ * @param path the pathname of the file/directory. * @param mask the action mask to use. */ - // package private for use by the FilePermissionCollection add method FilePermission(String path, int mask) { super(path); @@ -315,6 +312,7 @@ * null and is implied by this object, * false otherwise. */ + @Override public boolean implies(Permission p) { if (!(p instanceof FilePermission)) return false; @@ -387,6 +385,7 @@ * pathname and actions as this FilePermission object, * false otherwise. */ + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -407,6 +406,7 @@ * * @return a hash code value for this object. */ + @Override public int hashCode() { return 0; } @@ -587,6 +587,7 @@ * * @return the canonical string representation of the actions. */ + @Override public String getActions() { if (actions == null) actions = getActions(this.mask); @@ -625,6 +626,7 @@ * @return a new PermissionCollection object suitable for storing * FilePermissions. */ + @Override public PermissionCollection newPermissionCollection() { return new FilePermissionCollection(); } @@ -689,13 +691,13 @@ implements Serializable { // Not serialized; see serialization section at end of class - private transient List perms; + private transient ConcurrentHashMap perms; /** * Create an empty FilePermissionCollection object. */ public FilePermissionCollection() { - perms = new ArrayList<>(); + perms = new ConcurrentHashMap<>(); } /** @@ -710,6 +712,7 @@ * @exception SecurityException - if this FilePermissionCollection object * has been marked readonly */ + @Override public void add(Permission permission) { if (! (permission instanceof FilePermission)) throw new IllegalArgumentException("invalid permission: "+ @@ -718,9 +721,31 @@ throw new SecurityException( "attempt to add a Permission to a readonly PermissionCollection"); - synchronized (this) { - perms.add(permission); - } + FilePermission fp = (FilePermission)permission; + + // Add permission to map if it is absent, or replace with new + // permission if applicable. NOTE: cannot use lambda for + // remappingFunction parameter until JDK-8076596 is fixed. + perms.merge(fp.getName(), fp, + new java.util.function.BiFunction<>() { + @Override + public Permission apply(Permission existingVal, + Permission newVal) { + int oldMask = ((FilePermission)existingVal).getMask(); + int newMask = ((FilePermission)newVal).getMask(); + if (oldMask != newMask) { + int effective = oldMask | newMask; + if (effective == newMask) { + return newVal; + } + if (effective != oldMask) { + return new FilePermission(fp.getName(), effective); + } + } + return existingVal; + } + } + ); } /** @@ -732,26 +757,25 @@ * @return true if "permission" is a proper subset of a permission in * the set, false if not. */ + @Override public boolean implies(Permission permission) { if (! (permission instanceof FilePermission)) return false; - FilePermission fp = (FilePermission) permission; + FilePermission fperm = (FilePermission) permission; - int desired = fp.getMask(); + int desired = fperm.getMask(); int effective = 0; int needed = desired; - synchronized (this) { - int len = perms.size(); - for (int i = 0; i < len; i++) { - FilePermission x = (FilePermission) perms.get(i); - if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(fp)) { - effective |= x.getMask(); - if ((effective & desired) == desired) - return true; - needed = (desired ^ effective); + for (Permission perm : perms.values()) { + FilePermission fp = (FilePermission)perm; + if (((needed & fp.getMask()) != 0) && fp.impliesIgnoreMask(fperm)) { + effective |= fp.getMask(); + if ((effective & desired) == desired) { + return true; } + needed = (desired ^ effective); } } return false; @@ -763,11 +787,9 @@ * * @return an enumeration of all the FilePermission objects. */ + @Override public Enumeration elements() { - // Convert Iterator into Enumeration - synchronized (this) { - return Collections.enumeration(perms); - } + return perms.elements(); } private static final long serialVersionUID = 2202956749081564585L; @@ -795,10 +817,7 @@ // Don't call out.defaultWriteObject() // Write out Vector - Vector permissions = new Vector<>(perms.size()); - synchronized (this) { - permissions.addAll(perms); - } + Vector permissions = new Vector<>(perms.values()); ObjectOutputStream.PutField pfields = out.putFields(); pfields.put("permissions", permissions); @@ -819,7 +838,9 @@ // Get the one we want @SuppressWarnings("unchecked") Vector permissions = (Vector)gfields.get("permissions", null); - perms = new ArrayList<>(permissions.size()); - perms.addAll(permissions); + perms = new ConcurrentHashMap<>(permissions.size()); + for (Permission perm : permissions) { + perms.put(perm.getName(), perm); + } } } diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/src/java.base/share/classes/java/net/SocketPermission.java --- a/jdk/src/java.base/share/classes/java/net/SocketPermission.java Mon Jun 08 16:17:37 2015 +0300 +++ b/jdk/src/java.base/share/classes/java/net/SocketPermission.java Tue Jun 09 09:18:07 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2014, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,24 +25,24 @@ package java.net; -import java.util.Enumeration; -import java.util.Vector; -import java.util.List; -import java.util.ArrayList; -import java.util.Collections; -import java.util.StringJoiner; -import java.util.StringTokenizer; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; +import java.io.Serializable; import java.net.InetAddress; +import java.security.AccessController; import java.security.Permission; import java.security.PermissionCollection; import java.security.PrivilegedAction; -import java.security.AccessController; import java.security.Security; -import java.io.Serializable; -import java.io.ObjectStreamField; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; -import java.io.IOException; +import java.util.Collections; +import java.util.Comparator; +import java.util.Enumeration; +import java.util.Vector; +import java.util.StringJoiner; +import java.util.StringTokenizer; +import java.util.concurrent.ConcurrentSkipListMap; import sun.net.util.IPAddressUtil; import sun.net.RegisteredDomain; import sun.net.PortConfig; @@ -832,6 +832,7 @@ * @return true if the specified permission is implied by this object, * false if not. */ + @Override public boolean implies(Permission p) { int i,j; @@ -1010,6 +1011,7 @@ * SocketPermission object. However, port range will be ignored * in the comparison if obj only contains the action, 'resolve'. */ + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -1069,7 +1071,7 @@ * * @return a hash code value for this object. */ - + @Override public int hashCode() { /* * If this SocketPermission was initialized with an IP address @@ -1137,6 +1139,7 @@ * * @return the canonical string representation of the actions. */ + @Override public String getActions() { if (actions == null) @@ -1156,7 +1159,7 @@ * * @return a new PermissionCollection object suitable for storing SocketPermissions. */ - + @Override public PermissionCollection newPermissionCollection() { return new SocketPermissionCollection(); } @@ -1320,15 +1323,16 @@ implements Serializable { // Not serialized; see serialization section at end of class - private transient List perms; + // A ConcurrentSkipListMap is used to preserve order, so that most + // recently added permissions are checked first (see JDK-4301064). + private transient ConcurrentSkipListMap perms; /** * Create an empty SocketPermissions object. * */ - public SocketPermissionCollection() { - perms = new ArrayList<>(); + perms = new ConcurrentSkipListMap<>(new SPCComparator()); } /** @@ -1343,6 +1347,7 @@ * @exception SecurityException - if this SocketPermissionCollection object * has been marked readonly */ + @Override public void add(Permission permission) { if (! (permission instanceof SocketPermission)) throw new IllegalArgumentException("invalid permission: "+ @@ -1351,11 +1356,32 @@ throw new SecurityException( "attempt to add a Permission to a readonly PermissionCollection"); - // optimization to ensure perms most likely to be tested - // show up early (4301064) - synchronized (this) { - perms.add(0, (SocketPermission)permission); - } + SocketPermission sp = (SocketPermission)permission; + + // Add permission to map if it is absent, or replace with new + // permission if applicable. NOTE: cannot use lambda for + // remappingFunction parameter until JDK-8076596 is fixed. + perms.merge(sp.getName(), sp, + new java.util.function.BiFunction<>() { + @Override + public SocketPermission apply(SocketPermission existingVal, + SocketPermission newVal) { + int oldMask = existingVal.getMask(); + int newMask = newVal.getMask(); + if (oldMask != newMask) { + int effective = oldMask | newMask; + if (effective == newMask) { + return newVal; + } + if (effective != oldMask) { + return new SocketPermission(sp.getName(), + effective); + } + } + return existingVal; + } + } + ); } /** @@ -1367,7 +1393,7 @@ * @return true if "permission" is a proper subset of a permission in * the collection, false if not. */ - + @Override public boolean implies(Permission permission) { if (! (permission instanceof SocketPermission)) @@ -1379,18 +1405,15 @@ int effective = 0; int needed = desired; - synchronized (this) { - int len = perms.size(); - //System.out.println("implies "+np); - for (int i = 0; i < len; i++) { - SocketPermission x = perms.get(i); - //System.out.println(" trying "+x); - if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) { - effective |= x.getMask(); - if ((effective & desired) == desired) - return true; - needed = (desired ^ effective); + //System.out.println("implies "+np); + for (SocketPermission x : perms.values()) { + //System.out.println(" trying "+x); + if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) { + effective |= x.getMask(); + if ((effective & desired) == desired) { + return true; } + needed = (desired ^ effective); } } return false; @@ -1402,13 +1425,10 @@ * * @return an enumeration of all the SocketPermission objects. */ - + @Override @SuppressWarnings("unchecked") public Enumeration elements() { - // Convert Iterator into Enumeration - synchronized (this) { - return Collections.enumeration((List)(List)perms); - } + return (Enumeration)Collections.enumeration(perms.values()); } private static final long serialVersionUID = 2787186408602843674L; @@ -1441,11 +1461,7 @@ // Don't call out.defaultWriteObject() // Write out Vector - Vector permissions = new Vector<>(perms.size()); - - synchronized (this) { - permissions.addAll(perms); - } + Vector permissions = new Vector<>(perms.values()); ObjectOutputStream.PutField pfields = out.putFields(); pfields.put("permissions", permissions); @@ -1466,7 +1482,22 @@ // Get the one we want @SuppressWarnings("unchecked") Vector permissions = (Vector)gfields.get("permissions", null); - perms = new ArrayList<>(permissions.size()); - perms.addAll(permissions); + perms = new ConcurrentSkipListMap<>(new SPCComparator()); + for (SocketPermission sp : permissions) { + perms.put(sp.getName(), sp); + } + } + + /** + * A simple comparator that orders new non-equal entries at the beginning. + */ + private static class SPCComparator implements Comparator { + @Override + public int compare(String s1, String s2) { + if (s1.equals(s2)) { + return 0; + } + return -1; + } } } diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/src/java.base/share/classes/java/security/BasicPermission.java --- a/jdk/src/java.base/share/classes/java/security/BasicPermission.java Mon Jun 08 16:17:37 2015 +0300 +++ b/jdk/src/java.base/share/classes/java/security/BasicPermission.java Tue Jun 09 09:18:07 2015 -0400 @@ -25,15 +25,13 @@ package java.security; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; import java.util.Enumeration; -import java.util.Map; -import java.util.HashMap; import java.util.Hashtable; -import java.util.Collections; -import java.io.ObjectStreamField; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; -import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; /** * The BasicPermission class extends the Permission class, and @@ -165,6 +163,7 @@ * @return true if the passed permission is equal to or * implied by this permission, false otherwise. */ + @Override public boolean implies(Permission p) { if ((p == null) || (p.getClass() != getClass())) return false; @@ -200,6 +199,7 @@ * @return true if {@code obj}'s class is the same as this object's class * and has the same name as this BasicPermission object, false otherwise. */ + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -221,6 +221,7 @@ * * @return a hash code value for this object. */ + @Override public int hashCode() { return this.getName().hashCode(); } @@ -232,6 +233,7 @@ * * @return the empty string "". */ + @Override public String getActions() { return ""; } @@ -248,6 +250,7 @@ * @return a new PermissionCollection object suitable for * storing BasicPermissions. */ + @Override public PermissionCollection newPermissionCollection() { return new BasicPermissionCollection(this.getClass()); } @@ -308,7 +311,7 @@ * collection must be of the same type. * Not serialized; see serialization section at end of class. */ - private transient Map perms; + private transient ConcurrentHashMap perms; /** * This is set to {@code true} if this BasicPermissionCollection @@ -320,7 +323,7 @@ /** * The class to which all BasicPermissions in this - * BasicPermissionCollection belongs. + * BasicPermissionCollection belong. * * @see #serialPersistentFields */ @@ -330,9 +333,8 @@ * Create an empty BasicPermissionCollection object. * */ - public BasicPermissionCollection(Class clazz) { - perms = new HashMap<>(11); + perms = new ConcurrentHashMap<>(11); all_allowed = false; permClass = clazz; } @@ -352,6 +354,7 @@ * @exception SecurityException - if this BasicPermissionCollection object * has been marked readonly */ + @Override public void add(Permission permission) { if (! (permission instanceof BasicPermission)) throw new IllegalArgumentException("invalid permission: "+ @@ -373,13 +376,12 @@ permission); } - synchronized (this) { - perms.put(bp.getCanonicalName(), permission); - } + String canonName = bp.getCanonicalName(); + perms.put(canonName, permission); // No sync on all_allowed; staleness OK if (!all_allowed) { - if (bp.getCanonicalName().equals("*")) + if (canonName.equals("*")) all_allowed = true; } } @@ -393,6 +395,7 @@ * @return true if "permission" is a proper subset of a permission in * the set, false if not. */ + @Override public boolean implies(Permission permission) { if (! (permission instanceof BasicPermission)) return false; @@ -414,11 +417,7 @@ String path = bp.getCanonicalName(); //System.out.println("check "+path); - Permission x; - - synchronized (this) { - x = perms.get(path); - } + Permission x = perms.get(path); if (x != null) { // we have a direct hit! @@ -435,9 +434,7 @@ path = path.substring(0, last+1) + "*"; //System.out.println("check "+path); - synchronized (this) { - x = perms.get(path); - } + x = perms.get(path); if (x != null) { return x.implies(permission); @@ -456,11 +453,9 @@ * * @return an enumeration of all the BasicPermission objects. */ + @Override public Enumeration elements() { - // Convert Iterator of Map values into an Enumeration - synchronized (this) { - return Collections.enumeration(perms.values()); - } + return perms.elements(); } // Need to maintain serialization interoperability with earlier releases, @@ -503,9 +498,7 @@ Hashtable permissions = new Hashtable<>(perms.size()*2); - synchronized (this) { - permissions.putAll(perms); - } + permissions.putAll(perms); // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); @@ -533,7 +526,7 @@ @SuppressWarnings("unchecked") Hashtable permissions = (Hashtable)gfields.get("permissions", null); - perms = new HashMap<>(permissions.size()*2); + perms = new ConcurrentHashMap<>(permissions.size()*2); perms.putAll(permissions); // Get all_allowed diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/src/java.base/share/classes/java/security/Permissions.java --- a/jdk/src/java.base/share/classes/java/security/Permissions.java Mon Jun 08 16:17:37 2015 +0300 +++ b/jdk/src/java.base/share/classes/java/security/Permissions.java Tue Jun 09 09:18:07 2015 -0400 @@ -33,6 +33,7 @@ import java.util.List; import java.util.Iterator; import java.util.Collections; +import java.util.concurrent.ConcurrentHashMap; import java.io.Serializable; import java.io.ObjectStreamField; import java.io.ObjectOutputStream; @@ -85,7 +86,7 @@ * Key is permissions Class, value is PermissionCollection for that class. * Not serialized; see serialization section at end of class. */ - private transient Map, PermissionCollection> permsMap; + private transient ConcurrentHashMap, PermissionCollection> permsMap; // optimization. keep track of whether unresolved permissions need to be // checked @@ -99,7 +100,7 @@ * Creates a new Permissions object containing no PermissionCollections. */ public Permissions() { - permsMap = new HashMap<>(11); + permsMap = new ConcurrentHashMap<>(11); allPermission = null; } @@ -120,18 +121,14 @@ * * @see PermissionCollection#isReadOnly() */ - + @Override public void add(Permission permission) { if (isReadOnly()) throw new SecurityException( "attempt to add a Permission to a readonly Permissions object"); - PermissionCollection pc; - - synchronized (this) { - pc = getPermissionCollection(permission, true); - pc.add(permission); - } + PermissionCollection pc = getPermissionCollection(permission, true); + pc.add(permission); // No sync; staleness -> optimizations delayed, which is OK if (permission instanceof AllPermission) { @@ -169,21 +166,19 @@ * PermissionCollection it * belongs to, false if not. */ - + @Override public boolean implies(Permission permission) { // No sync; staleness -> skip optimization, which is OK if (allPermission != null) { return true; // AllPermission has already been added } else { - synchronized (this) { - PermissionCollection pc = getPermissionCollection(permission, - false); - if (pc != null) { - return pc.implies(permission); - } else { - // none found - return false; - } + PermissionCollection pc = getPermissionCollection(permission, + false); + if (pc != null) { + return pc.implies(permission); + } else { + // none found + return false; } } } @@ -194,14 +189,12 @@ * * @return an enumeration of all the Permissions. */ - + @Override public Enumeration elements() { // go through each Permissions in the hash table // and call their elements() function. - synchronized (this) { - return new PermissionsEnumerator(permsMap.values().iterator()); - } + return new PermissionsEnumerator(permsMap.values().iterator()); } /** @@ -236,34 +229,39 @@ * It should be set to true when invoked from add(). */ private PermissionCollection getPermissionCollection(Permission p, - boolean createEmpty) { + boolean createEmpty) { Class c = p.getClass(); - PermissionCollection pc = permsMap.get(c); - if (!hasUnresolved && !createEmpty) { - return pc; - } else if (pc == null) { + return permsMap.get(c); + } - // Check for unresolved permissions - pc = (hasUnresolved ? getUnresolvedPermissions(p) : null); - - // if still null, create a new collection - if (pc == null && createEmpty) { - - pc = p.newPermissionCollection(); + // Create and add permission collection to map if it is absent. + // NOTE: cannot use lambda for mappingFunction parameter until + // JDK-8076596 is fixed. + return permsMap.computeIfAbsent(c, + new java.util.function.Function<>() { + @Override + public PermissionCollection apply(Class k) { + // Check for unresolved permissions + PermissionCollection pc = + (hasUnresolved ? getUnresolvedPermissions(p) : null); - // still no PermissionCollection? - // We'll give them a PermissionsHash. - if (pc == null) - pc = new PermissionsHash(); - } + // if still null, create a new collection + if (pc == null && createEmpty) { + + pc = p.newPermissionCollection(); - if (pc != null) { - permsMap.put(c, pc); + // still no PermissionCollection? + // We'll give them a PermissionsHash. + if (pc == null) { + pc = new PermissionsHash(); + } + } + return pc; + } } - } - return pc; + ); } /** @@ -277,8 +275,6 @@ */ private PermissionCollection getUnresolvedPermissions(Permission p) { - // Called from within synchronized method so permsMap doesn't need lock - UnresolvedPermissionCollection uc = (UnresolvedPermissionCollection) permsMap.get(UnresolvedPermission.class); @@ -362,9 +358,7 @@ // Copy perms into a Hashtable Hashtable, PermissionCollection> perms = new Hashtable<>(permsMap.size()*2); // no sync; estimate - synchronized (this) { - perms.putAll(permsMap); - } + perms.putAll(permsMap); // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); @@ -394,7 +388,7 @@ @SuppressWarnings("unchecked") Hashtable, PermissionCollection> perms = (Hashtable, PermissionCollection>)gfields.get("perms", null); - permsMap = new HashMap<>(perms.size()*2); + permsMap = new ConcurrentHashMap<>(perms.size()*2); permsMap.putAll(perms); // Set hasUnresolved @@ -481,14 +475,13 @@ * Key and value are (same) permissions objects. * Not serialized; see serialization section at end of class. */ - private transient Map permsMap; + private transient ConcurrentHashMap permsMap; /** * Create an empty PermissionsHash object. */ - PermissionsHash() { - permsMap = new HashMap<>(11); + permsMap = new ConcurrentHashMap<>(11); } /** @@ -496,11 +489,9 @@ * * @param permission the Permission object to add. */ - + @Override public void add(Permission permission) { - synchronized (this) { - permsMap.put(permission, permission); - } + permsMap.put(permission, permission); } /** @@ -512,23 +503,21 @@ * @return true if "permission" is a proper subset of a permission in * the set, false if not. */ - + @Override public boolean implies(Permission permission) { // attempt a fast lookup and implies. If that fails // then enumerate through all the permissions. - synchronized (this) { - Permission p = permsMap.get(permission); + Permission p = permsMap.get(permission); - // If permission is found, then p.equals(permission) - if (p == null) { - for (Permission p_ : permsMap.values()) { - if (p_.implies(permission)) - return true; - } - return false; - } else { - return true; + // If permission is found, then p.equals(permission) + if (p == null) { + for (Permission p_ : permsMap.values()) { + if (p_.implies(permission)) + return true; } + return false; + } else { + return true; } } @@ -537,12 +526,9 @@ * * @return an enumeration of all the Permissions. */ - + @Override public Enumeration elements() { - // Convert Iterator of Map values into an Enumeration - synchronized (this) { - return Collections.enumeration(permsMap.values()); - } + return permsMap.elements(); } private static final long serialVersionUID = -8491988220802933440L; @@ -570,9 +556,7 @@ // Copy perms into a Hashtable Hashtable perms = new Hashtable<>(permsMap.size()*2); - synchronized (this) { - perms.putAll(permsMap); - } + perms.putAll(permsMap); // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); @@ -597,7 +581,7 @@ @SuppressWarnings("unchecked") Hashtable perms = (Hashtable)gfields.get("perms", null); - permsMap = new HashMap<>(perms.size()*2); + permsMap = new ConcurrentHashMap<>(perms.size()*2); permsMap.putAll(perms); } } diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java --- a/jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java Mon Jun 08 16:17:37 2015 +0300 +++ b/jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java Tue Jun 09 09:18:07 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2011, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,11 +25,13 @@ package java.security; -import java.util.*; -import java.io.ObjectStreamField; +import java.io.IOException; +import java.io.ObjectInputStream; import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; -import java.io.IOException; +import java.io.ObjectStreamField; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; +import java.util.concurrent.CopyOnWriteArrayList; /** * A UnresolvedPermissionCollection stores a collection @@ -54,14 +56,14 @@ * of the same type. * Not serialized; see serialization section at end of class. */ - private transient Map> perms; + private transient ConcurrentHashMap> perms; /** * Create an empty UnresolvedPermissionCollection object. * */ public UnresolvedPermissionCollection() { - perms = new HashMap<>(11); + perms = new ConcurrentHashMap<>(11); } /** @@ -70,25 +72,32 @@ * * @param permission the Permission object to add. */ - - public void add(Permission permission) - { + @Override + public void add(Permission permission) { if (! (permission instanceof UnresolvedPermission)) throw new IllegalArgumentException("invalid permission: "+ permission); UnresolvedPermission up = (UnresolvedPermission) permission; - List v; - synchronized (this) { - v = perms.get(up.getName()); - if (v == null) { - v = new ArrayList<>(); - perms.put(up.getName(), v); + // Add permission to map. NOTE: cannot use lambda for + // remappingFunction parameter until JDK-8076596 is fixed. + perms.compute(up.getName(), + new java.util.function.BiFunction<>() { + @Override + public List apply(String key, + List oldValue) { + if (oldValue == null) { + List v = + new CopyOnWriteArrayList<>(); + v.add(up); + return v; + } else { + oldValue.add(up); + return oldValue; + } + } } - } - synchronized (v) { - v.add(up); - } + ); } /** @@ -96,17 +105,15 @@ * and return the List containing them. */ List getUnresolvedPermissions(Permission p) { - synchronized (this) { - return perms.get(p.getClass().getName()); - } + return perms.get(p.getClass().getName()); } /** * always returns false for unresolved permissions * */ - public boolean implies(Permission permission) - { + @Override + public boolean implies(Permission permission) { return false; } @@ -116,18 +123,14 @@ * * @return an enumeration of all the UnresolvedPermission objects. */ - + @Override public Enumeration elements() { List results = new ArrayList<>(); // where results are stored // Get iterator of Map values (which are lists of permissions) - synchronized (this) { - for (List l : perms.values()) { - synchronized (l) { - results.addAll(l); - } - } + for (List l : perms.values()) { + results.addAll(l); } return Collections.enumeration(results); @@ -164,19 +167,14 @@ new Hashtable<>(perms.size()*2); // Convert each entry (List) into a Vector - synchronized (this) { - Set>> set = perms.entrySet(); - for (Map.Entry> e : set) { - // Convert list into Vector - List list = e.getValue(); - Vector vec = new Vector<>(list.size()); - synchronized (list) { - vec.addAll(list); - } + Set>> set = perms.entrySet(); + for (Map.Entry> e : set) { + // Convert list into Vector + List list = e.getValue(); + Vector vec = new Vector<>(list); - // Add to Hashtable being serialized - permissions.put(e.getKey(), vec); - } + // Add to Hashtable being serialized + permissions.put(e.getKey(), vec); } // Write out serializable fields @@ -203,15 +201,14 @@ Hashtable> permissions = (Hashtable>) gfields.get("permissions", null); - perms = new HashMap<>(permissions.size()*2); + perms = new ConcurrentHashMap<>(permissions.size()*2); // Convert each entry (Vector) into a List Set>> set = permissions.entrySet(); for (Map.Entry> e : set) { // Convert Vector into ArrayList Vector vec = e.getValue(); - List list = new ArrayList<>(vec.size()); - list.addAll(vec); + List list = new CopyOnWriteArrayList<>(vec); // Add to Hashtable being serialized perms.put(e.getKey(), list); diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/src/java.base/share/classes/java/util/PropertyPermission.java --- a/jdk/src/java.base/share/classes/java/util/PropertyPermission.java Mon Jun 08 16:17:37 2015 +0300 +++ b/jdk/src/java.base/share/classes/java/util/PropertyPermission.java Tue Jun 09 09:18:07 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 1997, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 1997, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,18 +25,15 @@ package java.util; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; import java.io.Serializable; -import java.io.IOException; import java.security.*; -import java.util.Map; -import java.util.HashMap; import java.util.Enumeration; import java.util.Hashtable; -import java.util.Collections; -import java.io.ObjectStreamField; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; -import java.io.IOException; +import java.util.concurrent.ConcurrentHashMap; import sun.security.util.SecurityConstants; /** @@ -162,6 +159,16 @@ } /** + * Creates a PropertyPermission object with the specified name and + * a pre-calculated mask. Avoids the overhead of re-computing the mask. + * Called by PropertyPermissionCollection. + */ + PropertyPermission(String name, int mask) { + super(name, getActions(mask)); + this.mask = mask; + } + + /** * Checks if this PropertyPermission object "implies" the specified * permission. *

@@ -178,6 +185,7 @@ * @return true if the specified permission is implied by this object, * false if not. */ + @Override public boolean implies(Permission p) { if (!(p instanceof PropertyPermission)) return false; @@ -198,6 +206,7 @@ * @return true if obj is a PropertyPermission, and has the same name and * actions as this PropertyPermission object. */ + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -219,6 +228,7 @@ * * @return a hash code value for this object. */ + @Override public int hashCode() { return this.getName().hashCode(); } @@ -345,6 +355,7 @@ * * @return the canonical string representation of the actions. */ + @Override public String getActions() { if (actions == null) actions = getActions(this.mask); @@ -369,6 +380,7 @@ * @return a new PermissionCollection object suitable for storing * PropertyPermissions. */ + @Override public PermissionCollection newPermissionCollection() { return new PropertyPermissionCollection(); } @@ -425,7 +437,7 @@ * Key is property name; value is PropertyPermission. * Not serialized; see serialization section at end of class. */ - private transient Map perms; + private transient ConcurrentHashMap perms; /** * Boolean saying if "*" is in the collection. @@ -439,7 +451,7 @@ * Create an empty PropertyPermissionCollection object. */ public PropertyPermissionCollection() { - perms = new HashMap<>(32); // Capacity for default policy + perms = new ConcurrentHashMap<>(32); // Capacity for default policy all_allowed = false; } @@ -455,6 +467,7 @@ * @exception SecurityException - if this PropertyPermissionCollection * object has been marked readonly */ + @Override public void add(Permission permission) { if (! (permission instanceof PropertyPermission)) throw new IllegalArgumentException("invalid permission: "+ @@ -466,21 +479,30 @@ PropertyPermission pp = (PropertyPermission) permission; String propName = pp.getName(); - synchronized (this) { - PropertyPermission existing = perms.get(propName); + // Add permission to map if it is absent, or replace with new + // permission if applicable. NOTE: cannot use lambda for + // remappingFunction parameter until JDK-8076596 is fixed. + perms.merge(propName, pp, + new java.util.function.BiFunction<>() { + @Override + public PropertyPermission apply(PropertyPermission existingVal, + PropertyPermission newVal) { - if (existing != null) { - int oldMask = existing.getMask(); - int newMask = pp.getMask(); - if (oldMask != newMask) { - int effective = oldMask | newMask; - String actions = PropertyPermission.getActions(effective); - perms.put(propName, new PropertyPermission(propName, actions)); + int oldMask = existingVal.getMask(); + int newMask = newVal.getMask(); + if (oldMask != newMask) { + int effective = oldMask | newMask; + if (effective == newMask) { + return newVal; + } + if (effective != oldMask) { + return new PropertyPermission(propName, effective); + } + } + return existingVal; } - } else { - perms.put(propName, pp); } - } + ); if (!all_allowed) { if (propName.equals("*")) @@ -497,9 +519,10 @@ * @return true if "permission" is a proper subset of a permission in * the set, false if not. */ + @Override public boolean implies(Permission permission) { if (! (permission instanceof PropertyPermission)) - return false; + return false; PropertyPermission pp = (PropertyPermission) permission; PropertyPermission x; @@ -509,9 +532,7 @@ // short circuit if the "*" Permission was added if (all_allowed) { - synchronized (this) { - x = perms.get("*"); - } + x = perms.get("*"); if (x != null) { effective |= x.getMask(); if ((effective & desired) == desired) @@ -526,9 +547,7 @@ String name = pp.getName(); //System.out.println("check "+name); - synchronized (this) { - x = perms.get(name); - } + x = perms.get(name); if (x != null) { // we have a direct hit! @@ -546,9 +565,7 @@ name = name.substring(0, last+1) + "*"; //System.out.println("check "+name); - synchronized (this) { - x = perms.get(name); - } + x = perms.get(name); if (x != null) { effective |= x.getMask(); @@ -569,16 +586,14 @@ * * @return an enumeration of all the PropertyPermission objects. */ + @Override @SuppressWarnings("unchecked") public Enumeration elements() { - // Convert Iterator of Map values into an Enumeration - synchronized (this) { - /** - * Casting to rawtype since Enumeration - * cannot be directly cast to Enumeration - */ - return (Enumeration)Collections.enumeration(perms.values()); - } + /** + * Casting to rawtype since Enumeration + * cannot be directly cast to Enumeration + */ + return (Enumeration)perms.elements(); } private static final long serialVersionUID = 7015263904581634791L; @@ -616,9 +631,7 @@ // Copy perms into a Hashtable Hashtable permissions = new Hashtable<>(perms.size()*2); - synchronized (this) { - permissions.putAll(perms); - } + permissions.putAll(perms); // Write out serializable fields ObjectOutputStream.PutField pfields = out.putFields(); @@ -646,7 +659,7 @@ @SuppressWarnings("unchecked") Hashtable permissions = (Hashtable)gfields.get("permissions", null); - perms = new HashMap<>(permissions.size()*2); + perms = new ConcurrentHashMap<>(permissions.size()*2); perms.putAll(permissions); } } diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java --- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java Mon Jun 08 16:17:37 2015 +0300 +++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java Tue Jun 09 09:18:07 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2000, 2013, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2000, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -25,14 +25,15 @@ package javax.security.auth.kerberos; -import java.util.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; +import java.security.BasicPermission; import java.security.Permission; -import java.security.BasicPermission; import java.security.PermissionCollection; -import java.io.ObjectStreamField; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; -import java.io.IOException; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * This class is used to restrict the usage of the Kerberos @@ -137,6 +138,7 @@ * @return true if the specified permission is implied by this object, * false if not. */ + @Override public boolean implies(Permission p) { if (!(p instanceof DelegationPermission)) return false; @@ -159,6 +161,7 @@ * has the same subordinate and service principal as this. * DelegationPermission object. */ + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -175,11 +178,11 @@ * * @return a hash code value for this object. */ + @Override public int hashCode() { return getName().hashCode(); } - /** * Returns a PermissionCollection object for storing * DelegationPermission objects. @@ -192,7 +195,7 @@ * @return a new PermissionCollection object suitable for storing * DelegationPermissions. */ - + @Override public PermissionCollection newPermissionCollection() { return new KrbDelegationPermissionCollection(); } @@ -263,13 +266,12 @@ implements java.io.Serializable { // Not serialized; see serialization section at end of class. - private transient List perms; + private transient ConcurrentHashMap perms; public KrbDelegationPermissionCollection() { - perms = new ArrayList(); + perms = new ConcurrentHashMap<>(); } - /** * Check and see if this collection of permissions implies the permissions * expressed in "permission". @@ -279,18 +281,13 @@ * @return true if "permission" is a proper subset of a permission in * the collection, false if not. */ + @Override public boolean implies(Permission permission) { if (! (permission instanceof DelegationPermission)) - return false; + return false; - synchronized (this) { - for (Permission x : perms) { - if (x.implies(permission)) - return true; - } - } - return false; - + // if map contains key, then it automatically implies it + return perms.containsKey(permission); } /** @@ -305,6 +302,7 @@ * @exception SecurityException - if this PermissionCollection object * has been marked readonly */ + @Override public void add(Permission permission) { if (! (permission instanceof DelegationPermission)) throw new IllegalArgumentException("invalid permission: "+ @@ -312,9 +310,7 @@ if (isReadOnly()) throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection"); - synchronized (this) { - perms.add(0, permission); - } + perms.put(permission, Boolean.TRUE); } /** @@ -323,11 +319,9 @@ * * @return an enumeration of all the DelegationPermission objects. */ + @Override public Enumeration elements() { - // Convert Iterator into Enumeration - synchronized (this) { - return Collections.enumeration(perms); - } + return perms.keys(); } private static final long serialVersionUID = -3383936936589966948L; @@ -354,11 +348,7 @@ // Don't call out.defaultWriteObject() // Write out Vector - Vector permissions = new Vector<>(perms.size()); - - synchronized (this) { - permissions.addAll(perms); - } + Vector permissions = new Vector<>(perms.keySet()); ObjectOutputStream.PutField pfields = out.putFields(); pfields.put("permissions", permissions); @@ -379,8 +369,10 @@ // Get the one we want Vector permissions = - (Vector)gfields.get("permissions", null); - perms = new ArrayList(permissions.size()); - perms.addAll(permissions); + (Vector)gfields.get("permissions", null); + perms = new ConcurrentHashMap<>(permissions.size()); + for (Permission perm : permissions) { + perms.put(perm, Boolean.TRUE); + } } } diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java --- a/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java Mon Jun 08 16:17:37 2015 +0300 +++ b/jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java Tue Jun 09 09:18:07 2015 -0400 @@ -25,13 +25,14 @@ package javax.security.auth.kerberos; -import java.util.*; +import java.io.IOException; +import java.io.ObjectInputStream; +import java.io.ObjectOutputStream; +import java.io.ObjectStreamField; import java.security.Permission; import java.security.PermissionCollection; -import java.io.ObjectStreamField; -import java.io.ObjectOutputStream; -import java.io.ObjectInputStream; -import java.io.IOException; +import java.util.*; +import java.util.concurrent.ConcurrentHashMap; /** * This class is used to protect Kerberos services and the @@ -149,6 +150,15 @@ init(servicePrincipal, getMask(action)); } + /** + * Creates a ServicePermission object with the specified servicePrincipal + * and a pre-calculated mask. Avoids the overhead of re-computing the mask. + * Called by ServicePermissionCollection. + */ + ServicePermission(String servicePrincipal, int mask) { + super(servicePrincipal); + init(servicePrincipal, mask); + } /** * Initialize the ServicePermission object. @@ -175,6 +185,7 @@ * @return true if the specified permission is implied by this object, * false if not. */ + @Override public boolean implies(Permission p) { if (!(p instanceof ServicePermission)) return false; @@ -200,6 +211,7 @@ * same service principal, and actions as this * ServicePermission object. */ + @Override public boolean equals(Object obj) { if (obj == this) return true; @@ -219,7 +231,7 @@ * * @return a hash code value for this object. */ - + @Override public int hashCode() { return (getName().hashCode() ^ mask); } @@ -234,7 +246,7 @@ * @param mask a specific integer action mask to translate into a string * @return the canonical string representation of the actions */ - private static String getActions(int mask) + static String getActions(int mask) { StringBuilder sb = new StringBuilder(); boolean comma = false; @@ -259,6 +271,7 @@ * Always returns present actions in the following order: * initiate, accept. */ + @Override public String getActions() { if (actions == null) actions = getActions(this.mask); @@ -279,6 +292,7 @@ * @return a new PermissionCollection object suitable for storing * ServicePermissions. */ + @Override public PermissionCollection newPermissionCollection() { return new KrbServicePermissionCollection(); } @@ -453,11 +467,12 @@ final class KrbServicePermissionCollection extends PermissionCollection implements java.io.Serializable { + // Key is the service principal, value is the ServicePermission. // Not serialized; see serialization section at end of class - private transient List perms; + private transient ConcurrentHashMap perms; public KrbServicePermissionCollection() { - perms = new ArrayList(); + perms = new ConcurrentHashMap<>(); } /** @@ -469,32 +484,28 @@ * @return true if "permission" is a proper subset of a permission in * the collection, false if not. */ + @Override public boolean implies(Permission permission) { if (! (permission instanceof ServicePermission)) - return false; + return false; ServicePermission np = (ServicePermission) permission; int desired = np.getMask(); - int effective = 0; - int needed = desired; - - synchronized (this) { - int len = perms.size(); - - // need to deal with the case where the needed permission has - // more than one action and the collection has individual permissions - // that sum up to the needed. - for (int i = 0; i < len; i++) { - ServicePermission x = (ServicePermission) perms.get(i); + // first, check for wildcard principal + ServicePermission x = (ServicePermission)perms.get("*"); + if (x != null) { + if ((x.getMask() & desired) == desired) { + return true; + } + } - //System.out.println(" trying "+x); - if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(np)) { - effective |= x.getMask(); - if ((effective & desired) == desired) - return true; - needed = (desired ^ effective); - } + // otherwise, check for match on principal + x = (ServicePermission)perms.get(np.getName()); + if (x != null) { + //System.out.println(" trying "+x); + if ((x.getMask() & desired) == desired) { + return true; } } return false; @@ -512,6 +523,7 @@ * @exception SecurityException - if this PermissionCollection object * has been marked readonly */ + @Override public void add(Permission permission) { if (! (permission instanceof ServicePermission)) throw new IllegalArgumentException("invalid permission: "+ @@ -519,9 +531,32 @@ if (isReadOnly()) throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection"); - synchronized (this) { - perms.add(0, permission); - } + ServicePermission sp = (ServicePermission)permission; + String princName = sp.getName(); + + // Add permission to map if it is absent, or replace with new + // permission if applicable. NOTE: cannot use lambda for + // remappingFunction parameter until JDK-8076596 is fixed. + perms.merge(princName, sp, + new java.util.function.BiFunction<>() { + @Override + public Permission apply(Permission existingVal, + Permission newVal) { + int oldMask = ((ServicePermission)existingVal).getMask(); + int newMask = ((ServicePermission)newVal).getMask(); + if (oldMask != newMask) { + int effective = oldMask | newMask; + if (effective == newMask) { + return newVal; + } + if (effective != oldMask) { + return new ServicePermission(princName, effective); + } + } + return existingVal; + } + } + ); } /** @@ -530,12 +565,9 @@ * * @return an enumeration of all the ServicePermission objects. */ - + @Override public Enumeration elements() { - // Convert Iterator into Enumeration - synchronized (this) { - return Collections.enumeration(perms); - } + return perms.elements(); } private static final long serialVersionUID = -4118834211490102011L; @@ -563,11 +595,7 @@ // Don't call out.defaultWriteObject() // Write out Vector - Vector permissions = new Vector<>(perms.size()); - - synchronized (this) { - permissions.addAll(perms); - } + Vector permissions = new Vector<>(perms.values()); ObjectOutputStream.PutField pfields = out.putFields(); pfields.put("permissions", permissions); @@ -589,7 +617,9 @@ // Get the one we want Vector permissions = (Vector)gfields.get("permissions", null); - perms = new ArrayList(permissions.size()); - perms.addAll(permissions); + perms = new ConcurrentHashMap<>(permissions.size()); + for (Permission perm : permissions) { + perms.put(perm.getName(), perm); + } } } diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/test/java/io/FilePermission/FilePermissionCollection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/io/FilePermission/FilePermissionCollection.java Tue Jun 09 09:18:07 2015 -0400 @@ -0,0 +1,171 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8056179 + * @summary Unit test for FilePermissionCollection subclass + */ + +import java.io.FilePermission; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.SecurityPermission; +import java.util.Enumeration; + +public class FilePermissionCollection { + + public static void main(String[] args) throws Exception { + + int testFail = 0; + + FilePermission perm = new FilePermission("/tmp/foo", "read"); + PermissionCollection perms = perm.newPermissionCollection(); + + // test 1 + System.out.println + ("test 1: add throws IllegalArgExc for wrong perm type"); + try { + perms.add(new SecurityPermission("createAccessControlContext")); + System.err.println("Expected IllegalArgumentException"); + testFail++; + } catch (IllegalArgumentException iae) {} + + // test 2 + System.out.println("test 2: implies returns false for wrong perm type"); + if (perms.implies(new SecurityPermission("getPolicy"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 3 + System.out.println("test 3: implies returns true for match on " + + "name and action"); + perms.add(new FilePermission("/tmp/foo", "read")); + if (!perms.implies(new FilePermission("/tmp/foo", "read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 4 + System.out.println("test 4: implies returns false for match on " + + "name but not action"); + if (perms.implies(new FilePermission("/tmp/foo", "write"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 5 + System.out.println("test 5: implies returns true for match on " + + "name and subset of actions"); + perms.add(new FilePermission("/tmp/bar", "read, write")); + if (!perms.implies(new FilePermission("/tmp/bar", "write"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 6 + System.out.println("test 6: implies returns true for aggregate " + + "match on name and action"); + perms.add(new FilePermission("/tmp/baz", "read")); + perms.add(new FilePermission("/tmp/baz", "write")); + if (!perms.implies(new FilePermission("/tmp/baz", "read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + if (!perms.implies(new FilePermission("/tmp/baz", "write,read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 7 + System.out.println("test 7: implies returns true for wildcard " + + "and match on action"); + perms.add(new FilePermission("/usr/tmp/*", "read")); + if (!perms.implies(new FilePermission("/usr/tmp/foo", "read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 8 + System.out.println + ("test 8: implies returns false for non-match on wildcard"); + if (perms.implies(new FilePermission("/usr/tmp/bar/foo", "read"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 9 + System.out.println + ("test 9: implies returns true for deep wildcard match"); + perms.add(new FilePermission("/usr/tmp/-", "read")); + if (!perms.implies(new FilePermission("/usr/tmp/bar/foo", "read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 10 + System.out.println("test 10: implies returns true for relative match"); + perms.add(new FilePermission(".", "read")); + if (!perms.implies(new FilePermission(System.getProperty("user.dir"), + "read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 11 + System.out.println("test 11: implies returns true for all " + + "wildcard and match on action"); + perms.add(new FilePermission("<>", "read")); + if (!perms.implies(new FilePermission("/tmp/foobar", "read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 12 + System.out.println("test 12: implies returns false for wildcard " + + "and non-match on action"); + if (perms.implies(new FilePermission("/tmp/foobar", "write"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 13 + System.out.println("test 13: elements returns correct number of perms"); + int numPerms = 0; + Enumeration e = perms.elements(); + while (e.hasMoreElements()) { + numPerms++; + System.out.println(e.nextElement()); + } + // the two "/tmp/baz" entries were combined into one + if (numPerms != 7) { + System.err.println("Expected 7, got " + numPerms); + testFail++; + } + + if (testFail > 0) { + throw new Exception(testFail + " test(s) failed"); + } + } +} diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/test/java/net/SocketPermission/SocketPermissionCollection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/net/SocketPermission/SocketPermissionCollection.java Tue Jun 09 09:18:07 2015 -0400 @@ -0,0 +1,147 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8056179 + * @summary Unit test for PermissionCollection subclasses + */ + +import java.net.SocketPermission; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.SecurityPermission; +import java.util.Enumeration; + +public class SocketPermissionCollection { + + public static void main(String[] args) throws Exception { + + int testFail = 0; + + SocketPermission perm = new SocketPermission("www.example.com", + "connect"); + PermissionCollection perms = perm.newPermissionCollection(); + + // test 1 + System.out.println + ("test 1: add throws IllegalArgExc for wrong perm type"); + try { + perms.add(new SecurityPermission("createAccessControlContext")); + System.err.println("Expected IllegalArgumentException"); + testFail++; + } catch (IllegalArgumentException iae) {} + + // test 2 + System.out.println("test 2: implies returns false for wrong perm type"); + if (perms.implies(new SecurityPermission("getPolicy"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 3 + System.out.println + ("test 3: implies returns true for match on name and action"); + perms.add(new SocketPermission("www.example.com", "connect")); + if (!perms.implies(new SocketPermission("www.example.com", "connect"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 4 + System.out.println + ("test 4: implies returns false for match on name but not action"); + if (perms.implies(new SocketPermission("www.example.com", "accept"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 5 + System.out.println("test 5: implies returns true for match on " + + "name and subset of actions"); + perms.add(new SocketPermission("www.example.org", "accept, connect")); + if (!perms.implies(new SocketPermission("www.example.org", "connect"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 6 + System.out.println("test 6: implies returns true for aggregate " + + "match on name and action"); + perms.add(new SocketPermission("www.example.us", "accept")); + perms.add(new SocketPermission("www.example.us", "connect")); + if (!perms.implies(new SocketPermission("www.example.us", "accept"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + if (!perms.implies(new SocketPermission("www.example.us", + "connect,accept"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 7 + System.out.println("test 7: implies returns true for wildcard " + + "and match on action"); + perms.add(new SocketPermission("*.example.edu", "resolve")); + if (!perms.implies(new SocketPermission("foo.example.edu", "resolve"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 8 + System.out.println("test 8: implies returns false for non-match " + + "on wildcard"); + if (perms.implies(new SocketPermission("foo.example.edu", "connect"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 9 + System.out.println("test 9: implies returns true for matching " + + "port range and action"); + perms.add(new SocketPermission("204.160.241.0:1024-65535", "connect")); + if (!perms.implies(new SocketPermission("204.160.241.0:1025", "connect"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 13 + System.out.println("test 13: elements returns correct number of perms"); + int numPerms = 0; + Enumeration e = perms.elements(); + while (e.hasMoreElements()) { + numPerms++; + System.out.println(e.nextElement()); + } + // the two "/tmp/baz" entries were combined into one + if (numPerms != 5) { + System.err.println("Expected 5, got " + numPerms); + testFail++; + } + + if (testFail > 0) { + throw new Exception(testFail + " test(s) failed"); + } + } +} diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/test/java/security/BasicPermission/BasicPermissionCollection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/security/BasicPermission/BasicPermissionCollection.java Tue Jun 09 09:18:07 2015 -0400 @@ -0,0 +1,125 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8056179 + * @summary Unit test for BasicPermissionCollection subclass + */ + +import java.security.BasicPermission; +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.SecurityPermission; +import java.util.Enumeration; + +public class BasicPermissionCollection { + + public static void main(String[] args) throws Exception { + + int testFail = 0; + + TestPermission perm = new TestPermission("foo"); + PermissionCollection perms = perm.newPermissionCollection(); + + // test 1 + System.out.println("test 1: add throws IllegalArgumentExc"); + try { + perms.add(new SecurityPermission("createAccessControlContext")); + System.err.println("Expected IllegalArgumentException"); + testFail++; + } catch (IllegalArgumentException iae) {} + + // test 2 + System.out.println("test 2: implies returns false for wrong class"); + if (perms.implies(new SecurityPermission("getPolicy"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 3 + System.out.println("test 3: implies returns true for match on name"); + perms.add(new TestPermission("foo")); + if (!perms.implies(new TestPermission("foo"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 4 + System.out.println("test 4: implies returns true for wildcard match"); + perms.add(new TestPermission("bar.*")); + if (!perms.implies(new TestPermission("bar.foo"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 5 + System.out.println + ("test 5: implies returns false for invalid wildcard"); + perms.add(new TestPermission("baz*")); + if (perms.implies(new TestPermission("baz.foo"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 6 + System.out.println + ("test 6: implies returns true for deep wildcard match"); + if (!perms.implies(new TestPermission("bar.foo.baz"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 7 + System.out.println + ("test 7: implies returns true for all wildcard match"); + perms.add(new TestPermission("*")); + if (!perms.implies(new TestPermission("yes"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 8 + System.out.println("test 8: elements returns correct number of perms"); + int numPerms = 0; + Enumeration e = perms.elements(); + while (e.hasMoreElements()) { + numPerms++; + System.out.println(e.nextElement()); + } + if (numPerms != 4) { + System.err.println("Expected 4, got " + numPerms); + testFail++; + } + + if (testFail > 0) { + throw new Exception(testFail + " test(s) failed"); + } + } + + private static class TestPermission extends BasicPermission { + TestPermission(String name) { + super(name); + } + } +} diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/test/java/security/PermissionCollection/Concurrent.java --- a/jdk/test/java/security/PermissionCollection/Concurrent.java Mon Jun 08 16:17:37 2015 +0300 +++ b/jdk/test/java/security/PermissionCollection/Concurrent.java Tue Jun 09 09:18:07 2015 -0400 @@ -1,5 +1,5 @@ /* - * Copyright (c) 2003, Oracle and/or its affiliates. All rights reserved. + * Copyright (c) 2003, 2015, Oracle and/or its affiliates. All rights reserved. * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. * * This code is free software; you can redistribute it and/or modify it @@ -104,13 +104,11 @@ System.out.println(perm[perm.length-1] + " implies " + result); } - synchronized (pc) { - Enumeration en = pc.elements(); - while (en.hasMoreElements()) { - Object obj = en.nextElement(); - if (debug) { - System.out.println(obj); - } + Enumeration en = pc.elements(); + while (en.hasMoreElements()) { + Object obj = en.nextElement(); + if (debug) { + System.out.println(obj); } } } @@ -151,13 +149,11 @@ } } - synchronized (pc) { - Enumeration en = pc.elements(); - while (en.hasMoreElements()) { - Object obj = en.nextElement(); - if (debug) { - System.out.println(obj); - } + Enumeration en = pc.elements(); + while (en.hasMoreElements()) { + Object obj = en.nextElement(); + if (debug) { + System.out.println(obj); } } } diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/test/java/util/PropertyPermission/PropertyPermissionCollection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/java/util/PropertyPermission/PropertyPermissionCollection.java Tue Jun 09 09:18:07 2015 -0400 @@ -0,0 +1,162 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8056179 + * @summary Unit test for PropertyPermissionCollection subclass + */ + +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.SecurityPermission; +import java.util.Enumeration; +import java.util.PropertyPermission; + +public class PropertyPermissionCollection { + + public static void main(String[] args) throws Exception { + + int testFail = 0; + + PropertyPermission perm = new PropertyPermission("user.home", "read"); + PermissionCollection perms = perm.newPermissionCollection(); + + // test 1 + System.out.println + ("test 1: add throws IllegalArgExc for wrong perm type"); + try { + perms.add(new SecurityPermission("createAccessControlContext")); + System.err.println("Expected IllegalArgumentException"); + testFail++; + } catch (IllegalArgumentException iae) {} + + // test 2 + System.out.println("test 2: implies returns false for wrong perm type"); + if (perms.implies(new SecurityPermission("getPolicy"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 3 + System.out.println + ("test 3: implies returns true for match on name and action"); + perms.add(new PropertyPermission("user.home", "read")); + if (!perms.implies(new PropertyPermission("user.home", "read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 4 + System.out.println + ("test 4: implies returns false for match on name but not action"); + if (perms.implies(new PropertyPermission("user.home", "write"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 5 + System.out.println("test 5: implies returns true for match " + + "on name and subset of actions"); + perms.add(new PropertyPermission("java.home", "read, write")); + if (!perms.implies(new PropertyPermission("java.home", "write"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 6 + System.out.println("test 6: implies returns true for aggregate " + + "match on name and action"); + perms.add(new PropertyPermission("user.name", "read")); + perms.add(new PropertyPermission("user.name", "write")); + if (!perms.implies(new PropertyPermission("user.name", "read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + if (!perms.implies(new PropertyPermission("user.name", "write,read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 7 + System.out.println("test 7: implies returns true for wildcard " + + "and match on action"); + perms.add(new PropertyPermission("foo.*", "read")); + if (!perms.implies(new PropertyPermission("foo.bar", "read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 8 + System.out.println("test 8: implies returns true for deep " + + "wildcard and match on action"); + if (!perms.implies(new PropertyPermission("foo.bar.baz", "read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 8 + System.out.println + ("test 8: implies returns false for invalid wildcard"); + perms.add(new PropertyPermission("baz*", "read")); + if (perms.implies(new PropertyPermission("baz.foo", "read"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 9 + System.out.println("test 9: implies returns true for all " + + "wildcard and match on action"); + perms.add(new PropertyPermission("*", "read")); + if (!perms.implies(new PropertyPermission("java.version", "read"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 10 + System.out.println("test 10: implies returns false for wildcard " + + "and non-match on action"); + if (perms.implies(new PropertyPermission("java.version", "write"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 11 + System.out.println("test 11: elements returns correct number of perms"); + int numPerms = 0; + Enumeration e = perms.elements(); + while (e.hasMoreElements()) { + numPerms++; + System.out.println(e.nextElement()); + } + // the 2 user.name permissions added were combined into one + if (numPerms != 6) { + System.err.println("Expected 6, got " + numPerms); + testFail++; + } + + if (testFail > 0) { + throw new Exception(testFail + " test(s) failed"); + } + } +} diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/test/javax/security/auth/kerberos/DelegationPermissionCollection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/security/auth/kerberos/DelegationPermissionCollection.java Tue Jun 09 09:18:07 2015 -0400 @@ -0,0 +1,98 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8056179 + * @summary Unit test for DelegationPermissionCollection subclass + */ + +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.SecurityPermission; +import java.util.Enumeration; +import javax.security.auth.kerberos.DelegationPermission; + +public class DelegationPermissionCollection { + + private static final String FOO = "\"host/foo.example.com@EXAMPLE.COM\""; + private static final String BAR = "\"host/bar.example.com@EXAMPLE.COM\""; + private static final String TGT = "\"krbtgt/EXAMPLE.COM@EXAMPLE.COM\""; + + public static void main(String[] args) throws Exception { + + int testFail = 0; + + DelegationPermission perm = new DelegationPermission(FOO + " " + TGT); + PermissionCollection perms = perm.newPermissionCollection(); + + // test 1 + System.out.println + ("test 1: add throws IllegalArgException for wrong perm type"); + try { + perms.add(new SecurityPermission("createAccessControlContext")); + System.err.println("Expected IllegalArgumentException"); + testFail++; + } catch (IllegalArgumentException iae) {} + + // test 2 + System.out.println("test 2: implies returns false for wrong perm type"); + if (perms.implies(new SecurityPermission("getPolicy"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 3 + System.out.println("test 3: implies returns true for match on name"); + perms.add(new DelegationPermission(FOO + " " + TGT)); + if (!perms.implies(new DelegationPermission(FOO + " " + TGT))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 4 + System.out.println + ("test 4: implies returns false for non-match on name"); + if (perms.implies(new DelegationPermission(BAR + " " + TGT))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 5 + System.out.println("test 5: elements returns correct number of perms"); + int numPerms = 0; + Enumeration e = perms.elements(); + while (e.hasMoreElements()) { + numPerms++; + System.out.println(e.nextElement()); + } + if (numPerms != 1) { + System.err.println("Expected 1, got " + numPerms); + testFail++; + } + + if (testFail > 0) { + throw new Exception(testFail + " test(s) failed"); + } + } +} diff -r a6b5f444cb68 -r 00a25f4c4d44 jdk/test/javax/security/auth/kerberos/ServicePermissionCollection.java --- /dev/null Thu Jan 01 00:00:00 1970 +0000 +++ b/jdk/test/javax/security/auth/kerberos/ServicePermissionCollection.java Tue Jun 09 09:18:07 2015 -0400 @@ -0,0 +1,133 @@ +/* + * Copyright (c) 2015, Oracle and/or its affiliates. All rights reserved. + * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. + * + * This code is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License version 2 only, as + * published by the Free Software Foundation. + * + * This code is distributed in the hope that it will be useful, but WITHOUT + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or + * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * version 2 for more details (a copy is included in the LICENSE file that + * accompanied this code). + * + * You should have received a copy of the GNU General Public License version + * 2 along with this work; if not, write to the Free Software Foundation, + * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. + * + * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA + * or visit www.oracle.com if you need additional information or have any + * questions. + */ + +/* + * @test + * @bug 8056179 + * @summary Unit test for ServicePermissionCollection subclass + */ + +import java.security.Permission; +import java.security.PermissionCollection; +import java.security.SecurityPermission; +import java.util.Enumeration; +import javax.security.auth.kerberos.ServicePermission; + +public class ServicePermissionCollection { + + private static final String FOO = "host/foo.example.com@EXAMPLE.COM"; + private static final String BAR = "host/bar.example.com@EXAMPLE.COM"; + private static final String BAZ = "host/baz.example.com@EXAMPLE.COM"; + + public static void main(String[] args) throws Exception { + + int testFail = 0; + + ServicePermission perm = new ServicePermission(FOO, "accept"); + PermissionCollection perms = perm.newPermissionCollection(); + + // test 1 + System.out.println + ("test 1: add throws IllegalArgExc for wrong permission type"); + try { + perms.add(new SecurityPermission("createAccessControlContext")); + System.err.println("Expected IllegalArgumentException"); + testFail++; + } catch (IllegalArgumentException iae) {} + + // test 2 + System.out.println("test 2: implies returns false for wrong perm type"); + if (perms.implies(new SecurityPermission("getPolicy"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 3 + System.out.println + ("test 3: implies returns true for match on name and action"); + perms.add(new ServicePermission(FOO, "accept")); + if (!perms.implies(new ServicePermission(FOO, "accept"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 4 + System.out.println + ("test 4: implies returns false for match on name but not action"); + if (perms.implies(new ServicePermission(FOO, "initiate"))) { + System.err.println("Expected false, returned true"); + testFail++; + } + + // test 5 + System.out.println("test 5: implies returns true for match on " + + "name and subset of actions"); + perms.add(new ServicePermission(BAR, "accept, initiate")); + if (!perms.implies(new ServicePermission(BAR, "accept"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 6 + System.out.println("test 6: implies returns false for aggregate " + + "match on name and action"); + perms.add(new ServicePermission(BAZ, "accept")); + perms.add(new ServicePermission(BAZ, "initiate")); + if (!perms.implies(new ServicePermission(BAZ, "initiate"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + if (!perms.implies(new ServicePermission(BAZ, "initiate, accept"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 7 + System.out.println("test 7: implies returns true for wildcard " + + "match on name and action"); + perms.add(new ServicePermission("*", "initiate")); + if (!perms.implies(new ServicePermission("Duke", "initiate"))) { + System.err.println("Expected true, returned false"); + testFail++; + } + + // test 8 + System.out.println("test 8: elements returns correct number of perms"); + int numPerms = 0; + Enumeration e = perms.elements(); + while (e.hasMoreElements()) { + numPerms++; + System.out.println(e.nextElement()); + } + // the 2 FOO permissions and the 2 BAZ permisssions + // are combined into one + if (numPerms != 4) { + System.err.println("Expected 4, got " + numPerms); + testFail++; + } + + if (testFail > 0) { + throw new Exception(testFail + " test(s) failed"); + } + } +}