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