001 /*
002 * Copyright 1997-2006 Sun Microsystems, Inc. All Rights Reserved.
003 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
004 *
005 * This code is free software; you can redistribute it and/or modify it
006 * under the terms of the GNU General Public License version 2 only, as
007 * published by the Free Software Foundation. Sun designates this
008 * particular file as subject to the "Classpath" exception as provided
009 * by Sun in the LICENSE file that accompanied this code.
010 *
011 * This code is distributed in the hope that it will be useful, but WITHOUT
012 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
013 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
014 * version 2 for more details (a copy is included in the LICENSE file that
015 * accompanied this code).
016 *
017 * You should have received a copy of the GNU General Public License version
018 * 2 along with this work; if not, write to the Free Software Foundation,
019 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
020 *
021 * Please contact Sun Microsystems, Inc., 4150 Network Circle, Santa Clara,
022 * CA 95054 USA or visit www.sun.com if you need additional information or
023 * have any questions.
024 */
025
026 package java.security;
027
028 import java.io.*;
029 import java.lang.RuntimePermission;
030 import java.net.MalformedURLException;
031 import java.net.URL;
032 import java.util.Enumeration;
033 import java.util.Hashtable;
034 import java.util.Vector;
035 import java.util.StringTokenizer;
036 import java.util.PropertyPermission;
037
038 import java.lang.reflect.*;
039
040 import java.util.WeakHashMap;
041 import sun.security.util.Debug;
042 import sun.security.jca.GetInstance;
043 import sun.security.util.SecurityConstants;
044
045 /**
046 * A Policy object is responsible for determining whether code executing
047 * in the Java runtime environment has permission to perform a
048 * security-sensitive operation.
049 *
050 * <p> There is only one Policy object installed in the runtime at any
051 * given time. A Policy object can be installed by calling the
052 * <code>setPolicy</code> method. The installed Policy object can be
053 * obtained by calling the <code>getPolicy</code> method.
054 *
055 * <p> If no Policy object has been installed in the runtime, a call to
056 * <code>getPolicy</code> installs an instance of the default Policy
057 * implementation (a default subclass implementation of this abstract class).
058 * The default Policy implementation can be changed by setting the value
059 * of the "policy.provider" security property (in the Java security properties
060 * file) to the fully qualified name of the desired Policy subclass
061 * implementation. The Java security properties file is located in the
062 * file named <JAVA_HOME>/lib/security/java.security.
063 * <JAVA_HOME> refers to the value of the java.home system property,
064 * and specifies the directory where the JRE is installed.
065 *
066 * <p> Application code can directly subclass Policy to provide a custom
067 * implementation. In addition, an instance of a Policy object can be
068 * constructed by invoking one of the <code>getInstance</code> factory methods
069 * with a standard type. The default policy type is "JavaPolicy".
070 * See Appendix A in the <a href="../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
071 * Java Cryptography Architecture API Specification & Reference </a>
072 * for a list of standard Policy types.
073 *
074 * <p> Once a Policy instance has been installed (either by default, or by
075 * calling <code>setPolicy</code>),
076 * the Java runtime invokes its <code>implies</code> when it needs to
077 * determine whether executing code (encapsulated in a ProtectionDomain)
078 * can perform SecurityManager-protected operations. How a Policy object
079 * retrieves its policy data is up to the Policy implementation itself.
080 * The policy data may be stored, for example, in a flat ASCII file,
081 * in a serialized binary file of the Policy class, or in a database.
082 *
083 * <p> The <code>refresh</code> method causes the policy object to
084 * refresh/reload its data. This operation is implementation-dependent.
085 * For example, if the policy object stores its data in configuration files,
086 * calling <code>refresh</code> will cause it to re-read the configuration
087 * policy files. If a refresh operation is not supported, this method does
088 * nothing. Note that refreshed policy may not have an effect on classes
089 * in a particular ProtectionDomain. This is dependent on the Policy
090 * provider's implementation of the <code>implies</code>
091 * method and its PermissionCollection caching strategy.
092 *
093 * @author Roland Schemers
094 * @author Gary Ellison
095 * @version 1.109, 05/05/07
096 * @see java.security.Provider
097 * @see java.security.ProtectionDomain
098 * @see java.security.Permission
099 */
100
101 public abstract class Policy {
102
103 /**
104 * A read-only empty PermissionCollection instance.
105 * @since 1.6
106 */
107 public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION = new UnsupportedEmptyCollection();
108
109 /** the system-wide policy. */
110 private static Policy policy; // package private for AccessControlContext
111
112 private static final Debug debug = Debug.getInstance("policy");
113
114 // Cache mapping ProtectionDomain to PermissionCollection
115 private WeakHashMap<ProtectionDomain, PermissionCollection> pdMapping;
116
117 /** package private for AccessControlContext */
118 static boolean isSet() {
119 return policy != null;
120 }
121
122 private static void checkPermission(String type) {
123 SecurityManager sm = System.getSecurityManager();
124 if (sm != null) {
125 sm.checkPermission(new SecurityPermission("createPolicy."
126 + type));
127 }
128 }
129
130 /**
131 * Returns the installed Policy object. This value should not be cached,
132 * as it may be changed by a call to <code>setPolicy</code>.
133 * This method first calls
134 * <code>SecurityManager.checkPermission</code> with a
135 * <code>SecurityPermission("getPolicy")</code> permission
136 * to ensure it's ok to get the Policy object..
137 *
138 * @return the installed Policy.
139 *
140 * @throws SecurityException
141 * if a security manager exists and its
142 * <code>checkPermission</code> method doesn't allow
143 * getting the Policy object.
144 *
145 * @see SecurityManager#checkPermission(Permission)
146 * @see #setPolicy(java.security.Policy)
147 */
148 public static Policy getPolicy() {
149 SecurityManager sm = System.getSecurityManager();
150 if (sm != null)
151 sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
152 return getPolicyNoCheck();
153 }
154
155 /**
156 * Returns the installed Policy object, skipping the security check.
157 * Used by SecureClassLoader and getPolicy.
158 *
159 * @return the installed Policy.
160 *
161 */
162 static synchronized Policy getPolicyNoCheck() {
163 if (policy == null) {
164 String policy_class = null;
165 policy_class = AccessController
166 .doPrivileged(new PrivilegedAction<String>() {
167 public String run() {
168 return Security
169 .getProperty("policy.provider");
170 }
171 });
172 if (policy_class == null) {
173 policy_class = "sun.security.provider.PolicyFile";
174 }
175
176 try {
177 policy = (Policy) Class.forName(policy_class)
178 .newInstance();
179 } catch (Exception e) {
180 /*
181 * The policy_class seems to be an extension
182 * so we have to bootstrap loading it via a policy
183 * provider that is on the bootclasspath
184 * If it loads then shift gears to using the configured
185 * provider.
186 */
187
188 // install the bootstrap provider to avoid recursion
189 policy = new sun.security.provider.PolicyFile();
190
191 final String pc = policy_class;
192 Policy p = AccessController
193 .doPrivileged(new PrivilegedAction<Policy>() {
194 public Policy run() {
195 try {
196 ClassLoader cl = ClassLoader
197 .getSystemClassLoader();
198 // we want the extension loader
199 ClassLoader extcl = null;
200 while (cl != null) {
201 extcl = cl;
202 cl = cl.getParent();
203 }
204 return (extcl != null ? (Policy) Class
205 .forName(pc, true, extcl)
206 .newInstance()
207 : null);
208 } catch (Exception e) {
209 if (debug != null) {
210 debug
211 .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
229 .println("using sun.security.provider.PolicyFile");
230 }
231 }
232 }
233 }
234 return policy;
235 }
236
237 /**
238 * Sets the system-wide Policy object. This method first calls
239 * <code>SecurityManager.checkPermission</code> with a
240 * <code>SecurityPermission("setPolicy")</code>
241 * permission to ensure it's ok to set the Policy.
242 *
243 * @param p the new system Policy object.
244 *
245 * @throws SecurityException
246 * if a security manager exists and its
247 * <code>checkPermission</code> method doesn't allow
248 * setting the Policy.
249 *
250 * @see SecurityManager#checkPermission(Permission)
251 * @see #getPolicy()
252 *
253 */
254 public static void setPolicy(Policy p) {
255 SecurityManager sm = System.getSecurityManager();
256 if (sm != null)
257 sm.checkPermission(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 = AccessController
295 .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 = new WeakHashMap<ProtectionDomain, PermissionCollection>();
310 }
311 }
312
313 if (policyDomain.getCodeSource() != null) {
314 if (Policy.isSet()) {
315 policyPerms = policy.getPermissions(policyDomain);
316 }
317
318 if (policyPerms == null) { // assume it has all
319 policyPerms = new Permissions();
320 policyPerms.add(SecurityConstants.ALL_PERMISSION);
321 }
322
323 synchronized (p.pdMapping) {
324 // cache of pd to permissions
325 p.pdMapping.put(policyDomain, policyPerms);
326 }
327 }
328 return;
329 }
330
331 /**
332 * Returns a Policy object of the specified type.
333 *
334 * <p> This method traverses the list of registered security providers,
335 * starting with the most preferred Provider.
336 * A new Policy object encapsulating the
337 * PolicySpi implementation from the first
338 * Provider that supports the specified type is returned.
339 *
340 * <p> Note that the list of registered providers may be retrieved via
341 * the {@link Security#getProviders() Security.getProviders()} method.
342 *
343 * @param type the specified Policy type. See Appendix A in the
344 * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
345 * Java Cryptography Architecture API Specification & Reference </a>
346 * for a list of standard Policy types.
347 *
348 * @param params parameters for the Policy, which may be null.
349 *
350 * @return the new Policy object.
351 *
352 * @exception SecurityException if the caller does not have permission
353 * to get a Policy instance for the specified type.
354 *
355 * @exception NullPointerException if the specified type is null.
356 *
357 * @exception IllegalArgumentException if the specified parameters
358 * are not understood by the PolicySpi implementation
359 * from the selected Provider.
360 *
361 * @exception NoSuchAlgorithmException if no Provider supports a PolicySpi
362 * implementation for the specified type.
363 *
364 * @see Provider
365 * @since 1.6
366 */
367 public static Policy getInstance(String type,
368 Policy.Parameters params) throws NoSuchAlgorithmException {
369
370 checkPermission(type);
371 try {
372 GetInstance.Instance instance = GetInstance.getInstance(
373 "Policy", PolicySpi.class, type, params);
374 return new PolicyDelegate((PolicySpi) instance.impl,
375 instance.provider, type, params);
376 } catch (NoSuchAlgorithmException nsae) {
377 return handleException(nsae);
378 }
379 }
380
381 /**
382 * Returns a Policy object of the specified type.
383 *
384 * <p> A new Policy object encapsulating the
385 * PolicySpi implementation from the specified provider
386 * is returned. The specified provider must be registered
387 * in the provider list.
388 *
389 * <p> Note that the list of registered providers may be retrieved via
390 * the {@link Security#getProviders() Security.getProviders()} method.
391 *
392 * @param type the specified Policy type. See Appendix A in the
393 * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
394 * Java Cryptography Architecture API Specification & Reference </a>
395 * for a list of standard Policy types.
396 *
397 * @param params parameters for the Policy, which may be null.
398 *
399 * @param provider the provider.
400 *
401 * @return the new Policy object.
402 *
403 * @exception SecurityException if the caller does not have permission
404 * to get a Policy instance for the specified type.
405 *
406 * @exception NullPointerException if the specified type is null.
407 *
408 * @exception IllegalArgumentException if the specified provider
409 * is null or empty,
410 * or if the specified parameters are not understood by
411 * the PolicySpi implementation from the specified provider.
412 *
413 * @exception NoSuchProviderException if the specified provider is not
414 * registered in the security provider list.
415 *
416 * @exception NoSuchAlgorithmException if the specified provider does not
417 * support a PolicySpi implementation for the specified type.
418 *
419 * @see Provider
420 * @since 1.6
421 */
422 public static Policy getInstance(String type,
423 Policy.Parameters params, String provider)
424 throws NoSuchProviderException, NoSuchAlgorithmException {
425
426 if (provider == null || provider.length() == 0) {
427 throw new IllegalArgumentException("missing provider");
428 }
429
430 checkPermission(type);
431 try {
432 GetInstance.Instance instance = GetInstance.getInstance(
433 "Policy", PolicySpi.class, type, params, provider);
434 return new PolicyDelegate((PolicySpi) instance.impl,
435 instance.provider, type, params);
436 } catch (NoSuchAlgorithmException nsae) {
437 return handleException(nsae);
438 }
439 }
440
441 /**
442 * Returns a Policy object of the specified type.
443 *
444 * <p> A new Policy object encapsulating the
445 * PolicySpi implementation from the specified Provider
446 * object is returned. Note that the specified Provider object
447 * does not have to be registered in the provider list.
448 *
449 * @param type the specified Policy type. See Appendix A in the
450 * <a href="../../../technotes/guides/security/crypto/CryptoSpec.html#AppA">
451 * Java Cryptography Architecture API Specification & Reference </a>
452 * for a list of standard Policy types.
453 *
454 * @param params parameters for the Policy, which may be null.
455 *
456 * @param provider the Provider.
457 *
458 * @return the new Policy object.
459 *
460 * @exception SecurityException if the caller does not have permission
461 * to get a Policy instance for the specified type.
462 *
463 * @exception NullPointerException if the specified type is null.
464 *
465 * @exception IllegalArgumentException if the specified Provider is null,
466 * or if the specified parameters are not understood by
467 * the PolicySpi implementation from the specified Provider.
468 *
469 * @exception NoSuchAlgorithmException if the specified Provider does not
470 * support a PolicySpi implementation for the specified type.
471 *
472 * @see Provider
473 * @since 1.6
474 */
475 public static Policy getInstance(String type,
476 Policy.Parameters params, Provider provider)
477 throws NoSuchAlgorithmException {
478
479 if (provider == null) {
480 throw new IllegalArgumentException("missing provider");
481 }
482
483 checkPermission(type);
484 try {
485 GetInstance.Instance instance = GetInstance.getInstance(
486 "Policy", PolicySpi.class, type, params, provider);
487 return new PolicyDelegate((PolicySpi) instance.impl,
488 instance.provider, type, params);
489 } catch (NoSuchAlgorithmException nsae) {
490 return handleException(nsae);
491 }
492 }
493
494 private static Policy handleException(NoSuchAlgorithmException nsae)
495 throws NoSuchAlgorithmException {
496 Throwable cause = nsae.getCause();
497 if (cause instanceof IllegalArgumentException) {
498 throw (IllegalArgumentException) cause;
499 }
500 throw nsae;
501 }
502
503 /**
504 * Return the Provider of this Policy.
505 *
506 * <p> This Policy instance will only have a Provider if it
507 * was obtained via a call to <code>Policy.getInstance</code>.
508 * Otherwise this method returns null.
509 *
510 * @return the Provider of this Policy, or null.
511 *
512 * @since 1.6
513 */
514 public Provider getProvider() {
515 return null;
516 }
517
518 /**
519 * Return the type of this Policy.
520 *
521 * <p> This Policy instance will only have a type if it
522 * was obtained via a call to <code>Policy.getInstance</code>.
523 * Otherwise this method returns null.
524 *
525 * @return the type of this Policy, or null.
526 *
527 * @since 1.6
528 */
529 public String getType() {
530 return null;
531 }
532
533 /**
534 * Return Policy parameters.
535 *
536 * <p> This Policy instance will only have parameters if it
537 * was obtained via a call to <code>Policy.getInstance</code>.
538 * Otherwise this method returns null.
539 *
540 * @return Policy parameters, or null.
541 *
542 * @since 1.6
543 */
544 public Policy.Parameters getParameters() {
545 return null;
546 }
547
548 /**
549 * Return a PermissionCollection object containing the set of
550 * permissions granted to the specified CodeSource.
551 *
552 * <p> Applications are discouraged from calling this method
553 * since this operation may not be supported by all policy implementations.
554 * Applications should solely rely on the <code>implies</code> method
555 * to perform policy checks. If an application absolutely must call
556 * a getPermissions method, it should call
557 * <code>getPermissions(ProtectionDomain)</code>.
558 *
559 * <p> The default implementation of this method returns
560 * Policy.UNSUPPORTED_EMPTY_COLLECTION. This method can be
561 * overridden if the policy implementation can return a set of
562 * permissions granted to a CodeSource.
563 *
564 * @param codesource the CodeSource to which the returned
565 * PermissionCollection has been granted.
566 *
567 * @return a set of permissions granted to the specified CodeSource.
568 * If this operation is supported, the returned
569 * set of permissions must be a new mutable instance
570 * and it must support heterogeneous Permission types.
571 * If this operation is not supported,
572 * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
573 */
574 public PermissionCollection getPermissions(CodeSource codesource) {
575 return Policy.UNSUPPORTED_EMPTY_COLLECTION;
576 }
577
578 /**
579 * Return a PermissionCollection object containing the set of
580 * permissions granted to the specified ProtectionDomain.
581 *
582 * <p> Applications are discouraged from calling this method
583 * since this operation may not be supported by all policy implementations.
584 * Applications should rely on the <code>implies</code> method
585 * to perform policy checks.
586 *
587 * <p> The default implementation of this method first retrieves
588 * the permissions returned via <code>getPermissions(CodeSource)</code>
589 * (the CodeSource is taken from the specified ProtectionDomain),
590 * as well as the permissions located inside the specified ProtectionDomain.
591 * All of these permissions are then combined and returned in a new
592 * PermissionCollection object. If <code>getPermissions(CodeSource)</code>
593 * returns Policy.UNSUPPORTED_EMPTY_COLLECTION, then this method
594 * returns the permissions contained inside the specified ProtectionDomain
595 * in a new PermissionCollection object.
596 *
597 * <p> This method can be overridden if the policy implementation
598 * supports returning a set of permissions granted to a ProtectionDomain.
599 *
600 * @param domain the ProtectionDomain to which the returned
601 * PermissionCollection has been granted.
602 *
603 * @return a set of permissions granted to the specified ProtectionDomain.
604 * If this operation is supported, the returned
605 * set of permissions must be a new mutable instance
606 * and it must support heterogeneous Permission types.
607 * If this operation is not supported,
608 * Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
609 *
610 * @since 1.4
611 */
612 public PermissionCollection getPermissions(ProtectionDomain domain) {
613 PermissionCollection pc = null;
614
615 if (domain == null)
616 return new Permissions();
617
618 if (pdMapping == null) {
619 initPolicy(this );
620 }
621
622 synchronized (pdMapping) {
623 pc = pdMapping.get(domain);
624 }
625
626 if (pc != null) {
627 Permissions perms = new Permissions();
628 synchronized (pc) {
629 for (Enumeration<Permission> e = pc.elements(); e
630 .hasMoreElements();) {
631 perms.add(e.nextElement());
632 }
633 }
634 return perms;
635 }
636
637 pc = getPermissions(domain.getCodeSource());
638 if (pc == null || pc == UNSUPPORTED_EMPTY_COLLECTION) {
639 pc = new Permissions();
640 }
641
642 addStaticPerms(pc, domain.getPermissions());
643 return pc;
644 }
645
646 /**
647 * add static permissions to provided permission collection
648 */
649 private void addStaticPerms(PermissionCollection perms,
650 PermissionCollection statics) {
651 if (statics != null) {
652 synchronized (statics) {
653 Enumeration<Permission> e = statics.elements();
654 while (e.hasMoreElements()) {
655 perms.add(e.nextElement());
656 }
657 }
658 }
659 }
660
661 /**
662 * Evaluates the global policy for the permissions granted to
663 * the ProtectionDomain and tests whether the permission is
664 * granted.
665 *
666 * @param domain the ProtectionDomain to test
667 * @param permission the Permission object to be tested for implication.
668 *
669 * @return true if "permission" is a proper subset of a permission
670 * granted to this ProtectionDomain.
671 *
672 * @see java.security.ProtectionDomain
673 * @since 1.4
674 */
675 public boolean implies(ProtectionDomain domain,
676 Permission permission) {
677 PermissionCollection pc;
678
679 if (pdMapping == null) {
680 initPolicy(this );
681 }
682
683 synchronized (pdMapping) {
684 pc = pdMapping.get(domain);
685 }
686
687 if (pc != null) {
688 return pc.implies(permission);
689 }
690
691 pc = getPermissions(domain);
692 if (pc == null) {
693 return false;
694 }
695
696 synchronized (pdMapping) {
697 // cache it
698 pdMapping.put(domain, pc);
699 }
700
701 return pc.implies(permission);
702 }
703
704 /**
705 * Refreshes/reloads the policy configuration. The behavior of this method
706 * depends on the implementation. For example, calling <code>refresh</code>
707 * on a file-based policy will cause the file to be re-read.
708 *
709 * <p> The default implementation of this method does nothing.
710 * This method should be overridden if a refresh operation is supported
711 * by the policy implementation.
712 */
713 public void refresh() {
714 }
715
716 /**
717 * This subclass is returned by the getInstance calls. All Policy calls
718 * are delegated to the underlying PolicySpi.
719 */
720 private static class PolicyDelegate extends Policy {
721
722 private PolicySpi spi;
723 private Provider p;
724 private String type;
725 private Policy.Parameters params;
726
727 private PolicyDelegate(PolicySpi spi, Provider p, String type,
728 Policy.Parameters params) {
729 this .spi = spi;
730 this .p = p;
731 this .type = type;
732 this .params = params;
733 }
734
735 public String getType() {
736 return type;
737 }
738
739 public Policy.Parameters getParameters() {
740 return params;
741 }
742
743 public Provider getProvider() {
744 return p;
745 }
746
747 public PermissionCollection getPermissions(CodeSource codesource) {
748 return spi.engineGetPermissions(codesource);
749 }
750
751 public PermissionCollection getPermissions(
752 ProtectionDomain domain) {
753 return spi.engineGetPermissions(domain);
754 }
755
756 public boolean implies(ProtectionDomain domain, Permission perm) {
757 return spi.engineImplies(domain, perm);
758 }
759
760 public void refresh() {
761 spi.engineRefresh();
762 }
763 }
764
765 /**
766 * This represents a marker interface for Policy parameters.
767 *
768 * @since 1.6
769 */
770 public static interface Parameters {
771 }
772
773 /**
774 * This class represents a read-only empty PermissionCollection object that
775 * is returned from the <code>getPermissions(CodeSource)</code> and
776 * <code>getPermissions(ProtectionDomain)</code>
777 * methods in the Policy class when those operations are not
778 * supported by the Policy implementation.
779 */
780 private static class UnsupportedEmptyCollection extends
781 PermissionCollection {
782
783 private Permissions perms;
784
785 /**
786 * Create a read-only empty PermissionCollection object.
787 */
788 public UnsupportedEmptyCollection() {
789 this .perms = new Permissions();
790 perms.setReadOnly();
791 }
792
793 /**
794 * Adds a permission object to the current collection of permission
795 * objects.
796 *
797 * @param permission the Permission object to add.
798 *
799 * @exception SecurityException - if this PermissionCollection object
800 * has been marked readonly
801 */
802 public void add(Permission permission) {
803 perms.add(permission);
804 }
805
806 /**
807 * Checks to see if the specified permission is implied by the
808 * collection of Permission objects held in this PermissionCollection.
809 *
810 * @param permission the Permission object to compare.
811 *
812 * @return true if "permission" is implied by the permissions in
813 * the collection, false if not.
814 */
815 public boolean implies(Permission permission) {
816 return perms.implies(permission);
817 }
818
819 /**
820 * Returns an enumeration of all the Permission objects in the
821 * collection.
822 *
823 * @return an enumeration of all the Permissions.
824 */
825 public Enumeration<Permission> elements() {
826 return perms.elements();
827 }
828 }
829 }
|