Source for java.io.FilePermission

   1: /* FilePermission.java --
   2:    Copyright (C) 1998, 2000, 2003, 2004, 2005  Free Software Foundation, Inc.
   3: 
   4: This file is part of GNU Classpath.
   5: 
   6: GNU Classpath is free software; you can redistribute it and/or modify
   7: it under the terms of the GNU General Public License as published by
   8: the Free Software Foundation; either version 2, or (at your option)
   9: any later version.
  10: 
  11: GNU Classpath is distributed in the hope that it will be useful, but
  12: WITHOUT ANY WARRANTY; without even the implied warranty of
  13: MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14: General Public License for more details.
  15: 
  16: You should have received a copy of the GNU General Public License
  17: along with GNU Classpath; see the file COPYING.  If not, write to the
  18: Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA
  19: 02110-1301 USA.
  20: 
  21: Linking this library statically or dynamically with other modules is
  22: making a combined work based on this library.  Thus, the terms and
  23: conditions of the GNU General Public License cover the whole
  24: combination.
  25: 
  26: As a special exception, the copyright holders of this library give you
  27: permission to link this library with independent modules to produce an
  28: executable, regardless of the license terms of these independent
  29: modules, and to copy and distribute the resulting executable under
  30: terms of your choice, provided that you also meet, for each linked
  31: independent module, the terms and conditions of the license of that
  32: module.  An independent module is a module which is not derived from
  33: or based on this library.  If you modify this library, you may extend
  34: this exception to your version of the library, but you are not
  35: obligated to do so.  If you do not wish to do so, delete this
  36: exception statement from your version. */
  37: 
  38: 
  39: package java.io;
  40: 
  41: import java.security.Permission;
  42: 
  43: public final class FilePermission extends Permission implements Serializable
  44: {
  45:   private static final long serialVersionUID = 7930732926638008763L;
  46: 
  47:   private static final String CURRENT_DIRECTORY = 
  48:     System.getProperty("user.dir");
  49: 
  50:   private static final String ALL_FILES = "<<ALL FILES>>";
  51: 
  52:   private boolean readPerm = false;
  53:   private boolean writePerm = false;
  54:   private boolean executePerm = false;
  55:   private boolean deletePerm = false;
  56:   private final String actionsString;
  57: 
  58:   // Checks and caches the actions
  59:   private void checkPerms() throws IllegalArgumentException
  60:   {
  61:     String action;
  62:     int i = actionsString.indexOf(',');
  63:     int startI = 0;
  64:     while (i != -1) 
  65:       {
  66:         action = actionsString.substring(startI, i).trim().toLowerCase();
  67:         if (action.equals("read"))
  68:           readPerm = true;
  69:         else if (action.equals("write"))
  70:           writePerm = true;
  71:         else if (action.equals("execute"))
  72:           executePerm = true;
  73:         else if (action.equals("delete"))
  74:           deletePerm = true;
  75:     else
  76:       throw new IllegalArgumentException("Unknown action: " + action);
  77:       
  78:         startI = i + 1;
  79:         i = actionsString.indexOf(',', startI);
  80:       }
  81: 
  82:     action = actionsString.substring(startI).trim().toLowerCase();
  83:     if (action.equals("read"))
  84:       readPerm = true;
  85:     else if (action.equals("write"))
  86:       writePerm = true;
  87:     else if (action.equals("execute"))
  88:       executePerm = true;
  89:     else if (action.equals("delete"))
  90:       deletePerm = true;
  91:     else
  92:       throw new IllegalArgumentException("Unknown action: " + action);
  93:   }
  94: 
  95:   /**
  96:    * Create a new FilePermission.
  97:    *
  98:    * @param pathExpression an expression specifying the paths this
  99:    *        permission represents.
 100:    * @param actionsString a comma-separated list of the actions this
 101:    *        permission represents. The actions must be "read", "write",
 102:    *        "execute" and/or "delete".
 103:    */
 104:   public FilePermission(String pathExpression, String actionsString) 
 105:   {
 106:     // FIXME: what to do when the file string is malformed?
 107:     super(pathExpression);
 108:     if (pathExpression == null)
 109:       throw new NullPointerException("pathExpression");
 110:     if (actionsString == null)
 111:       throw new IllegalArgumentException("actionsString");
 112:     this.actionsString = actionsString;
 113:     checkPerms();
 114:   }
 115:   
 116:   /**
 117:    * Get the actions this FilePermission supports.
 118:    * @return the String representing the actions this FilePermission supports.
 119:    */
 120:   public String getActions() 
 121:   {
 122:     return actionsString;
 123:   }
 124: 
 125:   /**
 126:    * Get the hash code for this Object.<P>
 127:    * FilePermission's hash code is calculated as the exclusive or of the 
 128:    * target
 129:    * String's hash code and the action String's hash code.
 130:    * @specnote Sun did not specify how to calculate the hash code; 
 131:    * I made this up.
 132:    * @return the hash code for this Object.
 133:    */
 134:   public int hashCode() 
 135:   {
 136:     return getName().hashCode() ^ actionsString.hashCode();
 137:   }
 138: 
 139:   /**
 140:    * Check two FilePermissions for semantic equality.
 141:    * Two FilePermissions are exactly equivalent if they have identical path
 142:    * expressions and have exactly the same access permissions.
 143:    * @param o the Object to compare to.
 144:    * @return whether the Objects are semantically equivalent.
 145:    */
 146:   public boolean equals(Object o) 
 147:   {
 148:     if (! (o instanceof FilePermission))
 149:       return false;
 150:     FilePermission p = (FilePermission) o;
 151: 
 152:     String f1 = getName();
 153:     String f2 = p.getName();
 154: 
 155:     // Compare names, taking into account if they refer to a directory
 156:     // and one has a separator and the other does not.
 157:     if (f1.length() > 0 && f1.charAt(f1.length() - 1) == File.separatorChar) 
 158:       {
 159:         if (f2.length() > 0
 160:         && f2.charAt(f2.length() - 1) == File.separatorChar) 
 161:           {
 162:         if (! f2.equals(f1))
 163:           return false;
 164:           }
 165:         else
 166:           {
 167:         if (! f2.equals(f1.substring(0, f1.length() - 1)))
 168:           return false;
 169:           }
 170:       }
 171:     else
 172:       {
 173:         if (f2.length() > 0
 174:         && f2.charAt(f2.length() - 1) == File.separatorChar)
 175:           {
 176:         if (! f1.equals(f2.substring(0, f2.length() - 1)))
 177:           return false;
 178:           }
 179:         else
 180:           {
 181:         if (! f1.equals(f2))
 182:           return false;
 183:           }
 184:       }
 185:     return (readPerm == p.readPerm
 186:         && writePerm == p.writePerm
 187:         && executePerm == p.executePerm
 188:         && deletePerm == p.deletePerm);
 189:   }
 190: 
 191:   /**
 192:    * Check to see if this permission implies another.
 193:    * Permission A implies permission B if these things are all true:
 194:    * <OL>
 195:    * <LI>A and B are both FilePermissions.</LI>
 196:    * <LI>All possible files in B are included in A 
 197:    * (possibly more are in A).</LI>
 198:    * <LI>All actions B supports, A also supports.</LI>
 199:    * </OL>
 200:    * @param p the Permission to compare against.
 201:    * @return whether this Permission implies p
 202:    */
 203:   public boolean implies(Permission p) 
 204:   {
 205:     if (! (p instanceof FilePermission))
 206:       return false;
 207: 
 208:     String f1 = getName();
 209: 
 210:     if (f1.equals(ALL_FILES))
 211:       return true;
 212:     
 213:     FilePermission fp = (FilePermission) p;
 214:     String f2 = fp.getName();
 215: 
 216:     if (f1.charAt(0) != File.separatorChar)
 217:       f1 = CURRENT_DIRECTORY + f1;
 218:     if (f2.charAt(0) != File.separatorChar)
 219:       f2 = CURRENT_DIRECTORY + f2;
 220: 
 221:     String sub1;
 222: 
 223:     switch (f1.charAt(f1.length() - 1))
 224:       {
 225:       case '*':
 226:     sub1 = f1.substring(0, f1.length() - 1); // chop off "*"
 227:     if (f2.length() <= sub1.length())
 228:       {
 229:         // If it's smaller, there is no way it could be part of
 230:         // this directory.  If it's the same (or length - 1), it
 231:         // could be the same directory but specifies access to
 232:         // the directory rather than the files in it.
 233:         return false;
 234:       } 
 235:     else if (f2.charAt(sub1.length() - 1) == File.separatorChar)
 236:       {
 237:         // Make sure the part before the "/" is the same.
 238:         if (! f2.substring(0, sub1.length()).equals(sub1))
 239:           return false;
 240:         // Make sure there are no subdirectories specified
 241:         // underneath this one.
 242:         if (f2.substring(sub1.length() + 1).indexOf(File.separatorChar)
 243:         != -1)
 244:           return false;
 245:       }
 246:     else
 247:       {
 248:         // Obviously not equal: f2 is either not a directory or
 249:         // is not the same directory (its name continues further
 250:         // than we want).
 251:         return false;
 252:       }
 253:     break;
 254:       case '-':
 255:     // Chop off "/-".
 256:     sub1 = f1.substring(0, f1.length() - 2);
 257:     if (f2.length() < sub1.length())
 258:       {
 259:         // If it's smaller, there is no way it could be part of
 260:         // this directory.
 261:         return false;
 262:       }
 263:     else if (f2.length() > sub1.length()
 264:          && f2.charAt(sub1.length()) != File.separatorChar)
 265:       return false;
 266:     else if (! f2.substring(0, sub1.length()).equals(sub1))
 267:       return false;
 268:     break;
 269: 
 270:       default:
 271:     if (f2.charAt(f2.length() - 1) == File.separatorChar)
 272:       {
 273:         if (! f1.equals(f2.substring(0, f2.length() - 1)))
 274:           return false;
 275:       }
 276:     else if (!f1.equals(f2))
 277:       return false;
 278:     break;
 279:       }
 280: 
 281:     if (fp.readPerm && ! readPerm)
 282:       return false;
 283:     if (fp.writePerm && ! writePerm)
 284:       return false;
 285:     if (fp.executePerm && ! executePerm)
 286:       return false;
 287:     if (fp.deletePerm && ! deletePerm)
 288:       return false;
 289:     
 290:     return true;
 291:   }
 292: }