1 /*
   2  * Copyright (c) 1997, 2017, 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      * A read-only empty PermissionCollection instance.
  92      * @since 1.6
  93      */
  94     public static final PermissionCollection UNSUPPORTED_EMPTY_COLLECTION =
  95                         new UnsupportedEmptyCollection();
  96 
  97     // Information about the system-wide policy.
  98     private static class PolicyInfo {
  99         // the system-wide policy
 100         final Policy policy;
 101         // a flag indicating if the system-wide policy has been initialized
 102         final boolean initialized;
 103 
 104         PolicyInfo(Policy policy, boolean initialized) {
 105             this.policy = policy;
 106             this.initialized = initialized;
 107         }
 108     }
 109 
 110     // PolicyInfo is volatile since we apply DCL during initialization.
 111     // For correctness, care must be taken to read the field only once and only
 112     // write to it after any other initialization action has taken place.
 113     private static volatile PolicyInfo policyInfo = new PolicyInfo(null, false);
 114 
 115     private static final Debug debug = Debug.getInstance("policy");
 116 
 117     // Default policy provider
 118     private static final String DEFAULT_POLICY =
 119         "sun.security.provider.PolicyFile";
 120 
 121     // Cache mapping ProtectionDomain.Key to PermissionCollection
 122     private WeakHashMap<ProtectionDomain.Key, PermissionCollection> pdMapping;
 123 
 124     /** package private for AccessControlContext and ProtectionDomain */
 125     static boolean isSet() {
 126         PolicyInfo pi = policyInfo;
 127         return pi.policy != null && pi.initialized == true;
 128     }
 129 
 130     private static void checkPermission(String type) {
 131         SecurityManager sm = System.getSecurityManager();
 132         if (sm != null) {
 133             sm.checkPermission(new SecurityPermission("createPolicy." + type));
 134         }
 135     }
 136 
 137     /**
 138      * Returns the installed Policy object. This value should not be cached,
 139      * as it may be changed by a call to {@code setPolicy}.
 140      * This method first calls
 141      * {@code SecurityManager.checkPermission} with a
 142      * {@code SecurityPermission("getPolicy")} permission
 143      * to ensure it's ok to get the Policy object.
 144      *
 145      * @return the installed Policy.
 146      *
 147      * @throws SecurityException
 148      *        if a security manager exists and its
 149      *        {@code checkPermission} method doesn't allow
 150      *        getting the Policy object.
 151      *
 152      * @see SecurityManager#checkPermission(Permission)
 153      * @see #setPolicy(java.security.Policy)
 154      */
 155     public static Policy getPolicy()
 156     {
 157         SecurityManager sm = System.getSecurityManager();
 158         if (sm != null)
 159             sm.checkPermission(SecurityConstants.GET_POLICY_PERMISSION);
 160         return getPolicyNoCheck();
 161     }
 162 
 163     /**
 164      * Returns the installed Policy object, skipping the security check.
 165      * Used by ProtectionDomain and getPolicy.
 166      *
 167      * @return the installed Policy.
 168      */
 169     static Policy getPolicyNoCheck()
 170     {
 171         PolicyInfo pi = policyInfo;
 172         // Use double-check idiom to avoid locking if system-wide policy is
 173         // already initialized
 174         if (pi.initialized == false || pi.policy == null) {
 175             synchronized (Policy.class) {
 176                 pi = policyInfo;
 177                 if (pi.policy == null) {
 178                     return loadPolicyProvider();
 179                 }
 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             policyInfo = 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         policyInfo = 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         policyInfo = 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             policyInfo = 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 = policyInfo.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}/../specs/security/standard-names.html#policy-types">
 370      *    Java Security Standard Algorithm Names Specification</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 {@code Policy} object
 376      *
 377      * @throws IllegalArgumentException if the specified parameters
 378      *         are not understood by the {@code PolicySpi} implementation
 379      *         from the selected {@code Provider}
 380      *
 381      * @throws NoSuchAlgorithmException if no {@code Provider} supports
 382      *         a {@code PolicySpi} implementation for the specified type
 383      *
 384      * @throws NullPointerException if {@code type} is {@code null}
 385      *
 386      * @throws SecurityException if the caller does not have permission
 387      *         to get a {@code Policy} instance 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         Objects.requireNonNull(type, "null type name");
 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}/../specs/security/standard-names.html#policy-types">
 424      *    Java Security Standard Algorithm Names Specification</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 {@code Policy} object
 432      *
 433      * @throws IllegalArgumentException if the specified provider
 434      *         is {@code null} or empty, or if the specified parameters are
 435      *         not understood by the {@code PolicySpi} implementation from
 436      *         the specified provider
 437      *
 438      * @throws NoSuchAlgorithmException if the specified provider does not
 439      *         support a {@code PolicySpi} implementation for the specified
 440      *         type
 441      *
 442      * @throws NoSuchProviderException if the specified provider is not
 443      *         registered in the security provider list
 444      *
 445      * @throws NullPointerException if {@code type} is {@code null}
 446      *
 447      * @throws SecurityException if the caller does not have permission
 448      *         to get a {@code Policy} instance for the specified type
 449      *
 450      * @see Provider
 451      * @since 1.6
 452      */
 453     public static Policy getInstance(String type,
 454                                 Policy.Parameters params,
 455                                 String provider)
 456                 throws NoSuchProviderException, NoSuchAlgorithmException {
 457 
 458         Objects.requireNonNull(type, "null type name");
 459         if (provider == null || provider.isEmpty()) {
 460             throw new IllegalArgumentException("missing provider");
 461         }
 462 
 463         checkPermission(type);
 464         try {
 465             GetInstance.Instance instance = GetInstance.getInstance("Policy",
 466                                                         PolicySpi.class,
 467                                                         type,
 468                                                         params,
 469                                                         provider);
 470             return new PolicyDelegate((PolicySpi)instance.impl,
 471                                                         instance.provider,
 472                                                         type,
 473                                                         params);
 474         } catch (NoSuchAlgorithmException nsae) {
 475             return handleException(nsae);
 476         }
 477     }
 478 
 479     /**
 480      * Returns a Policy object of the specified type.
 481      *
 482      * <p> A new Policy object encapsulating the
 483      * PolicySpi implementation from the specified Provider
 484      * object is returned.  Note that the specified Provider object
 485      * does not have to be registered in the provider list.
 486      *
 487      * @param type the specified Policy type.  See the Policy section in the
 488      *    <a href=
 489      *    "{@docRoot}/../specs/security/standard-names.html#policy-types">
 490      *    Java Security Standard Algorithm Names Specification</a>
 491      *    for a list of standard Policy types.
 492      *
 493      * @param params parameters for the Policy, which may be null.
 494      *
 495      * @param provider the Provider.
 496      *
 497      * @return the new {@code Policy} object
 498      *
 499      * @throws IllegalArgumentException if the specified {@code Provider}
 500      *         is {@code null}, or if the specified parameters are not
 501      *         understood by the {@code PolicySpi} implementation from the
 502      *         specified {@code Provider}
 503      *
 504      * @throws NoSuchAlgorithmException if the specified {@code Provider}
 505      *         does not support a {@code PolicySpi} implementation for
 506      *         the specified type
 507      *
 508      * @throws NullPointerException if {@code type} is {@code null}
 509      *
 510      * @throws SecurityException if the caller does not have permission
 511      *         to get a {@code Policy} instance for the specified type
 512      *
 513      * @see Provider
 514      * @since 1.6
 515      */
 516     public static Policy getInstance(String type,
 517                                 Policy.Parameters params,
 518                                 Provider provider)
 519                 throws NoSuchAlgorithmException {
 520 
 521         Objects.requireNonNull(type, "null type name");
 522         if (provider == null) {
 523             throw new IllegalArgumentException("missing provider");
 524         }
 525 
 526         checkPermission(type);
 527         try {
 528             GetInstance.Instance instance = GetInstance.getInstance("Policy",
 529                                                         PolicySpi.class,
 530                                                         type,
 531                                                         params,
 532                                                         provider);
 533             return new PolicyDelegate((PolicySpi)instance.impl,
 534                                                         instance.provider,
 535                                                         type,
 536                                                         params);
 537         } catch (NoSuchAlgorithmException nsae) {
 538             return handleException(nsae);
 539         }
 540     }
 541 
 542     private static Policy handleException(NoSuchAlgorithmException nsae)
 543                 throws NoSuchAlgorithmException {
 544         Throwable cause = nsae.getCause();
 545         if (cause instanceof IllegalArgumentException) {
 546             throw (IllegalArgumentException)cause;
 547         }
 548         throw nsae;
 549     }
 550 
 551     /**
 552      * Return the Provider of this Policy.
 553      *
 554      * <p> This Policy instance will only have a Provider if it
 555      * was obtained via a call to {@code Policy.getInstance}.
 556      * Otherwise this method returns null.
 557      *
 558      * @return the Provider of this Policy, or null.
 559      *
 560      * @since 1.6
 561      */
 562     public Provider getProvider() {
 563         return null;
 564     }
 565 
 566     /**
 567      * Return the type of this Policy.
 568      *
 569      * <p> This Policy instance will only have a type if it
 570      * was obtained via a call to {@code Policy.getInstance}.
 571      * Otherwise this method returns null.
 572      *
 573      * @return the type of this Policy, or null.
 574      *
 575      * @since 1.6
 576      */
 577     public String getType() {
 578         return null;
 579     }
 580 
 581     /**
 582      * Return Policy parameters.
 583      *
 584      * <p> This Policy instance will only have parameters if it
 585      * was obtained via a call to {@code Policy.getInstance}.
 586      * Otherwise this method returns null.
 587      *
 588      * @return Policy parameters, or null.
 589      *
 590      * @since 1.6
 591      */
 592     public Policy.Parameters getParameters() {
 593         return null;
 594     }
 595 
 596     /**
 597      * Return a PermissionCollection object containing the set of
 598      * permissions granted to the specified CodeSource.
 599      *
 600      * <p> Applications are discouraged from calling this method
 601      * since this operation may not be supported by all policy implementations.
 602      * Applications should solely rely on the {@code implies} method
 603      * to perform policy checks.  If an application absolutely must call
 604      * a getPermissions method, it should call
 605      * {@code getPermissions(ProtectionDomain)}.
 606      *
 607      * <p> The default implementation of this method returns
 608      * Policy.UNSUPPORTED_EMPTY_COLLECTION.  This method can be
 609      * overridden if the policy implementation can return a set of
 610      * permissions granted to a CodeSource.
 611      *
 612      * @param codesource the CodeSource to which the returned
 613      *          PermissionCollection has been granted.
 614      *
 615      * @return a set of permissions granted to the specified CodeSource.
 616      *          If this operation is supported, the returned
 617      *          set of permissions must be a new mutable instance
 618      *          and it must support heterogeneous Permission types.
 619      *          If this operation is not supported,
 620      *          Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
 621      */
 622     public PermissionCollection getPermissions(CodeSource codesource) {
 623         return Policy.UNSUPPORTED_EMPTY_COLLECTION;
 624     }
 625 
 626     /**
 627      * Return a PermissionCollection object containing the set of
 628      * permissions granted to the specified ProtectionDomain.
 629      *
 630      * <p> Applications are discouraged from calling this method
 631      * since this operation may not be supported by all policy implementations.
 632      * Applications should rely on the {@code implies} method
 633      * to perform policy checks.
 634      *
 635      * <p> The default implementation of this method first retrieves
 636      * the permissions returned via {@code getPermissions(CodeSource)}
 637      * (the CodeSource is taken from the specified ProtectionDomain),
 638      * as well as the permissions located inside the specified ProtectionDomain.
 639      * All of these permissions are then combined and returned in a new
 640      * PermissionCollection object.  If {@code getPermissions(CodeSource)}
 641      * returns Policy.UNSUPPORTED_EMPTY_COLLECTION, then this method
 642      * returns the permissions contained inside the specified ProtectionDomain
 643      * in a new PermissionCollection object.
 644      *
 645      * <p> This method can be overridden if the policy implementation
 646      * supports returning a set of permissions granted to a ProtectionDomain.
 647      *
 648      * @param domain the ProtectionDomain to which the returned
 649      *          PermissionCollection has been granted.
 650      *
 651      * @return a set of permissions granted to the specified ProtectionDomain.
 652      *          If this operation is supported, the returned
 653      *          set of permissions must be a new mutable instance
 654      *          and it must support heterogeneous Permission types.
 655      *          If this operation is not supported,
 656      *          Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
 657      *
 658      * @since 1.4
 659      */
 660     public PermissionCollection getPermissions(ProtectionDomain domain) {
 661         PermissionCollection pc = null;
 662 
 663         if (domain == null)
 664             return new Permissions();
 665 
 666         if (pdMapping == null) {
 667             initPolicy(this);
 668         }
 669 
 670         synchronized (pdMapping) {
 671             pc = pdMapping.get(domain.key);
 672         }
 673 
 674         if (pc != null) {
 675             Permissions perms = new Permissions();
 676             synchronized (pc) {
 677                 for (Enumeration<Permission> e = pc.elements() ; e.hasMoreElements() ;) {
 678                     perms.add(e.nextElement());
 679                 }
 680             }
 681             return perms;
 682         }
 683 
 684         pc = getPermissions(domain.getCodeSource());
 685         if (pc == null || pc == UNSUPPORTED_EMPTY_COLLECTION) {
 686             pc = new Permissions();
 687         }
 688 
 689         addStaticPerms(pc, domain.getPermissions());
 690         return pc;
 691     }
 692 
 693     /**
 694      * add static permissions to provided permission collection
 695      */
 696     private void addStaticPerms(PermissionCollection perms,
 697                                 PermissionCollection statics) {
 698         if (statics != null) {
 699             synchronized (statics) {
 700                 Enumeration<Permission> e = statics.elements();
 701                 while (e.hasMoreElements()) {
 702                     perms.add(e.nextElement());
 703                 }
 704             }
 705         }
 706     }
 707 
 708     /**
 709      * Evaluates the global policy for the permissions granted to
 710      * the ProtectionDomain and tests whether the permission is
 711      * granted.
 712      *
 713      * @param domain the ProtectionDomain to test
 714      * @param permission the Permission object to be tested for implication.
 715      *
 716      * @return true if "permission" is a proper subset of a permission
 717      * granted to this ProtectionDomain.
 718      *
 719      * @see java.security.ProtectionDomain
 720      * @since 1.4
 721      */
 722     public boolean implies(ProtectionDomain domain, Permission permission) {
 723         PermissionCollection pc;
 724 
 725         if (pdMapping == null) {
 726             initPolicy(this);
 727         }
 728 
 729         synchronized (pdMapping) {
 730             pc = pdMapping.get(domain.key);
 731         }
 732 
 733         if (pc != null) {
 734             return pc.implies(permission);
 735         }
 736 
 737         pc = getPermissions(domain);
 738         if (pc == null) {
 739             return false;
 740         }
 741 
 742         synchronized (pdMapping) {
 743             // cache it
 744             pdMapping.put(domain.key, pc);
 745         }
 746 
 747         return pc.implies(permission);
 748     }
 749 
 750     /**
 751      * Refreshes/reloads the policy configuration. The behavior of this method
 752      * depends on the implementation. For example, calling {@code refresh}
 753      * on a file-based policy will cause the file to be re-read.
 754      *
 755      * <p> The default implementation of this method does nothing.
 756      * This method should be overridden if a refresh operation is supported
 757      * by the policy implementation.
 758      */
 759     public void refresh() { }
 760 
 761     /**
 762      * This subclass is returned by the getInstance calls.  All Policy calls
 763      * are delegated to the underlying PolicySpi.
 764      */
 765     private static class PolicyDelegate extends Policy {
 766 
 767         private PolicySpi spi;
 768         private Provider p;
 769         private String type;
 770         private Policy.Parameters params;
 771 
 772         private PolicyDelegate(PolicySpi spi, Provider p,
 773                         String type, Policy.Parameters params) {
 774             this.spi = spi;
 775             this.p = p;
 776             this.type = type;
 777             this.params = params;
 778         }
 779 
 780         @Override public String getType() { return type; }
 781 
 782         @Override public Policy.Parameters getParameters() { return params; }
 783 
 784         @Override public Provider getProvider() { return p; }
 785 
 786         @Override
 787         public PermissionCollection getPermissions(CodeSource codesource) {
 788             return spi.engineGetPermissions(codesource);
 789         }
 790         @Override
 791         public PermissionCollection getPermissions(ProtectionDomain domain) {
 792             return spi.engineGetPermissions(domain);
 793         }
 794         @Override
 795         public boolean implies(ProtectionDomain domain, Permission perm) {
 796             return spi.engineImplies(domain, perm);
 797         }
 798         @Override
 799         public void refresh() {
 800             spi.engineRefresh();
 801         }
 802     }
 803 
 804     /**
 805      * This represents a marker interface for Policy parameters.
 806      *
 807      * @since 1.6
 808      */
 809     public static interface Parameters { }
 810 
 811     /**
 812      * This class represents a read-only empty PermissionCollection object that
 813      * is returned from the {@code getPermissions(CodeSource)} and
 814      * {@code getPermissions(ProtectionDomain)}
 815      * methods in the Policy class when those operations are not
 816      * supported by the Policy implementation.
 817      */
 818     private static class UnsupportedEmptyCollection
 819         extends PermissionCollection {
 820 
 821         private static final long serialVersionUID = -8492269157353014774L;
 822 
 823         private Permissions perms;
 824 
 825         /**
 826          * Create a read-only empty PermissionCollection object.
 827          */
 828         public UnsupportedEmptyCollection() {
 829             this.perms = new Permissions();
 830             perms.setReadOnly();
 831         }
 832 
 833         /**
 834          * Adds a permission object to the current collection of permission
 835          * objects.
 836          *
 837          * @param permission the Permission object to add.
 838          *
 839          * @exception SecurityException - if this PermissionCollection object
 840          *                                has been marked readonly
 841          */
 842         @Override public void add(Permission permission) {
 843             perms.add(permission);
 844         }
 845 
 846         /**
 847          * Checks to see if the specified permission is implied by the
 848          * collection of Permission objects held in this PermissionCollection.
 849          *
 850          * @param permission the Permission object to compare.
 851          *
 852          * @return true if "permission" is implied by the permissions in
 853          * the collection, false if not.
 854          */
 855         @Override public boolean implies(Permission permission) {
 856             return perms.implies(permission);
 857         }
 858 
 859         /**
 860          * Returns an enumeration of all the Permission objects in the
 861          * collection.
 862          *
 863          * @return an enumeration of all the Permissions.
 864          */
 865         @Override public Enumeration<Permission> elements() {
 866             return perms.elements();
 867         }
 868     }
 869 }