home *** CD-ROM | disk | FTP | other *** search
/ Apple Developer Connection Student Program / ADC Tools Sampler CD Disk 3 1999.iso / Metrowerks CodeWarrior / Java Support / Java_Source / Java2 / src / java / security / Permissions.java < prev    next >
Encoding:
Java Source  |  1999-05-28  |  12.4 KB  |  417 lines  |  [TEXT/CWIE]

  1. /*
  2.  * @(#)Permissions.java    1.37 98/07/30
  3.  *
  4.  * Copyright 1997, 1998 by Sun Microsystems, Inc.,
  5.  * 901 San Antonio Road, Palo Alto, California, 94303, U.S.A.
  6.  * All rights reserved.
  7.  *
  8.  * This software is the confidential and proprietary information
  9.  * of Sun Microsystems, Inc. ("Confidential Information").  You
  10.  * shall not disclose such Confidential Information and shall use
  11.  * it only in accordance with the terms of the license agreement
  12.  * you entered into with Sun.
  13.  */
  14.  
  15. package java.security;
  16.  
  17. import java.util.Enumeration; 
  18. import java.util.Hashtable;
  19. import java.util.NoSuchElementException;
  20. import java.io.Serializable;
  21. import java.util.ArrayList;
  22.  
  23. /**  
  24.  * This class represents a heterogeneous collection of Permissions. That is,
  25.  * it contains different types of Permission objects, organized into
  26.  * PermissionCollections. For example, if any <code>java.io.FilePermission</code>
  27.  * objects are added to an instance of this class, they are all stored in a single
  28.  * PermissionCollection. It is the PermissionCollection returned by a call to
  29.  * the <code>newPermissionCollection</code> method in the FilePermission class.
  30.  * Similarly, any <code>java.lang.RuntimePermission</code> objects are stored in 
  31.  * the PermissionCollection returned by a call to the 
  32.  * <code>newPermissionCollection</code> method in the
  33.  * RuntimePermission class. Thus, this class represents a collection of
  34.  * PermissionCollections.
  35.  * 
  36.  * <p>When the <code>add</code> method is called to add a Permission, the 
  37.  * Permission is stored in the appropriate PermissionCollection. If no such 
  38.  * collection exists yet, the Permission object's class is determined and the
  39.  * <code>newPermissionCollection</code> method is called on that class to create
  40.  * the PermissionCollection and add it to the Permissions object. If
  41.  * <code>newPermissionCollection</code> returns null, then a default 
  42.  * PermissionCollection that uses a hashtable will be created and used. Each 
  43.  * hashtable entry stores a Permission object as both the key and the value.
  44.  * 
  45.  * @see Permission
  46.  * @see PermissionCollection
  47.  * @see AllPermission
  48.  * 
  49.  * @version 1.37, 99/03/26
  50.  *
  51.  * @author Marianne Mueller
  52.  * @author Roland Schemers
  53.  */
  54.  
  55. public final class Permissions extends PermissionCollection 
  56. implements Serializable 
  57. {
  58.  
  59.     private Hashtable perms;
  60.  
  61.     // optimization. keep track of the AllPermission collection
  62.     private PermissionCollection allPermission;
  63.  
  64.     /**
  65.      * Creates a new Permissions object containing no PermissionCollections.
  66.      */
  67.     public Permissions() {
  68.     perms = new Hashtable(11);
  69.     allPermission = null;
  70.     }
  71.  
  72.     /**
  73.      * Adds a permission object to the PermissionCollection for the class the
  74.      * permission belongs to. For example, if <i>permission</i> is a FilePermission,
  75.      * it is added to the FilePermissionCollection stored in this
  76.      * Permissions object. 
  77.      * 
  78.      * This method creates
  79.      * a new PermissionCollection object (and adds the permission to it)
  80.      * if an appropriate collection does not yet exist. <p>
  81.      *
  82.      * @param permission the Permission object to add.
  83.      * 
  84.      * @exception SecurityException if this Permissions object is
  85.      * marked as readonly.
  86.      * 
  87.      * @see isReadOnly
  88.      */
  89.  
  90.     public void add(Permission permission) {
  91.     if (isReadOnly())
  92.         throw new SecurityException(
  93.               "attempt to add a Permission to a readonly Permissions object");
  94.     PermissionCollection pc = getPermissionCollection(permission);
  95.     pc.add(permission);
  96.     if (permission instanceof AllPermission) {
  97.         allPermission = pc;
  98.     }
  99.     }
  100.  
  101.     /**
  102.      * Checks to see if this object's PermissionCollection for permissions of the
  103.      * specified permission's type implies the permissions 
  104.      * expressed in the <i>permission</i> object. Returns true if the combination
  105.      * of permissions in the appropriate PermissionCollection (e.g., a
  106.      * FilePermissionCollection for a FilePermission) together imply the
  107.      * specified permission.
  108.      * 
  109.      * <p>For example, suppose there is a FilePermissionCollection in this Permissions
  110.      * object, and it contains one FilePermission that specifies "read" access for
  111.      * all files in all subdirectories of the "/tmp" directory, and another
  112.      * FilePermission that specifies "write" access for all files in the
  113.      * "/tmp/scratch/foo" directory. Then if the <code>implies</code> method
  114.      * is called with a permission specifying both "read" and "write" access
  115.      * to files in the "/tmp/scratch/foo" directory, <code>true</code> is returned.
  116.      * <p>Additionally, if this PermissionCollection contains the
  117.      * AllPermission, this method will always return true.
  118.      * <p>
  119.      * @param permission the Permission object to check.
  120.      *
  121.      * @return true if "permission" is implied by the permissions in the
  122.      * PermissionCollection it
  123.      * belongs to, false if not.
  124.      */
  125.  
  126.     public boolean implies(Permission permission) {
  127.     PermissionCollection pc = getPermissionCollection(permission);
  128.  
  129.     if (allPermission != null && allPermission.implies(permission))
  130.         return true;
  131.     else 
  132.         return pc.implies(permission);
  133.     }
  134.  
  135.     /**
  136.      * Returns an enumeration of all the Permission objects in all the
  137.      * PermissionCollections in this Permissions object.
  138.      *
  139.      * @return an enumeration of all the Permissions.
  140.      */
  141.  
  142.     public Enumeration elements() {
  143.     // go through each Permissions in the hash table 
  144.     // and call their elements() function.
  145.     return new PermissionsEnumerator(perms.elements());
  146.     }
  147.  
  148.     /**
  149.      * Returns an enumeration of all the Permission objects with the same
  150.      * type as <i>p</i>.
  151.      *
  152.      * @param p the prototype Permission object.
  153.      *
  154.      * @return an enumeration of all the Permissions with the same type as <i>p</i>.
  155.      */
  156.  
  157.     // XXX this could be public. Question is, do we want to make it public?
  158.     // it is currently trivial to implement, but that might change...
  159.  
  160.     private Enumeration elements(Permission p) {
  161.     PermissionCollection pc = getPermissionCollection(p);
  162.     return pc.elements();
  163.     }
  164.  
  165.     /** 
  166.      * Gets the PermissionCollection in this Permissions object for
  167.      * permissions whose type is the same as that of <i>p</i>.
  168.      * For example, if <i>p</i> is a FilePermission, the FilePermissionCollection
  169.      * stored in this Permissions object will be returned. 
  170.      * 
  171.      * This method creates a new PermissionCollection object for the specified 
  172.      * type of permission objects if one does not yet exist. 
  173.      * To do so, it first calls the <code>newPermissionCollection</code> method
  174.      * on <i>p</i>.  Subclasses of class Permission 
  175.      * override that method if they need to store their permissions in a particular
  176.      * PermissionCollection object in order to provide the correct semantics
  177.      * when the <code>PermissionCollection.implies</code> method is called.
  178.      * If the call returns a PermissionCollection, that collection is stored
  179.      * in this Permissions object. If the call returns null, then
  180.      * this method instantiates and stores a default PermissionCollection 
  181.      * that uses a hashtable to store its permission objects.
  182.      */
  183.  
  184.     private PermissionCollection getPermissionCollection(Permission p) {
  185.     Class c = p.getClass();
  186.     PermissionCollection pc = (PermissionCollection) perms.get(c);
  187.     if (pc == null) {
  188.         synchronized (perms) {
  189.         // check again, in case someone else created one
  190.         // between the time we checked and the time we
  191.         // got the lock. We do this here to avoid 
  192.         // making this whole method synchronized, because
  193.         // it is called by every public method.
  194.         pc = (PermissionCollection) perms.get(c);
  195.  
  196.         //check for unresolved permissions
  197.         if (pc == null) {
  198.  
  199.             pc = getUnresolvedPermissions(p);
  200.  
  201.             // if still null, create a new collection
  202.             if (pc == null) {
  203.  
  204.             pc = p.newPermissionCollection();
  205.  
  206.             // still no PermissionCollection? 
  207.             // We'll give them a PermissionsHash.
  208.             if (pc == null)
  209.                 pc = new PermissionsHash();
  210.             }
  211.         }
  212.         perms.put(c, pc);
  213.         }
  214.     }
  215.     return pc;
  216.     }
  217.  
  218.     /**
  219.      * Resolves any unresolved permissions of type p.
  220.      *
  221.      * @param p the type of unresolved permission to resolve
  222.      *
  223.      * @return PermissionCollection containing the unresolved permissions,
  224.      *  or null if there were no unresolved permissions of type p.
  225.      *
  226.      */
  227.     private PermissionCollection getUnresolvedPermissions(Permission p)
  228.     {
  229.     UnresolvedPermissionCollection uc = 
  230.     (UnresolvedPermissionCollection) perms.get(UnresolvedPermission.class);
  231.  
  232.     // we have no unresolved permissions if uc is null
  233.     if (uc == null) 
  234.         return null;
  235.  
  236.     java.util.Vector v = uc.getUnresolvedPermissions(p);
  237.     
  238.     // we have no unresolved permissions of this type if v is null
  239.     if (v == null)
  240.         return null;
  241.  
  242.     java.security.cert.Certificate certs[] = null;
  243.  
  244.     Object signers[] = p.getClass().getSigners();
  245.  
  246.     int n = 0;
  247.     if (signers != null) {
  248.         for (int j=0; j < signers.length; j++) {
  249.         if (signers[j] instanceof java.security.cert.Certificate) {
  250.             n++;
  251.         }
  252.         }
  253.         certs = new java.security.cert.Certificate[n];
  254.         n = 0;
  255.         for (int j=0; j < signers.length; j++) {
  256.         if (signers[j] instanceof java.security.cert.Certificate) {
  257.             certs[n] = (java.security.cert.Certificate)signers[j];
  258.         }
  259.         }
  260.     }
  261.  
  262.     PermissionCollection pc = null;
  263.     Enumeration e = v.elements();
  264.  
  265.     while(e.hasMoreElements()) {
  266.         UnresolvedPermission up = (UnresolvedPermission) e.nextElement();
  267.         Permission perm = up.resolve(p, certs);
  268.         if (perm != null) {
  269.         if (pc == null) {
  270.             pc = p.newPermissionCollection();
  271.             if (pc == null) 
  272.             pc = new PermissionsHash();
  273.         }
  274.         pc.add(perm);
  275.         }
  276.  
  277.     }
  278.     return pc;
  279.     }
  280. }
  281.  
  282. final class PermissionsEnumerator implements Enumeration {
  283.  
  284.     // all the perms
  285.     private Enumeration perms;
  286.     // the current set
  287.     private Enumeration permset;
  288.    
  289.     PermissionsEnumerator(Enumeration e) {
  290.     perms = e;
  291.     permset = getNextEnumWithMore();
  292.     }
  293.  
  294.     public synchronized boolean hasMoreElements() {
  295.     // if we enter with permissionimpl null, we know
  296.     // there are no more left.
  297.  
  298.     if (permset == null) 
  299.         return  false;
  300.  
  301.     // try to see if there are any left in the current one
  302.  
  303.     if (permset.hasMoreElements())
  304.         return true;
  305.  
  306.     // get the next one that has something in it...
  307.     permset = getNextEnumWithMore();
  308.  
  309.     // if it is null, we are done!
  310.     return (permset != null);
  311.     }
  312.  
  313.     public synchronized Object nextElement() {
  314.  
  315.     // hasMoreElements will update permset to the next permset
  316.     // with something in it...
  317.  
  318.     if (hasMoreElements()) {
  319.         return permset.nextElement();
  320.     } else {
  321.         throw new NoSuchElementException("PermissionsEnumerator");
  322.     }
  323.  
  324.     }
  325.  
  326.     private Enumeration getNextEnumWithMore() {
  327.     while (perms.hasMoreElements()) {
  328.         PermissionCollection pc = (PermissionCollection) perms.nextElement();
  329.         Enumeration next = (Enumeration) pc.elements();
  330.         if (next.hasMoreElements())
  331.         return next;
  332.     }
  333.     return null;
  334.     }
  335. }
  336.  
  337. /**
  338.  * A PermissionsHash stores a homogeneous set of permissions in a hashtable.
  339.  *
  340.  * @see Permission
  341.  * @see Permissions
  342.  *
  343.  * @version 1.37, 99/03/26
  344.  *
  345.  * @author Roland Schemers
  346.  */
  347.  
  348. final class PermissionsHash extends PermissionCollection
  349. implements Serializable
  350. {
  351.  
  352.     private Hashtable perms;
  353.  
  354.     /**
  355.      * Create an empty PermissionsHash object.
  356.      */
  357.  
  358.     PermissionsHash() {
  359.     perms = new Hashtable(11);
  360.     }
  361.  
  362.     /**
  363.      * Adds a permission to the PermissionsHash.
  364.      *
  365.      * @param permission the Permission object to add.
  366.      */
  367.  
  368.     public void add(Permission permission)
  369.     {
  370.     perms.put(permission, permission);
  371.     }
  372.  
  373.     /**
  374.      * Check and see if this set of permissions implies the permissions 
  375.      * expressed in "permission".
  376.      *
  377.      * @param permission the Permission object to compare
  378.      *
  379.      * @return true if "permission" is a proper subset of a permission in 
  380.      * the set, false if not.
  381.      */
  382.  
  383.     public boolean implies(Permission permission) 
  384.     {
  385.     // attempt a fast lookup and implies. If that fails
  386.     // then enumerate through all the permissions.
  387.     Permission p = (Permission) perms.get(permission);
  388.     if ((p == null) || (!p.implies(permission))) {
  389.         Enumeration enum = elements();
  390.         try {
  391.         while (enum.hasMoreElements()) {
  392.             p = (Permission) enum.nextElement();
  393.             if (p.implies(permission))
  394.             return true;
  395.         }
  396.         } catch (NoSuchElementException e){
  397.         // ignore
  398.         }
  399.         return false;
  400.     } else {
  401.         return true;
  402.     }
  403.     }
  404.  
  405.     /**
  406.      * Returns an enumeration of all the Permission objects in the container.
  407.      *
  408.      * @return an enumeration of all the Permissions.
  409.      */
  410.  
  411.     public Enumeration elements()
  412.     {
  413.     return perms.elements();
  414.     }
  415. }
  416.  
  417.