home *** CD-ROM | disk | FTP | other *** search
Java Source | 1998-03-20 | 13.2 KB | 438 lines |
- /*
- * @(#)Permissions.java 1.30 98/03/18
- *
- * Copyright 1997, 1998 by Sun Microsystems, Inc.,
- * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
- * All rights reserved.
- *
- * This software is the confidential and proprietary information
- * of Sun Microsystems, Inc. ("Confidential Information"). You
- * shall not disclose such Confidential Information and shall use
- * it only in accordance with the terms of the license agreement
- * you entered into with Sun.
- */
-
- package java.security;
-
- import java.util.Enumeration;
- import java.util.Hashtable;
- import java.util.NoSuchElementException;
- import java.io.Serializable;
- import java.util.ArrayList;
-
- /**
- * This class represents a heterogeneous collection of Permissions. That is,
- * it contains different types of Permission objects, organized into
- * PermissionCollections. For example, if any <code>java.io.FilePermission</code>
- * objects are added to an instance of this class, they are all stored in a single
- * PermissionCollection. It is the PermissionCollection returned by a call to
- * the <code>newPermissionCollection</code> method in the FilePermission class.
- * Similarly, any <code>java.lang.RuntimePermission</code> objects are stored in
- * the PermissionCollection returned by a call to the
- * <code>newPermissionCollection</code> method in the
- * RuntimePermission class. Thus, this class represents a collection of
- * PermissionCollections.
- *
- * <p>When the <code>add</code> method is called to add a Permission, the
- * Permission is stored in the appropriate PermissionCollection. If no such
- * collection exists yet, the Permission object's class is determined and the
- * <code>newPermissionCollection</code> method is called on that class to create
- * the PermissionCollection and add it to the Permissions object. If
- * <code>newPermissionCollection</code> returns null, then a default
- * PermissionCollection that uses a hashtable will be created and used. Each
- * hashtable entry has a Permission object's name as the key, and the Permission
- * object as the value.
- *
- * @see Permission
- * @see PermissionCollection
- * @see AllPermission
- *
- * @version 1.30, 98/03/18
- *
- * @author Marianne Mueller
- * @author Roland Schemers
- */
-
- public final class Permissions extends PermissionCollection
- implements Serializable
- {
- /** use serialVersionUID from JDK 1.2 for interoperability */
- private static final long serialVersionUID = -564687543657373888L;
-
-
- private Hashtable perms;
-
- // optimization. keep track of the AllPermission collection
- private PermissionCollection allPermission;
-
- // when set, add will throw an exception.
- private boolean readOnly;
-
- /**
- * Creates a new Permissions object containing no PermissionCollections.
- */
- public Permissions() {
- perms = new Hashtable();
- allPermission = null;
- readOnly = false;
- }
-
- /**
- * Adds a permission object to the PermissionCollection for the class the
- * permission belongs to. For example, if <i>permission</i> is a FilePermission,
- * it is added to the FilePermissionCollection stored in this
- * Permissions object.
- *
- * This method creates
- * a new PermissionCollection object (and adds the permission to it)
- * if an appropriate collection does not yet exist. <p>
- *
- * @param permission the Permission object to add.
- *
- * @exception SecurityException if this Permissions object is
- * marked as readonly.
- *
- * @see isReadOnly
- */
-
- public void add(Permission permission) {
- if (readOnly)
- throw new SecurityException(
- "attempt to add a Permission to a readonly Permissions object");
- PermissionCollection pc = getPermissionCollection(permission);
- pc.add(permission);
- if (permission instanceof AllPermission) {
- allPermission = pc;
- }
- }
-
- /**
- * Checks to see if this object's PermissionCollection for permissions of the
- * specified permission's type implies the permissions
- * expressed in the <i>permission</i> object. Returns true if the combination
- * of permissions in the appropriate PermissionCollection (e.g., a
- * FilePermissionCollection for a FilePermission) together imply the
- * specified permission.
- *
- * <p>For example, suppose there is a FilePermissionCollection in this Permissions
- * object, and it contains one FilePermission that specifies "read" access for
- * all files in all subdirectories of the "/tmp" directory, and another
- * FilePermission that specifies "write" access for all files in the
- * "/tmp/scratch/foo" directory. Then if the <code>implies</code> method
- * is called with a permission specifying both "read" and "write" access
- * to files in the "/tmp/scratch/foo" directory, <code>true</code> is returned.
- * <p>Additionally, if this PermissionCollection contains the
- * AllPermission, this method will always return true.
- * <p>
- * @param permission the Permission object to check.
- *
- * @return true if "permission" is implied by the permissions in the
- * PermissionCollection it
- * belongs to, false if not.
- */
-
- public boolean implies(Permission permission) {
- PermissionCollection pc = getPermissionCollection(permission);
-
- if (allPermission != null && allPermission.implies(permission))
- return true;
- else
- return pc.implies(permission);
- }
-
- /**
- * Returns an enumeration of all the Permission objects in all the
- * PermissionCollections in this Permissions object.
- *
- * @return an enumeration of all the Permissions.
- */
-
- public Enumeration elements() {
- // go through each Permissions in the hash table
- // and call their elements() function.
- return new PermissionsEnumerator(perms.elements());
- }
-
- /**
- * Returns an enumeration of all the Permission objects with the same
- * type as <i>p</i>.
- *
- * @param p the prototype Permission object.
- *
- * @return an enumeration of all the Permissions with the same type as <i>p</i>.
- */
-
- // XXX this could be public. Question is, do we want to make it public?
- // it is currently trivial to implement, but that might change...
-
- private Enumeration elements(Permission p) {
- PermissionCollection pc = getPermissionCollection(p);
- return pc.elements();
- }
-
- /**
- * Gets the PermissionCollection in this Permissions object for
- * permissions whose type is the same as that of <i>p</i>.
- * For example, if <i>p</i> is a FilePermission, the FilePermissionCollection
- * stored in this Permissions object will be returned.
- *
- * This method creates a new PermissionCollection object for the specified
- * type of permission objects if one does not yet exist.
- * To do so, it first calls the <code>newPermissionCollection</code> method
- * on <i>p</i>. Subclasses of class Permission
- * override that method if they need to store their permissions in a particular
- * PermissionCollection object in order to provide the correct semantics
- * when the <code>PermissionCollection.implies</code> method is called.
- * If the call returns a PermissionCollection, that collection is stored
- * in this Permissions object. If the call returns null, then
- * this method instantiates and stores a default PermissionCollection
- * that uses a hashtable to store its permission objects.
- */
-
- private PermissionCollection getPermissionCollection(Permission p) {
- Class c = p.getClass();
- PermissionCollection pc = (PermissionCollection) perms.get(c);
- if (pc == null) {
- synchronized (perms) {
- // check again, in case someone else created one
- // between the time we checked and the time we
- // got the lock. We do this here to avoid
- // making this whole method synchronized, because
- // it is called by every public method.
- pc = (PermissionCollection) perms.get(c);
-
- //check for unresolved permissions
- if (pc == null) {
-
- pc = getUnresolvedPermissions(p);
-
- // if still null, create a new collection
- if (pc == null) {
-
- pc = p.newPermissionCollection();
-
- // still no PermissionCollection?
- // We'll give them a PermissionsHash.
- if (pc == null)
- pc = new PermissionsHash();
- }
- }
- perms.put(c, pc);
- }
- }
- return pc;
- }
-
- /**
- * Resolves any unresolved permissions of type p.
- *
- * @param p the type of unresolved permission to resolve
- *
- * @return PermissionCollection containing the unresolved permissions,
- * or null if there were no unresolved permissions of type p.
- *
- */
- private PermissionCollection getUnresolvedPermissions(Permission p)
- {
- UnresolvedPermissionCollection uc =
- (UnresolvedPermissionCollection) perms.get(UnresolvedPermission.class);
-
- // we have no unresolved permissions if uc is null
- if (uc == null)
- return null;
-
- java.util.Vector v = uc.removeUnresolvedPermissions(p);
-
- // we have no unresolved permissions of this type if v is null
- if (v == null)
- return null;
-
- PublicKey keys[] = null;
-
- Object signers[] = p.getClass().getSigners();
-
- if (signers != null) {
- ArrayList keysAL = new ArrayList();
- for (int j=0; j < signers.length; j++) {
- if (signers[j] instanceof Identity) {
- PublicKey pk = ((Identity) signers[j]).getPublicKey();
- if (pk != null)
- keysAL.add(pk);
- }
- }
- keys = new PublicKey[keysAL.size()];
- for (int k=0; k< keysAL.size(); k++) {
- keys[k] = (PublicKey) keysAL.get(k);
- }
- }
-
- PermissionCollection pc = null;
- Enumeration e = v.elements();
-
- while(e.hasMoreElements()) {
- UnresolvedPermission up = (UnresolvedPermission) e.nextElement();
- Permission perm = up.resolve(p, keys);
- if (perm != null) {
- if (pc == null) {
- pc = p.newPermissionCollection();
- if (pc == null)
- pc = new PermissionsHash();
- }
- pc.add(perm);
- }
-
- }
- return pc;
- }
-
- /**
- * Marks this Permissions object as "readonly". After a Permissions object
- * is marked as readonly, no new Permission objects can be added to it
- * using <code>addPermission</code>.
- */
- public void setReadOnly() {
- readOnly = true;
- }
-
- /**
- * Returns true if this Permissions object is marked as readonly. If it
- * is readonly, no new Permission objects can be added to it
- * using <code>addPermission</code>.
- *
- * <p>By default, the object is <i>not</i> readonly. It can be set to readonly
- * by a call to <code>setReadOnly</code>.
- *
- * @return true if this Permissions object is marked as readonly, false
- * otherwise.
- */
- public boolean isReadOnly() {
- return readOnly;
- }
- }
-
- final class PermissionsEnumerator implements Enumeration {
-
- // all the perms
- private Enumeration perms;
- // the current set
- private Enumeration permset;
-
- PermissionsEnumerator(Enumeration e) {
- perms = e;
- permset = getNextEnumWithMore();
- }
-
- public synchronized boolean hasMoreElements() {
- // if we enter with permissionimpl null, we know
- // there are no more left.
-
- if (permset == null)
- return false;
-
- // try to see if there are any left in the current one
-
- if (permset.hasMoreElements())
- return true;
-
- // get the next one that has something in it...
- permset = getNextEnumWithMore();
-
- // if it is null, we are done!
- return (permset != null);
- }
-
- public synchronized Object nextElement() {
-
- // hasMoreElements will update permset to the next permset
- // with something in it...
-
- if (hasMoreElements()) {
- return permset.nextElement();
- } else {
- throw new NoSuchElementException("PermissionsEnumerator");
- }
-
- }
-
- private Enumeration getNextEnumWithMore() {
- while (perms.hasMoreElements()) {
- PermissionCollection pc = (PermissionCollection) perms.nextElement();
- Enumeration next = (Enumeration) pc.elements();
- if (next.hasMoreElements())
- return next;
- }
- return null;
- }
- }
-
- /**
- * A PermissionsHash stores a homogeneous set of permissions in a hashtable.
- *
- * @see Permission
- * @see Permissions
- *
- * @version 1.30, 98/03/18
- *
- * @author Roland Schemers
- */
-
- final class PermissionsHash extends PermissionCollection
- implements Serializable
- {
- /** use serialVersionUID from JDK 1.2 for interoperability */
- private static final long serialVersionUID = -8491988220802933440L;
-
- private Hashtable perms;
-
- /**
- * Create an empty PermissionsHash object.
- */
-
- PermissionsHash() {
- perms = new Hashtable();
- }
-
- /**
- * Adds a permission to the PermissionsHash.
- *
- * @param permission the Permission object to add.
- */
-
- public void add(Permission permission)
- {
- // XXX this assumes we replace duplicate Permissions
- perms.put(permission.getName(), permission);
- }
-
- /**
- * Check and see if this set of permissions implies the permissions
- * expressed in "permission".
- *
- * @param permission the Permission object to compare
- *
- * @return true if "permission" is a proper subset of a permission in
- * the set, false if not.
- */
-
- public boolean implies(Permission permission)
- {
- Permission p = (Permission) perms.get(permission.getName());
- if (p == null)
- return false;
- else
- return p.implies(permission);
- }
-
- /**
- * Returns an enumeration of all the Permission objects in the container.
- *
- * @return an enumeration of all the Permissions.
- */
-
- public Enumeration elements()
- {
- return perms.elements();
- }
- }
-
-