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