1 module hunt.security.PermissionCollection; 2 3 import hunt.security.Permission; 4 import hunt.collection; 5 6 import hunt.Exceptions; 7 import hunt.text.Common; 8 import hunt.util.StringBuilder; 9 10 /** 11 * Abstract class representing a collection of Permission objects. 12 * 13 * <p>With a PermissionCollection, you can: 14 * <UL> 15 * <LI> add a permission to the collection using the {@code add} method. 16 * <LI> check to see if a particular permission is implied in the 17 * collection, using the {@code implies} method. 18 * <LI> enumerate all the permissions, using the {@code elements} method. 19 * </UL> 20 * 21 * <p>When it is desirable to group together a number of Permission objects 22 * of the same type, the {@code newPermissionCollection} method on that 23 * particular type of Permission object should first be called. The default 24 * behavior (from the Permission class) is to simply return null. 25 * Subclasses of class Permission override the method if they need to store 26 * their permissions in a particular PermissionCollection object in order 27 * to provide the correct semantics when the 28 * {@code PermissionCollection.implies} method is called. 29 * If a non-null value is returned, that PermissionCollection must be used. 30 * If null is returned, then the caller of {@code newPermissionCollection} 31 * is free to store permissions of the 32 * given type in any PermissionCollection they choose 33 * (one that uses a Hashtable, one that uses a Vector, etc). 34 * 35 * <p>The PermissionCollection returned by the 36 * {@code Permission.newPermissionCollection} 37 * method is a homogeneous collection, which stores only Permission objects 38 * for a given Permission type. A PermissionCollection may also be 39 * heterogeneous. For example, Permissions is a PermissionCollection 40 * subclass that represents a collection of PermissionCollections. 41 * That is, its members are each a homogeneous PermissionCollection. 42 * For example, a Permissions object might have a FilePermissionCollection 43 * for all the FilePermission objects, a SocketPermissionCollection for all the 44 * SocketPermission objects, and so on. Its {@code add} method adds a 45 * permission to the appropriate collection. 46 * 47 * <p>Whenever a permission is added to a heterogeneous PermissionCollection 48 * such as Permissions, and the PermissionCollection doesn't yet contain a 49 * PermissionCollection of the specified permission's type, the 50 * PermissionCollection should call 51 * the {@code newPermissionCollection} method on the permission's class 52 * to see if it requires a special PermissionCollection. If 53 * {@code newPermissionCollection} 54 * returns null, the PermissionCollection 55 * is free to store the permission in any type of PermissionCollection it 56 * desires (one using a Hashtable, one using a Vector, etc.). For example, 57 * the Permissions object uses a default PermissionCollection implementation 58 * that stores the permission objects in a Hashtable. 59 * 60 * <p> Subclass implementations of PermissionCollection should assume 61 * that they may be called simultaneously from multiple threads, 62 * and therefore should be synchronized properly. Furthermore, 63 * Enumerations returned via the {@code elements} method are 64 * not <em>fail-fast</em>. Modifications to a collection should not be 65 * performed while enumerating over that collection. 66 * 67 * @see Permission 68 * @see Permissions 69 * 70 * 71 * @author Roland Schemers 72 */ 73 74 abstract class PermissionCollection { 75 76 private enum long serialVersionUID = -6727011328946861783L; 77 78 // when set, add will throw an exception. 79 private bool readOnly; 80 81 /** 82 * Adds a permission object to the current collection of permission objects. 83 * 84 * @param permission the Permission object to add. 85 * 86 * @exception SecurityException - if this PermissionCollection object 87 * has been marked readonly 88 * @exception IllegalArgumentException - if this PermissionCollection 89 * object is a homogeneous collection and the permission 90 * is not of the correct type. 91 */ 92 abstract void add(Permission permission); 93 94 /** 95 * Checks to see if the specified permission is implied by 96 * the collection of Permission objects held in this PermissionCollection. 97 * 98 * @param permission the Permission object to compare. 99 * 100 * @return true if "permission" is implied by the permissions in 101 * the collection, false if not. 102 */ 103 abstract bool implies(Permission permission); 104 105 /** 106 * Returns an enumeration of all the Permission objects in the collection. 107 * 108 * @return an enumeration of all the Permissions. 109 */ 110 abstract Enumeration!Permission elements(); 111 112 /** 113 * Marks this PermissionCollection object as "readonly". After 114 * a PermissionCollection object 115 * is marked as readonly, no new Permission objects can be added to it 116 * using {@code add}. 117 */ 118 void setReadOnly() { 119 readOnly = true; 120 } 121 122 /** 123 * Returns true if this PermissionCollection object is marked as readonly. 124 * If it is readonly, no new Permission objects can be added to it 125 * using {@code add}. 126 * 127 * <p>By default, the object is <i>not</i> readonly. It can be set to 128 * readonly by a call to {@code setReadOnly}. 129 * 130 * @return true if this PermissionCollection object is marked as readonly, 131 * false otherwise. 132 */ 133 bool isReadOnly() { 134 return readOnly; 135 } 136 137 /** 138 * Returns a string describing this PermissionCollection object, 139 * providing information about all the permissions it contains. 140 * The format is: 141 * <pre> 142 * super.toString() ( 143 * // enumerate all the Permission 144 * // objects and call toString() on them, 145 * // one per line.. 146 * )</pre> 147 * 148 * {@code super.toString} is a call to the {@code toString} 149 * method of this 150 * object's superclass, which is Object. The result is 151 * this PermissionCollection's type name followed by this object's 152 * hashcode, thus enabling clients to differentiate different 153 * PermissionCollections object, even if they contain the same permissions. 154 * 155 * @return information about this PermissionCollection object, 156 * as described above. 157 * 158 */ 159 override 160 string toString() { 161 Enumeration!Permission enum_ = elements(); 162 StringBuilder sb = new StringBuilder(); 163 sb.append(super.toString() ~ " (\n"); 164 while (enum_.hasMoreElements()) { 165 try { 166 sb.append(" "); 167 sb.append(enum_.nextElement().toString()); 168 sb.append("\n"); 169 } catch (NoSuchElementException e){ 170 // ignore 171 } 172 } 173 sb.append(")\n"); 174 return sb.toString(); 175 } 176 }