1 /*
2 * Copyright 1997-2006 Sun Microsystems, Inc. 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. Sun designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Sun 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 Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
22 * CA 95054 USA or visit www.sun.com if you need additional information or
23 * have any questions.
24 */
25
26
27 package java.security;
28
29 import java.io;
30 import java.lang.RuntimePermission;
31 import java.net.MalformedURLException;
32 import java.net.URL;
33 import java.util.Enumeration;
34 import java.util.Hashtable;
35 import java.util.Vector;
36 import java.util.StringTokenizer;
37 import java.util.PropertyPermission;
38
39 import java.lang.reflect;
40
41 import java.util.WeakHashMap;
42 import sun.security.util.Debug;
43 import sun.security.jca.GetInstance;
44 import sun.security.util.SecurityConstants;
45
46
47 /**
48 * A Policy object is responsible for determining whether code executing
49 * in the Java runtime environment has permission to perform a
50 * security-sensitive operation.
51 *
52 * <p> There is only one Policy object installed in the runtime at any
53 * given time. A Policy object can be installed by calling the
54 * <code>setPolicy</code> method. The installed Policy object can be
55 * obtained by calling the <code>getPolicy</code> method.
56 *
57 * <p> If no Policy object has been installed in the runtime, a call to
58 * <code>getPolicy</code> installs an instance of the default Policy
59 * implementation (a default subclass implementation of this abstract class).
60 * The default Policy implementation can be changed by setting the value
61 * of the "policy.provider" security property (in the Java security properties
62 * file) to the fully qualified name of the desired Policy subclass
63 * implementation. The Java security properties file is located in the
64 * file named <JAVA_HOME>/lib/security/java.security.
65 * <JAVA_HOME> refers to the value of the java.home system property,
66 * and specifies the directory where the JRE is installed.
67 *
68 * <p> Application code can directly subclass Policy to provide a custom
69 * implementation. In addition, an instance of a Policy object can be
70 * constructed by invoking one of the <code>getInstance</code> factory methods
71 * with a standard type. The default policy type is "JavaPolicy".
72 * See Appendix A in the <a href="../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
73 * Java Cryptography Architecture API Specification & Reference </a>
74 * for a list of standard Policy types.
75 *
76 * <p> Once a Policy instance has been installed (either by default, or by
77 * calling <code>setPolicy</code>),
78 * the Java runtime invokes its <code>implies</code> when it needs to
79 * determine whether executing code (encapsulated in a ProtectionDomain)
80 * can perform SecurityManager-protected operations. How a Policy object
81 * retrieves its policy data is up to the Policy implementation itself.
82 * The policy data may be stored, for example, in a flat ASCII file,
83 * in a serialized binary file of the Policy class, or in a database.
84 *
85 * <p> The <code>refresh</code> method causes the policy object to
86 * refresh/reload its data. This operation is implementation-dependent.
87 * For example, if the policy object stores its data in configuration files,
88 * calling <code>refresh</code> will cause it to re-read the configuration
89 * policy files. If a refresh operation is not supported, this method does
90 * nothing. Note that refreshed policy may not have an effect on classes
91 * in a particular ProtectionDomain. This is dependent on the Policy
92 * provider's implementation of the <code>implies</code>
93 * method and its PermissionCollection caching strategy.
94 *
95 * @author Roland Schemers
96 * @author Gary Ellison
97 * @see java.security.Provider
98 * @see java.security.ProtectionDomain
99 * @see java.security.Permission
100 */
101
102 public abstract class Policy {
103
104 /**
105 * A read-only empty PermissionCollection instance.
106 * @since 1.6
107 */
108 public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION =
109 new UnsupportedEmptyCollection();
110
111 /** the system-wide policy. */
112 private static Policy policy; // package private for AccessControlContext
113
114 private static final Debug debug = Debug.getInstance("policy");
115
116 // Cache mapping ProtectionDomain to PermissionCollection
117 private WeakHashMap<ProtectionDomain, PermissionCollection> pdMapping;
118
119 /** package private for AccessControlContext */
120 static boolean isSet()
121 {
122 return policy != null;
123 }
124
125 private static void checkPermission(String type) {
126 SecurityManager sm = System.getSecurityManager();
127 if (sm != null) {
128 sm.checkPermission(new SecurityPermission("createPolicy." + type));
129 }
130 }
131
132 /**
133 * Returns the installed Policy object. This value should not be cached,
134 * as it may be changed by a call to <code>setPolicy</code>.
135 * This method first calls
136 * <code>SecurityManager.checkPermission</code> with a
137 * <code>SecurityPermission("getPolicy")</code> permission
138 * to ensure it's ok to get the Policy object..
139 *
140 * @return the installed Policy.
141 *
142 * @throws SecurityException
143 * if a security manager exists and its
144 * <code>checkPermission</code> method doesn't allow
145 * getting the Policy object.
146 *
147 * @see SecurityManager#checkPermission(Permission)
148 * @see #setPolicy(java.security.Policy)
149 */
150 public static Policy getPolicy()
151 {
152 SecurityManager sm = System.getSecurityManager();
153 if (sm != null)
154 sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
155 return getPolicyNoCheck();
156 }
157
158 /**
159 * Returns the installed Policy object, skipping the security check.
160 * Used by SecureClassLoader and getPolicy.
161 *
162 * @return the installed Policy.
163 *
164 */
165 static synchronized Policy getPolicyNoCheck()
166 {
167 if (policy == null) {
168 String policy_class = null;
169 policy_class = AccessController.doPrivileged(
170 new PrivilegedAction<String>() {
171 public String run() {
172 return Security.getProperty("policy.provider");
173 }
174 });
175 if (policy_class == null) {
176 policy_class = "sun.security.provider.PolicyFile";
177 }
178
179 try {
180 policy = (Policy)
181 Class.forName(policy_class).newInstance();
182 } catch (Exception e) {
183 /*
184 * The policy_class seems to be an extension
185 * so we have to bootstrap loading it via a policy
186 * provider that is on the bootclasspath
187 * If it loads then shift gears to using the configured
188 * provider.
189 */
190
191 // install the bootstrap provider to avoid recursion
192 policy = new sun.security.provider.PolicyFile();
193
194 final String pc = policy_class;
195 Policy p = AccessController.doPrivileged(
196 new PrivilegedAction<Policy>() {
197 public Policy run() {
198 try {
199 ClassLoader cl =
200 ClassLoader.getSystemClassLoader();
201 // we want the extension loader
202 ClassLoader extcl = null;
203 while (cl != null) {
204 extcl = cl;
205 cl = cl.getParent();
206 }
207 return (extcl != null ? (Policy)Class.forName(
208 pc, true, extcl).newInstance() : null);
209 } catch (Exception e) {
210 if (debug != null) {
211 debug.println("policy provider " +
212 pc +
213 " not available");
214 e.printStackTrace();
215 }
216 return null;
217 }
218 }
219 });
220 /*
221 * if it loaded install it as the policy provider. Otherwise
222 * continue to use the system default implementation
223 */
224 if (p != null) {
225 policy = p;
226 } else {
227 if (debug != null) {
228 debug.println("using sun.security.provider.PolicyFile");
229 }
230 }
231 }
232 }
233 return policy;
234 }
235
236 /**
237 * Sets the system-wide Policy object. This method first calls
238 * <code>SecurityManager.checkPermission</code> with a
239 * <code>SecurityPermission("setPolicy")</code>
240 * permission to ensure it's ok to set the Policy.
241 *
242 * @param p the new system Policy object.
243 *
244 * @throws SecurityException
245 * if a security manager exists and its
246 * <code>checkPermission</code> method doesn't allow
247 * setting the Policy.
248 *
249 * @see SecurityManager#checkPermission(Permission)
250 * @see #getPolicy()
251 *
252 */
253 public static void setPolicy(Policy p)
254 {
255 SecurityManager sm = System.getSecurityManager();
256 if (sm != null) sm.checkPermission(
257 new SecurityPermission("setPolicy"));
258 if (p != null) {
259 initPolicy(p);
260 }
261 synchronized (Policy.class) {
262 Policy.policy = p;
263 }
264 }
265
266 /**
267 * Initialize superclass state such that a legacy provider can
268 * handle queries for itself.
269 *
270 * @since 1.4
271 */
272 private static void initPolicy (final Policy p) {
273 /*
274 * A policy provider not on the bootclasspath could trigger
275 * security checks fulfilling a call to either Policy.implies
276 * or Policy.getPermissions. If this does occur the provider
277 * must be able to answer for it's own ProtectionDomain
278 * without triggering additional security checks, otherwise
279 * the policy implementation will end up in an infinite
280 * recursion.
281 *
282 * To mitigate this, the provider can collect it's own
283 * ProtectionDomain and associate a PermissionCollection while
284 * it is being installed. The currently installed policy
285 * provider (if there is one) will handle calls to
286 * Policy.implies or Policy.getPermissions during this
287 * process.
288 *
289 * This Policy superclass caches away the ProtectionDomain and
290 * statically binds permissions so that legacy Policy
291 * implementations will continue to function.
292 */
293
294 ProtectionDomain policyDomain =
295 AccessController.doPrivileged(new PrivilegedAction<ProtectionDomain>() {
296 public ProtectionDomain run() {
297 return p.getClass().getProtectionDomain();
298 }
299 });
300
301 /*
302 * Collect the permissions granted to this protection domain
303 * so that the provider can be security checked while processing
304 * calls to Policy.implies or Policy.getPermissions.
305 */
306 PermissionCollection policyPerms = null;
307 synchronized (p) {
308 if (p.pdMapping == null) {
309 p.pdMapping =
310 new WeakHashMap<ProtectionDomain, PermissionCollection>();
311 }
312 }
313
314 if (policyDomain.getCodeSource() != null) {
315 if (Policy.isSet()) {
316 policyPerms = policy.getPermissions(policyDomain);
317 }
318
319 if (policyPerms == null) { // assume it has all
320 policyPerms = new Permissions();
321 policyPerms.add(SecurityConstants.ALL_PERMISSION);
322 }
323
324 synchronized (p.pdMapping) {
325 // cache of pd to permissions
326 p.pdMapping.put(policyDomain, policyPerms);
327 }
328 }
329 return;
330 }
331
332
333 /**
334 * Returns a Policy object of the specified type.
335 *
336 * <p> This method traverses the list of registered security providers,
337 * starting with the most preferred Provider.
338 * A new Policy object encapsulating the
339 * PolicySpi implementation from the first
340 * Provider that supports the specified type is returned.
341 *
342 * <p> Note that the list of registered providers may be retrieved via
343 * the {@link Security#getProviders() Security.getProviders()} method.
344 *
345 * @param type the specified Policy type. See Appendix A in the
346 * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
347 * Java Cryptography Architecture API Specification & Reference </a>
348 * for a list of standard Policy types.
349 *
350 * @param params parameters for the Policy, which may be null.
351 *
352 * @return the new Policy object.
353 *
354 * @exception SecurityException if the caller does not have permission
355 * to get a Policy instance for the specified type.
356 *
357 * @exception NullPointerException if the specified type is null.
358 *
359 * @exception IllegalArgumentException if the specified parameters
360 * are not understood by the PolicySpi implementation
361 * from the selected Provider.
362 *
363 * @exception NoSuchAlgorithmException if no Provider supports a PolicySpi
364 * implementation for the specified type.
365 *
366 * @see Provider
367 * @since 1.6
368 */
369 public static Policy getInstance(String type, Policy.Parameters params)
370 throws NoSuchAlgorithmException {
371
372 checkPermission(type);
373 try {
374 GetInstance.Instance instance = GetInstance.getInstance("Policy",
375 PolicySpi.class,
376 type,
377 params);
378 return new PolicyDelegate((PolicySpi)instance.impl,
379 instance.provider,
380 type,
381 params);
382 } catch (NoSuchAlgorithmException nsae) {
383 return handleException(nsae);
384 }
385 }
386
387 /**
388 * Returns a Policy object of the specified type.
389 *
390 * <p> A new Policy object encapsulating the
391 * PolicySpi implementation from the specified provider
392 * is returned. The specified provider must be registered
393 * in the provider list.
394 *
395 * <p> Note that the list of registered providers may be retrieved via
396 * the {@link Security#getProviders() Security.getProviders()} method.
397 *
398 * @param type the specified Policy type. See Appendix A in the
399 * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
400 * Java Cryptography Architecture API Specification & Reference </a>
401 * for a list of standard Policy types.
402 *
403 * @param params parameters for the Policy, which may be null.
404 *
405 * @param provider the provider.
406 *
407 * @return the new Policy object.
408 *
409 * @exception SecurityException if the caller does not have permission
410 * to get a Policy instance for the specified type.
411 *
412 * @exception NullPointerException if the specified type is null.
413 *
414 * @exception IllegalArgumentException if the specified provider
415 * is null or empty,
416 * or if the specified parameters are not understood by
417 * the PolicySpi implementation from the specified provider.
418 *
419 * @exception NoSuchProviderException if the specified provider is not
420 * registered in the security provider list.
421 *
422 * @exception NoSuchAlgorithmException if the specified provider does not
423 * support a PolicySpi implementation for the specified type.
424 *
425 * @see Provider
426 * @since 1.6
427 */
428 public static Policy getInstance(String type,
429 Policy.Parameters params,
430 String provider)
431 throws NoSuchProviderException, NoSuchAlgorithmException {
432
433 if (provider == null || provider.length() == 0) {
434 throw new IllegalArgumentException("missing provider");
435 }
436
437 checkPermission(type);
438 try {
439 GetInstance.Instance instance = GetInstance.getInstance("Policy",
440 PolicySpi.class,
441 type,
442 params,
443 provider);
444 return new PolicyDelegate((PolicySpi)instance.impl,
445 instance.provider,
446 type,
447 params);
448 } catch (NoSuchAlgorithmException nsae) {
449 return handleException (nsae);
450 }
451 }
452
453 /**
454 * Returns a Policy object of the specified type.
455 *
456 * <p> A new Policy object encapsulating the
457 * PolicySpi implementation from the specified Provider
458 * object is returned. Note that the specified Provider object
459 * does not have to be registered in the provider list.
460 *
461 * @param type the specified Policy type. See Appendix A in the
462 * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
463 * Java Cryptography Architecture API Specification & Reference </a>
464 * for a list of standard Policy types.
465 *
466 * @param params parameters for the Policy, which may be null.
467 *
468 * @param provider the Provider.
469 *
470 * @return the new Policy object.
471 *
472 * @exception SecurityException if the caller does not have permission
473 * to get a Policy instance for the specified type.
474 *
475 * @exception NullPointerException if the specified type is null.
476 *
477 * @exception IllegalArgumentException if the specified Provider is null,
478 * or if the specified parameters are not understood by
479 * the PolicySpi implementation from the specified Provider.
480 *
481 * @exception NoSuchAlgorithmException if the specified Provider does not
482 * support a PolicySpi implementation for the specified type.
483 *
484 * @see Provider
485 * @since 1.6
486 */
487 public static Policy getInstance(String type,
488 Policy.Parameters params,
489 Provider provider)
490 throws NoSuchAlgorithmException {
491
492 if (provider == null) {
493 throw new IllegalArgumentException("missing provider");
494 }
495
496 checkPermission(type);
497 try {
498 GetInstance.Instance instance = GetInstance.getInstance("Policy",
499 PolicySpi.class,
500 type,
501 params,
502 provider);
503 return new PolicyDelegate((PolicySpi)instance.impl,
504 instance.provider,
505 type,
506 params);
507 } catch (NoSuchAlgorithmException nsae) {
508 return handleException (nsae);
509 }
510 }
511
512 private static Policy handleException(NoSuchAlgorithmException nsae)
513 throws NoSuchAlgorithmException {
514 Throwable cause = nsae.getCause();
515 if (cause instanceof IllegalArgumentException) {
516 throw (IllegalArgumentException)cause;
517 }
518 throw nsae;
519 }
520
521 /**
522 * Return the Provider of this Policy.
523 *
524 * <p> This Policy instance will only have a Provider if it
525 * was obtained via a call to <code>Policy.getInstance</code>.
526 * Otherwise this method returns null.
527 *
528 * @return the Provider of this Policy, or null.
529 *
530 * @since 1.6
531 */
532 public Provider getProvider() {
533 return null;
534 }
535
536 /**
537 * Return the type of this Policy.
538 *
539 * <p> This Policy instance will only have a type if it
540 * was obtained via a call to <code>Policy.getInstance</code>.
541 * Otherwise this method returns null.
542 *
543 * @return the type of this Policy, or null.
544 *
545 * @since 1.6
546 */
547 public String getType() {
548 return null;
549 }
550
551 /**
552 * Return Policy parameters.
553 *
554 * <p> This Policy instance will only have parameters if it
555 * was obtained via a call to <code>Policy.getInstance</code>.
556 * Otherwise this method returns null.
557 *
558 * @return Policy parameters, or null.
559 *
560 * @since 1.6
561 */
562 public Policy.Parameters getParameters() {
563 return null;
564 }
565
566 /**
567 * Return a PermissionCollection object containing the set of
568 * permissions granted to the specified CodeSource.
569 *
570 * <p> Applications are discouraged from calling this method
571 * since this operation may not be supported by all policy implementations.
572 * Applications should solely rely on the <code>implies</code> method
573 * to perform policy checks. If an application absolutely must call
574 * a getPermissions method, it should call
575 * <code>getPermissions(ProtectionDomain)</code>.
576 *
577 * <p> The default implementation of this method returns
578 * Policy.UNSUPPORTED_EMPTY_COLLECTION. This method can be
579 * overridden if the policy implementation can return a set of
580 * permissions granted to a CodeSource.
581 *
582 * @param codesource the CodeSource to which the returned
583 * PermissionCollection has been granted.
584 *
585 * @return a set of permissions granted to the specified CodeSource.
586 * If this operation is supported, the returned
587 * set of permissions must be a new mutable instance
588 * and it must support heterogeneous Permission types.
589 * If this operation is not supported,
590 * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
591 */
592 public PermissionCollection getPermissions(CodeSource codesource) {
593 return Policy.UNSUPPORTED_EMPTY_COLLECTION;
594 }
595
596 /**
597 * Return a PermissionCollection object containing the set of
598 * permissions granted to the specified ProtectionDomain.
599 *
600 * <p> Applications are discouraged from calling this method
601 * since this operation may not be supported by all policy implementations.
602 * Applications should rely on the <code>implies</code> method
603 * to perform policy checks.
604 *
605 * <p> The default implementation of this method first retrieves
606 * the permissions returned via <code>getPermissions(CodeSource)</code>
607 * (the CodeSource is taken from the specified ProtectionDomain),
608 * as well as the permissions located inside the specified ProtectionDomain.
609 * All of these permissions are then combined and returned in a new
610 * PermissionCollection object. If <code>getPermissions(CodeSource)</code>
611 * returns Policy.UNSUPPORTED_EMPTY_COLLECTION, then this method
612 * returns the permissions contained inside the specified ProtectionDomain
613 * in a new PermissionCollection object.
614 *
615 * <p> This method can be overridden if the policy implementation
616 * supports returning a set of permissions granted to a ProtectionDomain.
617 *
618 * @param domain the ProtectionDomain to which the returned
619 * PermissionCollection has been granted.
620 *
621 * @return a set of permissions granted to the specified ProtectionDomain.
622 * If this operation is supported, the returned
623 * set of permissions must be a new mutable instance
624 * and it must support heterogeneous Permission types.
625 * If this operation is not supported,
626 * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
627 *
628 * @since 1.4
629 */
630 public PermissionCollection getPermissions(ProtectionDomain domain) {
631 PermissionCollection pc = null;
632
633 if (domain == null)
634 return new Permissions();
635
636 if (pdMapping == null) {
637 initPolicy(this);
638 }
639
640 synchronized (pdMapping) {
641 pc = pdMapping.get(domain);
642 }
643
644 if (pc != null) {
645 Permissions perms = new Permissions();
646 synchronized (pc) {
647 for (Enumeration<Permission> e = pc.elements() ; e.hasMoreElements() ;) {
648 perms.add(e.nextElement());
649 }
650 }
651 return perms;
652 }
653
654 pc = getPermissions(domain.getCodeSource());
655 if (pc == null || pc == UNSUPPORTED_EMPTY_COLLECTION) {
656 pc = new Permissions();
657 }
658
659 addStaticPerms(pc, domain.getPermissions());
660 return pc;
661 }
662
663 /**
664 * add static permissions to provided permission collection
665 */
666 private void addStaticPerms(PermissionCollection perms,
667 PermissionCollection statics) {
668 if (statics != null) {
669 synchronized (statics) {
670 Enumeration<Permission> e = statics.elements();
671 while (e.hasMoreElements()) {
672 perms.add(e.nextElement());
673 }
674 }
675 }
676 }
677
678 /**
679 * Evaluates the global policy for the permissions granted to
680 * the ProtectionDomain and tests whether the permission is
681 * granted.
682 *
683 * @param domain the ProtectionDomain to test
684 * @param permission the Permission object to be tested for implication.
685 *
686 * @return true if "permission" is a proper subset of a permission
687 * granted to this ProtectionDomain.
688 *
689 * @see java.security.ProtectionDomain
690 * @since 1.4
691 */
692 public boolean implies(ProtectionDomain domain, Permission permission) {
693 PermissionCollection pc;
694
695 if (pdMapping == null) {
696 initPolicy(this);
697 }
698
699 synchronized (pdMapping) {
700 pc = pdMapping.get(domain);
701 }
702
703 if (pc != null) {
704 return pc.implies(permission);
705 }
706
707 pc = getPermissions(domain);
708 if (pc == null) {
709 return false;
710 }
711
712 synchronized (pdMapping) {
713 // cache it
714 pdMapping.put(domain, pc);
715 }
716
717 return pc.implies(permission);
718 }
719
720 /**
721 * Refreshes/reloads the policy configuration. The behavior of this method
722 * depends on the implementation. For example, calling <code>refresh</code>
723 * on a file-based policy will cause the file to be re-read.
724 *
725 * <p> The default implementation of this method does nothing.
726 * This method should be overridden if a refresh operation is supported
727 * by the policy implementation.
728 */
729 public void refresh() { }
730
731 /**
732 * This subclass is returned by the getInstance calls. All Policy calls
733 * are delegated to the underlying PolicySpi.
734 */
735 private static class PolicyDelegate extends Policy {
736
737 private PolicySpi spi;
738 private Provider p;
739 private String type;
740 private Policy.Parameters params;
741
742 private PolicyDelegate(PolicySpi spi, Provider p,
743 String type, Policy.Parameters params) {
744 this.spi = spi;
745 this.p = p;
746 this.type = type;
747 this.params = params;
748 }
749
750 public String getType() { return type; }
751
752 public Policy.Parameters getParameters() { return params; }
753
754 public Provider getProvider() { return p; }
755
756 public PermissionCollection getPermissions(CodeSource codesource) {
757 return spi.engineGetPermissions(codesource);
758 }
759 public PermissionCollection getPermissions(ProtectionDomain domain) {
760 return spi.engineGetPermissions(domain);
761 }
762 public boolean implies(ProtectionDomain domain, Permission perm) {
763 return spi.engineImplies(domain, perm);
764 }
765 public void refresh() {
766 spi.engineRefresh();
767 }
768 }
769
770 /**
771 * This represents a marker interface for Policy parameters.
772 *
773 * @since 1.6
774 */
775 public static interface Parameters { }
776
777 /**
778 * This class represents a read-only empty PermissionCollection object that
779 * is returned from the <code>getPermissions(CodeSource)</code> and
780 * <code>getPermissions(ProtectionDomain)</code>
781 * methods in the Policy class when those operations are not
782 * supported by the Policy implementation.
783 */
784 private static class UnsupportedEmptyCollection
785 extends PermissionCollection {
786
787 private Permissions perms;
788
789 /**
790 * Create a read-only empty PermissionCollection object.
791 */
792 public UnsupportedEmptyCollection() {
793 this.perms = new Permissions();
794 perms.setReadOnly();
795 }
796
797 /**
798 * Adds a permission object to the current collection of permission
799 * objects.
800 *
801 * @param permission the Permission object to add.
802 *
803 * @exception SecurityException - if this PermissionCollection object
804 * has been marked readonly
805 */
806 public void add(Permission permission) {
807 perms.add(permission);
808 }
809
810 /**
811 * Checks to see if the specified permission is implied by the
812 * collection of Permission objects held in this PermissionCollection.
813 *
814 * @param permission the Permission object to compare.
815 *
816 * @return true if "permission" is implied by the permissions in
817 * the collection, false if not.
818 */
819 public boolean implies(Permission permission) {
820 return perms.implies(permission);
821 }
822
823 /**
824 * Returns an enumeration of all the Permission objects in the
825 * collection.
826 *
827 * @return an enumeration of all the Permissions.
828 */
829 public Enumeration<Permission> elements() {
830 return perms.elements();
831 }
832 }
833 }