001 /* BasicPermission.java -- implements a simple named permission 002 Copyright (C) 1998, 1999, 2002, 2003, 2004, 2005, 2006 003 Free Software Foundation, Inc. 004 005 This file is part of GNU Classpath. 006 007 GNU Classpath is free software; you can redistribute it and/or modify 008 it under the terms of the GNU General Public License as published by 009 the Free Software Foundation; either version 2, or (at your option) 010 any later version. 011 012 GNU Classpath is distributed in the hope that it will be useful, but 013 WITHOUT ANY WARRANTY; without even the implied warranty of 014 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 015 General Public License for more details. 016 017 You should have received a copy of the GNU General Public License 018 along with GNU Classpath; see the file COPYING. If not, write to the 019 Free Software Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 020 02110-1301 USA. 021 022 Linking this library statically or dynamically with other modules is 023 making a combined work based on this library. Thus, the terms and 024 conditions of the GNU General Public License cover the whole 025 combination. 026 027 As a special exception, the copyright holders of this library give you 028 permission to link this library with independent modules to produce an 029 executable, regardless of the license terms of these independent 030 modules, and to copy and distribute the resulting executable under 031 terms of your choice, provided that you also meet, for each linked 032 independent module, the terms and conditions of the license of that 033 module. An independent module is a module which is not derived from 034 or based on this library. If you modify this library, you may extend 035 this exception to your version of the library, but you are not 036 obligated to do so. If you do not wish to do so, delete this 037 exception statement from your version. */ 038 039 040 package java.security; 041 042 import java.io.Serializable; 043 import java.util.Enumeration; 044 import java.util.Hashtable; 045 046 /** 047 * This class implements a simple model for named permissions without an 048 * associated action list. That is, either the named permission is granted 049 * or it is not. 050 * 051 * <p>It also supports trailing wildcards to allow the easy granting of 052 * permissions in a hierarchical fashion. (For example, the name "org.gnu.*" 053 * might grant all permissions under the "org.gnu" permissions hierarchy). 054 * The only valid wildcard character is a '*' which matches anything. It 055 * must be the rightmost element in the permission name and must follow a 056 * '.' or else the Permission name must consist of only a '*'. Any other 057 * occurrence of a '*' is not valid. 058 * 059 * <p>This class ignores the action list. Subclasses can choose to implement 060 * actions on top of this class if desired. 061 * 062 * @author Aaron M. Renn (arenn@urbanophile.com) 063 * @author Eric Blake (ebb9@email.byu.edu) 064 * @see Permission 065 * @see Permissions 066 * @see PermissionCollection 067 * @see RuntimePermission 068 * @see SecurityPermission 069 * @see PropertyPermission 070 * @see AWTPermission 071 * @see NetPermission 072 * @see SecurityManager 073 * @since 1.1 074 * @status updated to 1.4 075 */ 076 public abstract class BasicPermission extends Permission 077 implements Serializable 078 { 079 /** 080 * Compatible with JDK 1.1+. 081 */ 082 private static final long serialVersionUID = 6279438298436773498L; 083 084 /** 085 * Create a new instance with the specified permission name. If the 086 * name is empty an exception is thrown. 087 * 088 * @param name the name of this permission 089 * @throws NullPointerException if name is null 090 * @throws IllegalArgumentException if name is invalid 091 */ 092 public BasicPermission(String name) 093 { 094 super(name); 095 096 // This routine used to check for illegal wildcards, but no such 097 // requirement exists in the specification and Sun's runtime 098 // doesn't appear to do it. 099 100 if (name.equals("")) 101 throw new IllegalArgumentException("Empty name"); 102 } 103 104 /** 105 * Create a new instance with the specified permission name. If the name 106 * is empty, or contains an illegal wildcard character, an exception is 107 * thrown. The actions parameter is ignored. 108 * 109 * @param name the name of this permission 110 * @param actions ignored 111 * @throws NullPointerException if name is null 112 * @throws IllegalArgumentException if name is invalid 113 */ 114 public BasicPermission(String name, String actions) 115 { 116 this(name); 117 } 118 119 /** 120 * This method tests to see if the specified permission is implied by this 121 * permission. This will be true if the following conditions are met:<ul> 122 * <li>The specified object is an instance of the same class as this 123 * object.</li> 124 * <li>The name of the specified permission is implied by this permission's 125 * name based on wildcard matching. For example, "a.*" implies "a.b".</li> 126 * </ul> 127 * 128 * @param perm the <code>Permission</code> object to test against 129 * @return true if the specified permission is implied 130 */ 131 public boolean implies(Permission perm) 132 { 133 if (! getClass().isInstance(perm)) 134 return false; 135 136 String otherName = perm.getName(); 137 String name = getName(); 138 139 if (name.equals(otherName)) 140 return true; 141 142 int last = name.length() - 1; 143 return name.charAt(last) == '*' 144 && otherName.startsWith(name.substring(0, last)); 145 } 146 147 /** 148 * This method tests to see if this object is equal to the specified 149 * <code>Object</code>. This will be true if and only if the specified 150 * object meets the following conditions:<ul> 151 * <li>It is an instance of the same class as this.</li> 152 * <li>It has the same name as this permission.</li> 153 * </ul> 154 * 155 * @param obj the <code>Object</code> to test for equality 156 * @return true if obj is semantically equal to this 157 */ 158 public boolean equals(Object obj) 159 { 160 return getClass().isInstance(obj) 161 && getName().equals(((BasicPermission) obj).getName()); 162 } 163 164 /** 165 * This method returns a hash code for this permission object. The hash 166 * code returned is the value returned by calling the <code>hashCode</code> 167 * method on the <code>String</code> that is the name of this permission. 168 * 169 * @return a hash value for this object 170 */ 171 public int hashCode() 172 { 173 return getName().hashCode(); 174 } 175 176 /** 177 * This method returns a list of the actions associated with this 178 * permission. This method always returns the empty string ("") since 179 * this class ignores actions. 180 * 181 * @return the action list 182 */ 183 public String getActions() 184 { 185 return ""; 186 } 187 188 /** 189 * This method returns an instance of <code>PermissionCollection</code> 190 * suitable for storing <code>BasicPermission</code> objects. The 191 * collection returned can only store objects of the same type as this. 192 * Subclasses which use actions must override this method; but a class with 193 * no actions will work fine with this. 194 * 195 * @return a new empty <code>PermissionCollection</code> object 196 */ 197 public PermissionCollection newPermissionCollection() 198 { 199 return new BasicPermissionCollection(getClass()); 200 } 201 202 /** 203 * Implements AllPermission.newPermissionCollection, and obeys serialization 204 * of JDK. 205 * 206 * @author Eric Blake (ebb9@email.byu.edu) 207 */ 208 private static final class BasicPermissionCollection extends PermissionCollection 209 { 210 /** 211 * Compatible with JDK 1.1+. 212 */ 213 private static final long serialVersionUID = 739301742472979399L; 214 215 /** 216 * The permissions in the collection. 217 * 218 * @serial a hash mapping name to permissions, all of type permClass 219 */ 220 private final Hashtable permissions = new Hashtable(); 221 222 /** 223 * If "*" is in the collection. 224 * 225 * @serial true if a permission named "*" is in the collection 226 */ 227 private boolean all_allowed; 228 229 /** 230 * The runtime class which all entries in the table must belong to. 231 * 232 * @serial the limiting subclass of this collection 233 */ 234 private final Class permClass; 235 236 /** 237 * Construct a collection over the given runtime class. 238 * 239 * @param c the class 240 */ 241 BasicPermissionCollection(Class c) 242 { 243 permClass = c; 244 } 245 246 /** 247 * Add a Permission. It must be of the same type as the permission which 248 * created this collection. 249 * 250 * @param perm the permission to add 251 * @throws IllegalArgumentException if perm is not the correct type 252 * @throws SecurityException if the collection is read-only 253 */ 254 public void add(Permission perm) 255 { 256 if (isReadOnly()) 257 throw new SecurityException("readonly"); 258 if (! permClass.isInstance(perm)) 259 throw new IllegalArgumentException("Expecting instance of " + permClass); 260 BasicPermission bp = (BasicPermission) perm; 261 String name = bp.getName(); 262 if (name.equals("*")) 263 all_allowed = true; 264 permissions.put(name, bp); 265 } 266 267 /** 268 * Returns true if this collection implies the given permission. 269 * 270 * @param permission the permission to check 271 * @return true if it is implied by this 272 */ 273 public boolean implies(Permission permission) 274 { 275 if (! permClass.isInstance(permission)) 276 return false; 277 if (all_allowed) 278 return true; 279 BasicPermission toImply = (BasicPermission) permission; 280 String name = toImply.getName(); 281 if (name.equals("*")) 282 return false; 283 int prefixLength = name.length(); 284 if (name.endsWith("*")) 285 prefixLength -= 2; 286 287 while (true) 288 { 289 if (permissions.get(name) != null) 290 return true; 291 prefixLength = name.lastIndexOf('.', prefixLength); 292 if (prefixLength < 0) 293 return false; 294 name = name.substring(0, prefixLength + 1) + '*'; 295 } 296 } 297 298 /** 299 * Enumerate over the collection. 300 * 301 * @return an enumeration of the collection contents 302 */ 303 public Enumeration elements() 304 { 305 return permissions.elements(); 306 } 307 } // class BasicPermissionCollection 308 } // class BasicPermission