- /*
 - * @(#)Permissions.java 1.46 00/02/02
 - *
 - * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
 - *
 - * This software is the proprietary information of Sun Microsystems, Inc.
 - * Use is subject to license terms.
 - *
 - */
 - 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 stores a Permission object as both the key and the value.
 - *
 - * @see Permission
 - * @see PermissionCollection
 - * @see AllPermission
 - *
 - * @version 1.46, 00/02/02
 - *
 - * @author Marianne Mueller
 - * @author Roland Schemers
 - *
 - * @serial exclude
 - */
 - public final class Permissions extends PermissionCollection
 - implements Serializable
 - {
 - private Hashtable perms;
 - // optimization. keep track of the AllPermission collection
 - private PermissionCollection allPermission;
 - /**
 - * Creates a new Permissions object containing no PermissionCollections.
 - */
 - public Permissions() {
 - perms = new Hashtable(11);
 - allPermission = null;
 - }
 - /**
 - * 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 PermissionCollection#isReadOnly()
 - */
 - public void add(Permission permission) {
 - if (isReadOnly())
 - 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.getUnresolvedPermissions(p);
 - // we have no unresolved permissions of this type if v is null
 - if (v == null)
 - return null;
 - java.security.cert.Certificate certs[] = null;
 - Object signers[] = p.getClass().getSigners();
 - int n = 0;
 - if (signers != null) {
 - for (int j=0; j < signers.length; j++) {
 - if (signers[j] instanceof java.security.cert.Certificate) {
 - n++;
 - }
 - }
 - certs = new java.security.cert.Certificate[n];
 - n = 0;
 - for (int j=0; j < signers.length; j++) {
 - if (signers[j] instanceof java.security.cert.Certificate) {
 - certs[n++] = (java.security.cert.Certificate)signers[j];
 - }
 - }
 - }
 - PermissionCollection pc = null;
 - Enumeration e = v.elements();
 - while(e.hasMoreElements()) {
 - UnresolvedPermission up = (UnresolvedPermission) e.nextElement();
 - Permission perm = up.resolve(p, certs);
 - if (perm != null) {
 - if (pc == null) {
 - pc = p.newPermissionCollection();
 - if (pc == null)
 - pc = new PermissionsHash();
 - }
 - pc.add(perm);
 - }
 - }
 - return pc;
 - }
 - }
 - 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.46, 02/02/00
 - *
 - * @author Roland Schemers
 - *
 - * @serial include
 - */
 - final class PermissionsHash extends PermissionCollection
 - implements Serializable
 - {
 - private Hashtable perms;
 - /**
 - * Create an empty PermissionsHash object.
 - */
 - PermissionsHash() {
 - perms = new Hashtable(11);
 - }
 - /**
 - * Adds a permission to the PermissionsHash.
 - *
 - * @param permission the Permission object to add.
 - */
 - public void add(Permission permission)
 - {
 - perms.put(permission, 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)
 - {
 - // attempt a fast lookup and implies. If that fails
 - // then enumerate through all the permissions.
 - Permission p = (Permission) perms.get(permission);
 - if ((p == null) || (!p.implies(permission))) {
 - Enumeration enum = elements();
 - try {
 - while (enum.hasMoreElements()) {
 - p = (Permission) enum.nextElement();
 - if (p.implies(permission))
 - return true;
 - }
 - } catch (NoSuchElementException e){
 - // ignore
 - }
 - return false;
 - } else {
 - return true;
 - }
 - }
 - /**
 - * Returns an enumeration of all the Permission objects in the container.
 - *
 - * @return an enumeration of all the Permissions.
 - */
 - public Enumeration elements()
 - {
 - return perms.elements();
 - }
 - }