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.io.IOException;
29 import java.io.ObjectInputStream;
30 import java.io.ObjectOutputStream;
31 import java.io.ObjectStreamField;
32 import java.util.*;
33 import java.util.concurrent.ConcurrentHashMap;
34 import java.util.concurrent.CopyOnWriteArrayList;
35 
36 /**
37  * A UnresolvedPermissionCollection stores a collection
38  * of UnresolvedPermission permissions.
39  *
40  * @see java.security.Permission
41  * @see java.security.Permissions
42  * @see java.security.UnresolvedPermission
43  *
44  *
45  * @author Roland Schemers
46  * @since 1.2
47  *
48  * @serial include
49  */
50 
51 final class UnresolvedPermissionCollection
52 extends PermissionCollection
53 implements java.io.Serializable
54 {
55     /**
56      * Key is permission type, value is a list of the UnresolvedPermissions
57      * of the same type.
58      * Not serialized; see serialization section at end of class.
59      */
60     private transient ConcurrentHashMap<String, List<UnresolvedPermission>> perms;
61 
62     /**
63      * Create an empty UnresolvedPermissionCollection object.
64      *
65      */
UnresolvedPermissionCollection()66     public UnresolvedPermissionCollection() {
67         perms = new ConcurrentHashMap<>(11);
68     }
69 
70     /**
71      * Adds a permission to this UnresolvedPermissionCollection.
72      * The key for the hash is the unresolved permission's type (class) name.
73      *
74      * @param permission the Permission object to add.
75      */
76     @Override
add(Permission permission)77     public void add(Permission permission) {
78         if (! (permission instanceof UnresolvedPermission))
79             throw new IllegalArgumentException("invalid permission: "+
80                                                permission);
81         UnresolvedPermission up = (UnresolvedPermission) permission;
82 
83         // Add permission to map. NOTE: cannot use lambda for
84         // remappingFunction parameter until JDK-8076596 is fixed.
85         perms.compute(up.getName(),
86             new java.util.function.BiFunction<>() {
87                 @Override
88                 public List<UnresolvedPermission> apply(String key,
89                                         List<UnresolvedPermission> oldValue) {
90                     if (oldValue == null) {
91                         List<UnresolvedPermission> v =
92                             new CopyOnWriteArrayList<>();
93                         v.add(up);
94                         return v;
95                     } else {
96                         oldValue.add(up);
97                         return oldValue;
98                     }
99                 }
100             }
101         );
102     }
103 
104     /**
105      * get any unresolved permissions of the same type as p,
106      * and return the List containing them.
107      */
getUnresolvedPermissions(Permission p)108     List<UnresolvedPermission> getUnresolvedPermissions(Permission p) {
109         return perms.get(p.getClass().getName());
110     }
111 
112     /**
113      * always returns false for unresolved permissions
114      *
115      */
116     @Override
implies(Permission permission)117     public boolean implies(Permission permission) {
118         return false;
119     }
120 
121     /**
122      * Returns an enumeration of all the UnresolvedPermission lists in the
123      * container.
124      *
125      * @return an enumeration of all the UnresolvedPermission objects.
126      */
127     @Override
elements()128     public Enumeration<Permission> elements() {
129         List<Permission> results =
130             new ArrayList<>(); // where results are stored
131 
132         // Get iterator of Map values (which are lists of permissions)
133         for (List<UnresolvedPermission> l : perms.values()) {
134             results.addAll(l);
135         }
136 
137         return Collections.enumeration(results);
138     }
139 
140     private static final long serialVersionUID = -7176153071733132400L;
141 
142     // Need to maintain serialization interoperability with earlier releases,
143     // which had the serializable field:
144     // private Hashtable permissions; // keyed on type
145 
146     /**
147      * @serialField permissions java.util.Hashtable
148      *     A table of the UnresolvedPermissions keyed on type, value is Vector
149      *     of permissions
150      */
151     private static final ObjectStreamField[] serialPersistentFields = {
152         new ObjectStreamField("permissions", Hashtable.class),
153     };
154 
155     /**
156      * @serialData Default field.
157      */
158     /*
159      * Writes the contents of the perms field out as a Hashtable
160      * in which the values are Vectors for
161      * serialization compatibility with earlier releases.
162      */
writeObject(ObjectOutputStream out)163     private void writeObject(ObjectOutputStream out) throws IOException {
164         // Don't call out.defaultWriteObject()
165 
166         // Copy perms into a Hashtable
167         Hashtable<String, Vector<UnresolvedPermission>> permissions =
168             new Hashtable<>(perms.size()*2);
169 
170         // Convert each entry (List) into a Vector
171         Set<Map.Entry<String, List<UnresolvedPermission>>> set = perms.entrySet();
172         for (Map.Entry<String, List<UnresolvedPermission>> e : set) {
173             // Convert list into Vector
174             List<UnresolvedPermission> list = e.getValue();
175             Vector<UnresolvedPermission> vec = new Vector<>(list);
176 
177             // Add to Hashtable being serialized
178             permissions.put(e.getKey(), vec);
179         }
180 
181         // Write out serializable fields
182         ObjectOutputStream.PutField pfields = out.putFields();
183         pfields.put("permissions", permissions);
184         out.writeFields();
185     }
186 
187     /*
188      * Reads in a Hashtable in which the values are Vectors of
189      * UnresolvedPermissions and saves them in the perms field.
190      */
readObject(ObjectInputStream in)191     private void readObject(ObjectInputStream in) throws IOException,
192     ClassNotFoundException {
193         // Don't call defaultReadObject()
194 
195         // Read in serialized fields
196         ObjectInputStream.GetField gfields = in.readFields();
197 
198         // Get permissions
199         @SuppressWarnings("unchecked")
200         // writeObject writes a Hashtable<String, Vector<UnresolvedPermission>>
201         // for the permissions key, so this cast is safe, unless the data is corrupt.
202         Hashtable<String, Vector<UnresolvedPermission>> permissions =
203                 (Hashtable<String, Vector<UnresolvedPermission>>)
204                 gfields.get("permissions", null);
205         perms = new ConcurrentHashMap<>(permissions.size()*2);
206 
207         // Convert each entry (Vector) into a List
208         Set<Map.Entry<String, Vector<UnresolvedPermission>>> set = permissions.entrySet();
209         for (Map.Entry<String, Vector<UnresolvedPermission>> e : set) {
210             // Convert Vector into ArrayList
211             Vector<UnresolvedPermission> vec = e.getValue();
212             List<UnresolvedPermission> list = new CopyOnWriteArrayList<>(vec);
213 
214             // Add to Hashtable being serialized
215             perms.put(e.getKey(), list);
216         }
217     }
218 }
219