Save This Page
Home » openjdk-7 » java » io » [javadoc | source]
    1   /*
    2    * Copyright 1997-2005 Sun Microsystems, Inc.  All Rights Reserved.
    3    * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
    4    *
    5    * This code is free software; you can redistribute it and/or modify it
    6    * under the terms of the GNU General Public License version 2 only, as
    7    * published by the Free Software Foundation.  Sun designates this
    8    * particular file as subject to the "Classpath" exception as provided
    9    * by Sun in the LICENSE file that accompanied this code.
   10    *
   11    * This code is distributed in the hope that it will be useful, but WITHOUT
   12    * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
   13    * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
   14    * version 2 for more details (a copy is included in the LICENSE file that
   15    * accompanied this code).
   16    *
   17    * You should have received a copy of the GNU General Public License version
   18    * 2 along with this work; if not, write to the Free Software Foundation,
   19    * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
   20    *
   21    * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
   22    * CA 95054 USA or visit www.sun.com if you need additional information or
   23    * have any questions.
   24    */
   25   
   26   package java.io;
   27   
   28   import java.security;
   29   import java.util.Enumeration;
   30   import java.util.List;
   31   import java.util.ArrayList;
   32   import java.util.StringTokenizer;
   33   import java.util.Vector;
   34   import java.util.Collections;
   35   import java.io.ObjectStreamField;
   36   import java.io.ObjectOutputStream;
   37   import java.io.ObjectInputStream;
   38   import java.io.IOException;
   39   import sun.security.util.SecurityConstants;
   40   
   41   /**
   42    * This class represents access to a file or directory.  A FilePermission consists
   43    * of a pathname and a set of actions valid for that pathname.
   44    * <P>
   45    * Pathname is the pathname of the file or directory granted the specified
   46    * actions. A pathname that ends in "/*" (where "/" is
   47    * the file separator character, <code>File.separatorChar</code>) indicates
   48    * all the files and directories contained in that directory. A pathname
   49    * that ends with "/-" indicates (recursively) all files
   50    * and subdirectories contained in that directory. A pathname consisting of
   51    * the special token "&lt;&lt;ALL FILES&gt;&gt;" matches <b>any</b> file.
   52    * <P>
   53    * Note: A pathname consisting of a single "*" indicates all the files
   54    * in the current directory, while a pathname consisting of a single "-"
   55    * indicates all the files in the current directory and
   56    * (recursively) all files and subdirectories contained in the current
   57    * directory.
   58    * <P>
   59    * The actions to be granted are passed to the constructor in a string containing
   60    * a list of one or more comma-separated keywords. The possible keywords are
   61    * "read", "write", "execute", and "delete". Their meaning is defined as follows:
   62    * <P>
   63    * <DL>
   64    *    <DT> read <DD> read permission
   65    *    <DT> write <DD> write permission
   66    *    <DT> execute
   67    *    <DD> execute permission. Allows <code>Runtime.exec</code> to
   68    *         be called. Corresponds to <code>SecurityManager.checkExec</code>.
   69    *    <DT> delete
   70    *    <DD> delete permission. Allows <code>File.delete</code> to
   71    *         be called. Corresponds to <code>SecurityManager.checkDelete</code>.
   72    * </DL>
   73    * <P>
   74    * The actions string is converted to lowercase before processing.
   75    * <P>
   76    * Be careful when granting FilePermissions. Think about the implications
   77    * of granting read and especially write access to various files and
   78    * directories. The "&lt;&lt;ALL FILES>>" permission with write action is
   79    * especially dangerous. This grants permission to write to the entire
   80    * file system. One thing this effectively allows is replacement of the
   81    * system binary, including the JVM runtime environment.
   82    *
   83    * <p>Please note: Code can always read a file from the same
   84    * directory it's in (or a subdirectory of that directory); it does not
   85    * need explicit permission to do so.
   86    *
   87    * @see java.security.Permission
   88    * @see java.security.Permissions
   89    * @see java.security.PermissionCollection
   90    *
   91    *
   92    * @author Marianne Mueller
   93    * @author Roland Schemers
   94    * @since 1.2
   95    *
   96    * @serial exclude
   97    */
   98   
   99   public final class FilePermission extends Permission implements Serializable {
  100   
  101       /**
  102        * Execute action.
  103        */
  104       private final static int EXECUTE = 0x1;
  105       /**
  106        * Write action.
  107        */
  108       private final static int WRITE   = 0x2;
  109       /**
  110        * Read action.
  111        */
  112       private final static int READ    = 0x4;
  113       /**
  114        * Delete action.
  115        */
  116       private final static int DELETE  = 0x8;
  117   
  118       /**
  119        * All actions (read,write,execute,delete)
  120        */
  121       private final static int ALL     = READ|WRITE|EXECUTE|DELETE;
  122       /**
  123        * No actions.
  124        */
  125       private final static int NONE    = 0x0;
  126   
  127       // the actions mask
  128       private transient int mask;
  129   
  130       // does path indicate a directory? (wildcard or recursive)
  131       private transient boolean directory;
  132   
  133       // is it a recursive directory specification?
  134       private transient boolean recursive;
  135   
  136       /**
  137        * the actions string.
  138        *
  139        * @serial
  140        */
  141       private String actions; // Left null as long as possible, then
  142                               // created and re-used in the getAction function.
  143   
  144       // canonicalized dir path. In the case of
  145       // directories, it is the name "/blah/*" or "/blah/-" without
  146       // the last character (the "*" or "-").
  147   
  148       private transient String cpath;
  149   
  150       // static Strings used by init(int mask)
  151       private static final char RECURSIVE_CHAR = '-';
  152       private static final char WILD_CHAR = '*';
  153   
  154   /*
  155       public String toString()
  156       {
  157           StringBuffer sb = new StringBuffer();
  158           sb.append("***\n");
  159           sb.append("cpath = "+cpath+"\n");
  160           sb.append("mask = "+mask+"\n");
  161           sb.append("actions = "+getActions()+"\n");
  162           sb.append("directory = "+directory+"\n");
  163           sb.append("recursive = "+recursive+"\n");
  164           sb.append("***\n");
  165           return sb.toString();
  166       }
  167   */
  168   
  169       private static final long serialVersionUID = 7930732926638008763L;
  170   
  171       /**
  172        * initialize a FilePermission object. Common to all constructors.
  173        * Also called during de-serialization.
  174        *
  175        * @param mask the actions mask to use.
  176        *
  177        */
  178       private void init(int mask)
  179       {
  180   
  181           if ((mask & ALL) != mask)
  182                   throw new IllegalArgumentException("invalid actions mask");
  183   
  184           if (mask == NONE)
  185                   throw new IllegalArgumentException("invalid actions mask");
  186   
  187           if ((cpath = getName()) == null)
  188                   throw new NullPointerException("name can't be null");
  189   
  190           this.mask = mask;
  191   
  192           if (cpath.equals("<<ALL FILES>>")) {
  193               directory = true;
  194               recursive = true;
  195               cpath = "";
  196               return;
  197           }
  198   
  199           // store only the canonical cpath if possible
  200           cpath = AccessController.doPrivileged(new PrivilegedAction<String>() {
  201               public String run() {
  202                   try {
  203                       return sun.security.provider.PolicyFile.canonPath(cpath);
  204                   } catch (IOException ioe) {
  205                       return cpath;
  206                   }
  207               }
  208           });
  209   
  210           int len = cpath.length();
  211           char last = ((len > 0) ? cpath.charAt(len - 1) : 0);
  212   
  213           if (last == RECURSIVE_CHAR &&
  214               cpath.charAt(len - 2) == File.separatorChar) {
  215               directory = true;
  216               recursive = true;
  217               cpath = cpath.substring(0, --len);
  218           } else if (last == WILD_CHAR &&
  219               cpath.charAt(len - 2) == File.separatorChar) {
  220               directory = true;
  221               //recursive = false;
  222               cpath = cpath.substring(0, --len);
  223           } else {
  224               // overkill since they are initialized to false, but
  225               // commented out here to remind us...
  226               //directory = false;
  227               //recursive = false;
  228           }
  229   
  230           // XXX: at this point the path should be absolute. die if it isn't?
  231       }
  232   
  233       /**
  234        * Creates a new FilePermission object with the specified actions.
  235        * <i>path</i> is the pathname of a file or directory, and <i>actions</i>
  236        * contains a comma-separated list of the desired actions granted on the
  237        * file or directory. Possible actions are
  238        * "read", "write", "execute", and "delete".
  239        *
  240        * <p>A pathname that ends in "/*" (where "/" is
  241        * the file separator character, <code>File.separatorChar</code>)
  242        * indicates all the files and directories contained in that directory.
  243        * A pathname that ends with "/-" indicates (recursively) all files and
  244        * subdirectories contained in that directory. The special pathname
  245        * "&lt;&lt;ALL FILES&gt;&gt;" matches any file.
  246        *
  247        * <p>A pathname consisting of a single "*" indicates all the files
  248        * in the current directory, while a pathname consisting of a single "-"
  249        * indicates all the files in the current directory and
  250        * (recursively) all files and subdirectories contained in the current
  251        * directory.
  252        *
  253        * <p>A pathname containing an empty string represents an empty path.
  254        *
  255        * @param path the pathname of the file/directory.
  256        * @param actions the action string.
  257        *
  258        * @throws IllegalArgumentException
  259        *          If actions is <code>null</code>, empty or contains an action
  260        *          other than the specified possible actions.
  261        */
  262   
  263       public FilePermission(String path, String actions)
  264       {
  265           super(path);
  266           init(getMask(actions));
  267       }
  268   
  269       /**
  270        * Creates a new FilePermission object using an action mask.
  271        * More efficient than the FilePermission(String, String) constructor.
  272        * Can be used from within
  273        * code that needs to create a FilePermission object to pass into the
  274        * <code>implies</code> method.
  275        *
  276        * @param path the pathname of the file/directory.
  277        * @param mask the action mask to use.
  278        */
  279   
  280       // package private for use by the FilePermissionCollection add method
  281       FilePermission(String path, int mask)
  282       {
  283           super(path);
  284           init(mask);
  285       }
  286   
  287       /**
  288        * Checks if this FilePermission object "implies" the specified permission.
  289        * <P>
  290        * More specifically, this method returns true if:<p>
  291        * <ul>
  292        * <li> <i>p</i> is an instanceof FilePermission,<p>
  293        * <li> <i>p</i>'s actions are a proper subset of this
  294        * object's actions, and <p>
  295        * <li> <i>p</i>'s pathname is implied by this object's
  296        *      pathname. For example, "/tmp/*" implies "/tmp/foo", since
  297        *      "/tmp/*" encompasses all files in the "/tmp" directory,
  298        *      including the one named "foo".
  299        * </ul>
  300        *
  301        * @param p the permission to check against.
  302        *
  303        * @return <code>true</code> if the specified permission is not
  304        *                  <code>null</code> and is implied by this object,
  305        *                  <code>false</code> otherwise.
  306        */
  307       public boolean implies(Permission p) {
  308           if (!(p instanceof FilePermission))
  309               return false;
  310   
  311           FilePermission that = (FilePermission) p;
  312   
  313           // we get the effective mask. i.e., the "and" of this and that.
  314           // They must be equal to that.mask for implies to return true.
  315   
  316           return ((this.mask & that.mask) == that.mask) && impliesIgnoreMask(that);
  317       }
  318   
  319       /**
  320        * Checks if the Permission's actions are a proper subset of the
  321        * this object's actions. Returns the effective mask iff the
  322        * this FilePermission's path also implies that FilePermission's path.
  323        *
  324        * @param that the FilePermission to check against.
  325        * @param exact return immediately if the masks are not equal
  326        * @return the effective mask
  327        */
  328       boolean impliesIgnoreMask(FilePermission that) {
  329           if (this.directory) {
  330               if (this.recursive) {
  331                   // make sure that.path is longer then path so
  332                   // something like /foo/- does not imply /foo
  333                   if (that.directory) {
  334                       return (that.cpath.length() >= this.cpath.length()) &&
  335                               that.cpath.startsWith(this.cpath);
  336                   }  else {
  337                       return ((that.cpath.length() > this.cpath.length()) &&
  338                           that.cpath.startsWith(this.cpath));
  339                   }
  340               } else {
  341                   if (that.directory) {
  342                       // if the permission passed in is a directory
  343                       // specification, make sure that a non-recursive
  344                       // permission (i.e., this object) can't imply a recursive
  345                       // permission.
  346                       if (that.recursive)
  347                           return false;
  348                       else
  349                           return (this.cpath.equals(that.cpath));
  350                   } else {
  351                       int last = that.cpath.lastIndexOf(File.separatorChar);
  352                       if (last == -1)
  353                           return false;
  354                       else {
  355                           // this.cpath.equals(that.cpath.substring(0, last+1));
  356                           // Use regionMatches to avoid creating new string
  357                           return (this.cpath.length() == (last + 1)) &&
  358                               this.cpath.regionMatches(0, that.cpath, 0, last+1);
  359                       }
  360                   }
  361               }
  362           } else if (that.directory) {
  363               // if this is NOT recursive/wildcarded,
  364               // do not let it imply a recursive/wildcarded permission
  365               return false;
  366           } else {
  367               return (this.cpath.equals(that.cpath));
  368           }
  369       }
  370   
  371       /**
  372        * Checks two FilePermission objects for equality. Checks that <i>obj</i> is
  373        * a FilePermission, and has the same pathname and actions as this object.
  374        * <P>
  375        * @param obj the object we are testing for equality with this object.
  376        * @return <code>true</code> if obj is a FilePermission, and has the same
  377        *          pathname and actions as this FilePermission object,
  378        *          <code>false</code> otherwise.
  379        */
  380       public boolean equals(Object obj) {
  381           if (obj == this)
  382               return true;
  383   
  384           if (! (obj instanceof FilePermission))
  385               return false;
  386   
  387           FilePermission that = (FilePermission) obj;
  388   
  389           return (this.mask == that.mask) &&
  390               this.cpath.equals(that.cpath) &&
  391               (this.directory == that.directory) &&
  392               (this.recursive == that.recursive);
  393       }
  394   
  395       /**
  396        * Returns the hash code value for this object.
  397        *
  398        * @return a hash code value for this object.
  399        */
  400   
  401       public int hashCode() {
  402           return this.cpath.hashCode();
  403       }
  404   
  405       /**
  406        * Converts an actions String to an actions mask.
  407        *
  408        * @param action the action string.
  409        * @return the actions mask.
  410        */
  411       private static int getMask(String actions) {
  412   
  413           int mask = NONE;
  414   
  415           // Null action valid?
  416           if (actions == null) {
  417               return mask;
  418           }
  419           // Check against use of constants (used heavily within the JDK)
  420           if (actions == SecurityConstants.FILE_READ_ACTION) {
  421               return READ;
  422           } else if (actions == SecurityConstants.FILE_WRITE_ACTION) {
  423               return WRITE;
  424           } else if (actions == SecurityConstants.FILE_EXECUTE_ACTION) {
  425               return EXECUTE;
  426           } else if (actions == SecurityConstants.FILE_DELETE_ACTION) {
  427               return DELETE;
  428           }
  429   
  430           char[] a = actions.toCharArray();
  431   
  432           int i = a.length - 1;
  433           if (i < 0)
  434               return mask;
  435   
  436           while (i != -1) {
  437               char c;
  438   
  439               // skip whitespace
  440               while ((i!=-1) && ((c = a[i]) == ' ' ||
  441                                  c == '\r' ||
  442                                  c == '\n' ||
  443                                  c == '\f' ||
  444                                  c == '\t'))
  445                   i--;
  446   
  447               // check for the known strings
  448               int matchlen;
  449   
  450               if (i >= 3 && (a[i-3] == 'r' || a[i-3] == 'R') &&
  451                             (a[i-2] == 'e' || a[i-2] == 'E') &&
  452                             (a[i-1] == 'a' || a[i-1] == 'A') &&
  453                             (a[i] == 'd' || a[i] == 'D'))
  454               {
  455                   matchlen = 4;
  456                   mask |= READ;
  457   
  458               } else if (i >= 4 && (a[i-4] == 'w' || a[i-4] == 'W') &&
  459                                    (a[i-3] == 'r' || a[i-3] == 'R') &&
  460                                    (a[i-2] == 'i' || a[i-2] == 'I') &&
  461                                    (a[i-1] == 't' || a[i-1] == 'T') &&
  462                                    (a[i] == 'e' || a[i] == 'E'))
  463               {
  464                   matchlen = 5;
  465                   mask |= WRITE;
  466   
  467               } else if (i >= 6 && (a[i-6] == 'e' || a[i-6] == 'E') &&
  468                                    (a[i-5] == 'x' || a[i-5] == 'X') &&
  469                                    (a[i-4] == 'e' || a[i-4] == 'E') &&
  470                                    (a[i-3] == 'c' || a[i-3] == 'C') &&
  471                                    (a[i-2] == 'u' || a[i-2] == 'U') &&
  472                                    (a[i-1] == 't' || a[i-1] == 'T') &&
  473                                    (a[i] == 'e' || a[i] == 'E'))
  474               {
  475                   matchlen = 7;
  476                   mask |= EXECUTE;
  477   
  478               } else if (i >= 5 && (a[i-5] == 'd' || a[i-5] == 'D') &&
  479                                    (a[i-4] == 'e' || a[i-4] == 'E') &&
  480                                    (a[i-3] == 'l' || a[i-3] == 'L') &&
  481                                    (a[i-2] == 'e' || a[i-2] == 'E') &&
  482                                    (a[i-1] == 't' || a[i-1] == 'T') &&
  483                                    (a[i] == 'e' || a[i] == 'E'))
  484               {
  485                   matchlen = 6;
  486                   mask |= DELETE;
  487   
  488               } else {
  489                   // parse error
  490                   throw new IllegalArgumentException(
  491                           "invalid permission: " + actions);
  492               }
  493   
  494               // make sure we didn't just match the tail of a word
  495               // like "ackbarfaccept".  Also, skip to the comma.
  496               boolean seencomma = false;
  497               while (i >= matchlen && !seencomma) {
  498                   switch(a[i-matchlen]) {
  499                   case ',':
  500                       seencomma = true;
  501                       /*FALLTHROUGH*/
  502                   case ' ': case '\r': case '\n':
  503                   case '\f': case '\t':
  504                       break;
  505                   default:
  506                       throw new IllegalArgumentException(
  507                               "invalid permission: " + actions);
  508                   }
  509                   i--;
  510               }
  511   
  512               // point i at the location of the comma minus one (or -1).
  513               i -= matchlen;
  514           }
  515   
  516           return mask;
  517       }
  518   
  519       /**
  520        * Return the current action mask. Used by the FilePermissionCollection.
  521        *
  522        * @return the actions mask.
  523        */
  524   
  525       int getMask() {
  526           return mask;
  527       }
  528   
  529       /**
  530        * Return the canonical string representation of the actions.
  531        * Always returns present actions in the following order:
  532        * read, write, execute, delete.
  533        *
  534        * @return the canonical string representation of the actions.
  535        */
  536       private static String getActions(int mask)
  537       {
  538           StringBuilder sb = new StringBuilder();
  539           boolean comma = false;
  540   
  541           if ((mask & READ) == READ) {
  542               comma = true;
  543               sb.append("read");
  544           }
  545   
  546           if ((mask & WRITE) == WRITE) {
  547               if (comma) sb.append(',');
  548               else comma = true;
  549               sb.append("write");
  550           }
  551   
  552           if ((mask & EXECUTE) == EXECUTE) {
  553               if (comma) sb.append(',');
  554               else comma = true;
  555               sb.append("execute");
  556           }
  557   
  558           if ((mask & DELETE) == DELETE) {
  559               if (comma) sb.append(',');
  560               else comma = true;
  561               sb.append("delete");
  562           }
  563   
  564           return sb.toString();
  565       }
  566   
  567       /**
  568        * Returns the "canonical string representation" of the actions.
  569        * That is, this method always returns present actions in the following order:
  570        * read, write, execute, delete. For example, if this FilePermission object
  571        * allows both write and read actions, a call to <code>getActions</code>
  572        * will return the string "read,write".
  573        *
  574        * @return the canonical string representation of the actions.
  575        */
  576       public String getActions()
  577       {
  578           if (actions == null)
  579               actions = getActions(this.mask);
  580   
  581           return actions;
  582       }
  583   
  584   
  585       /**
  586        * Returns a new PermissionCollection object for storing FilePermission
  587        * objects.
  588        * <p>
  589        * FilePermission objects must be stored in a manner that allows them
  590        * to be inserted into the collection in any order, but that also enables the
  591        * PermissionCollection <code>implies</code>
  592        * method to be implemented in an efficient (and consistent) manner.
  593        *
  594        * <p>For example, if you have two FilePermissions:
  595        * <OL>
  596        * <LI>  <code>"/tmp/-", "read"</code>
  597        * <LI>  <code>"/tmp/scratch/foo", "write"</code>
  598        * </OL>
  599        *
  600        * <p>and you are calling the <code>implies</code> method with the FilePermission:
  601        *
  602        * <pre>
  603        *   "/tmp/scratch/foo", "read,write",
  604        * </pre>
  605        *
  606        * then the <code>implies</code> function must
  607        * take into account both the "/tmp/-" and "/tmp/scratch/foo"
  608        * permissions, so the effective permission is "read,write",
  609        * and <code>implies</code> returns true. The "implies" semantics for
  610        * FilePermissions are handled properly by the PermissionCollection object
  611        * returned by this <code>newPermissionCollection</code> method.
  612        *
  613        * @return a new PermissionCollection object suitable for storing
  614        * FilePermissions.
  615        */
  616   
  617       public PermissionCollection newPermissionCollection() {
  618           return new FilePermissionCollection();
  619       }
  620   
  621       /**
  622        * WriteObject is called to save the state of the FilePermission
  623        * to a stream. The actions are serialized, and the superclass
  624        * takes care of the name.
  625        */
  626       private void writeObject(ObjectOutputStream s)
  627           throws IOException
  628       {
  629           // Write out the actions. The superclass takes care of the name
  630           // call getActions to make sure actions field is initialized
  631           if (actions == null)
  632               getActions();
  633           s.defaultWriteObject();
  634       }
  635   
  636       /**
  637        * readObject is called to restore the state of the FilePermission from
  638        * a stream.
  639        */
  640       private void readObject(ObjectInputStream s)
  641            throws IOException, ClassNotFoundException
  642       {
  643           // Read in the actions, then restore everything else by calling init.
  644           s.defaultReadObject();
  645           init(getMask(actions));
  646       }
  647   }
  648   
  649   /**
  650    * A FilePermissionCollection stores a set of FilePermission permissions.
  651    * FilePermission objects
  652    * must be stored in a manner that allows them to be inserted in any
  653    * order, but enable the implies function to evaluate the implies
  654    * method.
  655    * For example, if you have two FilePermissions:
  656    * <OL>
  657    * <LI> "/tmp/-", "read"
  658    * <LI> "/tmp/scratch/foo", "write"
  659    * </OL>
  660    * And you are calling the implies function with the FilePermission:
  661    * "/tmp/scratch/foo", "read,write", then the implies function must
  662    * take into account both the /tmp/- and /tmp/scratch/foo
  663    * permissions, so the effective permission is "read,write".
  664    *
  665    * @see java.security.Permission
  666    * @see java.security.Permissions
  667    * @see java.security.PermissionCollection
  668    *
  669    *
  670    * @author Marianne Mueller
  671    * @author Roland Schemers
  672    *
  673    * @serial include
  674    *
  675    */
  676   
  677   final class FilePermissionCollection extends PermissionCollection
  678   implements Serializable {
  679   
  680       // Not serialized; see serialization section at end of class
  681       private transient List perms;
  682   
  683       /**
  684        * Create an empty FilePermissions object.
  685        *
  686        */
  687   
  688       public FilePermissionCollection() {
  689           perms = new ArrayList();
  690       }
  691   
  692       /**
  693        * Adds a permission to the FilePermissions. The key for the hash is
  694        * permission.path.
  695        *
  696        * @param permission the Permission object to add.
  697        *
  698        * @exception IllegalArgumentException - if the permission is not a
  699        *                                       FilePermission
  700        *
  701        * @exception SecurityException - if this FilePermissionCollection object
  702        *                                has been marked readonly
  703        */
  704   
  705       public void add(Permission permission)
  706       {
  707           if (! (permission instanceof FilePermission))
  708               throw new IllegalArgumentException("invalid permission: "+
  709                                                  permission);
  710           if (isReadOnly())
  711               throw new SecurityException(
  712                   "attempt to add a Permission to a readonly PermissionCollection");
  713   
  714           synchronized (this) {
  715               perms.add(permission);
  716           }
  717       }
  718   
  719       /**
  720        * Check and see if this set of permissions implies the permissions
  721        * expressed in "permission".
  722        *
  723        * @param p the Permission object to compare
  724        *
  725        * @return true if "permission" is a proper subset of a permission in
  726        * the set, false if not.
  727        */
  728   
  729       public boolean implies(Permission permission)
  730       {
  731           if (! (permission instanceof FilePermission))
  732                   return false;
  733   
  734           FilePermission fp = (FilePermission) permission;
  735   
  736           int desired = fp.getMask();
  737           int effective = 0;
  738           int needed = desired;
  739   
  740           synchronized (this) {
  741               int len = perms.size();
  742               for (int i = 0; i < len; i++) {
  743                   FilePermission x = (FilePermission) perms.get(i);
  744                   if (((needed & x.getMask()) != 0) && x.impliesIgnoreMask(fp)) {
  745                       effective |=  x.getMask();
  746                       if ((effective & desired) == desired)
  747                           return true;
  748                       needed = (desired ^ effective);
  749                   }
  750               }
  751           }
  752           return false;
  753       }
  754   
  755       /**
  756        * Returns an enumeration of all the FilePermission objects in the
  757        * container.
  758        *
  759        * @return an enumeration of all the FilePermission objects.
  760        */
  761   
  762       public Enumeration elements() {
  763           // Convert Iterator into Enumeration
  764           synchronized (this) {
  765               return Collections.enumeration(perms);
  766           }
  767       }
  768   
  769       private static final long serialVersionUID = 2202956749081564585L;
  770   
  771       // Need to maintain serialization interoperability with earlier releases,
  772       // which had the serializable field:
  773       //    private Vector permissions;
  774   
  775       /**
  776        * @serialField permissions java.util.Vector
  777        *     A list of FilePermission objects.
  778        */
  779       private static final ObjectStreamField[] serialPersistentFields = {
  780           new ObjectStreamField("permissions", Vector.class),
  781       };
  782   
  783       /**
  784        * @serialData "permissions" field (a Vector containing the FilePermissions).
  785        */
  786       /*
  787        * Writes the contents of the perms field out as a Vector for
  788        * serialization compatibility with earlier releases.
  789        */
  790       private void writeObject(ObjectOutputStream out) throws IOException {
  791           // Don't call out.defaultWriteObject()
  792   
  793           // Write out Vector
  794           Vector permissions = new Vector(perms.size());
  795           synchronized (this) {
  796               permissions.addAll(perms);
  797           }
  798   
  799           ObjectOutputStream.PutField pfields = out.putFields();
  800           pfields.put("permissions", permissions);
  801           out.writeFields();
  802       }
  803   
  804       /*
  805        * Reads in a Vector of FilePermissions and saves them in the perms field.
  806        */
  807       private void readObject(ObjectInputStream in) throws IOException,
  808       ClassNotFoundException {
  809           // Don't call defaultReadObject()
  810   
  811           // Read in serialized fields
  812           ObjectInputStream.GetField gfields = in.readFields();
  813   
  814           // Get the one we want
  815           Vector permissions = (Vector)gfields.get("permissions", null);
  816           perms = new ArrayList(permissions.size());
  817           perms.addAll(permissions);
  818       }
  819   }

Save This Page
Home » openjdk-7 » java » io » [javadoc | source]