| /* | |
| * Copyright (c) 1997, 2025, Oracle and/or its affiliates. All rights reserved. | |
| * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER. | |
| * | |
| * This code is free software; you can redistribute it and/or modify it | |
| * under the terms of the GNU General Public License version 2 only, as | |
| * published by the Free Software Foundation. Oracle designates this | |
| * particular file as subject to the "Classpath" exception as provided | |
| * by Oracle in the LICENSE file that accompanied this code. | |
| * | |
| * This code is distributed in the hope that it will be useful, but WITHOUT | |
| * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
| * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License | |
| * version 2 for more details (a copy is included in the LICENSE file that | |
| * accompanied this code). | |
| * | |
| * You should have received a copy of the GNU General Public License version | |
| * 2 along with this work; if not, write to the Free Software Foundation, | |
| * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA. | |
| * | |
| * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA | |
| * or visit www.oracle.com if you need additional information or have any | |
| * questions. | |
| */ | |
| package java.security; | |
| import java.io.IOException; | |
| import java.io.ObjectInputStream; | |
| import java.io.ObjectOutputStream; | |
| import java.io.ObjectStreamField; | |
| import java.io.InvalidObjectException; | |
| import java.util.*; | |
| import java.util.concurrent.ConcurrentHashMap; | |
| import java.util.concurrent.CopyOnWriteArrayList; | |
| /** | |
| * A {@code UnresolvedPermissionCollection} stores a collection | |
| * of UnresolvedPermission permissions. | |
| * | |
| * @see java.security.Permission | |
| * @see java.security.Permissions | |
| * @see java.security.UnresolvedPermission | |
| * | |
| * | |
| * @author Roland Schemers | |
| * @since 1.2 | |
| * | |
| * @serial include | |
| */ | |
| @SuppressWarnings("removal") | |
| final class UnresolvedPermissionCollection | |
| extends PermissionCollection | |
| implements java.io.Serializable | |
| { | |
| /** | |
| * Key is permission type, value is a list of the UnresolvedPermissions | |
| * of the same type. | |
| * Not serialized; see serialization section at end of class. | |
| */ | |
| private transient ConcurrentHashMap<String, List<UnresolvedPermission>> perms; | |
| /** | |
| * Create an empty {@code UnresolvedPermissionCollection} object. | |
| * | |
| */ | |
| public UnresolvedPermissionCollection() { | |
| perms = new ConcurrentHashMap<>(11); | |
| } | |
| /** | |
| * Adds a permission to this {@code UnresolvedPermissionCollection}. | |
| * The key for the hash is the unresolved permission's type (class) name. | |
| * | |
| * @param permission the Permission object to add. | |
| */ | |
| @Override | |
| public void add(Permission permission) { | |
| if (!(permission instanceof UnresolvedPermission unresolvedPermission)) | |
| throw new IllegalArgumentException("invalid permission: "+ | |
| permission); | |
| // Add permission to map. | |
| perms.compute(unresolvedPermission.getName(), (key, oldValue) -> { | |
| if (oldValue == null) { | |
| List<UnresolvedPermission> v = new CopyOnWriteArrayList<>(); | |
| v.add(unresolvedPermission); | |
| return v; | |
| } else { | |
| oldValue.add(unresolvedPermission); | |
| return oldValue; | |
| } | |
| } | |
| ); | |
| } | |
| /** | |
| * get any unresolved permissions of the same type as p, | |
| * and return the List containing them. | |
| */ | |
| List<UnresolvedPermission> getUnresolvedPermissions(Permission p) { | |
| return perms.get(p.getClass().getName()); | |
| } | |
| /** | |
| * always returns {@code false} for unresolved permissions | |
| * | |
| */ | |
| @Override | |
| public boolean implies(Permission permission) { | |
| return false; | |
| } | |
| /** | |
| * Returns an enumeration of all the UnresolvedPermission lists in the | |
| * container. | |
| * | |
| * @return an enumeration of all the UnresolvedPermission objects. | |
| */ | |
| @Override | |
| public Enumeration<Permission> elements() { | |
| List<Permission> results = | |
| new ArrayList<>(); // where results are stored | |
| // Get iterator of Map values (which are lists of permissions) | |
| for (List<UnresolvedPermission> l : perms.values()) { | |
| results.addAll(l); | |
| } | |
| return Collections.enumeration(results); | |
| } | |
| @java.io.Serial | |
| private static final long serialVersionUID = -7176153071733132400L; | |
| // Need to maintain serialization interoperability with earlier releases, | |
| // which had the serializable field: | |
| // private Hashtable permissions; // keyed on type | |
| /** | |
| * @serialField permissions java.util.Hashtable | |
| * A table of the UnresolvedPermissions keyed on type, value is Vector | |
| * of permissions | |
| */ | |
| @java.io.Serial | |
| private static final ObjectStreamField[] serialPersistentFields = { | |
| new ObjectStreamField("permissions", Hashtable.class), | |
| }; | |
| /** | |
| * Writes the contents of the perms field out as a Hashtable | |
| * in which the values are Vectors for | |
| * serialization compatibility with earlier releases. | |
| * | |
| * @param out the {@code ObjectOutputStream} to which data is written | |
| * @throws IOException if an I/O error occurs | |
| */ | |
| @java.io.Serial | |
| private void writeObject(ObjectOutputStream out) throws IOException { | |
| // Don't call out.defaultWriteObject() | |
| // Copy perms into a Hashtable | |
| Hashtable<String, Vector<UnresolvedPermission>> permissions = | |
| new Hashtable<>(perms.size()*2); | |
| // Convert each entry (List) into a Vector | |
| Set<Map.Entry<String, List<UnresolvedPermission>>> set = perms.entrySet(); | |
| for (Map.Entry<String, List<UnresolvedPermission>> e : set) { | |
| // Convert list into Vector | |
| List<UnresolvedPermission> list = e.getValue(); | |
| Vector<UnresolvedPermission> vec = new Vector<>(list); | |
| // Add to Hashtable being serialized | |
| permissions.put(e.getKey(), vec); | |
| } | |
| // Write out serializable fields | |
| ObjectOutputStream.PutField pfields = out.putFields(); | |
| pfields.put("permissions", permissions); | |
| out.writeFields(); | |
| } | |
| /** | |
| * Reads in a Hashtable in which the values are Vectors of | |
| * UnresolvedPermissions and saves them in the perms field. | |
| * | |
| * @param in the {@code ObjectInputStream} from which data is read | |
| * @throws IOException if an I/O error occurs | |
| * @throws ClassNotFoundException if a serialized class cannot be loaded | |
| */ | |
| @java.io.Serial | |
| private void readObject(ObjectInputStream in) throws IOException, | |
| ClassNotFoundException { | |
| // Don't call defaultReadObject() | |
| // Read in serialized fields | |
| ObjectInputStream.GetField gfields = in.readFields(); | |
| // Get permissions | |
| // writeObject writes a Hashtable<String, Vector<UnresolvedPermission>> | |
| // for the permissions key, so this cast is safe, unless the data is corrupt. | |
| try { | |
| @SuppressWarnings("unchecked") | |
| Hashtable<String, Vector<UnresolvedPermission>> permissions = | |
| (Hashtable<String, Vector<UnresolvedPermission>>) | |
| gfields.get("permissions", null); | |
| if (permissions == null) { | |
| throw new InvalidObjectException("Invalid null permissions"); | |
| } | |
| perms = new ConcurrentHashMap<>(permissions.size()*2); | |
| // Convert each entry (Vector) into a List | |
| Set<Map.Entry<String, Vector<UnresolvedPermission>>> set = permissions.entrySet(); | |
| for (Map.Entry<String, Vector<UnresolvedPermission>> e : set) { | |
| // Convert Vector into ArrayList | |
| Vector<UnresolvedPermission> vec = e.getValue(); | |
| List<UnresolvedPermission> list = new CopyOnWriteArrayList<>(vec); | |
| // Add to Hashtable being serialized | |
| perms.put(e.getKey(), list); | |
| } | |
| } catch (ClassCastException cce) { | |
| throw new InvalidObjectException("Invalid type for permissions"); | |
| } | |
| } | |
| } |