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