History

My first initial commit with all of mine experimental changes.

Dmitry Kabak (userdima committed 13 years ago

Commit d37b88d1 parent 3f5b46618352 files · +2598093 −-8690Browse files

Showing the changes to java/pkg/java/security/Permissions.java (1 of 18352 files). Show all

Unified · Split

java/pkg/java/security/Permissions.java+598−0
@@ -0,0 +1,598 @@
1+/*
2+ * Copyright (c) 1997, 2011, 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.Enumeration;
29+import java.util.Hashtable;
30+import java.util.NoSuchElementException;
31+import java.util.Map;
32+import java.util.HashMap;
33+import java.util.List;
34+import java.util.ArrayList;
35+import java.util.Iterator;
36+import java.util.Collections;
37+import java.io.Serializable;
38+import java.io.ObjectStreamField;
39+import java.io.ObjectOutputStream;
40+import java.io.ObjectInputStream;
41+import java.io.IOException;
42+
43+
44+/**
45+ * This class represents a heterogeneous collection of Permissions. That is,
46+ * it contains different types of Permission objects, organized into
47+ * PermissionCollections. For example, if any
48+ * <code>java.io.FilePermission</code> objects are added to an instance of
49+ * this class, they are all stored in a single
50+ * PermissionCollection. It is the PermissionCollection returned by a call to
51+ * the <code>newPermissionCollection</code> method in the FilePermission class.
52+ * Similarly, any <code>java.lang.RuntimePermission</code> objects are
53+ * stored in the PermissionCollection returned by a call to the
54+ * <code>newPermissionCollection</code> method in the
55+ * RuntimePermission class. Thus, this class represents a collection of
56+ * PermissionCollections.
57+ *
58+ * <p>When the <code>add</code> method is called to add a Permission, the
59+ * Permission is stored in the appropriate PermissionCollection. If no such
60+ * collection exists yet, the Permission object's class is determined and the
61+ * <code>newPermissionCollection</code> method is called on that class to create
62+ * the PermissionCollection and add it to the Permissions object. If
63+ * <code>newPermissionCollection</code> returns null, then a default
64+ * PermissionCollection that uses a hashtable will be created and used. Each
65+ * hashtable entry stores a Permission object as both the key and the value.
66+ *
67+ * <p> Enumerations returned via the <code>elements</code> method are
68+ * not <em>fail-fast</em>. Modifications to a collection should not be
69+ * performed while enumerating over that collection.
70+ *
71+ * @see Permission
72+ * @see PermissionCollection
73+ * @see AllPermission
74+ *
75+ *
76+ * @author Marianne Mueller
77+ * @author Roland Schemers
78+ *
79+ * @serial exclude
80+ */
81+
82+public final class Permissions extends PermissionCollection
83+implements Serializable
84+{
85+ /**
86+ * Key is permissions Class, value is PermissionCollection for that class.
87+ * Not serialized; see serialization section at end of class.
88+ */
89+ private transient Map<Class<?>, PermissionCollection> permsMap;
90+
91+ // optimization. keep track of whether unresolved permissions need to be
92+ // checked
93+ private transient boolean hasUnresolved = false;
94+
95+ // optimization. keep track of the AllPermission collection
96+ // - package private for ProtectionDomain optimization
97+ PermissionCollection allPermission;
98+
99+ /**
100+ * Creates a new Permissions object containing no PermissionCollections.
101+ */
102+ public Permissions() {
103+ permsMap = new HashMap<Class<?>, PermissionCollection>(11);
104+ allPermission = null;
105+ }
106+
107+ /**
108+ * Adds a permission object to the PermissionCollection for the class the
109+ * permission belongs to. For example, if <i>permission</i> is a
110+ * FilePermission, it is added to the FilePermissionCollection stored
111+ * in this Permissions object.
112+ *
113+ * This method creates
114+ * a new PermissionCollection object (and adds the permission to it)
115+ * if an appropriate collection does not yet exist. <p>
116+ *
117+ * @param permission the Permission object to add.
118+ *
119+ * @exception SecurityException if this Permissions object is
120+ * marked as readonly.
121+ *
122+ * @see PermissionCollection#isReadOnly()
123+ */
124+
125+ public void add(Permission permission) {
126+ if (isReadOnly())
127+ throw new SecurityException(
128+ "attempt to add a Permission to a readonly Permissions object");
129+
130+ PermissionCollection pc;
131+
132+ synchronized (this) {
133+ pc = getPermissionCollection(permission, true);
134+ pc.add(permission);
135+ }
136+
137+ // No sync; staleness -> optimizations delayed, which is OK
138+ if (permission instanceof AllPermission) {
139+ allPermission = pc;
140+ }
141+ if (permission instanceof UnresolvedPermission) {
142+ hasUnresolved = true;
143+ }
144+ }
145+
146+ /**
147+ * Checks to see if this object's PermissionCollection for permissions of
148+ * the specified permission's class implies the permissions
149+ * expressed in the <i>permission</i> object. Returns true if the
150+ * combination of permissions in the appropriate PermissionCollection
151+ * (e.g., a FilePermissionCollection for a FilePermission) together
152+ * imply the specified permission.
153+ *
154+ * <p>For example, suppose there is a FilePermissionCollection in this
155+ * Permissions object, and it contains one FilePermission that specifies
156+ * "read" access for all files in all subdirectories of the "/tmp"
157+ * directory, and another FilePermission that specifies "write" access
158+ * for all files in the "/tmp/scratch/foo" directory.
159+ * Then if the <code>implies</code> method
160+ * is called with a permission specifying both "read" and "write" access
161+ * to files in the "/tmp/scratch/foo" directory, <code>true</code> is
162+ * returned.
163+ *
164+ * <p>Additionally, if this PermissionCollection contains the
165+ * AllPermission, this method will always return true.
166+ * <p>
167+ * @param permission the Permission object to check.
168+ *
169+ * @return true if "permission" is implied by the permissions in the
170+ * PermissionCollection it
171+ * belongs to, false if not.
172+ */
173+
174+ public boolean implies(Permission permission) {
175+ // No sync; staleness -> skip optimization, which is OK
176+ if (allPermission != null) {
177+ return true; // AllPermission has already been added
178+ } else {
179+ synchronized (this) {
180+ PermissionCollection pc = getPermissionCollection(permission,
181+ false);
182+ if (pc != null) {
183+ return pc.implies(permission);
184+ } else {
185+ // none found
186+ return false;
187+ }
188+ }
189+ }
190+ }
191+
192+ /**
193+ * Returns an enumeration of all the Permission objects in all the
194+ * PermissionCollections in this Permissions object.
195+ *
196+ * @return an enumeration of all the Permissions.
197+ */
198+
199+ public Enumeration<Permission> elements() {
200+ // go through each Permissions in the hash table
201+ // and call their elements() function.
202+
203+ synchronized (this) {
204+ return new PermissionsEnumerator(permsMap.values().iterator());
205+ }
206+ }
207+
208+ /**
209+ * Gets the PermissionCollection in this Permissions object for
210+ * permissions whose type is the same as that of <i>p</i>.
211+ * For example, if <i>p</i> is a FilePermission,
212+ * the FilePermissionCollection
213+ * stored in this Permissions object will be returned.
214+ *
215+ * If createEmpty is true,
216+ * this method creates a new PermissionCollection object for the specified
217+ * type of permission objects if one does not yet exist.
218+ * To do so, it first calls the <code>newPermissionCollection</code> method
219+ * on <i>p</i>. Subclasses of class Permission
220+ * override that method if they need to store their permissions in a
221+ * particular PermissionCollection object in order to provide the
222+ * correct semantics when the <code>PermissionCollection.implies</code>
223+ * method is called.
224+ * If the call returns a PermissionCollection, that collection is stored
225+ * in this Permissions object. If the call returns null and createEmpty
226+ * is true, then
227+ * this method instantiates and stores a default PermissionCollection
228+ * that uses a hashtable to store its permission objects.
229+ *
230+ * createEmpty is ignored when creating empty PermissionCollection
231+ * for unresolved permissions because of the overhead of determining the
232+ * PermissionCollection to use.
233+ *
234+ * createEmpty should be set to false when this method is invoked from
235+ * implies() because it incurs the additional overhead of creating and
236+ * adding an empty PermissionCollection that will just return false.
237+ * It should be set to true when invoked from add().
238+ */
239+ private PermissionCollection getPermissionCollection(Permission p,
240+ boolean createEmpty) {
241+ Class c = p.getClass();
242+
243+ PermissionCollection pc = permsMap.get(c);
244+
245+ if (!hasUnresolved && !createEmpty) {
246+ return pc;
247+ } else if (pc == null) {
248+
249+ // Check for unresolved permissions
250+ pc = (hasUnresolved ? getUnresolvedPermissions(p) : null);
251+
252+ // if still null, create a new collection
253+ if (pc == null && createEmpty) {
254+
255+ pc = p.newPermissionCollection();
256+
257+ // still no PermissionCollection?
258+ // We'll give them a PermissionsHash.
259+ if (pc == null)
260+ pc = new PermissionsHash();
261+ }
262+
263+ if (pc != null) {
264+ permsMap.put(c, pc);
265+ }
266+ }
267+ return pc;
268+ }
269+
270+ /**
271+ * Resolves any unresolved permissions of type p.
272+ *
273+ * @param p the type of unresolved permission to resolve
274+ *
275+ * @return PermissionCollection containing the unresolved permissions,
276+ * or null if there were no unresolved permissions of type p.
277+ *
278+ */
279+ private PermissionCollection getUnresolvedPermissions(Permission p)
280+ {
281+ // Called from within synchronized method so permsMap doesn't need lock
282+
283+ UnresolvedPermissionCollection uc =
284+ (UnresolvedPermissionCollection) permsMap.get(UnresolvedPermission.class);
285+
286+ // we have no unresolved permissions if uc is null
287+ if (uc == null)
288+ return null;
289+
290+ List<UnresolvedPermission> unresolvedPerms =
291+ uc.getUnresolvedPermissions(p);
292+
293+ // we have no unresolved permissions of this type if unresolvedPerms is null
294+ if (unresolvedPerms == null)
295+ return null;
296+
297+ java.security.cert.Certificate certs[] = null;
298+
299+ Object signers[] = p.getClass().getSigners();
300+
301+ int n = 0;
302+ if (signers != null) {
303+ for (int j=0; j < signers.length; j++) {
304+ if (signers[j] instanceof java.security.cert.Certificate) {
305+ n++;
306+ }
307+ }
308+ certs = new java.security.cert.Certificate[n];
309+ n = 0;
310+ for (int j=0; j < signers.length; j++) {
311+ if (signers[j] instanceof java.security.cert.Certificate) {
312+ certs[n++] = (java.security.cert.Certificate)signers[j];
313+ }
314+ }
315+ }
316+
317+ PermissionCollection pc = null;
318+ synchronized (unresolvedPerms) {
319+ int len = unresolvedPerms.size();
320+ for (int i = 0; i < len; i++) {
321+ UnresolvedPermission up = unresolvedPerms.get(i);
322+ Permission perm = up.resolve(p, certs);
323+ if (perm != null) {
324+ if (pc == null) {
325+ pc = p.newPermissionCollection();
326+ if (pc == null)
327+ pc = new PermissionsHash();
328+ }
329+ pc.add(perm);
330+ }
331+ }
332+ }
333+ return pc;
334+ }
335+
336+ private static final long serialVersionUID = 4858622370623524688L;
337+
338+ // Need to maintain serialization interoperability with earlier releases,
339+ // which had the serializable field:
340+ // private Hashtable perms;
341+
342+ /**
343+ * @serialField perms java.util.Hashtable
344+ * A table of the Permission classes and PermissionCollections.
345+ * @serialField allPermission java.security.PermissionCollection
346+ */
347+ private static final ObjectStreamField[] serialPersistentFields = {
348+ new ObjectStreamField("perms", Hashtable.class),
349+ new ObjectStreamField("allPermission", PermissionCollection.class),
350+ };
351+
352+ /**
353+ * @serialData Default fields.
354+ */
355+ /*
356+ * Writes the contents of the permsMap field out as a Hashtable for
357+ * serialization compatibility with earlier releases. allPermission
358+ * unchanged.
359+ */
360+ private void writeObject(ObjectOutputStream out) throws IOException {
361+ // Don't call out.defaultWriteObject()
362+
363+ // Copy perms into a Hashtable
364+ Hashtable<Class<?>, PermissionCollection> perms =
365+ new Hashtable<>(permsMap.size()*2); // no sync; estimate
366+ synchronized (this) {
367+ perms.putAll(permsMap);
368+ }
369+
370+ // Write out serializable fields
371+ ObjectOutputStream.PutField pfields = out.putFields();
372+
373+ pfields.put("allPermission", allPermission); // no sync; staleness OK
374+ pfields.put("perms", perms);
375+ out.writeFields();
376+ }
377+
378+ /*
379+ * Reads in a Hashtable of Class/PermissionCollections and saves them in the
380+ * permsMap field. Reads in allPermission.
381+ */
382+ private void readObject(ObjectInputStream in) throws IOException,
383+ ClassNotFoundException {
384+ // Don't call defaultReadObject()
385+
386+ // Read in serialized fields
387+ ObjectInputStream.GetField gfields = in.readFields();
388+
389+ // Get allPermission
390+ allPermission = (PermissionCollection) gfields.get("allPermission", null);
391+
392+ // Get permissions
393+ Hashtable<Class<?>, PermissionCollection> perms =
394+ (Hashtable<Class<?>, PermissionCollection>)gfields.get("perms", null);
395+ permsMap = new HashMap<Class<?>, PermissionCollection>(perms.size()*2);
396+ permsMap.putAll(perms);
397+
398+ // Set hasUnresolved
399+ UnresolvedPermissionCollection uc =
400+ (UnresolvedPermissionCollection) permsMap.get(UnresolvedPermission.class);
401+ hasUnresolved = (uc != null && uc.elements().hasMoreElements());
402+ }
403+}
404+
405+final class PermissionsEnumerator implements Enumeration<Permission> {
406+
407+ // all the perms
408+ private Iterator<PermissionCollection> perms;
409+ // the current set
410+ private Enumeration<Permission> permset;
411+
412+ PermissionsEnumerator(Iterator<PermissionCollection> e) {
413+ perms = e;
414+ permset = getNextEnumWithMore();
415+ }
416+
417+ // No need to synchronize; caller should sync on object as required
418+ public boolean hasMoreElements() {
419+ // if we enter with permissionimpl null, we know
420+ // there are no more left.
421+
422+ if (permset == null)
423+ return false;
424+
425+ // try to see if there are any left in the current one
426+
427+ if (permset.hasMoreElements())
428+ return true;
429+
430+ // get the next one that has something in it...
431+ permset = getNextEnumWithMore();
432+
433+ // if it is null, we are done!
434+ return (permset != null);
435+ }
436+
437+ // No need to synchronize; caller should sync on object as required
438+ public Permission nextElement() {
439+
440+ // hasMoreElements will update permset to the next permset
441+ // with something in it...
442+
443+ if (hasMoreElements()) {
444+ return permset.nextElement();
445+ } else {
446+ throw new NoSuchElementException("PermissionsEnumerator");
447+ }
448+
449+ }
450+
451+ private Enumeration<Permission> getNextEnumWithMore() {
452+ while (perms.hasNext()) {
453+ PermissionCollection pc = perms.next();
454+ Enumeration<Permission> next =pc.elements();
455+ if (next.hasMoreElements())
456+ return next;
457+ }
458+ return null;
459+
460+ }
461+}
462+
463+/**
464+ * A PermissionsHash stores a homogeneous set of permissions in a hashtable.
465+ *
466+ * @see Permission
467+ * @see Permissions
468+ *
469+ *
470+ * @author Roland Schemers
471+ *
472+ * @serial include
473+ */
474+
475+final class PermissionsHash extends PermissionCollection
476+implements Serializable
477+{
478+ /**
479+ * Key and value are (same) permissions objects.
480+ * Not serialized; see serialization section at end of class.
481+ */
482+ private transient Map<Permission, Permission> permsMap;
483+
484+ /**
485+ * Create an empty PermissionsHash object.
486+ */
487+
488+ PermissionsHash() {
489+ permsMap = new HashMap<Permission, Permission>(11);
490+ }
491+
492+ /**
493+ * Adds a permission to the PermissionsHash.
494+ *
495+ * @param permission the Permission object to add.
496+ */
497+
498+ public void add(Permission permission) {
499+ synchronized (this) {
500+ permsMap.put(permission, permission);
501+ }
502+ }
503+
504+ /**
505+ * Check and see if this set of permissions implies the permissions
506+ * expressed in "permission".
507+ *
508+ * @param permission the Permission object to compare
509+ *
510+ * @return true if "permission" is a proper subset of a permission in
511+ * the set, false if not.
512+ */
513+
514+ public boolean implies(Permission permission) {
515+ // attempt a fast lookup and implies. If that fails
516+ // then enumerate through all the permissions.
517+ synchronized (this) {
518+ Permission p = permsMap.get(permission);
519+
520+ // If permission is found, then p.equals(permission)
521+ if (p == null) {
522+ for (Permission p_ : permsMap.values()) {
523+ if (p_.implies(permission))
524+ return true;
525+ }
526+ return false;
527+ } else {
528+ return true;
529+ }
530+ }
531+ }
532+
533+ /**
534+ * Returns an enumeration of all the Permission objects in the container.
535+ *
536+ * @return an enumeration of all the Permissions.
537+ */
538+
539+ public Enumeration<Permission> elements() {
540+ // Convert Iterator of Map values into an Enumeration
541+ synchronized (this) {
542+ return Collections.enumeration(permsMap.values());
543+ }
544+ }
545+
546+ private static final long serialVersionUID = -8491988220802933440L;
547+ // Need to maintain serialization interoperability with earlier releases,
548+ // which had the serializable field:
549+ // private Hashtable perms;
550+ /**
551+ * @serialField perms java.util.Hashtable
552+ * A table of the Permissions (both key and value are same).
553+ */
554+ private static final ObjectStreamField[] serialPersistentFields = {
555+ new ObjectStreamField("perms", Hashtable.class),
556+ };
557+
558+ /**
559+ * @serialData Default fields.
560+ */
561+ /*
562+ * Writes the contents of the permsMap field out as a Hashtable for
563+ * serialization compatibility with earlier releases.
564+ */
565+ private void writeObject(ObjectOutputStream out) throws IOException {
566+ // Don't call out.defaultWriteObject()
567+
568+ // Copy perms into a Hashtable
569+ Hashtable<Permission, Permission> perms =
570+ new Hashtable<>(permsMap.size()*2);
571+ synchronized (this) {
572+ perms.putAll(permsMap);
573+ }
574+
575+ // Write out serializable fields
576+ ObjectOutputStream.PutField pfields = out.putFields();
577+ pfields.put("perms", perms);
578+ out.writeFields();
579+ }
580+
581+ /*
582+ * Reads in a Hashtable of Permission/Permission and saves them in the
583+ * permsMap field.
584+ */
585+ private void readObject(ObjectInputStream in) throws IOException,
586+ ClassNotFoundException {
587+ // Don't call defaultReadObject()
588+
589+ // Read in serialized fields
590+ ObjectInputStream.GetField gfields = in.readFields();
591+
592+ // Get permissions
593+ Hashtable<Permission, Permission> perms =
594+ (Hashtable<Permission, Permission>)gfields.get("perms", null);
595+ permsMap = new HashMap<Permission, Permission>(perms.size()*2);
596+ permsMap.putAll(perms);
597+ }
598+}