8056179: Store permissions in concurrent collections in PermissionCollection subclasses
authormullan
Tue, 09 Jun 2015 09:18:07 -0400
changeset 31080 00a25f4c4d44
parent 31062 a6b5f444cb68
child 31081 1a9f254fb4b0
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
jdk/src/java.base/share/classes/java/io/FilePermission.java
jdk/src/java.base/share/classes/java/net/SocketPermission.java
jdk/src/java.base/share/classes/java/security/BasicPermission.java
jdk/src/java.base/share/classes/java/security/Permissions.java
jdk/src/java.base/share/classes/java/security/UnresolvedPermissionCollection.java
jdk/src/java.base/share/classes/java/util/PropertyPermission.java
jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/DelegationPermission.java
jdk/src/java.security.jgss/share/classes/javax/security/auth/kerberos/ServicePermission.java
jdk/test/java/io/FilePermission/FilePermissionCollection.java
jdk/test/java/net/SocketPermission/SocketPermissionCollection.java
jdk/test/java/security/BasicPermission/BasicPermissionCollection.java
jdk/test/java/security/PermissionCollection/Concurrent.java
jdk/test/java/util/PropertyPermission/PropertyPermissionCollection.java
jdk/test/javax/security/auth/kerberos/DelegationPermissionCollection.java
jdk/test/javax/security/auth/kerberos/ServicePermissionCollection.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 @@
      *                  <code>null</code> and is implied by this object,
      *                  <code>false</code> otherwise.
      */
+    @Override
     public boolean implies(Permission p) {
         if (!(p instanceof FilePermission))
             return false;
@@ -387,6 +385,7 @@
      *          pathname and actions as this FilePermission object,
      *          <code>false</code> 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<Permission> perms;
+    private transient ConcurrentHashMap<String, Permission> 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<Permission> 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<Permission> permissions = new Vector<>(perms.size());
-        synchronized (this) {
-            permissions.addAll(perms);
-        }
+        Vector<Permission> 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<Permission> permissions = (Vector<Permission>)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);
+        }
     }
 }
--- 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 <i>obj</i> 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<SocketPermission> perms;
+    // A ConcurrentSkipListMap is used to preserve order, so that most
+    // recently added permissions are checked first (see JDK-4301064).
+    private transient ConcurrentSkipListMap<String, SocketPermission> 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<Permission> elements() {
-        // Convert Iterator into Enumeration
-        synchronized (this) {
-            return Collections.enumeration((List<Permission>)(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<SocketPermission> permissions = new Vector<>(perms.size());
-
-        synchronized (this) {
-            permissions.addAll(perms);
-        }
+        Vector<SocketPermission> 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<SocketPermission> permissions = (Vector<SocketPermission>)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<String> {
+        @Override
+        public int compare(String s1, String s2) {
+            if (s1.equals(s2)) {
+                return 0;
+            }
+            return -1;
+        }
     }
 }
--- 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<String, Permission> perms;
+    private transient ConcurrentHashMap<String, Permission> 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<Permission> 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<String, Permission> 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<String, Permission> permissions =
                 (Hashtable<String, Permission>)gfields.get("permissions", null);
-        perms = new HashMap<>(permissions.size()*2);
+        perms = new ConcurrentHashMap<>(permissions.size()*2);
         perms.putAll(permissions);
 
         // Get all_allowed
--- 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<Class<?>, PermissionCollection> permsMap;
+    private transient ConcurrentHashMap<Class<?>, 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<Permission> 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<Class<?>, 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<Class<?>, PermissionCollection> perms =
             (Hashtable<Class<?>, 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<Permission, Permission> permsMap;
+    private transient ConcurrentHashMap<Permission, Permission> 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<Permission> 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<Permission, Permission> 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<Permission, Permission> perms =
                 (Hashtable<Permission, Permission>)gfields.get("perms", null);
-        permsMap = new HashMap<>(perms.size()*2);
+        permsMap = new ConcurrentHashMap<>(perms.size()*2);
         permsMap.putAll(perms);
     }
 }
--- 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<String, List<UnresolvedPermission>> perms;
+    private transient ConcurrentHashMap<String, List<UnresolvedPermission>> 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<UnresolvedPermission> 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<UnresolvedPermission> apply(String key,
+                                        List<UnresolvedPermission> oldValue) {
+                    if (oldValue == null) {
+                        List<UnresolvedPermission> 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<UnresolvedPermission> 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<Permission> elements() {
         List<Permission> results =
             new ArrayList<>(); // where results are stored
 
         // Get iterator of Map values (which are lists of permissions)
-        synchronized (this) {
-            for (List<UnresolvedPermission> l : perms.values()) {
-                synchronized (l) {
-                    results.addAll(l);
-                }
-            }
+        for (List<UnresolvedPermission> 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<Map.Entry<String, List<UnresolvedPermission>>> set = perms.entrySet();
-            for (Map.Entry<String, List<UnresolvedPermission>> e : set) {
-                // Convert list into Vector
-                List<UnresolvedPermission> list = e.getValue();
-                Vector<UnresolvedPermission> vec = new Vector<>(list.size());
-                synchronized (list) {
-                    vec.addAll(list);
-                }
+        Set<Map.Entry<String, List<UnresolvedPermission>>> set = perms.entrySet();
+        for (Map.Entry<String, List<UnresolvedPermission>> e : set) {
+            // Convert list into Vector
+            List<UnresolvedPermission> list = e.getValue();
+            Vector<UnresolvedPermission> 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<String, Vector<UnresolvedPermission>> permissions =
                 (Hashtable<String, Vector<UnresolvedPermission>>)
                 gfields.get("permissions", null);
-        perms = new HashMap<>(permissions.size()*2);
+        perms = new ConcurrentHashMap<>(permissions.size()*2);
 
         // Convert each entry (Vector) into a List
         Set<Map.Entry<String, Vector<UnresolvedPermission>>> set = permissions.entrySet();
         for (Map.Entry<String, Vector<UnresolvedPermission>> e : set) {
             // Convert Vector into ArrayList
             Vector<UnresolvedPermission> vec = e.getValue();
-            List<UnresolvedPermission> list = new ArrayList<>(vec.size());
-            list.addAll(vec);
+            List<UnresolvedPermission> list = new CopyOnWriteArrayList<>(vec);
 
             // Add to Hashtable being serialized
             perms.put(e.getKey(), list);
--- 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.
      * <P>
@@ -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<String, PropertyPermission> perms;
+    private transient ConcurrentHashMap<String, PropertyPermission> 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<Permission> elements() {
-        // Convert Iterator of Map values into an Enumeration
-        synchronized (this) {
-            /**
-             * Casting to rawtype since Enumeration<PropertyPermission>
-             * cannot be directly cast to Enumeration<Permission>
-             */
-            return (Enumeration)Collections.enumeration(perms.values());
-        }
+        /**
+         * Casting to rawtype since Enumeration<PropertyPermission>
+         * cannot be directly cast to Enumeration<Permission>
+         */
+        return (Enumeration)perms.elements();
     }
 
     private static final long serialVersionUID = 7015263904581634791L;
@@ -616,9 +631,7 @@
         // Copy perms into a Hashtable
         Hashtable<String, Permission> 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<String, PropertyPermission> permissions =
             (Hashtable<String, PropertyPermission>)gfields.get("permissions", null);
-        perms = new HashMap<>(permissions.size()*2);
+        perms = new ConcurrentHashMap<>(permissions.size()*2);
         perms.putAll(permissions);
     }
 }
--- 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<Permission> perms;
+    private transient ConcurrentHashMap<Permission, Boolean> perms;
 
     public KrbDelegationPermissionCollection() {
-        perms = new ArrayList<Permission>();
+        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<Permission> 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<Permission> permissions = new Vector<>(perms.size());
-
-        synchronized (this) {
-            permissions.addAll(perms);
-        }
+        Vector<Permission> permissions = new Vector<>(perms.keySet());
 
         ObjectOutputStream.PutField pfields = out.putFields();
         pfields.put("permissions", permissions);
@@ -379,8 +369,10 @@
 
         // Get the one we want
         Vector<Permission> permissions =
-                (Vector<Permission>)gfields.get("permissions", null);
-        perms = new ArrayList<Permission>(permissions.size());
-        perms.addAll(permissions);
+            (Vector<Permission>)gfields.get("permissions", null);
+        perms = new ConcurrentHashMap<>(permissions.size());
+        for (Permission perm : permissions) {
+            perms.put(perm, Boolean.TRUE);
+        }
     }
 }
--- 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<Permission> perms;
+    private transient ConcurrentHashMap<String, Permission> perms;
 
     public KrbServicePermissionCollection() {
-        perms = new ArrayList<Permission>();
+        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<Permission> 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<Permission> permissions = new Vector<>(perms.size());
-
-        synchronized (this) {
-            permissions.addAll(perms);
-        }
+        Vector<Permission> permissions = new Vector<>(perms.values());
 
         ObjectOutputStream.PutField pfields = out.putFields();
         pfields.put("permissions", permissions);
@@ -589,7 +617,9 @@
         // Get the one we want
         Vector<Permission> permissions =
                 (Vector<Permission>)gfields.get("permissions", null);
-        perms = new ArrayList<Permission>(permissions.size());
-        perms.addAll(permissions);
+        perms = new ConcurrentHashMap<>(permissions.size());
+        for (Permission perm : permissions) {
+            perms.put(perm.getName(), perm);
+        }
     }
 }
--- /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("<<ALL FILES>>", "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<Permission> 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");
+        }
+    }
+}
--- /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<Permission> 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");
+        }
+    }
+}
--- /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<Permission> 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);
+        }
+    }
+}
--- 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);
                     }
                 }
             }
--- /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<Permission> 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");
+        }
+    }
+}
--- /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<Permission> 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");
+        }
+    }
+}
--- /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<Permission> 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");
+        }
+    }
+}