--- old/src/share/classes/javax/security/auth/Subject.java 2014-06-04 14:13:11.651311957 -0700
+++ new/src/share/classes/javax/security/auth/Subject.java 2014-06-04 14:13:11.149248146 -0700
@@ -1,5 +1,5 @@
/*
- * 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
@@ -142,7 +142,9 @@
*
The newly constructed Sets check whether this {@code Subject}
* has been set read-only before permitting subsequent modifications.
* The newly created Sets also prevent illegal modifications
- * by ensuring that callers have sufficient permissions.
+ * by ensuring that callers have sufficient permissions. These Sets
+ * also prohibit null elements, and attempts to add or query a null
+ * element will result in a {@code NullPointerException}.
*
*
To modify the Principals Set, the caller must have
* {@code AuthPermission("modifyPrincipals")}.
@@ -170,7 +172,9 @@
* These newly created Sets check whether this {@code Subject}
* has been set read-only before permitting subsequent modifications.
* The newly created Sets also prevent illegal modifications
- * by ensuring that callers have sufficient permissions.
+ * by ensuring that callers have sufficient permissions. These Sets
+ * also prohibit null elements, and attempts to add or query a null
+ * element will result in a {@code NullPointerException}.
*
*
To modify the Principals Set, the caller must have
* {@code AuthPermission("modifyPrincipals")}.
@@ -194,17 +198,19 @@
*
* @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
(this, PRINCIPAL_SET, principals));
@@ -970,10 +976,6 @@
Set inputPrincs = (Set)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
(this, PRINCIPAL_SET, inputPrincs));
@@ -993,13 +995,36 @@
}
/**
+ * 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
- extends AbstractSet
- implements java.io.Serializable {
+ implements Set, java.io.Serializable {
private static final long serialVersionUID = 7911754171111800359L;
@@ -1098,6 +1123,11 @@
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"));
@@ -1139,6 +1169,11 @@
public boolean remove(Object o) {
+ if (o == null) {
+ throw new NullPointerException
+ (ResourcesMgr.getString("invalid.null.input.s."));
+ }
+
final Iterator e = iterator();
while (e.hasNext()) {
E next;
@@ -1153,12 +1188,7 @@
});
}
- if (next == null) {
- if (o == null) {
- e.remove();
- return true;
- }
- } else if (next.equals(o)) {
+ if (next.equals(o)) {
e.remove();
return true;
}
@@ -1167,6 +1197,12 @@
}
public boolean contains(Object o) {
+
+ if (o == null) {
+ throw new NullPointerException
+ (ResourcesMgr.getString("invalid.null.input.s."));
+ }
+
final Iterator e = iterator();
while (e.hasNext()) {
E next;
@@ -1194,19 +1230,34 @@
});
}
- 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) {
+ boolean result = false;
+
+ if (collectionNullClean(c) == false) {
+ throw new NullPointerException
+ (ResourcesMgr.getString("invalid.null.input.s."));
+ }
+
+ for (E item : c) {
+ result |= this.add(item);
+ }
+
+ return result;
+ }
+
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 = iterator();
while (e.hasNext()) {
@@ -1224,14 +1275,7 @@
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;
@@ -1241,13 +1285,30 @@
return modified;
}
+ public boolean containsAll(Collection> c) {
+ if (collectionNullClean(c) == false) {
+ throw new NullPointerException
+ (ResourcesMgr.getString("invalid.null.input.s."));
+ }
+
+ for (Object item : c) {
+ if (this.contains(item) == false) {
+ return false;
+ }
+ }
+
+ return true;
+ }
+
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 = iterator();
while (e.hasNext()) {
- retain = false;
E next;
if (which != Subject.PRIV_CREDENTIAL_SET) {
next = e.next();
@@ -1260,26 +1321,12 @@
});
}
- 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;
}
@@ -1301,6 +1348,56 @@
}
}
+ public boolean isEmpty() {
+ return elements.isEmpty();
+ }
+
+ public Object[] toArray() {
+ final Iterator e = iterator();
+ while (e.hasNext()) {
+ // The next() method performs a security manager check
+ // on each element in the SecureSet. If we make it all
+ // the way through we should be able to simply return
+ // element's toArray results. Otherwise we'll let
+ // the SecurityException pass up the call stack.
+ e.next();
+ }
+
+ return elements.toArray();
+ }
+
+ public T[] toArray(T[] a) {
+ final Iterator e = iterator();
+ while (e.hasNext()) {
+ // The next() method performs a security manager check
+ // on each element in the SecureSet. If we make it all
+ // the way through we should be able to simply return
+ // element's toArray results. Otherwise we'll let
+ // the SecurityException pass up the call stack.
+ e.next();
+ }
+
+ return elements.toArray(a);
+ }
+
+ public boolean equals(Object o) {
+ if (o == this)
+ return true;
+
+ if (!(o instanceof Set))
+ return false;
+ Collection> c = (Collection>) o;
+ if (c.size() != size())
+ return false;
+ try {
+ return containsAll(c);
+ } catch (ClassCastException unused) {
+ return false;
+ } catch (NullPointerException unused) {
+ return false;
+ }
+ }
+
/**
* Writes this object out to a stream (i.e., serializes it).
*
@@ -1338,12 +1435,19 @@
which = fields.get("which", 0);
LinkedList tmp = (LinkedList) 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(tmp);
} else {
elements = tmp;
}
}
+
}
/**