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