changeset 6344:86828e84654f

7019834: Eliminate dependency from PolicyFile to com.sun.security.auth.PrincipalComparator Summary: Add new java.security.Principal.implies method Reviewed-by: alanb
author mullan
date Tue, 08 Jan 2013 19:00:12 -0500
parents d91e6cb1da41
children bf6d0bca5ea7
files src/share/classes/java/security/Principal.java src/share/classes/sun/security/provider/PolicyFile.java src/share/classes/sun/security/provider/PolicyParser.java src/share/classes/sun/security/tools/policytool/PolicyTool.java test/java/security/Principal/Implies.java test/sun/security/provider/PolicyFile/Comparator.java
diffstat 6 files changed, 255 insertions(+), 239 deletions(-) [+]
line wrap: on
line diff
--- a/src/share/classes/java/security/Principal.java	Thu Nov 29 17:03:52 2012 +0000
+++ b/src/share/classes/java/security/Principal.java	Tue Jan 08 19:00:12 2013 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1996, 1998, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1996, 2012, 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,6 +25,8 @@
 
 package java.security;
 
+import javax.security.auth.Subject;
+
 /**
  * This interface represents the abstract notion of a principal, which
  * can be used to represent any entity, such as an individual, a
@@ -45,7 +47,6 @@
      *
      * @return true if the principal passed in is the same as that
      * encapsulated by this principal, and false otherwise.
-
      */
     public boolean equals(Object another);
 
@@ -69,4 +70,24 @@
      * @return the name of this principal.
      */
     public String getName();
+
+    /**
+     * Returns true if the specified subject is implied by this principal.
+     *
+     * <p>The default implementation of this method returns true if
+     * {@code subject} is non-null and contains at least one principal that
+     * is equal to this principal.
+     *
+     * <p>Subclasses may override this with a different implementation, if
+     * necessary.
+     *
+     * @return true if {@code subject} is non-null and is
+     *              implied by this principal, or false otherwise.
+     * @since 1.8
+     */
+    public default boolean implies(Subject subject) {
+        if (subject == null)
+            return false;
+        return subject.getPrincipals().contains(this);
+    }
 }
--- a/src/share/classes/sun/security/provider/PolicyFile.java	Thu Nov 29 17:03:52 2012 +0000
+++ b/src/share/classes/sun/security/provider/PolicyFile.java	Tue Jan 08 19:00:12 2013 -0500
@@ -31,13 +31,7 @@
 import java.net.URL;
 import java.net.URI;
 import java.util.*;
-import java.util.Enumeration;
-import java.util.List;
-import java.util.StringTokenizer;
-import java.util.ArrayList;
-import java.util.ListIterator;
 import java.text.MessageFormat;
-import com.sun.security.auth.PrincipalComparator;
 import java.security.*;
 import java.security.cert.Certificate;
 import java.security.cert.X509Certificate;
@@ -46,19 +40,7 @@
 import java.io.FilePermission;
 import java.net.SocketPermission;
 import java.net.NetPermission;
-import java.util.PropertyPermission;
 import java.util.concurrent.atomic.AtomicReference;
-/*
-import javax.security.auth.AuthPermission;
-import javax.security.auth.kerberos.ServicePermission;
-import javax.security.auth.kerberos.DelegationPermission;
-import java.io.SerializablePermission;
-import java.util.logging.LoggingPermission;
-import java.sql.SQLPermission;
-import java.lang.reflect.ReflectPermission;
-import javax.sound.sampled.AudioPermission;
-import javax.net.ssl.SSLPermission;
-*/
 import sun.misc.JavaSecurityProtectionDomainAccess;
 import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache;
 import sun.misc.SharedSecrets;
@@ -794,12 +776,9 @@
             debug.println("Adding policy entry: ");
             debug.println("  signedBy " + ge.signedBy);
             debug.println("  codeBase " + ge.codeBase);
-            if (ge.principals != null && ge.principals.size() > 0) {
-                ListIterator<PolicyParser.PrincipalEntry> li =
-                                                ge.principals.listIterator();
-                while (li.hasNext()) {
-                    PolicyParser.PrincipalEntry pppe = li.next();
-                debug.println("  " + pppe.toString());
+            if (ge.principals != null) {
+                for (PolicyParser.PrincipalEntry pppe : ge.principals) {
+                    debug.println("  " + pppe.toString());
                 }
             }
         }
@@ -955,11 +934,15 @@
                InvocationTargetException
     {
         //XXX we might want to keep a hash of created factories...
-        Class<?> pc = Class.forName(type);
+        Class<?> pc = Class.forName(type, false, null);
         Permission answer = getKnownInstance(pc, name, actions);
         if (answer != null) {
             return answer;
         }
+        if (!Permission.class.isAssignableFrom(pc)) {
+            // not the right subtype
+            throw new ClassCastException(type + " is not a Permission");
+        }
 
         if (name == null && actions == null) {
             try {
@@ -1001,7 +984,6 @@
      */
     private static final Permission getKnownInstance(Class<?> claz,
         String name, String actions) {
-        // XXX shorten list to most popular ones?
         if (claz.equals(FilePermission.class)) {
             return new FilePermission(name, actions);
         } else if (claz.equals(SocketPermission.class)) {
@@ -1014,30 +996,6 @@
             return new NetPermission(name, actions);
         } else if (claz.equals(AllPermission.class)) {
             return SecurityConstants.ALL_PERMISSION;
-/*
-        } else if (claz.equals(ReflectPermission.class)) {
-            return new ReflectPermission(name, actions);
-        } else if (claz.equals(SecurityPermission.class)) {
-            return new SecurityPermission(name, actions);
-        } else if (claz.equals(PrivateCredentialPermission.class)) {
-            return new PrivateCredentialPermission(name, actions);
-        } else if (claz.equals(AuthPermission.class)) {
-            return new AuthPermission(name, actions);
-        } else if (claz.equals(ServicePermission.class)) {
-            return new ServicePermission(name, actions);
-        } else if (claz.equals(DelegationPermission.class)) {
-            return new DelegationPermission(name, actions);
-        } else if (claz.equals(SerializablePermission.class)) {
-            return new SerializablePermission(name, actions);
-        } else if (claz.equals(AudioPermission.class)) {
-            return new AudioPermission(name, actions);
-        } else if (claz.equals(SSLPermission.class)) {
-            return new SSLPermission(name, actions);
-        } else if (claz.equals(LoggingPermission.class)) {
-            return new LoggingPermission(name, actions);
-        } else if (claz.equals(SQLPermission.class)) {
-            return new SQLPermission(name, actions);
-*/
         } else {
             return null;
         }
@@ -1079,7 +1037,7 @@
 
             if (cert != null) {
                 if (vcerts == null)
-                    vcerts = new ArrayList<Certificate>();
+                    vcerts = new ArrayList<>();
                 vcerts.add(cert);
             }
         }
@@ -1329,7 +1287,7 @@
 
         List<PolicyParser.PrincipalEntry> entryPs = entry.getPrincipals();
         if (debug != null) {
-            ArrayList<PolicyParser.PrincipalEntry> accPs = new ArrayList<>();
+            List<PolicyParser.PrincipalEntry> accPs = new ArrayList<>();
             if (principals != null) {
                 for (int i = 0; i < principals.length; i++) {
                     accPs.add(new PolicyParser.PrincipalEntry
@@ -1368,79 +1326,72 @@
         // has principals.  see if policy entry principals match
         // principals in current ACC
 
-        for (int i = 0; i < entryPs.size(); i++) {
-            PolicyParser.PrincipalEntry pppe = entryPs.get(i);
+        for (PolicyParser.PrincipalEntry pppe : entryPs) {
 
-            // see if principal entry is a PrincipalComparator
+            // Check for wildcards
+            if (pppe.isWildcardClass()) {
+                // a wildcard class matches all principals in current ACC
+                continue;
+            }
 
+            if (pppe.isWildcardName()) {
+                // a wildcard name matches any principal with the same class
+                for (Principal p : principals) {
+                    if (pppe.principalClass.equals(p.getClass().getName())) {
+                        continue;
+                    }
+                }
+                if (debug != null) {
+                    debug.println("evaluation (principal name wildcard) failed");
+                }
+                // policy entry principal not in current ACC -
+                // immediately return and go to next policy entry
+                return;
+            }
+
+            Set<Principal> pSet = new HashSet<>(Arrays.asList(principals));
+            Subject subject = new Subject(true, pSet,
+                                          Collections.EMPTY_SET,
+                                          Collections.EMPTY_SET);
             try {
-                Class<?> pClass = Class.forName
-                                (pppe.principalClass,
-                                true,
-                                Thread.currentThread().getContextClassLoader());
+                ClassLoader cl = Thread.currentThread().getContextClassLoader();
+                Class<?> pClass = Class.forName(pppe.principalClass, false, cl);
+                if (!Principal.class.isAssignableFrom(pClass)) {
+                    // not the right subtype
+                    throw new ClassCastException(pppe.principalClass +
+                                                 " is not a Principal");
+                }
 
-                if (!PrincipalComparator.class.isAssignableFrom(pClass)) {
+                Constructor<?> c = pClass.getConstructor(PARAMS1);
+                Principal p = (Principal)c.newInstance(new Object[] {
+                                                       pppe.principalName });
 
-                    // common case - dealing with regular Principal class.
-                    // see if policy entry principal is in current ACC
+                if (debug != null) {
+                    debug.println("found Principal " + p.getClass().getName());
+                }
 
-                    if (!checkEntryPs(principals, pppe)) {
-                        if (debug != null) {
-                            debug.println("evaluation (principals) failed");
-                        }
-
-                        // policy entry principal not in current ACC -
-                        // immediately return and go to next policy entry
-                        return;
+                // check if the Principal implies the current
+                // thread's principals
+                if (!p.implies(subject)) {
+                    if (debug != null) {
+                        debug.println("evaluation (principal implies) failed");
                     }
 
-                } else {
-
-                    // dealing with a PrincipalComparator
-
-                    Constructor<?> c = pClass.getConstructor(PARAMS1);
-                    PrincipalComparator pc = (PrincipalComparator)c.newInstance
-                                        (new Object[] { pppe.principalName });
-
-                    if (debug != null) {
-                        debug.println("found PrincipalComparator " +
-                                        pc.getClass().getName());
-                    }
-
-                    // check if the PrincipalComparator
-                    // implies the current thread's principals
-
-                    Set<Principal> pSet = new HashSet<>(principals.length);
-                    for (int j = 0; j < principals.length; j++) {
-                        pSet.add(principals[j]);
-                    }
-                    Subject subject = new Subject(true,
-                                                pSet,
-                                                Collections.EMPTY_SET,
-                                                Collections.EMPTY_SET);
-
-                    if (!pc.implies(subject)) {
-                        if (debug != null) {
-                            debug.println
-                                ("evaluation (principal comparator) failed");
-                        }
-
-                        // policy principal does not imply the current Subject -
-                        // immediately return and go to next policy entry
-                        return;
-                    }
+                    // policy principal does not imply the current Subject -
+                    // immediately return and go to next policy entry
+                    return;
                 }
             } catch (Exception e) {
-                // fall back to regular principal comparison.
+                // fall back to default principal comparison.
                 // see if policy entry principal is in current ACC
 
                 if (debug != null) {
                     e.printStackTrace();
                 }
 
-                if (!checkEntryPs(principals, pppe)) {
+                if (!pppe.implies(subject)) {
                     if (debug != null) {
-                        debug.println("evaluation (principals) failed");
+                        debug.println("evaluation (default principal implies) failed");
                     }
 
                     // policy entry principal not in current ACC -
@@ -1450,7 +1401,7 @@
             }
 
             // either the principal information matched,
-            // or the PrincipalComparator.implies succeeded.
+            // or the Principal.implies succeeded.
             // continue loop and test the next policy principal
         }
 
@@ -1485,47 +1436,6 @@
     }
 
     /**
-     * This method returns, true, if the principal in the policy entry,
-     * pppe, is part of the current thread's principal array, pList.
-     * This method also returns, true, if the policy entry's principal
-     * is appropriately wildcarded.
-     *
-     * Note that the provided <i>pppe</i> argument may have
-     * wildcards (*) for both the <code>Principal</code> class and name.
-     *
-     * @param pList an array of principals from the current thread's
-     *          AccessControlContext.
-     *
-     * @param pppe a Principal specified in a policy grant entry.
-     *
-     * @return true if the current thread's pList "contains" the
-     *          principal in the policy entry, pppe.  This method
-     *          also returns true if the policy entry's principal
-     *          appropriately wildcarded.
-     */
-    private boolean checkEntryPs(Principal[] pList,
-                                PolicyParser.PrincipalEntry pppe) {
-
-        for (int i = 0; i < pList.length; i++) {
-
-            if (pppe.principalClass.equals
-                        (PolicyParser.PrincipalEntry.WILDCARD_CLASS) ||
-                pppe.principalClass.equals
-                        (pList[i].getClass().getName())) {
-
-                if (pppe.principalName.equals
-                        (PolicyParser.PrincipalEntry.WILDCARD_NAME) ||
-                    pppe.principalName.equals
-                        (pList[i].getName())) {
-
-                    return true;
-                }
-            }
-        }
-        return false;
-    }
-
-    /**
      * <p>
      *
      * @param sp the SelfPermission that needs to be expanded <p>
@@ -1568,8 +1478,7 @@
             sb.append(sp.getSelfName().substring(startIndex, v));
 
             // expand SELF
-            ListIterator<PolicyParser.PrincipalEntry> pli =
-                                                entryPs.listIterator();
+            Iterator<PolicyParser.PrincipalEntry> pli = entryPs.iterator();
             while (pli.hasNext()) {
                 PolicyParser.PrincipalEntry pppe = pli.next();
                 String[][] principalInfo = getPrincipalInfo(pppe,pdp);
@@ -1596,8 +1505,8 @@
         try {
             // first try to instantiate the permission
             perms.add(getInstance(sp.getSelfType(),
-                                sb.toString(),
-                                sp.getSelfActions()));
+                                  sb.toString(),
+                                  sp.getSelfActions()));
         } catch (ClassNotFoundException cnfe) {
             // ok, the permission is not in the bootclasspath.
             // before we add an UnresolvedPermission, check to see
@@ -1673,10 +1582,7 @@
         // 2) the entry's Principal name is wildcarded only
         // 3) the entry's Principal class and name are wildcarded
 
-        if (!pe.principalClass.equals
-            (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
-            !pe.principalName.equals
-            (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
+        if (!pe.isWildcardClass() && !pe.isWildcardName()) {
 
             // build an info array for the principal
             // from the Policy entry
@@ -1685,24 +1591,19 @@
             info[0][1] = pe.principalName;
             return info;
 
-        } else if (!pe.principalClass.equals
-                   (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
-                   pe.principalName.equals
-                   (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {
+        } else if (!pe.isWildcardClass() && pe.isWildcardName()) {
 
             // build an info array for every principal
             // in the current domain which has a principal class
             // that is equal to policy entry principal class name
             List<Principal> plist = new ArrayList<>();
             for (int i = 0; i < pdp.length; i++) {
-                if(pe.principalClass.equals(pdp[i].getClass().getName()))
+                if (pe.principalClass.equals(pdp[i].getClass().getName()))
                     plist.add(pdp[i]);
             }
             String[][] info = new String[plist.size()][2];
             int i = 0;
-            java.util.Iterator<Principal> pIterator = plist.iterator();
-            while (pIterator.hasNext()) {
-                Principal p = pIterator.next();
+            for (Principal p : plist) {
                 info[i][0] = p.getClass().getName();
                 info[i][1] = p.getName();
                 i++;
@@ -1763,7 +1664,7 @@
             // Done
             return certs;
 
-        ArrayList<Certificate> userCertList = new ArrayList<>();
+        List<Certificate> userCertList = new ArrayList<>();
         i = 0;
         while (i < certs.length) {
             userCertList.add(certs[i]);
@@ -1889,10 +1790,8 @@
         if (principals == null || principals.isEmpty() || keystore == null)
             return true;
 
-        ListIterator<PolicyParser.PrincipalEntry> i = principals.listIterator();
-        while (i.hasNext()) {
-            PolicyParser.PrincipalEntry pppe = i.next();
-            if (pppe.principalClass.equals(PolicyParser.REPLACE_NAME)) {
+        for (PolicyParser.PrincipalEntry pppe : principals) {
+            if (pppe.isReplaceName()) {
 
                 // perform replacement
                 // (only X509 replacement is possible now)
@@ -2241,8 +2140,7 @@
 
                     if (this.certs == null) {
                         // extract the signer certs
-                        ArrayList<Certificate> signerCerts =
-                            new ArrayList<>();
+                        List<Certificate> signerCerts = new ArrayList<>();
                         i = 0;
                         while (i < certs.length) {
                             signerCerts.add(certs[i]);
@@ -2406,11 +2304,10 @@
         private java.util.Random random;
 
         PolicyInfo(int numCaches) {
-            policyEntries = new ArrayList<PolicyEntry>();
+            policyEntries = new ArrayList<>();
             identityPolicyEntries =
                 Collections.synchronizedList(new ArrayList<PolicyEntry>(2));
-            aliasMapping = Collections.synchronizedMap(
-                    new HashMap<Object, Object>(11));
+            aliasMapping = Collections.synchronizedMap(new HashMap<>(11));
 
             pdMapping = new ProtectionDomainCache[numCaches];
             JavaSecurityProtectionDomainAccess jspda
--- a/src/share/classes/sun/security/provider/PolicyParser.java	Thu Nov 29 17:03:52 2012 +0000
+++ b/src/share/classes/sun/security/provider/PolicyParser.java	Tue Jan 08 19:00:12 2013 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 1997, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1997, 2012, 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
@@ -29,16 +29,17 @@
 import java.lang.RuntimePermission;
 import java.net.SocketPermission;
 import java.net.URL;
+import java.security.GeneralSecurityException;
+import java.security.Principal;
+import java.text.MessageFormat;
 import java.util.Enumeration;
 import java.util.Hashtable;
+import java.util.Iterator;
 import java.util.LinkedList;
-import java.util.ListIterator;
 import java.util.Vector;
 import java.util.StringTokenizer;
-import java.text.MessageFormat;
 import javax.security.auth.x500.X500Principal;
 
-import java.security.GeneralSecurityException;
 import sun.security.util.Debug;
 import sun.security.util.PropertyExpander;
 import sun.security.util.ResourcesMgr;
@@ -72,7 +73,7 @@
  *  Permissions perms = policy.getPermissions(protectiondomain)
  * </pre>
  *
- * <p>The protection domain contains CodeSource
+ * <p>The protection domain contains a CodeSource
  * object, which encapsulates its codebase (URL) and public key attributes.
  * It also contains the principals associated with the domain.
  * The Policy object evaluates the global policy in light of who the
@@ -87,9 +88,6 @@
 
 public class PolicyParser {
 
-    // needs to be public for PolicyTool
-    public static final String REPLACE_NAME = "PolicyParser.REPLACE_NAME";
-
     private static final String EXTDIRS_PROPERTY = "java.ext.dirs";
     private static final String OLD_EXTDIRS_EXPANSION =
         "${" + EXTDIRS_PROPERTY + "}";
@@ -452,7 +450,7 @@
                 peekAndMatch(",");
             } else if (peekAndMatch("Principal")) {
                 if (principals == null) {
-                    principals = new LinkedList<PrincipalEntry>();
+                    principals = new LinkedList<>();
                 }
 
                 String principalClass;
@@ -461,7 +459,7 @@
                 if (peek("\"")) {
                     // both the principalClass and principalName
                     // will be replaced later
-                    principalClass = REPLACE_NAME;
+                    principalClass = PrincipalEntry.REPLACE_NAME;
                     principalName = match("principal type");
                 } else {
                     // check for principalClass wildcard
@@ -916,7 +914,7 @@
                     out.print(",\n");
             }
             if (principals != null && principals.size() > 0) {
-                ListIterator<PrincipalEntry> pli = principals.listIterator();
+                Iterator<PrincipalEntry> pli = principals.iterator();
                 while (pli.hasNext()) {
                     out.print("      ");
                     PrincipalEntry pe = pli.next();
@@ -949,23 +947,22 @@
     /**
      * Principal info (class and name) in a grant entry
      */
-    public static class PrincipalEntry {
+    public static class PrincipalEntry implements Principal {
 
         public static final String WILDCARD_CLASS = "WILDCARD_PRINCIPAL_CLASS";
         public static final String WILDCARD_NAME = "WILDCARD_PRINCIPAL_NAME";
+        public static final String REPLACE_NAME = "PolicyParser.REPLACE_NAME";
 
         String principalClass;
         String principalName;
 
         /**
-         * A PrincipalEntry consists of the <code>Principal</code>
-         * class and <code>Principal</code> name.
+         * A PrincipalEntry consists of the Principal class and Principal name.
          *
-         * <p>
-         *
-         * @param principalClass the <code>Principal</code> class. <p>
-         *
-         * @param principalName the <code>Principal</code> name. <p>
+         * @param principalClass the Principal class
+         * @param principalName the Principal name
+         * @throws NullPointerException if principalClass or principalName
+         *                              are null
          */
         public PrincipalEntry(String principalClass, String principalName) {
             if (principalClass == null || principalName == null)
@@ -975,6 +972,18 @@
             this.principalName = principalName;
         }
 
+        boolean isWildcardName() {
+            return principalName.equals(WILDCARD_NAME);
+        }
+
+        boolean isWildcardClass() {
+            return principalClass.equals(WILDCARD_CLASS);
+        }
+
+        boolean isReplaceName() {
+            return principalClass.equals(REPLACE_NAME);
+        }
+
         public String getPrincipalClass() {
             return principalClass;
         }
@@ -984,9 +993,9 @@
         }
 
         public String getDisplayClass() {
-            if (principalClass.equals(WILDCARD_CLASS)) {
+            if (isWildcardClass()) {
                 return "*";
-            } else if (principalClass.equals(REPLACE_NAME)) {
+            } else if (isReplaceName()) {
                 return "";
             }
             else return principalClass;
@@ -997,7 +1006,7 @@
         }
 
         public String getDisplayName(boolean addQuote) {
-            if (principalName.equals(WILDCARD_NAME)) {
+            if (isWildcardName()) {
                 return "*";
             }
             else {
@@ -1006,8 +1015,14 @@
             }
         }
 
+        @Override
+        public String getName() {
+            return principalName;
+        }
+
+        @Override
         public String toString() {
-            if (!principalClass.equals(REPLACE_NAME)) {
+            if (!isReplaceName()) {
                 return getDisplayClass() + "/" + getDisplayName();
             } else {
                 return getDisplayName();
@@ -1016,15 +1031,13 @@
 
         /**
          * Test for equality between the specified object and this object.
-         * Two PrincipalEntries are equal if their PrincipalClass and
-         * PrincipalName values are equal.
+         * Two PrincipalEntries are equal if their class and name values
+         * are equal.
          *
-         * <p>
-         *
-         * @param obj the object to test for equality with this object.
-         *
-         * @return true if the objects are equal, false otherwise.
+         * @param obj the object to test for equality with this object
+         * @return true if the objects are equal, false otherwise
          */
+        @Override
         public boolean equals(Object obj) {
             if (this == obj)
                 return true;
@@ -1033,27 +1046,23 @@
                 return false;
 
             PrincipalEntry that = (PrincipalEntry)obj;
-            if (this.principalClass.equals(that.principalClass) &&
-                this.principalName.equals(that.principalName)) {
-                return true;
-            }
-
-            return false;
+            return (principalClass.equals(that.principalClass) &&
+                    principalName.equals(that.principalName));
         }
 
         /**
-         * Return a hashcode for this <code>PrincipalEntry</code>.
+         * Return a hashcode for this PrincipalEntry.
          *
-         * <p>
-         *
-         * @return a hashcode for this <code>PrincipalEntry</code>.
+         * @return a hashcode for this PrincipalEntry
          */
+        @Override
         public int hashCode() {
             return principalClass.hashCode();
         }
+
         public void write(PrintWriter out) {
             out.print("principal " + getDisplayClass() + " " +
-                getDisplayName(true));
+                      getDisplayName(true));
         }
     }
 
@@ -1101,6 +1110,7 @@
          * Calculates a hash code value for the object.  Objects
          * which are equal will also have the same hashcode.
          */
+        @Override
         public int hashCode() {
             int retval = permission.hashCode();
             if (name != null) retval ^= name.hashCode();
@@ -1108,6 +1118,7 @@
             return retval;
         }
 
+        @Override
         public boolean equals(Object obj) {
             if (obj == this)
                 return true;
@@ -1210,28 +1221,18 @@
             i18nMessage = form.format(source);
         }
 
+        @Override
         public String getLocalizedMessage() {
             return i18nMessage;
         }
     }
 
     public static void main(String arg[]) throws Exception {
-        FileReader fr = null;
-        FileWriter fw = null;
-        try {
+        try (FileReader fr = new FileReader(arg[0]);
+             FileWriter fw = new FileWriter(arg[1])) {
             PolicyParser pp = new PolicyParser(true);
-            fr = new FileReader(arg[0]);
             pp.read(fr);
-            fw = new FileWriter(arg[1]);
             pp.write(fw);
-        } finally {
-            if (fr != null) {
-                fr.close();
-            }
-
-            if (fw != null) {
-                fw.close();
-            }
         }
     }
 }
--- a/src/share/classes/sun/security/tools/policytool/PolicyTool.java	Thu Nov 29 17:03:52 2012 +0000
+++ b/src/share/classes/sun/security/tools/policytool/PolicyTool.java	Tue Jan 08 19:00:12 2013 -0500
@@ -604,7 +604,7 @@
                InstantiationException
     {
         if (type.equals(PolicyParser.PrincipalEntry.WILDCARD_CLASS) ||
-            type.equals(PolicyParser.REPLACE_NAME)) {
+            type.equals(PolicyParser.PrincipalEntry.REPLACE_NAME)) {
             return;
         }
         Class<?> PRIN = Class.forName("java.security.Principal");
@@ -2094,7 +2094,7 @@
         } else if (pclass.equals("")) {
             // make this consistent with what PolicyParser does
             // when it sees an empty principal class
-            pclass = PolicyParser.REPLACE_NAME;
+            pclass = PolicyParser.PrincipalEntry.REPLACE_NAME;
             tool.warnings.addElement(
                         "Warning: Principal name '" + pname +
                                 "' specified without a Principal class.\n" +
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/test/java/security/Principal/Implies.java	Tue Jan 08 19:00:12 2013 -0500
@@ -0,0 +1,80 @@
+/*
+ * Copyright (c) 2012, 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 7019834
+ * @summary test default implementation of Principal.implies
+ */
+
+import java.security.Principal;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+import javax.security.auth.Subject;
+import javax.security.auth.kerberos.KerberosPrincipal;
+import javax.security.auth.x500.X500Principal;
+
+public class Implies {
+    public static void main(String[] args) throws Exception {
+        X500Principal duke = new X500Principal("CN=Duke");
+        // should not throw NullPointerException
+        testImplies(duke, (Subject)null, false);
+
+        Set<Principal> principals = new HashSet<>();
+        principals.add(duke);
+        testImplies(duke, principals, true);
+
+        X500Principal tux = new X500Principal("CN=Tux");
+        principals.add(tux);
+        testImplies(duke, principals, true);
+
+        principals.add(new KerberosPrincipal("duke@java.com"));
+        testImplies(duke, principals, true);
+
+        principals.clear();
+        principals.add(tux);
+        testImplies(duke, principals, false);
+
+        System.out.println("test passed");
+    }
+
+    private static void testImplies(Principal principal,
+                                    Set<? extends Principal> principals,
+                                    boolean result)
+        throws SecurityException
+    {
+        Subject subject = new Subject(true, principals, Collections.emptySet(),
+                                      Collections.emptySet());
+        testImplies(principal, subject, result);
+    }
+
+    private static void testImplies(Principal principal,
+                                    Subject subject, boolean result)
+        throws SecurityException
+    {
+        if (principal.implies(subject) != result) {
+            throw new SecurityException("test failed");
+        }
+    }
+}
--- a/test/sun/security/provider/PolicyFile/Comparator.java	Thu Nov 29 17:03:52 2012 +0000
+++ b/test/sun/security/provider/PolicyFile/Comparator.java	Tue Jan 08 19:00:12 2013 -0500
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2004, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2004, 2012, 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
@@ -39,7 +39,6 @@
 import javax.security.auth.x500.X500Principal;
 
 import sun.security.provider.PolicyFile;
-import com.sun.security.auth.PrincipalComparator;
 import com.sun.security.auth.UnixPrincipal;
 import com.sun.security.auth.NTUserPrincipal;
 import com.sun.security.auth.SolarisPrincipal;
@@ -90,7 +89,7 @@
     private static final Principal[] badP = new Principal[] {
                                 new SolarisPrincipal("bad") };
 
-    public static class PCompare1 implements PrincipalComparator {
+    public static class PCompare1 implements Principal {
 
         private String name;
 
@@ -98,6 +97,12 @@
             this.name = name;
         }
 
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
         public boolean implies (Subject subject) {
             if (subject.getPrincipals().contains(p1[0])) {
                 return true;
@@ -106,13 +111,19 @@
         }
     }
 
-    public static class PCompare2 implements PrincipalComparator {
+    public static class PCompare2 implements Principal {
         private String name;
 
         public PCompare2(String name) {
             this.name = name;
         }
 
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
         public boolean implies (Subject subject) {
             if (subject.getPrincipals().contains(p2[0]) &&
                 subject.getPrincipals().contains(p2[1])) {
@@ -122,13 +133,19 @@
         }
     }
 
-    public static class PCompare3 implements PrincipalComparator {
+    public static class PCompare3 implements Principal {
         private String name;
 
         public PCompare3(String name) {
             this.name = name;
         }
 
+        @Override
+        public String getName() {
+            return name;
+        }
+
+        @Override
         public boolean implies (Subject subject) {
             return false;
         }