* @return the value returned by the * PrivilegedExceptionAction's <code>run</code> method. * * @exception PrivilegedActionException if the * <code>PrivilegedExceptionAction.run</code> * method throws a checked exception. <p> * * @exception NullPointerException if the specified * <code>PrivilegedExceptionAction</code> is * <code>null</code>. <p> * * @exception SecurityException if the caller does not have permission * to invoke this method. */ public static <T> T doAsPrivileged(final Subject subject, final java.security.PrivilegedExceptionAction<T> action, final java.security.AccessControlContext acc) throws java.security.PrivilegedActionException { java.lang.SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(AuthPermissionHolder.DO_AS_PRIVILEGED_PERMISSION); } if (action == null) throw new NullPointerException (ResourcesMgr.getString("invalid.null.action.provided")); // set up the new Subject-based AccessControlContext for doPrivileged final AccessControlContext callerAcc = (acc == null ? new AccessControlContext(NULL_PD_ARRAY) : acc); // call doPrivileged and push this new context on the stack return java.security.AccessController.doPrivileged (action, createContext(subject, callerAcc)); } private static AccessControlContext createContext(final Subject subject, final AccessControlContext acc) { return java.security.AccessController.doPrivileged (new java.security.PrivilegedAction<AccessControlContext>() { public AccessControlContext run() { if (subject == null) return new AccessControlContext(acc, null); else return new AccessControlContext (acc, new SubjectDomainCombiner(subject)); } }); } /** * Return the <code>Set</code> of Principals associated with this * <code>Subject</code>. Each <code>Principal</code> represents * an identity for this <code>Subject</code>. * * <p> The returned <code>Set</code> is backed by this Subject's * internal <code>Principal</code> <code>Set</code>. Any modification * to the returned <code>Set</code> affects the internal * <code>Principal</code> <code>Set</code> as well. * * <p> * * @return The <code>Set</code> of Principals associated with this * <code>Subject</code>. */ public Set<Principal> getPrincipals() { // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return principals; } /** * Return a <code>Set</code> of Principals associated with this * <code>Subject</code> that are instances or subclasses of the specified * <code>Class</code>. * * <p> The returned <code>Set</code> is not backed by this Subject's * internal <code>Principal</code> <code>Set</code>. A new * <code>Set</code> is created and returned for each method invocation. * Modifications to the returned <code>Set</code> * will not affect the internal <code>Principal</code> <code>Set</code>. * * <p> * * @param c the returned <code>Set</code> of Principals will all be * instances of this class. * * @return a <code>Set</code> of Principals that are instances of the * specified <code>Class</code>. * * @exception NullPointerException if the specified <code>Class</code> * is <code>null</code>. */ public <T extends Principal> Set<T> getPrincipals(Class<T> c) { if (c == null) throw new NullPointerException (ResourcesMgr.getString("invalid.null.Class.provided")); // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return new ClassSet<T>(PRINCIPAL_SET, c); } /** * Return the <code>Set</code> of public credentials held by this * <code>Subject</code>. * * <p> The returned <code>Set</code> is backed by this Subject's * internal public Credential <code>Set</code>. Any modification * to the returned <code>Set</code> affects the internal public * Credential <code>Set</code> as well. * * <p> * * @return A <code>Set</code> of public credentials held by this * <code>Subject</code>. */ public Set<Object> getPublicCredentials() { // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return pubCredentials; } /** * Return the <code>Set</code> of private credentials held by this * <code>Subject</code>. * * <p> The returned <code>Set</code> is backed by this Subject's * internal private Credential <code>Set</code>. Any modification * to the returned <code>Set</code> affects the internal private * Credential <code>Set</code> as well. * * <p> A caller requires permissions to access the Credentials * in the returned <code>Set</code>, or to modify the * <code>Set</code> itself. A <code>SecurityException</code> * is thrown if the caller does not have the proper permissions. * * <p> While iterating through the <code>Set</code>, * a <code>SecurityException</code> is thrown * if the caller does not have permission to access a * particular Credential. The <code>Iterator</code> * is nevertheless advanced to next element in the <code>Set</code>. * * <p> * * @return A <code>Set</code> of private credentials held by this * <code>Subject</code>. */ public Set<Object> getPrivateCredentials() { // XXX // we do not need a security check for // AuthPermission(getPrivateCredentials) // because we already restrict access to private credentials // via the PrivateCredentialPermission. all the extra AuthPermission // would do is protect the set operations themselves // (like size()), which don't seem security-sensitive. // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return privCredentials; } /** * Return a <code>Set</code> of public credentials associated with this * <code>Subject</code> that are instances or subclasses of the specified * <code>Class</code>. * * <p> The returned <code>Set</code> is not backed by this Subject's * internal public Credential <code>Set</code>. A new * <code>Set</code> is created and returned for each method invocation. * Modifications to the returned <code>Set</code> * will not affect the internal public Credential <code>Set</code>. * * <p> * * @param c the returned <code>Set</code> of public credentials will all be * instances of this class. * * @return a <code>Set</code> of public credentials that are instances * of the specified <code>Class</code>. * * @exception NullPointerException if the specified <code>Class</code> * is <code>null</code>. */ public <T> Set<T> getPublicCredentials(Class<T> c) { if (c == null) throw new NullPointerException (ResourcesMgr.getString("invalid.null.Class.provided")); // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return new ClassSet<T>(PUB_CREDENTIAL_SET, c); } /** * Return a <code>Set</code> of private credentials associated with this * <code>Subject</code> that are instances or subclasses of the specified * <code>Class</code>. * * <p> The caller must have permission to access all of the * requested Credentials, or a <code>SecurityException</code> * will be thrown. * * <p> The returned <code>Set</code> is not backed by this Subject's * internal private Credential <code>Set</code>. A new * <code>Set</code> is created and returned for each method invocation. * Modifications to the returned <code>Set</code> * will not affect the internal private Credential <code>Set</code>. * * <p> * * @param c the returned <code>Set</code> of private credentials will all be * instances of this class. * * @return a <code>Set</code> of private credentials that are instances * of the specified <code>Class</code>. * * @exception NullPointerException if the specified <code>Class</code> * is <code>null</code>. */ public <T> Set<T> getPrivateCredentials(Class<T> c) { // XXX // we do not need a security check for // AuthPermission(getPrivateCredentials) // because we already restrict access to private credentials // via the PrivateCredentialPermission. all the extra AuthPermission // would do is protect the set operations themselves // (like size()), which don't seem security-sensitive. if (c == null) throw new NullPointerException (ResourcesMgr.getString("invalid.null.Class.provided")); // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return new ClassSet<T>(PRIV_CREDENTIAL_SET, c); } /** * Compares the specified Object with this <code>Subject</code> * for equality. Returns true if the given object is also a Subject * and the two <code>Subject</code> instances are equivalent. * More formally, two <code>Subject</code> instances are * equal if their <code>Principal</code> and <code>Credential</code> * Sets are equal. * * <p> * * @param o Object to be compared for equality with this * <code>Subject</code>. * * @return true if the specified Object is equal to this * <code>Subject</code>. * * @exception SecurityException if the caller does not have permission * to access the private credentials for this <code>Subject</code>, * or if the caller does not have permission to access the * private credentials for the provided <code>Subject</code>. */ public boolean equals(Object o) { if (o == null) return false; if (this == o) return true; if (o instanceof Subject) { final Subject that = (Subject)o; // check the principal and credential sets Set<Principal> thatPrincipals; synchronized(that.principals) { // avoid deadlock from dual locks thatPrincipals = new HashSet<Principal>(that.principals); } if (!principals.equals(thatPrincipals)) { return false; } Set<Object> thatPubCredentials; synchronized(that.pubCredentials) { // avoid deadlock from dual locks thatPubCredentials = new HashSet<Object>(that.pubCredentials); } if (!pubCredentials.equals(thatPubCredentials)) { return false; } Set<Object> thatPrivCredentials; synchronized(that.privCredentials) { // avoid deadlock from dual locks thatPrivCredentials = new HashSet<Object>(that.privCredentials); } if (!privCredentials.equals(thatPrivCredentials)) { return false; } return true; } return false; } /** * Return the String representation of this <code>Subject</code>. * * <p> * * @return the String representation of this <code>Subject</code>. */ public String toString() { return toString(true); } /** * package private convenience method to print out the Subject * without firing off a security check when trying to access * the Private Credentials */ String toString(boolean includePrivateCredentials) { String s = ResourcesMgr.getString("Subject."); String suffix = ""; synchronized(principals) { Iterator<Principal> pI = principals.iterator(); while (pI.hasNext()) { Principal p = pI.next(); suffix = suffix + ResourcesMgr.getString(".Principal.") + p.toString() + ResourcesMgr.getString("NEWLINE"); } } synchronized(pubCredentials) { Iterator<Object> pI = pubCredentials.iterator(); while (pI.hasNext()) { Object o = pI.next(); suffix = suffix + ResourcesMgr.getString(".Public.Credential.") + o.toString() + ResourcesMgr.getString("NEWLINE"); } } if (includePrivateCredentials) { synchronized(privCredentials) { Iterator<Object> pI = privCredentials.iterator(); while (pI.hasNext()) { try { Object o = pI.next(); suffix += ResourcesMgr.getString (".Private.Credential.") + o.toString() + ResourcesMgr.getString("NEWLINE"); } catch (SecurityException se) { suffix += ResourcesMgr.getString (".Private.Credential.inaccessible."); break; } } } } return s + suffix; } /** * Returns a hashcode for this <code>Subject</code>. * * <p> * * @return a hashcode for this <code>Subject</code>. * * @exception SecurityException if the caller does not have permission * to access this Subject's private credentials. */ public int hashCode() { /** * The hashcode is derived exclusive or-ing the * hashcodes of this Subject's Principals and credentials. * * If a particular credential was destroyed * (<code>credential.hashCode()</code> throws an * <code>IllegalStateException</code>), * the hashcode for that credential is derived via: * <code>credential.getClass().toString().hashCode()</code>. */ int hashCode = 0; synchronized(principals) { Iterator<Principal> pIterator = principals.iterator(); while (pIterator.hasNext()) { Principal p = pIterator.next(); hashCode ^= p.hashCode(); } } synchronized(pubCredentials) { Iterator<Object> pubCIterator = pubCredentials.iterator(); while (pubCIterator.hasNext()) { hashCode ^= getCredHashCode(pubCIterator.next()); } } return hashCode; } /** * get a credential's hashcode */ private int getCredHashCode(Object o) { try { return o.hashCode(); } catch (IllegalStateException ise) { return o.getClass().toString().hashCode(); } } /** * Writes this object out to a stream (i.e., serializes it). */ private void writeObject(java.io.ObjectOutputStream oos) throws java.io.IOException { synchronized(principals) { oos.defaultWriteObject(); } } /** * Reads this object from a stream (i.e., deserializes it) */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); // The Credential <code>Set</code> is not serialized, but we do not // want the default deserialization routine to set it to null. this.pubCredentials = Collections.synchronizedSet (new SecureSet<Object>(this, PUB_CREDENTIAL_SET)); this.privCredentials = Collections.synchronizedSet (new SecureSet<Object>(this, PRIV_CREDENTIAL_SET)); } /** * Prevent modifications unless caller has permission. * * @serial include */ private static class SecureSet<E> extends AbstractSet<E> implements java.io.Serializable { private static final long serialVersionUID = 7911754171111800359L; /** * @serialField this$0 Subject The outer Subject instance. * @serialField elements LinkedList The elements in this set. */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("this$0", Subject.class), new ObjectStreamField("elements", LinkedList.class), new ObjectStreamField("which", int.class) }; Subject subject; LinkedList<E> elements; /** * @serial An integer identifying the type of objects contained * in this set. If <code>which == 1</code>, * this is a Principal set and all the elements are * of type <code>java.security.Principal</code>. * If <code>which == 2</code>, this is a public credential * set and all the elements are of type <code>Object</code>. * If <code>which == 3</code>, this is a private credential * set and all the elements are of type <code>Object</code>. */ private int which; SecureSet(Subject subject, int which) { this.subject = subject; this.which = which; this.elements = new LinkedList<E>(); } SecureSet(Subject subject, int which, Set<? extends E> set) { this.subject = subject;Lines 501–1000 of 1421. Previous lines Load more
* @return the value returned by the * PrivilegedExceptionAction's <code>run</code> method. * * @exception PrivilegedActionException if the * <code>PrivilegedExceptionAction.run</code> * method throws a checked exception. <p> * * @exception NullPointerException if the specified * <code>PrivilegedExceptionAction</code> is * <code>null</code>. <p> * * @exception SecurityException if the caller does not have permission * to invoke this method. */ public static <T> T doAsPrivileged(final Subject subject, final java.security.PrivilegedExceptionAction<T> action, final java.security.AccessControlContext acc) throws java.security.PrivilegedActionException { java.lang.SecurityManager sm = System.getSecurityManager(); if (sm != null) { sm.checkPermission(AuthPermissionHolder.DO_AS_PRIVILEGED_PERMISSION); } if (action == null) throw new NullPointerException (ResourcesMgr.getString("invalid.null.action.provided")); // set up the new Subject-based AccessControlContext for doPrivileged final AccessControlContext callerAcc = (acc == null ? new AccessControlContext(NULL_PD_ARRAY) : acc); // call doPrivileged and push this new context on the stack return java.security.AccessController.doPrivileged (action, createContext(subject, callerAcc)); } private static AccessControlContext createContext(final Subject subject, final AccessControlContext acc) { return java.security.AccessController.doPrivileged (new java.security.PrivilegedAction<AccessControlContext>() { public AccessControlContext run() { if (subject == null) return new AccessControlContext(acc, null); else return new AccessControlContext (acc, new SubjectDomainCombiner(subject)); } }); } /** * Return the <code>Set</code> of Principals associated with this * <code>Subject</code>. Each <code>Principal</code> represents * an identity for this <code>Subject</code>. * * <p> The returned <code>Set</code> is backed by this Subject's * internal <code>Principal</code> <code>Set</code>. Any modification * to the returned <code>Set</code> affects the internal * <code>Principal</code> <code>Set</code> as well. * * <p> * * @return The <code>Set</code> of Principals associated with this * <code>Subject</code>. */ public Set<Principal> getPrincipals() { // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return principals; } /** * Return a <code>Set</code> of Principals associated with this * <code>Subject</code> that are instances or subclasses of the specified * <code>Class</code>. * * <p> The returned <code>Set</code> is not backed by this Subject's * internal <code>Principal</code> <code>Set</code>. A new * <code>Set</code> is created and returned for each method invocation. * Modifications to the returned <code>Set</code> * will not affect the internal <code>Principal</code> <code>Set</code>. * * <p> * * @param c the returned <code>Set</code> of Principals will all be * instances of this class. * * @return a <code>Set</code> of Principals that are instances of the * specified <code>Class</code>. * * @exception NullPointerException if the specified <code>Class</code> * is <code>null</code>. */ public <T extends Principal> Set<T> getPrincipals(Class<T> c) { if (c == null) throw new NullPointerException (ResourcesMgr.getString("invalid.null.Class.provided")); // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return new ClassSet<T>(PRINCIPAL_SET, c); } /** * Return the <code>Set</code> of public credentials held by this * <code>Subject</code>. * * <p> The returned <code>Set</code> is backed by this Subject's * internal public Credential <code>Set</code>. Any modification * to the returned <code>Set</code> affects the internal public * Credential <code>Set</code> as well. * * <p> * * @return A <code>Set</code> of public credentials held by this * <code>Subject</code>. */ public Set<Object> getPublicCredentials() { // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return pubCredentials; } /** * Return the <code>Set</code> of private credentials held by this * <code>Subject</code>. * * <p> The returned <code>Set</code> is backed by this Subject's * internal private Credential <code>Set</code>. Any modification * to the returned <code>Set</code> affects the internal private * Credential <code>Set</code> as well. * * <p> A caller requires permissions to access the Credentials * in the returned <code>Set</code>, or to modify the * <code>Set</code> itself. A <code>SecurityException</code> * is thrown if the caller does not have the proper permissions. * * <p> While iterating through the <code>Set</code>, * a <code>SecurityException</code> is thrown * if the caller does not have permission to access a * particular Credential. The <code>Iterator</code> * is nevertheless advanced to next element in the <code>Set</code>. * * <p> * * @return A <code>Set</code> of private credentials held by this * <code>Subject</code>. */ public Set<Object> getPrivateCredentials() { // XXX // we do not need a security check for // AuthPermission(getPrivateCredentials) // because we already restrict access to private credentials // via the PrivateCredentialPermission. all the extra AuthPermission // would do is protect the set operations themselves // (like size()), which don't seem security-sensitive. // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return privCredentials; } /** * Return a <code>Set</code> of public credentials associated with this * <code>Subject</code> that are instances or subclasses of the specified * <code>Class</code>. * * <p> The returned <code>Set</code> is not backed by this Subject's * internal public Credential <code>Set</code>. A new * <code>Set</code> is created and returned for each method invocation. * Modifications to the returned <code>Set</code> * will not affect the internal public Credential <code>Set</code>. * * <p> * * @param c the returned <code>Set</code> of public credentials will all be * instances of this class. * * @return a <code>Set</code> of public credentials that are instances * of the specified <code>Class</code>. * * @exception NullPointerException if the specified <code>Class</code> * is <code>null</code>. */ public <T> Set<T> getPublicCredentials(Class<T> c) { if (c == null) throw new NullPointerException (ResourcesMgr.getString("invalid.null.Class.provided")); // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return new ClassSet<T>(PUB_CREDENTIAL_SET, c); } /** * Return a <code>Set</code> of private credentials associated with this * <code>Subject</code> that are instances or subclasses of the specified * <code>Class</code>. * * <p> The caller must have permission to access all of the * requested Credentials, or a <code>SecurityException</code> * will be thrown. * * <p> The returned <code>Set</code> is not backed by this Subject's * internal private Credential <code>Set</code>. A new * <code>Set</code> is created and returned for each method invocation. * Modifications to the returned <code>Set</code> * will not affect the internal private Credential <code>Set</code>. * * <p> * * @param c the returned <code>Set</code> of private credentials will all be * instances of this class. * * @return a <code>Set</code> of private credentials that are instances * of the specified <code>Class</code>. * * @exception NullPointerException if the specified <code>Class</code> * is <code>null</code>. */ public <T> Set<T> getPrivateCredentials(Class<T> c) { // XXX // we do not need a security check for // AuthPermission(getPrivateCredentials) // because we already restrict access to private credentials // via the PrivateCredentialPermission. all the extra AuthPermission // would do is protect the set operations themselves // (like size()), which don't seem security-sensitive. if (c == null) throw new NullPointerException (ResourcesMgr.getString("invalid.null.Class.provided")); // always return an empty Set instead of null // so LoginModules can add to the Set if necessary return new ClassSet<T>(PRIV_CREDENTIAL_SET, c); } /** * Compares the specified Object with this <code>Subject</code> * for equality. Returns true if the given object is also a Subject * and the two <code>Subject</code> instances are equivalent. * More formally, two <code>Subject</code> instances are * equal if their <code>Principal</code> and <code>Credential</code> * Sets are equal. * * <p> * * @param o Object to be compared for equality with this * <code>Subject</code>. * * @return true if the specified Object is equal to this * <code>Subject</code>. * * @exception SecurityException if the caller does not have permission * to access the private credentials for this <code>Subject</code>, * or if the caller does not have permission to access the * private credentials for the provided <code>Subject</code>. */ public boolean equals(Object o) { if (o == null) return false; if (this == o) return true; if (o instanceof Subject) { final Subject that = (Subject)o; // check the principal and credential sets Set<Principal> thatPrincipals; synchronized(that.principals) { // avoid deadlock from dual locks thatPrincipals = new HashSet<Principal>(that.principals); } if (!principals.equals(thatPrincipals)) { return false; } Set<Object> thatPubCredentials; synchronized(that.pubCredentials) { // avoid deadlock from dual locks thatPubCredentials = new HashSet<Object>(that.pubCredentials); } if (!pubCredentials.equals(thatPubCredentials)) { return false; } Set<Object> thatPrivCredentials; synchronized(that.privCredentials) { // avoid deadlock from dual locks thatPrivCredentials = new HashSet<Object>(that.privCredentials); } if (!privCredentials.equals(thatPrivCredentials)) { return false; } return true; } return false; } /** * Return the String representation of this <code>Subject</code>. * * <p> * * @return the String representation of this <code>Subject</code>. */ public String toString() { return toString(true); } /** * package private convenience method to print out the Subject * without firing off a security check when trying to access * the Private Credentials */ String toString(boolean includePrivateCredentials) { String s = ResourcesMgr.getString("Subject."); String suffix = ""; synchronized(principals) { Iterator<Principal> pI = principals.iterator(); while (pI.hasNext()) { Principal p = pI.next(); suffix = suffix + ResourcesMgr.getString(".Principal.") + p.toString() + ResourcesMgr.getString("NEWLINE"); } } synchronized(pubCredentials) { Iterator<Object> pI = pubCredentials.iterator(); while (pI.hasNext()) { Object o = pI.next(); suffix = suffix + ResourcesMgr.getString(".Public.Credential.") + o.toString() + ResourcesMgr.getString("NEWLINE"); } } if (includePrivateCredentials) { synchronized(privCredentials) { Iterator<Object> pI = privCredentials.iterator(); while (pI.hasNext()) { try { Object o = pI.next(); suffix += ResourcesMgr.getString (".Private.Credential.") + o.toString() + ResourcesMgr.getString("NEWLINE"); } catch (SecurityException se) { suffix += ResourcesMgr.getString (".Private.Credential.inaccessible."); break; } } } } return s + suffix; } /** * Returns a hashcode for this <code>Subject</code>. * * <p> * * @return a hashcode for this <code>Subject</code>. * * @exception SecurityException if the caller does not have permission * to access this Subject's private credentials. */ public int hashCode() { /** * The hashcode is derived exclusive or-ing the * hashcodes of this Subject's Principals and credentials. * * If a particular credential was destroyed * (<code>credential.hashCode()</code> throws an * <code>IllegalStateException</code>), * the hashcode for that credential is derived via: * <code>credential.getClass().toString().hashCode()</code>. */ int hashCode = 0; synchronized(principals) { Iterator<Principal> pIterator = principals.iterator(); while (pIterator.hasNext()) { Principal p = pIterator.next(); hashCode ^= p.hashCode(); } } synchronized(pubCredentials) { Iterator<Object> pubCIterator = pubCredentials.iterator(); while (pubCIterator.hasNext()) { hashCode ^= getCredHashCode(pubCIterator.next()); } } return hashCode; } /** * get a credential's hashcode */ private int getCredHashCode(Object o) { try { return o.hashCode(); } catch (IllegalStateException ise) { return o.getClass().toString().hashCode(); } } /** * Writes this object out to a stream (i.e., serializes it). */ private void writeObject(java.io.ObjectOutputStream oos) throws java.io.IOException { synchronized(principals) { oos.defaultWriteObject(); } } /** * Reads this object from a stream (i.e., deserializes it) */ private void readObject(java.io.ObjectInputStream s) throws java.io.IOException, ClassNotFoundException { s.defaultReadObject(); // The Credential <code>Set</code> is not serialized, but we do not // want the default deserialization routine to set it to null. this.pubCredentials = Collections.synchronizedSet (new SecureSet<Object>(this, PUB_CREDENTIAL_SET)); this.privCredentials = Collections.synchronizedSet (new SecureSet<Object>(this, PRIV_CREDENTIAL_SET)); } /** * Prevent modifications unless caller has permission. * * @serial include */ private static class SecureSet<E> extends AbstractSet<E> implements java.io.Serializable { private static final long serialVersionUID = 7911754171111800359L; /** * @serialField this$0 Subject The outer Subject instance. * @serialField elements LinkedList The elements in this set. */ private static final ObjectStreamField[] serialPersistentFields = { new ObjectStreamField("this$0", Subject.class), new ObjectStreamField("elements", LinkedList.class), new ObjectStreamField("which", int.class) }; Subject subject; LinkedList<E> elements; /** * @serial An integer identifying the type of objects contained * in this set. If <code>which == 1</code>, * this is a Principal set and all the elements are * of type <code>java.security.Principal</code>. * If <code>which == 2</code>, this is a public credential * set and all the elements are of type <code>Object</code>. * If <code>which == 3</code>, this is a private credential * set and all the elements are of type <code>Object</code>. */ private int which; SecureSet(Subject subject, int which) { this.subject = subject; this.which = which; this.elements = new LinkedList<E>(); } SecureSet(Subject subject, int which, Set<? extends E> set) { this.subject = subject;