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