1. /*
  2. * @(#)BasicPermission.java 1.26 00/02/02
  3. *
  4. * Copyright 1997-2000 Sun Microsystems, Inc. All Rights Reserved.
  5. *
  6. * This software is the proprietary information of Sun Microsystems, Inc.
  7. * Use is subject to license terms.
  8. *
  9. */
  10. package java.security;
  11. import java.security.*;
  12. import java.util.Enumeration;
  13. import java.util.Hashtable;
  14. import java.util.StringTokenizer;
  15. import java.io.IOException;
  16. /**
  17. * The BasicPermission class extends the Permission class, and
  18. * can be used as the base class for permissions that want to
  19. * follow the same naming convention as BasicPermission.
  20. * <P>
  21. * The name for a BasicPermission is the name of the given permission
  22. * (for example, "exit",
  23. * "setFactory", "print.queueJob", etc). The naming
  24. * convention follows the hierarchical property naming convention.
  25. * An asterisk
  26. * may appear at the end of the name, following a ".", or by itself, to
  27. * signify a wildcard match. For example: "java.*" or "*" is valid,
  28. * "*java" or "a*b" is not valid.
  29. * <P>
  30. * The action string (inherited from Permission) is unused.
  31. * Thus, BasicPermission is commonly used as the base class for
  32. * "named" permissions
  33. * (ones that contain a name but no actions list; you either have the
  34. * named permission or you don't.)
  35. * Subclasses may implement actions on top of BasicPermission,
  36. * if desired.
  37. * <p>
  38. * <P>
  39. * @see java.security.Permission
  40. * @see java.security.Permissions
  41. * @see java.security.PermissionCollection
  42. * @see java.lang.RuntimePermission
  43. * @see java.security.SecurityPermission
  44. * @see java.util.PropertyPermission
  45. * @see java.awt.AWTPermission
  46. * @see java.net.NetPermission
  47. * @see java.lang.SecurityManager
  48. *
  49. * @version 1.26 00/02/02
  50. *
  51. * @author Marianne Mueller
  52. * @author Roland Schemers
  53. *
  54. * @serial exclude
  55. */
  56. public abstract class BasicPermission extends Permission
  57. implements java.io.Serializable
  58. {
  59. // does this permission have a wildcard at the end?
  60. private transient boolean wildcard;
  61. // the name without the wildcard on the end
  62. private transient String path;
  63. /**
  64. * initialize a BasicPermission object. Common to all constructors.
  65. *
  66. */
  67. private void init(String name)
  68. {
  69. if (name == null)
  70. throw new NullPointerException("name can't be null");
  71. if (name.equals("")) {
  72. throw new IllegalArgumentException("name can't be empty");
  73. }
  74. if (name.endsWith(".*") || name.equals("*")) {
  75. wildcard = true;
  76. if (name.length() == 1) {
  77. path = "";
  78. } else {
  79. path = name.substring(0, name.length()-1);
  80. }
  81. } else {
  82. path = name;
  83. }
  84. }
  85. /**
  86. * Creates a new BasicPermission with the specified name.
  87. * Name is the symbolic name of the permission, such as
  88. * "setFactory",
  89. * "print.queueJob", or "topLevelWindow", etc. An asterisk
  90. * may appear at the end of the name, following a ".", or by itself, to
  91. * signify a wildcard match.
  92. *
  93. * @param name the name of the BasicPermission.
  94. *
  95. * @throws NullPointerException if <code>name</code> is <code>null</code>.
  96. * @throws IllegalArgumentException if <code>name</code> is empty.
  97. */
  98. public BasicPermission(String name)
  99. {
  100. super(name);
  101. init(name);
  102. }
  103. /**
  104. * Creates a new BasicPermission object with the specified name.
  105. * The name is the symbolic name of the BasicPermission, and the
  106. * actions String is currently unused. This
  107. * constructor exists for use by the <code>Policy</code> object
  108. * to instantiate new Permission objects.
  109. *
  110. * @param name the name of the BasicPermission.
  111. * @param actions ignored.
  112. *
  113. * @throws NullPointerException if <code>name</code> is <code>null</code>.
  114. * @throws IllegalArgumentException if <code>name</code> is empty.
  115. */
  116. public BasicPermission(String name, String actions)
  117. {
  118. super(name);
  119. init(name);
  120. }
  121. /**
  122. * Checks if the specified permission is "implied" by
  123. * this object.
  124. * <P>
  125. * More specifically, this method returns true if:<p>
  126. * <ul>
  127. * <li> <i>p</i>'s class is the same as this object's class, and<p>
  128. * <li> <i>p</i>'s name equals or (in the case of wildcards)
  129. * is implied by this object's
  130. * name. For example, "a.b.*" implies "a.b.c".
  131. * </ul>
  132. *
  133. * @param p the permission to check against.
  134. *
  135. * @return true if the passed permission is equal to or
  136. * implied by this permission, false otherwise.
  137. */
  138. public boolean implies(Permission p) {
  139. if ((p == null) || (p.getClass() != getClass()))
  140. return false;
  141. BasicPermission that = (BasicPermission) p;
  142. if (this.wildcard) {
  143. if (that.wildcard)
  144. // one wildcard can imply another
  145. return that.path.startsWith(path);
  146. else
  147. // make sure ap.path is longer so a.b.* doesn't imply a.b
  148. return (that.path.length() > this.path.length()) &&
  149. that.path.startsWith(this.path);
  150. } else {
  151. if (that.wildcard) {
  152. // a non-wildcard can't imply a wildcard
  153. return false;
  154. }
  155. else {
  156. return this.path.equals(that.path);
  157. }
  158. }
  159. }
  160. /**
  161. * Checks two BasicPermission objects for equality.
  162. * Checks that <i>obj</i>'s class is the same as this object's class
  163. * and has the same name as this object.
  164. * <P>
  165. * @param obj the object we are testing for equality with this object.
  166. * @return true if <i>obj</i> is a BasicPermission, and has the same name
  167. * as this BasicPermission object, false otherwise.
  168. */
  169. public boolean equals(Object obj) {
  170. if (obj == this)
  171. return true;
  172. if ((obj == null) || (obj.getClass() != getClass()))
  173. return false;
  174. BasicPermission bp = (BasicPermission) obj;
  175. return getName().equals(bp.getName());
  176. }
  177. /**
  178. * Returns the hash code value for this object.
  179. * The hash code used is the hash code of the name, that is,
  180. * <code>getName().hashCode()</code>, where <code>getName</code> is
  181. * from the Permission superclass.
  182. *
  183. * @return a hash code value for this object.
  184. */
  185. public int hashCode() {
  186. return this.getName().hashCode();
  187. }
  188. /**
  189. * Returns the canonical string representation of the actions,
  190. * which currently is the empty string "", since there are no actions for
  191. * a BasicPermission.
  192. *
  193. * @return the empty string "".
  194. */
  195. public String getActions()
  196. {
  197. return "";
  198. }
  199. /**
  200. * Returns a new PermissionCollection object for storing BasicPermission
  201. * objects.
  202. * <p>
  203. * A BasicPermissionCollection stores a collection of
  204. * BasicPermission permissions.
  205. *
  206. * <p>BasicPermission objects must be stored in a manner that allows them
  207. * to be inserted in any order, but that also enables the
  208. * PermissionCollection <code>implies</code> method
  209. * to be implemented in an efficient (and consistent) manner.
  210. *
  211. * @return a new PermissionCollection object suitable for
  212. * storing BasicPermissions.
  213. */
  214. public PermissionCollection newPermissionCollection() {
  215. return new BasicPermissionCollection();
  216. }
  217. /**
  218. * readObject is called to restore the state of the BasicPermission from
  219. * a stream.
  220. */
  221. private synchronized void readObject(java.io.ObjectInputStream s)
  222. throws IOException, ClassNotFoundException
  223. {
  224. s.defaultReadObject();
  225. // init is called to initialize the rest of the values.
  226. init(getName());
  227. }
  228. }
  229. /**
  230. * A BasicPermissionCollection stores a collection
  231. * of BasicPermission permissions. BasicPermission objects
  232. * must be stored in a manner that allows them to be inserted in any
  233. * order, but enable the implies function to evaluate the implies
  234. * method in an efficient (and consistent) manner.
  235. *
  236. * A BasicPermissionCollection handles comparing a permission like "a.b.c.d.e"
  237. * with a Permission such as "a.b.*", or "*".
  238. *
  239. * @see java.security.Permission
  240. * @see java.security.Permissions
  241. * @see java.security.PermissionsImpl
  242. *
  243. * @version 1.26 02/02/00
  244. *
  245. * @author Roland Schemers
  246. *
  247. * @serial include
  248. */
  249. final class BasicPermissionCollection
  250. extends PermissionCollection
  251. implements java.io.Serializable
  252. {
  253. private Hashtable permissions;
  254. private boolean all_allowed; // true if "*" is in the collection
  255. /**
  256. * Create an empty BasicPermissions object.
  257. *
  258. */
  259. public BasicPermissionCollection() {
  260. permissions = new Hashtable(11);
  261. all_allowed = false;
  262. }
  263. /**
  264. * Adds a permission to the BasicPermissions. The key for the hash is
  265. * permission.path.
  266. *
  267. * @param permission the Permission object to add.
  268. *
  269. * @exception IllegalArgumentException - if the permission is not a
  270. * BasicPermission
  271. *
  272. * @exception SecurityException - if this BasicPermissionCollection object
  273. * has been marked readonly
  274. */
  275. public void add(Permission permission)
  276. {
  277. if (! (permission instanceof BasicPermission))
  278. throw new IllegalArgumentException("invalid permission: "+
  279. permission);
  280. if (isReadOnly())
  281. throw new SecurityException("attempt to add a Permission to a readonly PermissionCollection");
  282. BasicPermission bp = (BasicPermission) permission;
  283. permissions.put(bp.getName(), permission);
  284. if (!all_allowed) {
  285. if (bp.getName().equals("*"))
  286. all_allowed = true;
  287. }
  288. }
  289. /**
  290. * Check and see if this set of permissions implies the permissions
  291. * expressed in "permission".
  292. *
  293. * @param p the Permission object to compare
  294. *
  295. * @return true if "permission" is a proper subset of a permission in
  296. * the set, false if not.
  297. */
  298. public boolean implies(Permission permission)
  299. {
  300. if (! (permission instanceof BasicPermission))
  301. return false;
  302. BasicPermission bp = (BasicPermission) permission;
  303. // short circuit if the "*" Permission was added
  304. if (all_allowed)
  305. return true;
  306. // strategy:
  307. // Check for full match first. Then work our way up the
  308. // path looking for matches on a.b..*
  309. String path = bp.getName();
  310. //System.out.println("check "+path);
  311. Permission x = (Permission) permissions.get(path);
  312. if (x != null) {
  313. // we have a direct hit!
  314. return x.implies(permission);
  315. }
  316. // work our way up the tree...
  317. int last, offset;
  318. offset = path.length()-1;
  319. while ((last = path.lastIndexOf(".", offset)) != -1) {
  320. path = path.substring(0, last+1) + "*";
  321. //System.out.println("check "+path);
  322. x = (Permission) permissions.get(path);
  323. if (x != null) {
  324. return x.implies(permission);
  325. }
  326. offset = last -1;
  327. }
  328. // we don't have to check for "*" as it was already checked
  329. // at the top (all_allowed), so we just return false
  330. return false;
  331. }
  332. /**
  333. * Returns an enumeration of all the BasicPermission objects in the
  334. * container.
  335. *
  336. * @return an enumeration of all the BasicPermission objects.
  337. */
  338. public Enumeration elements()
  339. {
  340. return permissions.elements();
  341. }
  342. }