Source for java.util.PropertyPermission

   1: /* PropertyPermission.java -- permission to get and set System properties
   2:    Copyright (C) 1999, 2000, 2002, 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.util;
  40: 
  41: import java.io.IOException;
  42: import java.io.ObjectInputStream;
  43: import java.io.ObjectOutputStream;
  44: import java.io.ObjectStreamField;
  45: import java.security.BasicPermission;
  46: import java.security.Permission;
  47: import java.security.PermissionCollection;
  48: 
  49: /**
  50:  * This class represents the permission to access and modify a property.<br>
  51:  *
  52:  * The name is the name of the property, e.g. xxx.  You can also
  53:  * use an asterisk "*" as described in BasicPermission.<br>
  54:  *
  55:  * The action string is a comma-separated list of keywords.  There are
  56:  * two possible actions:
  57:  * <dl>
  58:  * <dt>read</dt>
  59:  * <dd>Allows to read the property via <code>System.getProperty</code>.</dd>
  60:  * <dt>write</dt>
  61:  * <dd>Allows to write the property via <code>System.setProperty</code>.</dd>
  62:  * </dl>
  63:  *
  64:  * The action string is case insensitive (it is converted to lower case).
  65:  *
  66:  * @see Permission
  67:  * @see BasicPermission
  68:  * @see SecurityManager
  69:  * @author Jochen Hoenicke
  70:  * @since 1.2
  71:  * @status updated to 1.4
  72:  */
  73: public final class PropertyPermission extends BasicPermission
  74: {
  75:   /**
  76:    * PropertyPermission uses a more efficient representation than the
  77:    * serialized form; this documents the difference.
  78:    *
  79:    * @serialField action String the action string
  80:    */
  81:   private static final ObjectStreamField[] serialPersistentFields =
  82:   {
  83:     new ObjectStreamField("action", String.class)
  84:   };
  85: 
  86:   /**
  87:    * Compatible with JDK 1.2+.
  88:    */
  89:   private static final long serialVersionUID = 885438825399942851L;
  90: 
  91:   /** Permission to read. */
  92:   private static final int READ = 1;
  93:   /** Permission to write. */
  94:   private static final int WRITE = 2;
  95: 
  96:   /** The set of actions permitted. */
  97:   // Package visible for use by PropertyPermissionCollection.
  98:   transient int actions;
  99: 
 100:   /**
 101:    * The String forms of the actions permitted.
 102:    */
 103:   private static final String actionStrings[] =
 104:   {
 105:     "", "read", "write", "read,write"
 106:   };
 107: 
 108:   /**
 109:    * Constructs a PropertyPermission with the specified property.  Possible
 110:    * actions are read and write, comma-separated and case-insensitive.
 111:    *
 112:    * @param name the name of the property
 113:    * @param actions the action string
 114:    * @throws NullPointerException if name is null
 115:    * @throws IllegalArgumentException if name string contains an
 116:    *         illegal wildcard or actions string contains an illegal action
 117:    *         (this includes a null actions string)
 118:    */
 119:   public PropertyPermission(String name, String actions)
 120:   {
 121:     super(name);
 122:     if (actions == null)
 123:       throw new IllegalArgumentException();
 124:     setActions(actions);
 125:   }
 126: 
 127:   /**
 128:    * Parse the action string and convert actions from external to internal
 129:    * form.  This will set the internal actions field.
 130:    *
 131:    * @param str the action string
 132:    * @throws IllegalArgumentException if actions string contains an
 133:    *         illegal action
 134:    */
 135:   private void setActions(String str)
 136:   {
 137:     // Initialising the class java.util.Locale ...
 138:     //    tries to initialise the Locale.defaultLocale static
 139:     //    which calls System.getProperty, 
 140:     //    which calls SecurityManager.checkPropertiesAccess,
 141:     //    which creates a PropertyPermission with action "read,write",
 142:     //    which calls setActions("read,write").
 143:     // If we now were to call toLowerCase on 'str',
 144:     //    this would call Locale.getDefault() which returns null
 145:     //       because Locale.defaultLocale hasn't been set yet
 146:     //    then toLowerCase will fail with a null pointer exception.
 147:     // 
 148:     // The solution is to take a punt on 'str' being lower case, and
 149:     // test accordingly.  If that fails, we convert 'str' to lower case 
 150:     // and try the tests again.
 151:     if ("read".equals(str))
 152:       actions = READ;
 153:     else if ("write".equals(str))
 154:       actions = WRITE;
 155:     else if ("read,write".equals(str) || "write,read".equals(str))
 156:       actions = READ | WRITE;
 157:     else
 158:       {
 159:     String lstr = str.toLowerCase();
 160:     if ("read".equals(lstr))
 161:        actions = READ;
 162:     else if ("write".equals(lstr))
 163:       actions = WRITE;
 164:     else if ("read,write".equals(lstr) || "write,read".equals(lstr))
 165:       actions = READ | WRITE;
 166:     else
 167:       throw new IllegalArgumentException("illegal action " + str);
 168:       }
 169:   }
 170: 
 171:   /**
 172:    * Reads an object from the stream. This converts the external to the
 173:    * internal representation.
 174:    *
 175:    * @param s the stream to read from
 176:    * @throws IOException if the stream fails
 177:    * @throws ClassNotFoundException if reserialization fails
 178:    */
 179:   private void readObject(ObjectInputStream s)
 180:     throws IOException, ClassNotFoundException
 181:   {
 182:     ObjectInputStream.GetField fields = s.readFields();
 183:     setActions((String) fields.get("actions", null));
 184:   }
 185: 
 186:   /**
 187:    * Writes an object to the stream. This converts the internal to the
 188:    * external representation.
 189:    *
 190:    * @param s the stram to write to
 191:    * @throws IOException if the stream fails
 192:    */
 193:   private void writeObject(ObjectOutputStream s) throws IOException
 194:   {
 195:     ObjectOutputStream.PutField fields = s.putFields();
 196:     fields.put("actions", getActions());
 197:     s.writeFields();
 198:   }
 199: 
 200:   /**
 201:    * Check if this permission implies p.  This returns true iff all of
 202:    * the following conditions are true:
 203:    * <ul>
 204:    * <li> p is a PropertyPermission </li>
 205:    * <li> this.getName() implies p.getName(),
 206:    *  e.g. <code>java.*</code> implies <code>java.home</code> </li>
 207:    * <li> this.getActions is a subset of p.getActions </li>
 208:    * </ul>
 209:    *
 210:    * @param p the permission to check
 211:    * @return true if this permission implies p
 212:    */
 213:   public boolean implies(Permission p)
 214:   {
 215:     // BasicPermission checks for name and type.
 216:     if (super.implies(p))
 217:       {
 218:         // We have to check the actions.
 219:         PropertyPermission pp = (PropertyPermission) p;
 220:         return (pp.actions & ~actions) == 0;
 221:       }
 222:     return false;
 223:   }
 224: 
 225:   /**
 226:    * Check to see whether this object is the same as another
 227:    * PropertyPermission object; this is true if it has the same name and
 228:    * actions.
 229:    *
 230:    * @param obj the other object
 231:    * @return true if the two are equivalent
 232:    */
 233:   public boolean equals(Object obj)
 234:   {
 235:     return super.equals(obj) && actions == ((PropertyPermission) obj).actions;
 236:   }
 237: 
 238:   /**
 239:    * Returns the hash code for this permission.  It is equivalent to
 240:    * <code>getName().hashCode()</code>.
 241:    *
 242:    * @return the hash code
 243:    */
 244:   public int hashCode()
 245:   {
 246:     return super.hashCode();
 247:   }
 248: 
 249:   /**
 250:    * Returns the action string.  Note that this may differ from the string
 251:    * given at the constructor:  The actions are converted to lowercase and
 252:    * may be reordered.
 253:    *
 254:    * @return one of "read", "write", or "read,write"
 255:    */
 256:   public String getActions()
 257:   {
 258:     return actionStrings[actions];
 259:   }
 260: 
 261:   /**
 262:    * Returns a permission collection suitable to take
 263:    * PropertyPermission objects.
 264:    *
 265:    * @return a new empty PermissionCollection
 266:    */
 267:   public PermissionCollection newPermissionCollection()
 268:   {
 269:     return new PropertyPermissionCollection();
 270:   }
 271: }