1 /*
   2  * Copyright (c) 1997, 2015, 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} property to determine
 361      * the preferred provider order for the specified algorithm. This
 362      * may be different than the order of providers returned by
 363      * {@link Security#getProviders() Security.getProviders()}.
 364      *
 365      * @param type the specified Policy type.  See the Policy section in the
 366      *    <a href=
 367      *    "{@docRoot}/../technotes/guides/security/StandardNames.html#Policy">
 368      *    Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 369      *    for a list of standard Policy types.
 370      *
 371      * @param params parameters for the Policy, which may be null.
 372      *
 373      * @return the new Policy object.
 374      *
 375      * @exception SecurityException if the caller does not have permission
 376      *          to get a Policy instance for the specified type.
 377      *
 378      * @exception NullPointerException if the specified type is null.
 379      *
 380      * @exception IllegalArgumentException if the specified parameters
 381      *          are not understood by the PolicySpi implementation
 382      *          from the selected Provider.
 383      *
 384      * @exception NoSuchAlgorithmException if no Provider supports a PolicySpi
 385      *          implementation for the specified type.
 386      *
 387      * @see Provider
 388      * @since 1.6
 389      */
 390     public static Policy getInstance(String type, Policy.Parameters params)
 391                 throws NoSuchAlgorithmException {
 392 
 393         checkPermission(type);
 394         try {
 395             GetInstance.Instance instance = GetInstance.getInstance("Policy",
 396                                                         PolicySpi.class,
 397                                                         type,
 398                                                         params);
 399             return new PolicyDelegate((PolicySpi)instance.impl,
 400                                                         instance.provider,
 401                                                         type,
 402                                                         params);
 403         } catch (NoSuchAlgorithmException nsae) {
 404             return handleException(nsae);
 405         }
 406     }
 407 
 408     /**
 409      * Returns a Policy object of the specified type.
 410      *
 411      * <p> A new Policy object encapsulating the
 412      * PolicySpi implementation from the specified provider
 413      * is returned.   The specified provider must be registered
 414      * in the provider list.
 415      *
 416      * <p> Note that the list of registered providers may be retrieved via
 417      * the {@link Security#getProviders() Security.getProviders()} method.
 418      *
 419      * @param type the specified Policy type.  See the Policy section in the
 420      *    <a href=
 421      *    "{@docRoot}/../technotes/guides/security/StandardNames.html#Policy">
 422      *    Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 423      *    for a list of standard Policy types.
 424      *
 425      * @param params parameters for the Policy, which may be null.
 426      *
 427      * @param provider the provider.
 428      *
 429      * @return the new Policy object.
 430      *
 431      * @exception SecurityException if the caller does not have permission
 432      *          to get a Policy instance for the specified type.
 433      *
 434      * @exception NullPointerException if the specified type is null.
 435      *
 436      * @exception IllegalArgumentException if the specified provider
 437      *          is null or empty,
 438      *          or if the specified parameters are not understood by
 439      *          the PolicySpi implementation from the specified provider.
 440      *
 441      * @exception NoSuchProviderException if the specified provider is not
 442      *          registered in the security provider list.
 443      *
 444      * @exception NoSuchAlgorithmException if the specified provider does not
 445      *          support a PolicySpi implementation for the specified type.
 446      *
 447      * @see Provider
 448      * @since 1.6
 449      */
 450     public static Policy getInstance(String type,
 451                                 Policy.Parameters params,
 452                                 String provider)
 453                 throws NoSuchProviderException, NoSuchAlgorithmException {
 454 
 455         if (provider == null || provider.length() == 0) {
 456             throw new IllegalArgumentException("missing provider");
 457         }
 458 
 459         checkPermission(type);
 460         try {
 461             GetInstance.Instance instance = GetInstance.getInstance("Policy",
 462                                                         PolicySpi.class,
 463                                                         type,
 464                                                         params,
 465                                                         provider);
 466             return new PolicyDelegate((PolicySpi)instance.impl,
 467                                                         instance.provider,
 468                                                         type,
 469                                                         params);
 470         } catch (NoSuchAlgorithmException nsae) {
 471             return handleException(nsae);
 472         }
 473     }
 474 
 475     /**
 476      * Returns a Policy object of the specified type.
 477      *
 478      * <p> A new Policy object encapsulating the
 479      * PolicySpi implementation from the specified Provider
 480      * object is returned.  Note that the specified Provider object
 481      * does not have to be registered in the provider list.
 482      *
 483      * @param type the specified Policy type.  See the Policy section in the
 484      *    <a href=
 485      *    "{@docRoot}/../technotes/guides/security/StandardNames.html#Policy">
 486      *    Java Cryptography Architecture Standard Algorithm Name Documentation</a>
 487      *    for a list of standard Policy types.
 488      *
 489      * @param params parameters for the Policy, which may be null.
 490      *
 491      * @param provider the Provider.
 492      *
 493      * @return the new Policy object.
 494      *
 495      * @exception SecurityException if the caller does not have permission
 496      *          to get a Policy instance for the specified type.
 497      *
 498      * @exception NullPointerException if the specified type is null.
 499      *
 500      * @exception IllegalArgumentException if the specified Provider is null,
 501      *          or if the specified parameters are not understood by
 502      *          the PolicySpi implementation from the specified Provider.
 503      *
 504      * @exception NoSuchAlgorithmException if the specified Provider does not
 505      *          support a PolicySpi implementation for the specified type.
 506      *
 507      * @see Provider
 508      * @since 1.6
 509      */
 510     public static Policy getInstance(String type,
 511                                 Policy.Parameters params,
 512                                 Provider provider)
 513                 throws NoSuchAlgorithmException {
 514 
 515         if (provider == null) {
 516             throw new IllegalArgumentException("missing provider");
 517         }
 518 
 519         checkPermission(type);
 520         try {
 521             GetInstance.Instance instance = GetInstance.getInstance("Policy",
 522                                                         PolicySpi.class,
 523                                                         type,
 524                                                         params,
 525                                                         provider);
 526             return new PolicyDelegate((PolicySpi)instance.impl,
 527                                                         instance.provider,
 528                                                         type,
 529                                                         params);
 530         } catch (NoSuchAlgorithmException nsae) {
 531             return handleException(nsae);
 532         }
 533     }
 534 
 535     private static Policy handleException(NoSuchAlgorithmException nsae)
 536                 throws NoSuchAlgorithmException {
 537         Throwable cause = nsae.getCause();
 538         if (cause instanceof IllegalArgumentException) {
 539             throw (IllegalArgumentException)cause;
 540         }
 541         throw nsae;
 542     }
 543 
 544     /**
 545      * Return the Provider of this Policy.
 546      *
 547      * <p> This Policy instance will only have a Provider if it
 548      * was obtained via a call to {@code Policy.getInstance}.
 549      * Otherwise this method returns null.
 550      *
 551      * @return the Provider of this Policy, or null.
 552      *
 553      * @since 1.6
 554      */
 555     public Provider getProvider() {
 556         return null;
 557     }
 558 
 559     /**
 560      * Return the type of this Policy.
 561      *
 562      * <p> This Policy instance will only have a type if it
 563      * was obtained via a call to {@code Policy.getInstance}.
 564      * Otherwise this method returns null.
 565      *
 566      * @return the type of this Policy, or null.
 567      *
 568      * @since 1.6
 569      */
 570     public String getType() {
 571         return null;
 572     }
 573 
 574     /**
 575      * Return Policy parameters.
 576      *
 577      * <p> This Policy instance will only have parameters if it
 578      * was obtained via a call to {@code Policy.getInstance}.
 579      * Otherwise this method returns null.
 580      *
 581      * @return Policy parameters, or null.
 582      *
 583      * @since 1.6
 584      */
 585     public Policy.Parameters getParameters() {
 586         return null;
 587     }
 588 
 589     /**
 590      * Return a PermissionCollection object containing the set of
 591      * permissions granted to the specified CodeSource.
 592      *
 593      * <p> Applications are discouraged from calling this method
 594      * since this operation may not be supported by all policy implementations.
 595      * Applications should solely rely on the {@code implies} method
 596      * to perform policy checks.  If an application absolutely must call
 597      * a getPermissions method, it should call
 598      * {@code getPermissions(ProtectionDomain)}.
 599      *
 600      * <p> The default implementation of this method returns
 601      * Policy.UNSUPPORTED_EMPTY_COLLECTION.  This method can be
 602      * overridden if the policy implementation can return a set of
 603      * permissions granted to a CodeSource.
 604      *
 605      * @param codesource the CodeSource to which the returned
 606      *          PermissionCollection has been granted.
 607      *
 608      * @return a set of permissions granted to the specified CodeSource.
 609      *          If this operation is supported, the returned
 610      *          set of permissions must be a new mutable instance
 611      *          and it must support heterogeneous Permission types.
 612      *          If this operation is not supported,
 613      *          Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
 614      */
 615     public PermissionCollection getPermissions(CodeSource codesource) {
 616         return Policy.UNSUPPORTED_EMPTY_COLLECTION;
 617     }
 618 
 619     /**
 620      * Return a PermissionCollection object containing the set of
 621      * permissions granted to the specified ProtectionDomain.
 622      *
 623      * <p> Applications are discouraged from calling this method
 624      * since this operation may not be supported by all policy implementations.
 625      * Applications should rely on the {@code implies} method
 626      * to perform policy checks.
 627      *
 628      * <p> The default implementation of this method first retrieves
 629      * the permissions returned via {@code getPermissions(CodeSource)}
 630      * (the CodeSource is taken from the specified ProtectionDomain),
 631      * as well as the permissions located inside the specified ProtectionDomain.
 632      * All of these permissions are then combined and returned in a new
 633      * PermissionCollection object.  If {@code getPermissions(CodeSource)}
 634      * returns Policy.UNSUPPORTED_EMPTY_COLLECTION, then this method
 635      * returns the permissions contained inside the specified ProtectionDomain
 636      * in a new PermissionCollection object.
 637      *
 638      * <p> This method can be overridden if the policy implementation
 639      * supports returning a set of permissions granted to a ProtectionDomain.
 640      *
 641      * @param domain the ProtectionDomain to which the returned
 642      *          PermissionCollection has been granted.
 643      *
 644      * @return a set of permissions granted to the specified ProtectionDomain.
 645      *          If this operation is supported, the returned
 646      *          set of permissions must be a new mutable instance
 647      *          and it must support heterogeneous Permission types.
 648      *          If this operation is not supported,
 649      *          Policy.UNSUPPORTED_EMPTY_COLLECTION is returned.
 650      *
 651      * @since 1.4
 652      */
 653     public PermissionCollection getPermissions(ProtectionDomain domain) {
 654         PermissionCollection pc = null;
 655 
 656         if (domain == null)
 657             return new Permissions();
 658 
 659         if (pdMapping == null) {
 660             initPolicy(this);
 661         }
 662 
 663         synchronized (pdMapping) {
 664             pc = pdMapping.get(domain.key);
 665         }
 666 
 667         if (pc != null) {
 668             Permissions perms = new Permissions();
 669             synchronized (pc) {
 670                 for (Enumeration<Permission> e = pc.elements() ; e.hasMoreElements() ;) {
 671                     perms.add(e.nextElement());
 672                 }
 673             }
 674             return perms;
 675         }
 676 
 677         pc = getPermissions(domain.getCodeSource());
 678         if (pc == null || pc == UNSUPPORTED_EMPTY_COLLECTION) {
 679             pc = new Permissions();
 680         }
 681 
 682         addStaticPerms(pc, domain.getPermissions());
 683         return pc;
 684     }
 685 
 686     /**
 687      * add static permissions to provided permission collection
 688      */
 689     private void addStaticPerms(PermissionCollection perms,
 690                                 PermissionCollection statics) {
 691         if (statics != null) {
 692             synchronized (statics) {
 693                 Enumeration<Permission> e = statics.elements();
 694                 while (e.hasMoreElements()) {
 695                     perms.add(e.nextElement());
 696                 }
 697             }
 698         }
 699     }
 700 
 701     /**
 702      * Evaluates the global policy for the permissions granted to
 703      * the ProtectionDomain and tests whether the permission is
 704      * granted.
 705      *
 706      * @param domain the ProtectionDomain to test
 707      * @param permission the Permission object to be tested for implication.
 708      *
 709      * @return true if "permission" is a proper subset of a permission
 710      * granted to this ProtectionDomain.
 711      *
 712      * @see java.security.ProtectionDomain
 713      * @since 1.4
 714      */
 715     public boolean implies(ProtectionDomain domain, Permission permission) {
 716         PermissionCollection pc;
 717 
 718         if (pdMapping == null) {
 719             initPolicy(this);
 720         }
 721 
 722         synchronized (pdMapping) {
 723             pc = pdMapping.get(domain.key);
 724         }
 725 
 726         if (pc != null) {
 727             return pc.implies(permission);
 728         }
 729 
 730         pc = getPermissions(domain);
 731         if (pc == null) {
 732             return false;
 733         }
 734 
 735         synchronized (pdMapping) {
 736             // cache it
 737             pdMapping.put(domain.key, pc);
 738         }
 739 
 740         return pc.implies(permission);
 741     }
 742 
 743     /**
 744      * Refreshes/reloads the policy configuration. The behavior of this method
 745      * depends on the implementation. For example, calling {@code refresh}
 746      * on a file-based policy will cause the file to be re-read.
 747      *
 748      * <p> The default implementation of this method does nothing.
 749      * This method should be overridden if a refresh operation is supported
 750      * by the policy implementation.
 751      */
 752     public void refresh() { }
 753 
 754     /**
 755      * This subclass is returned by the getInstance calls.  All Policy calls
 756      * are delegated to the underlying PolicySpi.
 757      */
 758     private static class PolicyDelegate extends Policy {
 759 
 760         private PolicySpi spi;
 761         private Provider p;
 762         private String type;
 763         private Policy.Parameters params;
 764 
 765         private PolicyDelegate(PolicySpi spi, Provider p,
 766                         String type, Policy.Parameters params) {
 767             this.spi = spi;
 768             this.p = p;
 769             this.type = type;
 770             this.params = params;
 771         }
 772 
 773         @Override public String getType() { return type; }
 774 
 775         @Override public Policy.Parameters getParameters() { return params; }
 776 
 777         @Override public Provider getProvider() { return p; }
 778 
 779         @Override
 780         public PermissionCollection getPermissions(CodeSource codesource) {
 781             return spi.engineGetPermissions(codesource);
 782         }
 783         @Override
 784         public PermissionCollection getPermissions(ProtectionDomain domain) {
 785             return spi.engineGetPermissions(domain);
 786         }
 787         @Override
 788         public boolean implies(ProtectionDomain domain, Permission perm) {
 789             return spi.engineImplies(domain, perm);
 790         }
 791         @Override
 792         public void refresh() {
 793             spi.engineRefresh();
 794         }
 795     }
 796 
 797     /**
 798      * This represents a marker interface for Policy parameters.
 799      *
 800      * @since 1.6
 801      */
 802     public static interface Parameters { }
 803 
 804     /**
 805      * This class represents a read-only empty PermissionCollection object that
 806      * is returned from the {@code getPermissions(CodeSource)} and
 807      * {@code getPermissions(ProtectionDomain)}
 808      * methods in the Policy class when those operations are not
 809      * supported by the Policy implementation.
 810      */
 811     private static class UnsupportedEmptyCollection
 812         extends PermissionCollection {
 813 
 814         private static final long serialVersionUID = -8492269157353014774L;
 815 
 816         private Permissions perms;
 817 
 818         /**
 819          * Create a read-only empty PermissionCollection object.
 820          */
 821         public UnsupportedEmptyCollection() {
 822             this.perms = new Permissions();
 823             perms.setReadOnly();
 824         }
 825 
 826         /**
 827          * Adds a permission object to the current collection of permission
 828          * objects.
 829          *
 830          * @param permission the Permission object to add.
 831          *
 832          * @exception SecurityException - if this PermissionCollection object
 833          *                                has been marked readonly
 834          */
 835         @Override public void add(Permission permission) {
 836             perms.add(permission);
 837         }
 838 
 839         /**
 840          * Checks to see if the specified permission is implied by the
 841          * collection of Permission objects held in this PermissionCollection.
 842          *
 843          * @param permission the Permission object to compare.
 844          *
 845          * @return true if "permission" is implied by the permissions in
 846          * the collection, false if not.
 847          */
 848         @Override public boolean implies(Permission permission) {
 849             return perms.implies(permission);
 850         }
 851 
 852         /**
 853          * Returns an enumeration of all the Permission objects in the
 854          * collection.
 855          *
 856          * @return an enumeration of all the Permissions.
 857          */
 858         @Override public Enumeration<Permission> elements() {
 859             return perms.elements();
 860         }
 861     }
 862 }