src/share/classes/javax/security/auth/Subject.java

Print this page

        

@@ -1,7 +1,7 @@
 /*
- * Copyright (c) 1998, 2013, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 1998, 2014, 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.  Oracle designates this

@@ -192,21 +192,23 @@
      * @param privCredentials the {@code Set} of private credentials
      *          to be associated with this {@code Subject}.
      *
      * @exception NullPointerException if the specified
      *          {@code principals}, {@code pubCredentials},
-     *          or {@code privCredentials} are {@code null}.
+     *          or {@code privCredentials} are {@code null},
+     *          or a null value exists within any of these three
+     *          Sets.
      */
     public Subject(boolean readOnly, Set<? extends Principal> principals,
                    Set<?> pubCredentials, Set<?> privCredentials)
     {
-
-        if (principals == null ||
-            pubCredentials == null ||
-            privCredentials == null)
+        if (collectionNullClean(principals) == false ||
+            collectionNullClean(pubCredentials) == false ||
+            collectionNullClean(privCredentials) == false) {
             throw new NullPointerException
                 (ResourcesMgr.getString("invalid.null.input.s."));
+        }
 
         this.principals = Collections.synchronizedSet(new SecureSet<Principal>
                                 (this, PRINCIPAL_SET, principals));
         this.pubCredentials = Collections.synchronizedSet(new SecureSet<Object>
                                 (this, PUB_CREDENTIAL_SET, pubCredentials));

@@ -968,14 +970,10 @@
         readOnly = gf.get("readOnly", false);
 
         Set<Principal> inputPrincs = (Set<Principal>)gf.get("principals", null);
 
         // Rewrap the principals into a SecureSet
-        if (inputPrincs == null) {
-            throw new NullPointerException
-                (ResourcesMgr.getString("invalid.null.input.s."));
-        }
         try {
             principals = Collections.synchronizedSet(new SecureSet<Principal>
                                 (this, PRINCIPAL_SET, inputPrincs));
         } catch (NullPointerException npe) {
             // Sometimes people deserialize the principals set only.

@@ -991,10 +989,34 @@
         this.privCredentials = Collections.synchronizedSet
                         (new SecureSet<Object>(this, PRIV_CREDENTIAL_SET));
     }
 
     /**
+     * Tests for null-clean collections (both non-null reference and
+     * no null elements)
+     *
+     * @param coll A {@code Collection} to be tested for null references
+     *
+     * @return true if {@code coll} is non-null and contains no null
+     *         elements, false otherwise.
+     */
+    private static boolean collectionNullClean(Collection<?> coll) {
+        boolean isClean = false;
+
+        try {
+            isClean = (coll != null) && !coll.contains(null);
+        } catch (NullPointerException npe) {
+            // A null-hostile collection may choose to return null if
+            // contains(null) is called on it rather than returning false.
+            // If so then we know no nulls are present.
+            isClean = true;
+        }
+
+        return isClean;
+    }
+
+    /**
      * Prevent modifications unless caller has permission.
      *
      * @serial include
      */
     private static class SecureSet<E>

@@ -1096,10 +1118,15 @@
             };
         }
 
         public boolean add(E o) {
 
+            if (o == null) {
+                throw new NullPointerException
+                        (ResourcesMgr.getString("invalid.null.input.s."));
+            }
+
             if (subject.isReadOnly()) {
                 throw new IllegalStateException
                         (ResourcesMgr.getString("Subject.is.read.only"));
             }
 

@@ -1137,10 +1164,15 @@
                 return false;
         }
 
         public boolean remove(Object o) {
 
+            if (o == null) {
+                throw new NullPointerException
+                        (ResourcesMgr.getString("invalid.null.input.s."));
+            }
+
             final Iterator<E> e = iterator();
             while (e.hasNext()) {
                 E next;
                 if (which != Subject.PRIV_CREDENTIAL_SET) {
                     next = e.next();

@@ -1151,24 +1183,25 @@
                             return e.next();
                         }
                     });
                 }
 
-                if (next == null) {
-                    if (o == null) {
-                        e.remove();
-                        return true;
-                    }
-                } else if (next.equals(o)) {
+                if (next.equals(o)) {
                     e.remove();
                     return true;
                 }
             }
             return false;
         }
 
         public boolean contains(Object o) {
+
+            if (o == null) {
+                throw new NullPointerException
+                        (ResourcesMgr.getString("invalid.null.input.s."));
+            }
+
             final Iterator<E> e = iterator();
             while (e.hasNext()) {
                 E next;
                 if (which != Subject.PRIV_CREDENTIAL_SET) {
                     next = e.next();

@@ -1192,23 +1225,32 @@
                             return e.next();
                         }
                     });
                 }
 
-                if (next == null) {
-                    if (o == null) {
-                        return true;
-                    }
-                } else if (next.equals(o)) {
+                if (next.equals(o)) {
                     return true;
                 }
             }
             return false;
         }
 
+        public boolean addAll(Collection<? extends E> c) {
+            if (collectionNullClean(c) == false) {
+                throw new NullPointerException
+                    (ResourcesMgr.getString("invalid.null.input.s."));
+            }
+
+            return (super.addAll(c));
+        }
+
         public boolean removeAll(Collection<?> c) {
-            Objects.requireNonNull(c);
+            if (collectionNullClean(c) == false) {
+                throw new NullPointerException
+                    (ResourcesMgr.getString("invalid.null.input.s."));
+            }
+
             boolean modified = false;
             final Iterator<E> e = iterator();
             while (e.hasNext()) {
                 E next;
                 if (which != Subject.PRIV_CREDENTIAL_SET) {

@@ -1222,34 +1264,38 @@
                     });
                 }
 
                 Iterator<?> ce = c.iterator();
                 while (ce.hasNext()) {
-                    Object o = ce.next();
-                    if (next == null) {
-                        if (o == null) {
-                            e.remove();
-                            modified = true;
-                            break;
-                        }
-                    } else if (next.equals(o)) {
+                    if (next.equals(ce.next())) {
                         e.remove();
                         modified = true;
                         break;
                     }
                 }
             }
             return modified;
         }
 
+        public boolean containsAll(Collection<?> c) {
+            if (collectionNullClean(c) == false) {
+                throw new NullPointerException
+                    (ResourcesMgr.getString("invalid.null.input.s."));
+            }
+
+            return super.containsAll(c);
+        }
+
         public boolean retainAll(Collection<?> c) {
-            Objects.requireNonNull(c);
+            if (collectionNullClean(c) == false) {
+                throw new NullPointerException
+                    (ResourcesMgr.getString("invalid.null.input.s."));
+            }
+
             boolean modified = false;
-            boolean retain = false;
             final Iterator<E> e = iterator();
             while (e.hasNext()) {
-                retain = false;
                 E next;
                 if (which != Subject.PRIV_CREDENTIAL_SET) {
                     next = e.next();
                 } else {
                     next = java.security.AccessController.doPrivileged

@@ -1258,30 +1304,16 @@
                             return e.next();
                         }
                     });
                 }
 
-                Iterator<?> ce = c.iterator();
-                while (ce.hasNext()) {
-                    Object o = ce.next();
-                    if (next == null) {
-                        if (o == null) {
-                            retain = true;
-                            break;
-                        }
-                    } else if (next.equals(o)) {
-                        retain = true;
-                        break;
-                    }
-                }
-
-                if (!retain) {
+                if (c.contains(next) == false) {
                     e.remove();
-                    retain = false;
                     modified = true;
                 }
             }
+
             return modified;
         }
 
         public void clear() {
             final Iterator<E> e = iterator();

@@ -1336,16 +1368,23 @@
             ObjectInputStream.GetField fields = ois.readFields();
             subject = (Subject) fields.get("this$0", null);
             which = fields.get("which", 0);
 
             LinkedList<E> tmp = (LinkedList<E>) fields.get("elements", null);
+
+            if (Subject.collectionNullClean(tmp) == false) {
+                throw new NullPointerException
+                    (ResourcesMgr.getString("invalid.null.input.s."));
+            }
+
             if (tmp.getClass() != LinkedList.class) {
                 elements = new LinkedList<E>(tmp);
             } else {
                 elements = tmp;
             }
         }
+
     }
 
     /**
      * This class implements a {@code Set} which returns only
      * members that are an instance of a specified Class.