1 /* 2 * Copyright (c) 1997, 2019, Oracle and/or its affiliates. All rights reserved. 3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. 4 * 5 * This code is free software; you can redistribute it and/or modify it 6 * under the terms of the GNU General Public License version 2 only, as 7 * published by the Free Software Foundation. Oracle designates this 8 * particular file as subject to the "Classpath" exception as provided 9 * by Oracle in the LICENSE file that accompanied this code. 10 * 11 * This code is distributed in the hope that it will be useful, but WITHOUT 12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 13 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License 14 * version 2 for more details (a copy is included in the LICENSE file that 15 * accompanied this code). 16 * 17 * You should have received a copy of the GNU General Public License version 18 * 2 along with this work; if not, write to the Free Software Foundation, 19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. 20 * 21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA 22 * or visit www.oracle.com if you need additional information or have any 23 * questions. 24 */ 25 26 package java.security; 27 28 import java.util.*; 29 import java.util.stream.Stream; 30 import java.util.stream.StreamSupport; 31 32 /** 33 * Abstract class representing a collection of Permission objects. 34 * 35 * <p>With a PermissionCollection, you can: 36 * <UL> 37 * <LI> add a permission to the collection using the {@code add} method. 38 * <LI> check to see if a particular permission is implied in the 39 * collection, using the {@code implies} method. 40 * <LI> enumerate all the permissions, using the {@code elements} method. 41 * </UL> 42 * 43 * <p>When it is desirable to group together a number of Permission objects 44 * of the same type, the {@code newPermissionCollection} method on that 45 * particular type of Permission object should first be called. The default 46 * behavior (from the Permission class) is to simply return null. 47 * Subclasses of class Permission override the method if they need to store 48 * their permissions in a particular PermissionCollection object in order 49 * to provide the correct semantics when the 50 * {@code PermissionCollection.implies} method is called. 51 * If a non-null value is returned, that PermissionCollection must be used. 52 * If null is returned, then the caller of {@code newPermissionCollection} 53 * is free to store permissions of the 54 * given type in any PermissionCollection they choose 55 * (one that uses a Hashtable, one that uses a Vector, etc). 56 * 57 * <p>The PermissionCollection returned by the 58 * {@code Permission.newPermissionCollection} 59 * method is a homogeneous collection, which stores only Permission objects 60 * for a given Permission type. A PermissionCollection may also be 61 * heterogeneous. For example, Permissions is a PermissionCollection 62 * subclass that represents a collection of PermissionCollections. 63 * That is, its members are each a homogeneous PermissionCollection. 64 * For example, a Permissions object might have a FilePermissionCollection 65 * for all the FilePermission objects, a SocketPermissionCollection for all the 66 * SocketPermission objects, and so on. Its {@code add} method adds a 67 * permission to the appropriate collection. 68 * 69 * <p>Whenever a permission is added to a heterogeneous PermissionCollection 70 * such as Permissions, and the PermissionCollection doesn't yet contain a 71 * PermissionCollection of the specified permission's type, the 72 * PermissionCollection should call 73 * the {@code newPermissionCollection} method on the permission's class 74 * to see if it requires a special PermissionCollection. If 75 * {@code newPermissionCollection} 76 * returns null, the PermissionCollection 77 * is free to store the permission in any type of PermissionCollection it 78 * desires (one using a Hashtable, one using a Vector, etc.). For example, 79 * the Permissions object uses a default PermissionCollection implementation 80 * that stores the permission objects in a Hashtable. 81 * 82 * <p> Subclass implementations of PermissionCollection should assume 83 * that they may be called simultaneously from multiple threads, 84 * and therefore should be synchronized properly. Furthermore, 85 * Enumerations returned via the {@code elements} method are 86 * not <em>fail-fast</em>. Modifications to a collection should not be 87 * performed while enumerating over that collection. 88 * 89 * @see Permission 90 * @see Permissions 91 * 92 * 93 * @author Roland Schemers 94 * @since 1.2 95 */ 96 97 public abstract class PermissionCollection implements java.io.Serializable { 98 99 @java.io.Serial 100 private static final long serialVersionUID = -6727011328946861783L; 101 102 // when set, add will throw an exception. 103 private volatile boolean readOnly; 104 105 /** 106 * Adds a permission object to the current collection of permission objects. 107 * 108 * @param permission the Permission object to add. 109 * 110 * @throws SecurityException - if this PermissionCollection object 111 * has been marked readonly 112 * @throws IllegalArgumentException - if this PermissionCollection 113 * object is a homogeneous collection and the permission 114 * is not of the correct type. 115 */ 116 public abstract void add(Permission permission); 117 118 /** 119 * Checks to see if the specified permission is implied by 120 * the collection of Permission objects held in this PermissionCollection. 121 * 122 * @param permission the Permission object to compare. 123 * 124 * @return true if "permission" is implied by the permissions in 125 * the collection, false if not. 126 */ 127 public abstract boolean implies(Permission permission); 128 129 /** 130 * Returns an enumeration of all the Permission objects in the collection. 131 * 132 * @return an enumeration of all the Permissions. 133 * @see #elementsAsStream() 134 */ 135 public abstract Enumeration<Permission> elements(); 136 137 /** 138 * Returns a stream of all the Permission objects in the collection. 139 * 140 * <p> The collection should not be modified (see {@link #add}) during the 141 * execution of the terminal stream operation. Otherwise, the result of the 142 * terminal stream operation is undefined. 143 * 144 * @implSpec 145 * The default implementation creates a stream whose source is derived from 146 * the enumeration returned from a call to {@link #elements()}. 147 * 148 * @return a stream of all the Permissions. 149 * @since 9 150 */ 151 public Stream<Permission> elementsAsStream() { 152 int characteristics = isReadOnly() 153 ? Spliterator.NONNULL | Spliterator.IMMUTABLE 154 : Spliterator.NONNULL; 155 return StreamSupport.stream( 156 Spliterators.spliteratorUnknownSize( 157 elements().asIterator(), characteristics), 158 false); 159 } 160 161 /** 162 * Marks this PermissionCollection object as "readonly". After 163 * a PermissionCollection object 164 * is marked as readonly, no new Permission objects can be added to it 165 * using {@code add}. 166 */ 167 public void setReadOnly() { 168 readOnly = true; 169 } 170 171 /** 172 * Returns true if this PermissionCollection object is marked as readonly. 173 * If it is readonly, no new Permission objects can be added to it 174 * using {@code add}. 175 * 176 * <p>By default, the object is <i>not</i> readonly. It can be set to 177 * readonly by a call to {@code setReadOnly}. 178 * 179 * @return true if this PermissionCollection object is marked as readonly, 180 * false otherwise. 181 */ 182 public boolean isReadOnly() { 183 return readOnly; 184 } 185 186 /** 187 * Returns a string describing this PermissionCollection object, 188 * providing information about all the permissions it contains. 189 * The format is: 190 * <pre> 191 * super.toString() ( 192 * // enumerate all the Permission 193 * // objects and call toString() on them, 194 * // one per line.. 195 * )</pre> 196 * 197 * {@code super.toString} is a call to the {@code toString} 198 * method of this 199 * object's superclass, which is Object. The result is 200 * this PermissionCollection's type name followed by this object's 201 * hashcode, thus enabling clients to differentiate different 202 * PermissionCollections object, even if they contain the same permissions. 203 * 204 * @return information about this PermissionCollection object, 205 * as described above. 206 * 207 */ 208 public String toString() { 209 Enumeration<Permission> enum_ = elements(); 210 StringBuilder sb = new StringBuilder(); 211 sb.append(super.toString()+" (\n"); 212 while (enum_.hasMoreElements()) { 213 try { 214 sb.append(" "); 215 sb.append(enum_.nextElement().toString()); 216 sb.append("\n"); 217 } catch (NoSuchElementException e){ 218 // ignore 219 } 220 } 221 sb.append(")\n"); 222 return sb.toString(); 223 } 224 }