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