1 /*
   2  * Copyright (c) 1997, 2016, 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(new PrivilegedAction<>() {
 194                 @Override
 195                 public String run() {
 196                     return Security.getProperty("policy.provider");
 197                 }
 198             });
 199 
 200         /*
 201          * If policy.provider is not set or is set to the default provider,
 202          * simply instantiate it and return.
 203          */
 204         if (policyProvider == null || policyProvider.isEmpty() ||
 205             policyProvider.equals(DEFAULT_POLICY))
 206         {
 207             Policy polFile = new sun.security.provider.PolicyFile();
 208             policy.set(new PolicyInfo(polFile, true));
 209             return polFile;
 210         }
 211 
 212         /*
 213          * Locate, load, and instantiate the policy.provider impl using
 214          * the system class loader. While doing so, install the bootstrap
 215          * provider to avoid potential recursion.
 216          */
 217         Policy polFile = new sun.security.provider.PolicyFile();
 218         policy.set(new PolicyInfo(polFile, false));
 219 
 220         Policy pol = AccessController.doPrivileged(new PrivilegedAction<>() {
 221             @Override
 222             public Policy run() {
 223                 try {
 224                     ClassLoader scl = ClassLoader.getSystemClassLoader();
 225                     @SuppressWarnings("deprecation")
 226                     Object o = Class.forName(policyProvider, true, scl).newInstance();
 227                     return (Policy)o;
 228                 } catch (Exception e) {
 229                     if (debug != null) {
 230                         debug.println("policy provider " + policyProvider +
 231                                       " not available");
 232                         e.printStackTrace();
 233                     }
 234                     return null;
 235                 }
 236             }
 237         });
 238 
 239         if (pol == null) {
 240             // Fallback and use the system default implementation
 241             if (debug != null) {
 242                 debug.println("using " + DEFAULT_POLICY);
 243             }
 244             pol = polFile;
 245         }
 246         policy.set(new PolicyInfo(pol, true));
 247         return pol;
 248     }
 249 
 250     /**
 251      * Sets the system-wide Policy object. This method first calls
 252      * {@code SecurityManager.checkPermission} with a
 253      * {@code SecurityPermission("setPolicy")}
 254      * permission to ensure it's ok to set the Policy.
 255      *
 256      * @param p the new system Policy object.
 257      *
 258      * @throws SecurityException
 259      *        if a security manager exists and its
 260      *        {@code checkPermission} method doesn't allow
 261      *        setting the Policy.
 262      *
 263      * @see SecurityManager#checkPermission(Permission)
 264      * @see #getPolicy()
 265      *
 266      */
 267     public static void setPolicy(Policy p)
 268     {
 269         SecurityManager sm = System.getSecurityManager();
 270         if (sm != null) sm.checkPermission(
 271                                  new SecurityPermission("setPolicy"));
 272         if (p != null) {
 273             initPolicy(p);
 274         }
 275         synchronized (Policy.class) {
 276             policy.set(new PolicyInfo(p, p != null));
 277         }
 278     }
 279 
 280     /**
 281      * Initialize superclass state such that a legacy provider can
 282      * handle queries for itself.
 283      *
 284      * @since 1.4
 285      */
 286     private static void initPolicy (final Policy p) {
 287         /*
 288          * A policy provider not on the bootclasspath could trigger
 289          * security checks fulfilling a call to either Policy.implies
 290          * or Policy.getPermissions. If this does occur the provider
 291          * must be able to answer for it's own ProtectionDomain
 292          * without triggering additional security checks, otherwise
 293          * the policy implementation will end up in an infinite
 294          * recursion.
 295          *
 296          * To mitigate this, the provider can collect it's own
 297          * ProtectionDomain and associate a PermissionCollection while
 298          * it is being installed. The currently installed policy
 299          * provider (if there is one) will handle calls to
 300          * Policy.implies or Policy.getPermissions during this
 301          * process.
 302          *
 303          * This Policy superclass caches away the ProtectionDomain and
 304          * statically binds permissions so that legacy Policy
 305          * implementations will continue to function.
 306          */
 307 
 308         ProtectionDomain policyDomain =
 309         AccessController.doPrivileged(new PrivilegedAction<>() {
 310             public ProtectionDomain run() {
 311                 return p.getClass().getProtectionDomain();
 312             }
 313         });
 314 
 315         /*
 316          * Collect the permissions granted to this protection domain
 317          * so that the provider can be security checked while processing
 318          * calls to Policy.implies or Policy.getPermissions.
 319          */
 320         PermissionCollection policyPerms = null;
 321         synchronized (p) {
 322             if (p.pdMapping == null) {
 323                 p.pdMapping = new WeakHashMap<>();
 324            }
 325         }
 326 
 327         if (policyDomain.getCodeSource() != null) {
 328             Policy pol = policy.get().policy;
 329             if (pol != null) {
 330                 policyPerms = pol.getPermissions(policyDomain);
 331             }
 332 
 333             if (policyPerms == null) { // assume it has all
 334                 policyPerms = new Permissions();
 335                 policyPerms.add(SecurityConstants.ALL_PERMISSION);
 336             }
 337 
 338             synchronized (p.pdMapping) {
 339                 // cache of pd to permissions
 340                 p.pdMapping.put(policyDomain.key, policyPerms);
 341             }
 342         }
 343         return;
 344     }
 345 
 346 
 347     /**
 348      * Returns a Policy object of the specified type.
 349      *
 350      * <p> This method traverses the list of registered security providers,
 351      * starting with the most preferred Provider.
 352      * A new Policy object encapsulating the
 353      * PolicySpi implementation from the first
 354      * Provider that supports the specified type is returned.
 355      *
 356      * <p> Note that the list of registered providers may be retrieved via
 357      * the {@link Security#getProviders() Security.getProviders()} method.
 358      *
 359      * @implNote
 360      * The JDK Reference Implementation additionally uses the
 361      * {@code jdk.security.provider.preferred}
 362      * {@link Security#getProperty(String) Security} property to determine
 363      * the preferred provider order for the specified algorithm. This
 364      * may be different than the order of providers returned by
 365      * {@link Security#getProviders() Security.getProviders()}.
 366      *
 367      * @param type the specified Policy type.  See the Policy section in the
 368      *    <a href=
 369      *    "{@docRoot}/../technotes/guides/security/StandardNames.html#Policy">
 370      *    Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 371      *    for a list of standard Policy types.
 372      *
 373      * @param params parameters for the Policy, which may be null.
 374      *
 375      * @return the new Policy object.
 376      *
 377      * @exception SecurityException if the caller does not have permission
 378      *          to get a Policy instance for the specified type.
 379      *
 380      * @exception NullPointerException if the specified type is null.
 381      *
 382      * @exception IllegalArgumentException if the specified parameters
 383      *          are not understood by the PolicySpi implementation
 384      *          from the selected Provider.
 385      *
 386      * @exception NoSuchAlgorithmException if no Provider supports a PolicySpi
 387      *          implementation for the specified type.
 388      *
 389      * @see Provider
 390      * @since 1.6
 391      */
 392     public static Policy getInstance(String type, Policy.Parameters params)
 393                 throws NoSuchAlgorithmException {
 394 
 395         checkPermission(type);
 396         try {
 397             GetInstance.Instance instance = GetInstance.getInstance("Policy",
 398                                                         PolicySpi.class,
 399                                                         type,
 400                                                         params);
 401             return new PolicyDelegate((PolicySpi)instance.impl,
 402                                                         instance.provider,
 403                                                         type,
 404                                                         params);
 405         } catch (NoSuchAlgorithmException nsae) {
 406             return handleException(nsae);
 407         }
 408     }
 409 
 410     /**
 411      * Returns a Policy object of the specified type.
 412      *
 413      * <p> A new Policy object encapsulating the
 414      * PolicySpi implementation from the specified provider
 415      * is returned.   The specified provider must be registered
 416      * in the provider list.
 417      *
 418      * <p> Note that the list of registered providers may be retrieved via
 419      * the {@link Security#getProviders() Security.getProviders()} method.
 420      *
 421      * @param type the specified Policy type.  See the Policy section in the
 422      *    <a href=
 423      *    "{@docRoot}/../technotes/guides/security/StandardNames.html#Policy">
 424      *    Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 425      *    for a list of standard Policy types.
 426      *
 427      * @param params parameters for the Policy, which may be null.
 428      *
 429      * @param provider the provider.
 430      *
 431      * @return the new Policy object.
 432      *
 433      * @exception SecurityException if the caller does not have permission
 434      *          to get a Policy instance for the specified type.
 435      *
 436      * @exception NullPointerException if the specified type is null.
 437      *
 438      * @exception IllegalArgumentException if the specified provider
 439      *          is null or empty,
 440      *          or if the specified parameters are not understood by
 441      *          the PolicySpi implementation from the specified provider.
 442      *
 443      * @exception NoSuchProviderException if the specified provider is not
 444      *          registered in the security provider list.
 445      *
 446      * @exception NoSuchAlgorithmException if the specified provider does not
 447      *          support a PolicySpi implementation for the specified type.
 448      *
 449      * @see Provider
 450      * @since 1.6
 451      */
 452     public static Policy getInstance(String type,
 453                                 Policy.Parameters params,
 454                                 String provider)
 455                 throws NoSuchProviderException, NoSuchAlgorithmException {
 456 
 457         if (provider == null || provider.length() == 0) {
 458             throw new IllegalArgumentException("missing provider");
 459         }
 460 
 461         checkPermission(type);
 462         try {
 463             GetInstance.Instance instance = GetInstance.getInstance("Policy",
 464                                                         PolicySpi.class,
 465                                                         type,
 466                                                         params,
 467                                                         provider);
 468             return new PolicyDelegate((PolicySpi)instance.impl,
 469                                                         instance.provider,
 470                                                         type,
 471                                                         params);
 472         } catch (NoSuchAlgorithmException nsae) {
 473             return handleException(nsae);
 474         }
 475     }
 476 
 477     /**
 478      * Returns a Policy object of the specified type.
 479      *
 480      * <p> A new Policy object encapsulating the
 481      * PolicySpi implementation from the specified Provider
 482      * object is returned.  Note that the specified Provider object
 483      * does not have to be registered in the provider list.
 484      *
 485      * @param type the specified Policy type.  See the Policy section in the
 486      *    <a href=
 487      *    "{@docRoot}/../technotes/guides/security/StandardNames.html#Policy">
 488      *    Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 489      *    for a list of standard Policy types.
 490      *
 491      * @param params parameters for the Policy, which may be null.
 492      *
 493      * @param provider the Provider.
 494      *
 495      * @return the new Policy object.
 496      *
 497      * @exception SecurityException if the caller does not have permission
 498      *          to get a Policy instance for the specified type.
 499      *
 500      * @exception NullPointerException if the specified type is null.
 501      *
 502      * @exception IllegalArgumentException if the specified Provider is null,
 503      *          or if the specified parameters are not understood by
 504      *          the PolicySpi implementation from the specified Provider.
 505      *
 506      * @exception NoSuchAlgorithmException if the specified Provider does not
 507      *          support a PolicySpi implementation for the specified type.
 508      *
 509      * @see Provider
 510      * @since 1.6
 511      */
 512     public static Policy getInstance(String type,
 513                                 Policy.Parameters params,
 514                                 Provider provider)
 515                 throws NoSuchAlgorithmException {
 516 
 517         if (provider == null) {
 518             throw new IllegalArgumentException("missing provider");
 519         }
 520 
 521         checkPermission(type);
 522         try {
 523             GetInstance.Instance instance = GetInstance.getInstance("Policy",
 524                                                         PolicySpi.class,
 525                                                         type,
 526                                                         params,
 527                                                         provider);
 528             return new PolicyDelegate((PolicySpi)instance.impl,
 529                                                         instance.provider,
 530                                                         type,
 531                                                         params);
 532         } catch (NoSuchAlgorithmException nsae) {
 533             return handleException(nsae);
 534         }
 535     }
 536 
 537     private static Policy handleException(NoSuchAlgorithmException nsae)
 538                 throws NoSuchAlgorithmException {
 539         Throwable cause = nsae.getCause();
 540         if (cause instanceof IllegalArgumentException) {
 541             throw (IllegalArgumentException)cause;
 542         }
 543         throw nsae;
 544     }
 545 
 546     /**
 547      * Return the Provider of this Policy.
 548      *
 549      * <p> This Policy instance will only have a Provider if it
 550      * was obtained via a call to {@code Policy.getInstance}.
 551      * Otherwise this method returns null.
 552      *
 553      * @return the Provider of this Policy, or null.
 554      *
 555      * @since 1.6
 556      */
 557     public Provider getProvider() {
 558         return null;
 559     }
 560 
 561     /**
 562      * Return the type of this Policy.
 563      *
 564      * <p> This Policy instance will only have a type if it
 565      * was obtained via a call to {@code Policy.getInstance}.
 566      * Otherwise this method returns null.
 567      *
 568      * @return the type of this Policy, or null.
 569      *
 570      * @since 1.6
 571      */
 572     public String getType() {
 573         return null;
 574     }
 575 
 576     /**
 577      * Return Policy parameters.
 578      *
 579      * <p> This Policy instance will only have parameters if it
 580      * was obtained via a call to {@code Policy.getInstance}.
 581      * Otherwise this method returns null.
 582      *
 583      * @return Policy parameters, or null.
 584      *
 585      * @since 1.6
 586      */
 587     public Policy.Parameters getParameters() {
 588         return null;
 589     }
 590 
 591     /**
 592      * Return a PermissionCollection object containing the set of
 593      * permissions granted to the specified CodeSource.
 594      *
 595      * <p> Applications are discouraged from calling this method
 596      * since this operation may not be supported by all policy implementations.
 597      * Applications should solely rely on the {@code implies} method
 598      * to perform policy checks.  If an application absolutely must call
 599      * a getPermissions method, it should call
 600      * {@code getPermissions(ProtectionDomain)}.
 601      *
 602      * <p> The default implementation of this method returns
 603      * Policy.UNSUPPORTED_EMPTY_COLLECTION.  This method can be
 604      * overridden if the policy implementation can return a set of
 605      * permissions granted to a CodeSource.
 606      *
 607      * @param codesource the CodeSource to which the returned
 608      *          PermissionCollection has been granted.
 609      *
 610      * @return a set of permissions granted to the specified CodeSource.
 611      *          If this operation is supported, the returned
 612      *          set of permissions must be a new mutable instance
 613      *          and it must support heterogeneous Permission types.
 614      *          If this operation is not supported,
 615      *          Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
 616      */
 617     public PermissionCollection getPermissions(CodeSource codesource) {
 618         return Policy.UNSUPPORTED_EMPTY_COLLECTION;
 619     }
 620 
 621     /**
 622      * Return a PermissionCollection object containing the set of
 623      * permissions granted to the specified ProtectionDomain.
 624      *
 625      * <p> Applications are discouraged from calling this method
 626      * since this operation may not be supported by all policy implementations.
 627      * Applications should rely on the {@code implies} method
 628      * to perform policy checks.
 629      *
 630      * <p> The default implementation of this method first retrieves
 631      * the permissions returned via {@code getPermissions(CodeSource)}
 632      * (the CodeSource is taken from the specified ProtectionDomain),
 633      * as well as the permissions located inside the specified ProtectionDomain.
 634      * All of these permissions are then combined and returned in a new
 635      * PermissionCollection object.  If {@code getPermissions(CodeSource)}
 636      * returns Policy.UNSUPPORTED_EMPTY_COLLECTION, then this method
 637      * returns the permissions contained inside the specified ProtectionDomain
 638      * in a new PermissionCollection object.
 639      *
 640      * <p> This method can be overridden if the policy implementation
 641      * supports returning a set of permissions granted to a ProtectionDomain.
 642      *
 643      * @param domain the ProtectionDomain to which the returned
 644      *          PermissionCollection has been granted.
 645      *
 646      * @return a set of permissions granted to the specified ProtectionDomain.
 647      *          If this operation is supported, the returned
 648      *          set of permissions must be a new mutable instance
 649      *          and it must support heterogeneous Permission types.
 650      *          If this operation is not supported,
 651      *          Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
 652      *
 653      * @since 1.4
 654      */
 655     public PermissionCollection getPermissions(ProtectionDomain domain) {
 656         PermissionCollection pc = null;
 657 
 658         if (domain == null)
 659             return new Permissions();
 660 
 661         if (pdMapping == null) {
 662             initPolicy(this);
 663         }
 664 
 665         synchronized (pdMapping) {
 666             pc = pdMapping.get(domain.key);
 667         }
 668 
 669         if (pc != null) {
 670             Permissions perms = new Permissions();
 671             synchronized (pc) {
 672                 for (Enumeration<Permission> e = pc.elements() ; e.hasMoreElements() ;) {
 673                     perms.add(e.nextElement());
 674                 }
 675             }
 676             return perms;
 677         }
 678 
 679         pc = getPermissions(domain.getCodeSource());
 680         if (pc == null || pc == UNSUPPORTED_EMPTY_COLLECTION) {
 681             pc = new Permissions();
 682         }
 683 
 684         addStaticPerms(pc, domain.getPermissions());
 685         return pc;
 686     }
 687 
 688     /**
 689      * add static permissions to provided permission collection
 690      */
 691     private void addStaticPerms(PermissionCollection perms,
 692                                 PermissionCollection statics) {
 693         if (statics != null) {
 694             synchronized (statics) {
 695                 Enumeration<Permission> e = statics.elements();
 696                 while (e.hasMoreElements()) {
 697                     perms.add(e.nextElement());
 698                 }
 699             }
 700         }
 701     }
 702 
 703     /**
 704      * Evaluates the global policy for the permissions granted to
 705      * the ProtectionDomain and tests whether the permission is
 706      * granted.
 707      *
 708      * @param domain the ProtectionDomain to test
 709      * @param permission the Permission object to be tested for implication.
 710      *
 711      * @return true if "permission" is a proper subset of a permission
 712      * granted to this ProtectionDomain.
 713      *
 714      * @see java.security.ProtectionDomain
 715      * @since 1.4
 716      */
 717     public boolean implies(ProtectionDomain domain, Permission permission) {
 718         PermissionCollection pc;
 719 
 720         if (pdMapping == null) {
 721             initPolicy(this);
 722         }
 723 
 724         synchronized (pdMapping) {
 725             pc = pdMapping.get(domain.key);
 726         }
 727 
 728         if (pc != null) {
 729             return pc.implies(permission);
 730         }
 731 
 732         pc = getPermissions(domain);
 733         if (pc == null) {
 734             return false;
 735         }
 736 
 737         synchronized (pdMapping) {
 738             // cache it
 739             pdMapping.put(domain.key, pc);
 740         }
 741 
 742         return pc.implies(permission);
 743     }
 744 
 745     /**
 746      * Refreshes/reloads the policy configuration. The behavior of this method
 747      * depends on the implementation. For example, calling {@code refresh}
 748      * on a file-based policy will cause the file to be re-read.
 749      *
 750      * <p> The default implementation of this method does nothing.
 751      * This method should be overridden if a refresh operation is supported
 752      * by the policy implementation.
 753      */
 754     public void refresh() { }
 755 
 756     /**
 757      * This subclass is returned by the getInstance calls.  All Policy calls
 758      * are delegated to the underlying PolicySpi.
 759      */
 760     private static class PolicyDelegate extends Policy {
 761 
 762         private PolicySpi spi;
 763         private Provider p;
 764         private String type;
 765         private Policy.Parameters params;
 766 
 767         private PolicyDelegate(PolicySpi spi, Provider p,
 768                         String type, Policy.Parameters params) {
 769             this.spi = spi;
 770             this.p = p;
 771             this.type = type;
 772             this.params = params;
 773         }
 774 
 775         @Override public String getType() { return type; }
 776 
 777         @Override public Policy.Parameters getParameters() { return params; }
 778 
 779         @Override public Provider getProvider() { return p; }
 780 
 781         @Override
 782         public PermissionCollection getPermissions(CodeSource codesource) {
 783             return spi.engineGetPermissions(codesource);
 784         }
 785         @Override
 786         public PermissionCollection getPermissions(ProtectionDomain domain) {
 787             return spi.engineGetPermissions(domain);
 788         }
 789         @Override
 790         public boolean implies(ProtectionDomain domain, Permission perm) {
 791             return spi.engineImplies(domain, perm);
 792         }
 793         @Override
 794         public void refresh() {
 795             spi.engineRefresh();
 796         }
 797     }
 798 
 799     /**
 800      * This represents a marker interface for Policy parameters.
 801      *
 802      * @since 1.6
 803      */
 804     public static interface Parameters { }
 805 
 806     /**
 807      * This class represents a read-only empty PermissionCollection object that
 808      * is returned from the {@code getPermissions(CodeSource)} and
 809      * {@code getPermissions(ProtectionDomain)}
 810      * methods in the Policy class when those operations are not
 811      * supported by the Policy implementation.
 812      */
 813     private static class UnsupportedEmptyCollection
 814         extends PermissionCollection {
 815 
 816         private static final long serialVersionUID = -8492269157353014774L;
 817 
 818         private Permissions perms;
 819 
 820         /**
 821          * Create a read-only empty PermissionCollection object.
 822          */
 823         public UnsupportedEmptyCollection() {
 824             this.perms = new Permissions();
 825             perms.setReadOnly();
 826         }
 827 
 828         /**
 829          * Adds a permission object to the current collection of permission
 830          * objects.
 831          *
 832          * @param permission the Permission object to add.
 833          *
 834          * @exception SecurityException - if this PermissionCollection object
 835          *                                has been marked readonly
 836          */
 837         @Override public void add(Permission permission) {
 838             perms.add(permission);
 839         }
 840 
 841         /**
 842          * Checks to see if the specified permission is implied by the
 843          * collection of Permission objects held in this PermissionCollection.
 844          *
 845          * @param permission the Permission object to compare.
 846          *
 847          * @return true if "permission" is implied by the permissions in
 848          * the collection, false if not.
 849          */
 850         @Override public boolean implies(Permission permission) {
 851             return perms.implies(permission);
 852         }
 853 
 854         /**
 855          * Returns an enumeration of all the Permission objects in the
 856          * collection.
 857          *
 858          * @return an enumeration of all the Permissions.
 859          */
 860         @Override public Enumeration<Permission> elements() {
 861             return perms.elements();
 862         }
 863     }
 864 }