1 /* 2 * Copyright (c) 1997, 2015, 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 */ 95 96 public abstract class PermissionCollection implements java.io.Serializable { 97 98 private static final long serialVersionUID = -6727011328946861783L; 99 100 // when set, add will throw an exception. 101 private volatile boolean readOnly; 102 103 /** 104 * Adds a permission object to the current collection of permission objects. 105 * 106 * @param permission the Permission object to add. 107 * 108 * @exception SecurityException - if this PermissionCollection object 109 * has been marked readonly 110 * @exception IllegalArgumentException - if this PermissionCollection 111 * object is a homogeneous collection and the permission 112 * is not of the correct type. 113 */ 114 public abstract void add(Permission permission); 115 116 /** 117 * Checks to see if the specified permission is implied by 118 * the collection of Permission objects held in this PermissionCollection. 119 * 120 * @param permission the Permission object to compare. 121 * 122 * @return true if "permission" is implied by the permissions in 123 * the collection, false if not. 124 */ 125 public abstract boolean implies(Permission permission); 126 127 /** 128 * Returns an enumeration of all the Permission objects in the collection. 129 * 130 * @return an enumeration of all the Permissions. 131 * @see #elementsAsStream() 132 */ 133 public abstract Enumeration<Permission> elements(); 134 135 /** 136 * Returns a stream of all the Permission objects in the collection. 137 * 138 * <p> The collection should not be modified (see {@link #add}) during the 139 * execution of the terminal stream operation. Otherwise, the result of the 140 * terminal stream operation is undefined. 141 * 142 * @implSpec 143 * The default implementation creates a stream whose source is derived from 144 * the enumeration returned from a call to {@link #elements()}. 145 * 146 * @return a stream of all the Permissions. 147 * @since 1.9 148 */ 149 public Stream<Permission> elementsAsStream() { 150 int characteristics = isReadOnly() 151 ? Spliterator.NONNULL | Spliterator.IMMUTABLE 152 : Spliterator.NONNULL; 153 return StreamSupport.stream( 154 Spliterators.spliteratorUnknownSize( 155 elements().asIterator(), characteristics), 156 false); 157 } 158 159 /** 160 * Marks this PermissionCollection object as "readonly". After 161 * a PermissionCollection object 162 * is marked as readonly, no new Permission objects can be added to it 163 * using {@code add}. 164 */ 165 public void setReadOnly() { 166 readOnly = true; 167 } 168 169 /** 170 * Returns true if this PermissionCollection object is marked as readonly. 171 * If it is readonly, no new Permission objects can be added to it 172 * using {@code add}. 173 * 174 * <p>By default, the object is <i>not</i> readonly. It can be set to 175 * readonly by a call to {@code setReadOnly}. 176 * 177 * @return true if this PermissionCollection object is marked as readonly, 178 * false otherwise. 179 */ 180 public boolean isReadOnly() { 181 return readOnly; 182 } 183 184 /** 185 * Returns a string describing this PermissionCollection object, 186 * providing information about all the permissions it contains. 187 * The format is: 188 * <pre> 189 * super.toString() ( 190 * // enumerate all the Permission 191 * // objects and call toString() on them, 192 * // one per line.. 193 * )</pre> 194 * 195 * {@code super.toString} is a call to the {@code toString} 196 * method of this 197 * object's superclass, which is Object. The result is 198 * this PermissionCollection's type name followed by this object's 199 * hashcode, thus enabling clients to differentiate different 200 * PermissionCollections object, even if they contain the same permissions. 201 * 202 * @return information about this PermissionCollection object, 203 * as described above. 204 * 205 */ 206 public String toString() { 207 Enumeration<Permission> enum_ = elements(); 208 StringBuilder sb = new StringBuilder(); 209 sb.append(super.toString()+" (\n"); 210 while (enum_.hasMoreElements()) { 211 try { 212 sb.append(" "); 213 sb.append(enum_.nextElement().toString()); 214 sb.append("\n"); 215 } catch (NoSuchElementException e){ 216 // ignore 217 } 218 } 219 sb.append(")\n"); 220 return sb.toString(); 221 } 222 }