/*
 * Copyright (c) 1997, 2009, Oracle and/or its affiliates. All rights reserved.
 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
 *
 * This code is free software; you can redistribute it and/or modify it
 * under the terms of the GNU General Public License version 2 only, as
 * published by the Free Software Foundation.  Oracle designates this
 * particular file as subject to the "Classpath" exception as provided
 * by Oracle in the LICENSE file that accompanied this code.
 *
 * This code is distributed in the hope that it will be useful, but WITHOUT
 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
 * version 2 for more details (a copy is included in the LICENSE file that
 * accompanied this code).
 *
 * You should have received a copy of the GNU General Public License version
 * 2 along with this work; if not, write to the Free Software Foundation,
 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
 *
 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
 * or visit www.oracle.com if you need additional information or have any
 * questions.
 */

package sun.security.provider;

import java.io.*;
import java.lang.RuntimePermission;
import java.lang.reflect.*;
import java.lang.ref.*;
import java.net.MalformedURLException;
import java.net.URL;
import java.net.URI;
import java.util.*;
import java.util.Enumeration;
import java.util.Hashtable;
import java.util.List;
import java.util.StringTokenizer;
import java.util.PropertyPermission;
import java.util.ArrayList;
import java.util.ListIterator;
import java.util.WeakHashMap;
import java.text.MessageFormat;
import com.sun.security.auth.PrincipalComparator;
import java.security.*;
import java.security.cert.Certificate;
import java.security.cert.X509Certificate;
import javax.security.auth.PrivateCredentialPermission;
import javax.security.auth.Subject;
import javax.security.auth.x500.X500Principal;
import java.io.FilePermission;
import java.net.SocketPermission;
import java.net.NetPermission;
import java.util.PropertyPermission;
import java.util.concurrent.atomic.AtomicReference;
/*
import javax.security.auth.AuthPermission;
import javax.security.auth.kerberos.ServicePermission;
import javax.security.auth.kerberos.DelegationPermission;
import java.io.SerializablePermission;
import java.util.logging.LoggingPermission;
import java.sql.SQLPermission;
import java.lang.reflect.ReflectPermission;
import javax.sound.sampled.AudioPermission;
import javax.net.ssl.SSLPermission;
*/
import sun.misc.JavaSecurityProtectionDomainAccess;
import static sun.misc.JavaSecurityProtectionDomainAccess.ProtectionDomainCache;
import sun.misc.SharedSecrets;
import sun.security.util.Password;
import sun.security.util.PolicyUtil;
import sun.security.util.PropertyExpander;
import sun.security.util.Debug;
import sun.security.util.ResourcesMgr;
import sun.security.util.SecurityConstants;
import sun.net.www.ParseUtil;

/**
 * This class represents a default implementation for
 * <code>java.security.Policy</code>.
 *
 * Note:
 * For backward compatibility with JAAS 1.0 it loads
 * both java.auth.policy and java.policy. However it
 * is recommended that java.auth.policy be not used
 * and the java.policy contain all grant entries including
 * that contain principal-based entries.
 *
 *
 * <p> This object stores the policy for entire Java runtime,
 * and is the amalgamation of multiple static policy
 * configurations that resides in files.
 * The algorithm for locating the policy file(s) and reading their
 * information into this <code>Policy</code> object is:
 *
 * <ol>
 * <li>
 *   Loop through the <code>java.security.Security</code> properties,
 *   <i>policy.url.1</i>, <i>policy.url.2</i>, ...,
 *   <i>policy.url.X</i>" and
 *   <i>auth.policy.url.1</i>, <i>auth.policy.url.2</i>, ...,
 *   <i>auth.policy.url.X</i>".  These properties are set
 *   in the Java security properties file, which is located in the file named
 *   &lt;JAVA_HOME&gt;/lib/security/java.security.
 *   &lt;JAVA_HOME&gt; refers to the value of the java.home system property,
 *   and specifies the directory where the JRE is installed.
 *   Each property value specifies a <code>URL</code> pointing to a
 *   policy file to be loaded.  Read in and load each policy.
 *
 *   <i>auth.policy.url</i> is supported only for backward compatibility.
 *
 * <li>
 *   The <code>java.lang.System</code> property <i>java.security.policy</i>
 *   may also be set to a <code>URL</code> pointing to another policy file
 *   (which is the case when a user uses the -D switch at runtime).
 *   If this property is defined, and its use is allowed by the
 *   security property file (the Security property,
 *   <i>policy.allowSystemProperty</i> is set to <i>true</i>),
 *   also load that policy.
 *
 * <li>
 *   The <code>java.lang.System</code> property
 *   <i>java.security.auth.policy</i> may also be set to a
 *   <code>URL</code> pointing to another policy file
 *   (which is the case when a user uses the -D switch at runtime).
 *   If this property is defined, and its use is allowed by the
 *   security property file (the Security property,
 *   <i>policy.allowSystemProperty</i> is set to <i>true</i>),
 *   also load that policy.
 *
 *   <i>java.security.auth.policy</i> is supported only for backward
 *   compatibility.
 *
 *   If the  <i>java.security.policy</i> or
 *   <i>java.security.auth.policy</i> property is defined using
 *   "==" (rather than "="), then ignore all other specified
 *   policies and only load this policy.
 * </ol>
 *
 * Each policy file consists of one or more grant entries, each of
 * which consists of a number of permission entries.
 *
 * <pre>
 *   grant signedBy "<b>alias</b>", codeBase "<b>URL</b>",
 *         principal <b>principalClass</b> "<b>principalName</b>",
 *         principal <b>principalClass</b> "<b>principalName</b>",
 *         ... {
 *
 *     permission <b>Type</b> "<b>name</b> "<b>action</b>",
 *         signedBy "<b>alias</b>";
 *     permission <b>Type</b> "<b>name</b> "<b>action</b>",
 *         signedBy "<b>alias</b>";
 *     ....
 *   };
 * </pre>
 *
 * All non-bold items above must appear as is (although case
 * doesn't matter and some are optional, as noted below).
 * principal entries are optional and need not be present.
 * Italicized items represent variable values.
 *
 * <p> A grant entry must begin with the word <code>grant</code>.
 * The <code>signedBy</code>,<code>codeBase</code> and <code>principal</code>
 * name/value pairs are optional.
 * If they are not present, then any signer (including unsigned code)
 * will match, and any codeBase will match.
 * Note that the <i>principalClass</i>
 * may be set to the wildcard value, *, which allows it to match
 * any <code>Principal</code> class.  In addition, the <i>principalName</i>
 * may also be set to the wildcard value, *, allowing it to match
 * any <code>Principal</code> name.  When setting the <i>principalName</i>
 * to the *, do not surround the * with quotes.
 *
 * <p> A permission entry must begin with the word <code>permission</code>.
 * The word <code><i>Type</i></code> in the template above is
 * a specific permission type, such as <code>java.io.FilePermission</code>
 * or <code>java.lang.RuntimePermission</code>.
 *
 * <p> The "<i>action</i>" is required for
 * many permission types, such as <code>java.io.FilePermission</code>
 * (where it specifies what type of file access that is permitted).
 * It is not required for categories such as
 * <code>java.lang.RuntimePermission</code>
 * where it is not necessary - you either have the
 * permission specified by the <code>"<i>name</i>"</code>
 * value following the type name or you don't.
 *
 * <p> The <code>signedBy</code> name/value pair for a permission entry
 * is optional. If present, it indicates a signed permission. That is,
 * the permission class itself must be signed by the given alias in
 * order for it to be granted. For example,
 * suppose you have the following grant entry:
 *
 * <pre>
 *   grant principal foo.com.Principal "Duke" {
 *     permission Foo "foobar", signedBy "FooSoft";
 *   }
 * </pre>
 *
 * <p> Then this permission of type <i>Foo</i> is granted if the
 * <code>Foo.class</code> permission has been signed by the
 * "FooSoft" alias, or if XXX <code>Foo.class</code> is a
 * system class (i.e., is found on the CLASSPATH).
 *
 *
 * <p> Items that appear in an entry must appear in the specified order
 * (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
 * "<i>action</i>"). An entry is terminated with a semicolon.
 *
 * <p> Case is unimportant for the identifiers (<code>permission</code>,
 * <code>signedBy</code>, <code>codeBase</code>, etc.) but is
 * significant for the <i>Type</i>
 * or for any string that is passed in as a value. <p>
 *
 * <p> An example of two entries in a policy configuration file is
 * <pre>
 *   // if the code is comes from "foo.com" and is running as "Duke",
 *   // grant it read/write to all files in /tmp.
 *
 *   grant codeBase "foo.com", principal foo.com.Principal "Duke" {
 *              permission java.io.FilePermission "/tmp/*", "read,write";
 *   };
 *
 *   // grant any code running as "Duke" permission to read
 *   // the "java.vendor" Property.
 *
 *   grant principal foo.com.Principal "Duke" {
 *         permission java.util.PropertyPermission "java.vendor";
 *
 *
 * </pre>
 *  This Policy implementation supports special handling of any
 *  permission that contains the string, "<b>${{self}}</b>", as part of
 *  its target name.  When such a permission is evaluated
 *  (such as during a security check), <b>${{self}}</b> is replaced
 *  with one or more Principal class/name pairs.  The exact
 *  replacement performed depends upon the contents of the
 *  grant clause to which the permission belongs.
 *<p>
 *
 *  If the grant clause does not contain any principal information,
 *  the permission will be ignored (permissions containing
 *  <b>${{self}}</b> in their target names are only valid in the context
 *  of a principal-based grant clause).  For example, BarPermission
 *  will always be ignored in the following grant clause:
 *
 *<pre>
 *    grant codebase "www.foo.com", signedby "duke" {
 *      permission BarPermission "... ${{self}} ...";
 *    };
 *</pre>
 *
 *  If the grant clause contains principal information, <b>${{self}}</b>
 *  will be replaced with that same principal information.
 *  For example, <b>${{self}}</b> in BarPermission will be replaced by
 *  <b>javax.security.auth.x500.X500Principal "cn=Duke"</b>
 *  in the following grant clause:
 *
 *  <pre>
 *    grant principal javax.security.auth.x500.X500Principal "cn=Duke" {
 *      permission BarPermission "... ${{self}} ...";
 *    };
 *  </pre>
 *
 *  If there is a comma-separated list of principals in the grant
 *  clause, then <b>${{self}}</b> will be replaced by the same
 *  comma-separated list or principals.
 *  In the case where both the principal class and name are
 *  wildcarded in the grant clause, <b>${{self}}</b> is replaced
 *  with all the principals associated with the <code>Subject</code>
 *  in the current <code>AccessControlContext</code>.
 *
 *
 * <p> For PrivateCredentialPermissions, you can also use "<b>self</b>"
 * instead of "<b>${{self}}</b>". However the use of "<b>self</b>" is
 * deprecated in favour of "<b>${{self}}</b>".
 *
 * @see java.security.CodeSource
 * @see java.security.Permissions
 * @see java.security.ProtectionDomain
 */
public class PolicyFile extends java.security.Policy {

    private static final Debug debug = Debug.getInstance("policy");

    private static final String NONE = "NONE";
    private static final String P11KEYSTORE = "PKCS11";

    private static final String SELF = "${{self}}";
    private static final String X500PRINCIPAL =
                        "javax.security.auth.x500.X500Principal";
    private static final String POLICY = "java.security.policy";
    private static final String SECURITY_MANAGER = "java.security.manager";
    private static final String POLICY_URL = "policy.url.";
    private static final String AUTH_POLICY = "java.security.auth.policy";
    private static final String AUTH_POLICY_URL = "auth.policy.url.";

    private static final int DEFAULT_CACHE_SIZE = 1;

    // contains the policy grant entries, PD cache, and alias mapping
    private AtomicReference<PolicyInfo> policyInfo =
        new AtomicReference<PolicyInfo>();
    private boolean constructed = false;

    private boolean expandProperties = true;
    private boolean ignoreIdentityScope = true;
    private boolean allowSystemProperties = true;
    private boolean notUtf8 = false;
    private URL url;

    // for use with the reflection API

    private static final Class[] PARAMS0 = { };
    private static final Class[] PARAMS1 = { String.class };
    private static final Class[] PARAMS2 = { String.class, String.class };

    /**
     * Initializes the Policy object and reads the default policy
     * configuration file(s) into the Policy object.
     */
    public PolicyFile() {
        init((URL)null);
    }

    /**
     * Initializes the Policy object and reads the default policy
     * from the specified URL only.
     */
    public PolicyFile(URL url) {
        this.url = url;
        init(url);
    }

    /**
     * Initializes the Policy object and reads the default policy
     * configuration file(s) into the Policy object.
     *
     * The algorithm for locating the policy file(s) and reading their
     * information into the Policy object is:
     * <pre>
     *   loop through the Security Properties named "policy.url.1",
     *  ""policy.url.2", "auth.policy.url.1",  "auth.policy.url.2" etc, until
     *   you don't find one. Each of these specify a policy file.
     *
     *   if none of these could be loaded, use a builtin static policy
     *      equivalent to the default lib/security/java.policy file.
     *
     *   if the system property "java.policy" or "java.auth.policy" is defined
     * (which is the
     *      case when the user uses the -D switch at runtime), and
     *     its use is allowed by the security property file,
     *     also load it.
     * </pre>
     *
     * Each policy file consists of one or more grant entries, each of
     * which consists of a number of permission entries.
     * <pre>
     *   grant signedBy "<i>alias</i>", codeBase "<i>URL</i>" {
     *     permission <i>Type</i> "<i>name</i>", "<i>action</i>",
     *         signedBy "<i>alias</i>";
     *     ....
     *     permission <i>Type</i> "<i>name</i>", "<i>action</i>",
     *         signedBy "<i>alias</i>";
     *   };
     *
     * </pre>
     *
     * All non-italicized items above must appear as is (although case
     * doesn't matter and some are optional, as noted below).
     * Italicized items represent variable values.
     *
     * <p> A grant entry must begin with the word <code>grant</code>.
     * The <code>signedBy</code> and <code>codeBase</code> name/value
     * pairs are optional.
     * If they are not present, then any signer (including unsigned code)
     * will match, and any codeBase will match.
     *
     * <p> A permission entry must begin with the word <code>permission</code>.
     * The word <code><i>Type</i></code> in the template above would actually
     * be a specific permission type, such as
     * <code>java.io.FilePermission</code> or
     * <code>java.lang.RuntimePermission</code>.
     *
     * <p>The "<i>action</i>" is required for
     * many permission types, such as <code>java.io.FilePermission</code>
     * (where it specifies what type of file access is permitted).
     * It is not required for categories such as
     * <code>java.lang.RuntimePermission</code>
     * where it is not necessary - you either have the
     * permission specified by the <code>"<i>name</i>"</code>
     * value following the type name or you don't.
     *
     * <p>The <code>signedBy</code> name/value pair for a permission entry
     * is optional. If present, it indicates a signed permission. That is,
     * the permission class itself must be signed by the given alias in
     * order for it to be granted. For example,
     * suppose you have the following grant entry:
     *
     * <pre>
     *   grant {
     *     permission Foo "foobar", signedBy "FooSoft";
     *   }
     * </pre>
     *
     * <p>Then this permission of type <i>Foo</i> is granted if the
     * <code>Foo.class</code> permission has been signed by the
     * "FooSoft" alias, or if <code>Foo.class</code> is a
     * system class (i.e., is found on the CLASSPATH).
     *
     * <p>Items that appear in an entry must appear in the specified order
     * (<code>permission</code>, <i>Type</i>, "<i>name</i>", and
     * "<i>action</i>"). An entry is terminated with a semicolon.
     *
     * <p>Case is unimportant for the identifiers (<code>permission</code>,
     * <code>signedBy</code>, <code>codeBase</code>, etc.) but is
     * significant for the <i>Type</i>
     * or for any string that is passed in as a value. <p>
     *
     * <p>An example of two entries in a policy configuration file is
     * <pre>
     *   //  if the code is signed by "Duke", grant it read/write to all
     *   // files in /tmp.
     *
     *   grant signedBy "Duke" {
     *          permission java.io.FilePermission "/tmp/*", "read,write";
     *   };
     * <p>
     *   // grant everyone the following permission
     *
     *   grant {
     *     permission java.util.PropertyPermission "java.vendor";
     *   };
     *  </pre>
     */
    private void init(URL url) {
        // Properties are set once for each init(); ignore changes between
        // between diff invocations of initPolicyFile(policy, url, info).
        String numCacheStr =
          AccessController.doPrivileged(new PrivilegedAction<String>() {
            public String run() {
                expandProperties = "true".equalsIgnoreCase
                    (Security.getProperty("policy.expandProperties"));
                ignoreIdentityScope = "true".equalsIgnoreCase
                    (Security.getProperty("policy.ignoreIdentityScope"));
                allowSystemProperties = "true".equalsIgnoreCase
                    (Security.getProperty("policy.allowSystemProperty"));
                notUtf8 = "false".equalsIgnoreCase
                    (System.getProperty("sun.security.policy.utf8"));
                return System.getProperty("sun.security.policy.numcaches");
            }});

        int numCaches;
        if (numCacheStr != null) {
            try {
                numCaches = Integer.parseInt(numCacheStr);
            } catch (NumberFormatException e) {
                numCaches = DEFAULT_CACHE_SIZE;
            }
        } else {
            numCaches = DEFAULT_CACHE_SIZE;
        }
        // System.out.println("number caches=" + numCaches);
        PolicyInfo newInfo = new PolicyInfo(numCaches);
        initPolicyFile(newInfo, url);
        policyInfo.set(newInfo);
    }

    private void initPolicyFile(final PolicyInfo newInfo, final URL url) {

        if (url != null) {

            /**
             * If the caller specified a URL via Policy.getInstance,
             * we only read from that URL
             */

            if (debug != null) {
                debug.println("reading "+url);
            }
            AccessController.doPrivileged(new PrivilegedAction<Void>() {
                public Void run() {
                    if (init(url, newInfo) == false) {
                        // use static policy if all else fails
                        initStaticPolicy(newInfo);
                    }
                    return null;
                }
            });

        } else {

            /**
             * Caller did not specify URL via Policy.getInstance.
             * Read from URLs listed in the java.security properties file.
             *
             * We call initPolicyFile with POLICY , POLICY_URL and then
             * call it with AUTH_POLICY and AUTH_POLICY_URL
             * So first we will process the JAVA standard policy
             * and then process the JAVA AUTH Policy.
             * This is for backward compatibility as well as to handle
             * cases where the user has a single unified policyfile
             * with both java policy entries and auth entries
             */

            boolean loaded_one = initPolicyFile(POLICY, POLICY_URL, newInfo);
            // To maintain strict backward compatibility
            // we load the static policy only if POLICY load failed
            if (!loaded_one) {
                // use static policy if all else fails
                initStaticPolicy(newInfo);
            }

            initPolicyFile(AUTH_POLICY, AUTH_POLICY_URL, newInfo);
        }
    }

    private boolean initPolicyFile(final String propname, final String urlname,
                                final PolicyInfo newInfo) {
        Boolean loadedPolicy =
            AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
            public Boolean run() {
                boolean loaded_policy = false;

                if (allowSystemProperties) {
                    String extra_policy = System.getProperty(propname);
                    if (extra_policy != null) {
                        boolean overrideAll = false;
                        if (extra_policy.startsWith("=")) {
                            overrideAll = true;
                            extra_policy = extra_policy.substring(1);
                        }
                        try {
                            extra_policy =
                                PropertyExpander.expand(extra_policy);
                            URL policyURL;

                            File policyFile = new File(extra_policy);
                            if (policyFile.exists()) {
                                policyURL = ParseUtil.fileToEncodedURL
                                    (new File(policyFile.getCanonicalPath()));
                            } else {
                                policyURL = new URL(extra_policy);
                            }
                            if (debug != null)
                                debug.println("reading "+policyURL);
                            if (init(policyURL, newInfo))
                                loaded_policy = true;
                        } catch (Exception e) {
                            // ignore.
                            if (debug != null) {
                                debug.println("caught exception: "+e);
                            }
                        }
                        if (overrideAll) {
                            if (debug != null) {
                                debug.println("overriding other policies!");
                            }
                            return Boolean.valueOf(loaded_policy);
                        }
                    }
                }

                int n = 1;
                String policy_uri;

                while ((policy_uri = Security.getProperty(urlname+n)) != null) {
                    try {
                        URL policy_url = null;
                        String expanded_uri = PropertyExpander.expand
                                (policy_uri).replace(File.separatorChar, '/');

                        if (policy_uri.startsWith("file:${java.home}/") ||
                            policy_uri.startsWith("file:${user.home}/")) {

                            // this special case accommodates
                            // the situation java.home/user.home
                            // expand to a single slash, resulting in
                            // a file://foo URI
                            policy_url = new File
                                (expanded_uri.substring(5)).toURI().toURL();
                        } else {
                            policy_url = new URI(expanded_uri).toURL();
                        }

                        if (debug != null)
                            debug.println("reading "+policy_url);
                        if (init(policy_url, newInfo))
                            loaded_policy = true;
                    } catch (Exception e) {
                        if (debug != null) {
                            debug.println("error reading policy "+e);
                            e.printStackTrace();
                        }
                        // ignore that policy
                    }
                    n++;
                }
                return Boolean.valueOf(loaded_policy);
            }
        });

        return loadedPolicy.booleanValue();
    }

    /**
     * Reads a policy configuration into the Policy object using a
     * Reader object.
     *
     * @param policyFile the policy Reader object.
     */
    private boolean init(URL policy, PolicyInfo newInfo) {
        boolean success = false;
        PolicyParser pp = new PolicyParser(expandProperties);
        InputStreamReader isr = null;
        try {

            // read in policy using UTF-8 by default
            //
            // check non-standard system property to see if
            // the default encoding should be used instead

            if (notUtf8) {
                isr = new InputStreamReader
                                (PolicyUtil.getInputStream(policy));
            } else {
                isr = new InputStreamReader
                                (PolicyUtil.getInputStream(policy), "UTF-8");
            }

            pp.read(isr);

            KeyStore keyStore = null;
            try {
                keyStore = PolicyUtil.getKeyStore
                                (policy,
                                pp.getKeyStoreUrl(),
                                pp.getKeyStoreType(),
                                pp.getKeyStoreProvider(),
                                pp.getStorePassURL(),
                                debug);
            } catch (Exception e) {
                // ignore, treat it like we have no keystore
                if (debug != null) {
                    e.printStackTrace();
                }
            }

            Enumeration<PolicyParser.GrantEntry> enum_ = pp.grantElements();
            while (enum_.hasMoreElements()) {
                PolicyParser.GrantEntry ge = enum_.nextElement();
                addGrantEntry(ge, keyStore, newInfo);
            }
        } catch (PolicyParser.ParsingException pe) {
            MessageFormat form = new MessageFormat(ResourcesMgr.getString
                (POLICY + ": error parsing policy:\n\tmessage"));
            Object[] source = {policy, pe.getLocalizedMessage()};
            System.err.println(form.format(source));
            if (debug != null)
                pe.printStackTrace();

        } catch (Exception e) {
            if (debug != null) {
                debug.println("error parsing "+policy);
                debug.println(e.toString());
                e.printStackTrace();
            }
        } finally {
            if (isr != null) {
                try {
                    isr.close();
                    success = true;
                } catch (IOException e) {
                    // ignore the exception
                }
            } else {
                success = true;
            }
        }

        return success;
    }

    private void initStaticPolicy(final PolicyInfo newInfo) {
        AccessController.doPrivileged(new PrivilegedAction<Void>() {
            public Void run() {
                PolicyEntry pe = new PolicyEntry(new CodeSource(null,
                    (Certificate[]) null));
                pe.add(SecurityConstants.LOCAL_LISTEN_PERMISSION);
                pe.add(new PropertyPermission("java.version",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("java.vendor",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("java.vendor.url",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("java.class.version",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("os.name",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("os.version",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("os.arch",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("file.separator",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("path.separator",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("line.separator",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission
                                ("java.specification.version",
                                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission
                                ("java.specification.vendor",
                                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission
                                ("java.specification.name",
                                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission
                                ("java.vm.specification.version",
                                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission
                                ("java.vm.specification.vendor",
                                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission
                                ("java.vm.specification.name",
                                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("java.vm.version",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("java.vm.vendor",
                    SecurityConstants.PROPERTY_READ_ACTION));
                pe.add(new PropertyPermission("java.vm.name",
                    SecurityConstants.PROPERTY_READ_ACTION));

                // No need to sync because noone has access to newInfo yet
                newInfo.policyEntries.add(pe);

                // Add AllPermissions for standard extensions
                String[] extCodebases = PolicyParser.parseExtDirs(
                    PolicyParser.EXTDIRS_EXPANSION, 0);
                if (extCodebases != null && extCodebases.length > 0) {
                    for (int i = 0; i < extCodebases.length; i++) {
                        try {
                            pe = new PolicyEntry(canonicalizeCodebase(
                                new CodeSource(new URL(extCodebases[i]),
                                    (Certificate[]) null), false ));
                            pe.add(SecurityConstants.ALL_PERMISSION);

                            // No need to sync because noone has access to
                            // newInfo yet
                            newInfo.policyEntries.add(pe);
                        } catch (Exception e) {
                            // this is probably bad (though not dangerous).
                            // What should we do?
                        }
                    }
                }
                return null;
            }
        });
    }

    /**
     * Given a GrantEntry, create a codeSource.
     *
     * @return null if signedBy alias is not recognized
     */
    private CodeSource getCodeSource(PolicyParser.GrantEntry ge, KeyStore keyStore,
        PolicyInfo newInfo) throws java.net.MalformedURLException
    {
        Certificate[] certs = null;
        if (ge.signedBy != null) {
            certs = getCertificates(keyStore, ge.signedBy, newInfo);
            if (certs == null) {
                // we don't have a key for this alias,
                // just return
                if (debug != null) {
                    debug.println("  -- No certs for alias '" +
                                       ge.signedBy + "' - ignoring entry");
                }
                return null;
            }
        }

        URL location;

        if (ge.codeBase != null)
            location = new URL(ge.codeBase);
        else
            location = null;

        return (canonicalizeCodebase(new CodeSource(location, certs),false));
    }

    /**
     * Add one policy entry to the list.
     */
    private void addGrantEntry(PolicyParser.GrantEntry ge,
                               KeyStore keyStore, PolicyInfo newInfo) {

        if (debug != null) {
            debug.println("Adding policy entry: ");
            debug.println("  signedBy " + ge.signedBy);
            debug.println("  codeBase " + ge.codeBase);
            if (ge.principals != null && ge.principals.size() > 0) {
                ListIterator<PolicyParser.PrincipalEntry> li =
                                                ge.principals.listIterator();
                while (li.hasNext()) {
                    PolicyParser.PrincipalEntry pppe = li.next();
                debug.println("  " + pppe.toString());
                }
            }
        }

        try {
            CodeSource codesource = getCodeSource(ge, keyStore, newInfo);
            // skip if signedBy alias was unknown...
            if (codesource == null) return;

            // perform keystore alias principal replacement.
            // for example, if alias resolves to X509 certificate,
            // replace principal with:  <X500Principal class>  <SubjectDN>
            // -- skip if alias is unknown
            if (replacePrincipals(ge.principals, keyStore) == false)
                return;
            PolicyEntry entry = new PolicyEntry(codesource, ge.principals);
            Enumeration<PolicyParser.PermissionEntry> enum_ =
                                                ge.permissionElements();
            while (enum_.hasMoreElements()) {
                PolicyParser.PermissionEntry pe = enum_.nextElement();

                try {
                    // perform ${{ ... }} expansions within permission name
                    expandPermissionName(pe, keyStore);

                    // XXX special case PrivateCredentialPermission-SELF
                    Permission perm;
                    if (pe.permission.equals
                        ("javax.security.auth.PrivateCredentialPermission") &&
                        pe.name.endsWith(" self")) {
                        pe.name = pe.name.substring(0, pe.name.indexOf("self"))
                                + SELF;
                    }
                    // check for self
                    if (pe.name != null && pe.name.indexOf(SELF) != -1) {
                        // Create a "SelfPermission" , it could be an
                        // an unresolved permission which will be resolved
                        // when implies is called
                        // Add it to entry
                        Certificate certs[];
                        if (pe.signedBy != null) {
                            certs = getCertificates(keyStore,
                                                    pe.signedBy,
                                                    newInfo);
                        } else {
                            certs = null;
                        }
                        perm = new SelfPermission(pe.permission,
                                                  pe.name,
                                                  pe.action,
                                                  certs);
                    } else {
                        perm = getInstance(pe.permission,
                                           pe.name,
                                           pe.action);
                    }
                    entry.add(perm);
                    if (debug != null) {
                        debug.println("  "+perm);
                    }
                } catch (ClassNotFoundException cnfe) {
                    Certificate certs[];
                    if (pe.signedBy != null) {
                        certs = getCertificates(keyStore,
                                                pe.signedBy,
                                                newInfo);
                    } else {
                        certs = null;
                    }

                    // only add if we had no signer or we had a
                    // a signer and found the keys for it.
                    if (certs != null || pe.signedBy == null) {
                        Permission perm = new UnresolvedPermission(
                                                  pe.permission,
                                                  pe.name,
                                                  pe.action,
                                                  certs);
                        entry.add(perm);
                        if (debug != null) {
                            debug.println("  "+perm);
                        }
                    }
                } catch (java.lang.reflect.InvocationTargetException ite) {
                    MessageFormat form = new MessageFormat
                        (ResourcesMgr.getString
                         (POLICY +
                          ": error adding Permission, perm:\n\tmessage"));
                    Object[] source = {pe.permission,
                                       ite.getTargetException().toString()};
                    System.err.println(form.format(source));
                } catch (Exception e) {
                    MessageFormat form = new MessageFormat
                        (ResourcesMgr.getString
                         (POLICY +
                          ": error adding Permission, perm:\n\tmessage"));
                    Object[] source = {pe.permission,
                                       e.toString()};
                    System.err.println(form.format(source));
                }
            }

            // No need to sync because noone has access to newInfo yet
            newInfo.policyEntries.add(entry);
        } catch (Exception e) {
            MessageFormat form = new MessageFormat(ResourcesMgr.getString
                                         (POLICY
                                         + ": error adding Entry:\n\tmessage"));
            Object[] source = {e.toString()};
            System.err.println(form.format(source));
        }
        if (debug != null)
            debug.println();
    }

    /**
     * Returns a new Permission object of the given Type. The Permission is
     * created by getting the
     * Class object using the <code>Class.forName</code> method, and using
     * the reflection API to invoke the (String name, String actions)
     * constructor on the
     * object.
     *
     * @param type the type of Permission being created.
     * @param name the name of the Permission being created.
     * @param actions the actions of the Permission being created.
     *
     * @exception  ClassNotFoundException  if the particular Permission
     *             class could not be found.
     *
     * @exception  IllegalAccessException  if the class or initializer is
     *               not accessible.
     *
     * @exception  InstantiationException  if getInstance tries to
     *               instantiate an abstract class or an interface, or if the
     *               instantiation fails for some other reason.
     *
     * @exception  NoSuchMethodException if the (String, String) constructor
     *               is not found.
     *
     * @exception  InvocationTargetException if the underlying Permission
     *               constructor throws an exception.
     *
     */

    private static final Permission getInstance(String type,
                                    String name,
                                    String actions)
        throws ClassNotFoundException,
               InstantiationException,
               IllegalAccessException,
               NoSuchMethodException,
               InvocationTargetException
    {
        //XXX we might want to keep a hash of created factories...
        Class<?> pc = Class.forName(type);
        Permission answer = getKnownInstance(pc, name, actions);
        if (answer != null) {
            return answer;
        }

        if (name == null && actions == null) {
            try {
                Constructor<?> c = pc.getConstructor(PARAMS0);
                return (Permission) c.newInstance(new Object[] {});
            } catch (NoSuchMethodException ne) {
                try {
                    Constructor<?> c = pc.getConstructor(PARAMS1);
                    return (Permission) c.newInstance(
                              new Object[] { name});
                } catch (NoSuchMethodException ne1 ) {
                    Constructor<?> c = pc.getConstructor(PARAMS2);
                    return (Permission) c.newInstance(
                        new Object[] { name, actions });
                }
            }
        } else {
            if (name != null && actions == null) {
                try {
                    Constructor<?> c = pc.getConstructor(PARAMS1);
                    return (Permission) c.newInstance(new Object[] { name});
                } catch (NoSuchMethodException ne) {
                    Constructor<?> c = pc.getConstructor(PARAMS2);
                    return (Permission) c.newInstance(
                          new Object[] { name, actions });
                }
            } else {
                Constructor<?> c = pc.getConstructor(PARAMS2);
                return (Permission) c.newInstance(
                      new Object[] { name, actions });
             }
        }
    }

    /**
     * Creates one of the well-known permissions directly instead of
     * via reflection. Keep list short to not penalize non-JDK-defined
     * permissions.
     */
    private static final Permission getKnownInstance(Class claz,
        String name, String actions) {
        // XXX shorten list to most popular ones?
        if (claz.equals(FilePermission.class)) {
            return new FilePermission(name, actions);
        } else if (claz.equals(SocketPermission.class)) {
            return new SocketPermission(name, actions);
        } else if (claz.equals(RuntimePermission.class)) {
            return new RuntimePermission(name, actions);
        } else if (claz.equals(PropertyPermission.class)) {
            return new PropertyPermission(name, actions);
        } else if (claz.equals(NetPermission.class)) {
            return new NetPermission(name, actions);
        } else if (claz.equals(AllPermission.class)) {
            return SecurityConstants.ALL_PERMISSION;
/*
        } else if (claz.equals(ReflectPermission.class)) {
            return new ReflectPermission(name, actions);
        } else if (claz.equals(SecurityPermission.class)) {
            return new SecurityPermission(name, actions);
        } else if (claz.equals(PrivateCredentialPermission.class)) {
            return new PrivateCredentialPermission(name, actions);
        } else if (claz.equals(AuthPermission.class)) {
            return new AuthPermission(name, actions);
        } else if (claz.equals(ServicePermission.class)) {
            return new ServicePermission(name, actions);
        } else if (claz.equals(DelegationPermission.class)) {
            return new DelegationPermission(name, actions);
        } else if (claz.equals(SerializablePermission.class)) {
            return new SerializablePermission(name, actions);
        } else if (claz.equals(AudioPermission.class)) {
            return new AudioPermission(name, actions);
        } else if (claz.equals(SSLPermission.class)) {
            return new SSLPermission(name, actions);
        } else if (claz.equals(LoggingPermission.class)) {
            return new LoggingPermission(name, actions);
        } else if (claz.equals(SQLPermission.class)) {
            return new SQLPermission(name, actions);
*/
        } else {
            return null;
        }
    }

    /**
     * Fetch all certs associated with this alias.
     */
    private Certificate[] getCertificates
                (KeyStore keyStore, String aliases, PolicyInfo newInfo) {

        List<Certificate> vcerts = null;

        StringTokenizer st = new StringTokenizer(aliases, ",");
        int n = 0;

        while (st.hasMoreTokens()) {
            String alias = st.nextToken().trim();
            n++;
            Certificate cert = null;
            // See if this alias's cert has already been cached
            synchronized (newInfo.aliasMapping) {
                cert = (Certificate)newInfo.aliasMapping.get(alias);

                if (cert == null && keyStore != null) {

                    try {
                        cert = keyStore.getCertificate(alias);
                    } catch (KeyStoreException kse) {
                        // never happens, because keystore has already been loaded
                        // when we call this
                    }
                    if (cert != null) {
                        newInfo.aliasMapping.put(alias, cert);
                        newInfo.aliasMapping.put(cert, alias);
                    }
                }
            }

            if (cert != null) {
                if (vcerts == null)
                    vcerts = new ArrayList<Certificate>();
                vcerts.add(cert);
            }
        }

        // make sure n == vcerts.size, since we are doing a logical *and*
        if (vcerts != null && n == vcerts.size()) {
            Certificate[] certs = new Certificate[vcerts.size()];
            vcerts.toArray(certs);
            return certs;
        } else {
            return null;
        }
    }

    /**
     * Refreshes the policy object by re-reading all the policy files.
     */
    @Override public void refresh() {
        init(url);
    }

    /**
     * Evaluates the the global policy for the permissions granted to
     * the ProtectionDomain and tests whether the permission is
     * granted.
     *
     * @param domain the ProtectionDomain to test
     * @param permission the Permission object to be tested for implication.
     *
     * @return true if "permission" is a proper subset of a permission
     * granted to this ProtectionDomain.
     *
     * @see java.security.ProtectionDomain
     */
    @Override
    public boolean implies(ProtectionDomain pd, Permission p) {
        PolicyInfo pi = policyInfo.get();
        ProtectionDomainCache pdMap = pi.getPdMapping();

        PermissionCollection pc = pdMap.get(pd);

        if (pc != null) {
            return pc.implies(p);
        }

        pc = getPermissions(pd);
        if (pc == null) {
            return false;
        }

        // cache mapping of protection domain to its PermissionCollection
        pdMap.put(pd, pc);
        return pc.implies(p);
    }

    /**
     * Examines this <code>Policy</code> and returns the permissions granted
     * to the specified <code>ProtectionDomain</code>.  This includes
     * the permissions currently associated with the domain as well
     * as the policy permissions granted to the domain's
     * CodeSource, ClassLoader, and Principals.
     *
     * <p> Note that this <code>Policy</code> implementation has
     * special handling for PrivateCredentialPermissions.
     * When this method encounters a <code>PrivateCredentialPermission</code>
     * which specifies "self" as the <code>Principal</code> class and name,
     * it does not add that <code>Permission</code> to the returned
     * <code>PermissionCollection</code>.  Instead, it builds
     * a new <code>PrivateCredentialPermission</code>
     * for each <code>Principal</code> associated with the provided
     * <code>Subject</code>.  Each new <code>PrivateCredentialPermission</code>
     * contains the same Credential class as specified in the
     * originally granted permission, as well as the Class and name
     * for the respective <code>Principal</code>.
     *
     * <p>
     *
     * @param domain the Permissions granted to this
     *          <code>ProtectionDomain</code> are returned.
     *
     * @return the Permissions granted to the provided
     *          <code>ProtectionDomain</code>.
     */
    @Override
    public PermissionCollection getPermissions(ProtectionDomain domain) {
        Permissions perms = new Permissions();

        if (domain == null)
           return perms;

        // first get policy perms
        getPermissions(perms, domain);

        // add static perms
        //      - adding static perms after policy perms is necessary
        //        to avoid a regression for 4301064
        PermissionCollection pc = domain.getPermissions();
        if (pc != null) {
            synchronized (pc) {
                Enumeration<Permission> e = pc.elements();
                while (e.hasMoreElements()) {
                    perms.add(e.nextElement());
                }
            }
        }

        return perms;
    }

    /**
     * Examines this Policy and creates a PermissionCollection object with
     * the set of permissions for the specified CodeSource.
     *
     * @param CodeSource the codesource associated with the caller.
     * This encapsulates the original location of the code (where the code
     * came from) and the public key(s) of its signer.
     *
     * @return the set of permissions according to the policy.
     */
    @Override
    public PermissionCollection getPermissions(CodeSource codesource) {
        return getPermissions(new Permissions(), codesource);
    }

    /**
     * Examines the global policy and returns the provided Permissions
     * object with additional permissions granted to the specified
     * ProtectionDomain.
     *
     * @param perm the Permissions to populate
     * @param pd the ProtectionDomain associated with the caller.
     *
     * @return the set of Permissions according to the policy.
     */
    private PermissionCollection getPermissions(Permissions perms,
                                        ProtectionDomain pd ) {
        if (debug != null) {
            debug.println("getPermissions:\n\t" + printPD(pd));
        }

        final CodeSource cs = pd.getCodeSource();
        if (cs == null)
            return perms;

        CodeSource canonCodeSource = AccessController.doPrivileged(
            new java.security.PrivilegedAction<CodeSource>(){
                public CodeSource run() {
                    return canonicalizeCodebase(cs, true);
                }
            });
        return getPermissions(perms, canonCodeSource, pd.getPrincipals());
    }

    /**
     * Examines the global policy and returns the provided Permissions
     * object with additional permissions granted to the specified
     * CodeSource.
     *
     * @param permissions the permissions to populate
     * @param codesource the codesource associated with the caller.
     * This encapsulates the original location of the code (where the code
     * came from) and the public key(s) of its signer.
     *
     * @return the set of permissions according to the policy.
     */
    private PermissionCollection getPermissions(Permissions perms,
                               final CodeSource cs) {

        CodeSource canonCodeSource = AccessController.doPrivileged(
            new java.security.PrivilegedAction<CodeSource>(){
                public CodeSource run() {
                    return canonicalizeCodebase(cs, true);
                }
            });

        return getPermissions(perms, canonCodeSource, null);
    }

    private Permissions getPermissions(Permissions perms,
                                       final CodeSource cs,
                                       Principal[] principals) {
        PolicyInfo pi = policyInfo.get();

        for (PolicyEntry entry : pi.policyEntries) {
            addPermissions(perms, cs, principals, entry);
        }

        // Go through policyEntries gotten from identity db; sync required
        // because checkForTrustedIdentity (below) might update list
        synchronized (pi.identityPolicyEntries) {
            for (PolicyEntry entry : pi.identityPolicyEntries) {
                addPermissions(perms, cs, principals, entry);
            }
        }

        // now see if any of the keys are trusted ids.
        if (!ignoreIdentityScope) {
            Certificate certs[] = cs.getCertificates();
            if (certs != null) {
                for (int k=0; k < certs.length; k++) {
                    Object idMap = pi.aliasMapping.get(certs[k]);
                    if (idMap == null &&
                        checkForTrustedIdentity(certs[k], pi)) {
                        // checkForTrustedIdentity added it
                        // to the policy for us. next time
                        // around we'll find it. This time
                        // around we need to add it.
                        perms.add(SecurityConstants.ALL_PERMISSION);
                    }
                }
            }
        }
        return perms;
    }

    private void addPermissions(Permissions perms,
        final CodeSource cs,
        Principal[] principals,
        final PolicyEntry entry) {

        if (debug != null) {
            debug.println("evaluate codesources:\n" +
                "\tPolicy CodeSource: " + entry.getCodeSource() + "\n" +
                "\tActive CodeSource: " + cs);
        }

        // check to see if the CodeSource implies
        Boolean imp = AccessController.doPrivileged
            (new PrivilegedAction<Boolean>() {
            public Boolean run() {
                return new Boolean(entry.getCodeSource().implies(cs));
            }
        });
        if (!imp.booleanValue()) {
            if (debug != null) {
                debug.println("evaluation (codesource) failed");
            }

            // CodeSource does not imply - return and try next policy entry
            return;
        }

        // check to see if the Principals imply

        List<PolicyParser.PrincipalEntry> entryPs = entry.getPrincipals();
        if (debug != null) {
            ArrayList<PolicyParser.PrincipalEntry> accPs =
                        new ArrayList<PolicyParser.PrincipalEntry>();
            if (principals != null) {
                for (int i = 0; i < principals.length; i++) {
                    accPs.add(new PolicyParser.PrincipalEntry
                                        (principals[i].getClass().getName(),
                                        principals[i].getName()));
                }
            }
            debug.println("evaluate principals:\n" +
                "\tPolicy Principals: " + entryPs + "\n" +
                "\tActive Principals: " + accPs);
        }

        if (entryPs == null || entryPs.size() == 0) {

            // policy entry has no principals -
            // add perms regardless of principals in current ACC

            addPerms(perms, principals, entry);
            if (debug != null) {
                debug.println("evaluation (codesource/principals) passed");
            }
            return;

        } else if (principals == null || principals.length == 0) {

            // current thread has no principals but this policy entry
            // has principals - perms are not added

            if (debug != null) {
                debug.println("evaluation (principals) failed");
            }
            return;
        }

        // current thread has principals and this policy entry
        // has principals.  see if policy entry principals match
        // principals in current ACC

        for (int i = 0; i < entryPs.size(); i++) {
            PolicyParser.PrincipalEntry pppe = entryPs.get(i);

            // see if principal entry is a PrincipalComparator

            try {
                Class<?> pClass = Class.forName
                                (pppe.principalClass,
                                true,
                                Thread.currentThread().getContextClassLoader());

                if (!PrincipalComparator.class.isAssignableFrom(pClass)) {

                    // common case - dealing with regular Principal class.
                    // see if policy entry principal is in current ACC

                    if (!checkEntryPs(principals, pppe)) {
                        if (debug != null) {
                            debug.println("evaluation (principals) failed");
                        }

                        // policy entry principal not in current ACC -
                        // immediately return and go to next policy entry
                        return;
                    }

                } else {

                    // dealing with a PrincipalComparator

                    Constructor<?> c = pClass.getConstructor(PARAMS1);
                    PrincipalComparator pc = (PrincipalComparator)c.newInstance
                                        (new Object[] { pppe.principalName });

                    if (debug != null) {
                        debug.println("found PrincipalComparator " +
                                        pc.getClass().getName());
                    }

                    // check if the PrincipalComparator
                    // implies the current thread's principals

                    Set<Principal> pSet =
                                new HashSet<Principal>(principals.length);
                    for (int j = 0; j < principals.length; j++) {
                        pSet.add(principals[j]);
                    }
                    Subject subject = new Subject(true,
                                                pSet,
                                                Collections.EMPTY_SET,
                                                Collections.EMPTY_SET);

                    if (!pc.implies(subject)) {
                        if (debug != null) {
                            debug.println
                                ("evaluation (principal comparator) failed");
                        }

                        // policy principal does not imply the current Subject -
                        // immediately return and go to next policy entry
                        return;
                    }
                }
            } catch (Exception e) {
                // fall back to regular principal comparison.
                // see if policy entry principal is in current ACC

                if (debug != null) {
                    e.printStackTrace();
                }

                if (!checkEntryPs(principals, pppe)) {
                    if (debug != null) {
                        debug.println("evaluation (principals) failed");
                    }

                    // policy entry principal not in current ACC -
                    // immediately return and go to next policy entry
                    return;
                }
            }

            // either the principal information matched,
            // or the PrincipalComparator.implies succeeded.
            // continue loop and test the next policy principal
        }

        // all policy entry principals were found in the current ACC -
        // grant the policy permissions

        if (debug != null) {
            debug.println("evaluation (codesource/principals) passed");
        }
        addPerms(perms, principals, entry);
    }

    private void addPerms(Permissions perms,
                        Principal[] accPs,
                        PolicyEntry entry) {
        for (int i = 0; i < entry.permissions.size(); i++) {
            Permission p = entry.permissions.get(i);
            if (debug != null) {
                debug.println("  granting " + p);
            }

            if (p instanceof SelfPermission) {
                // handle "SELF" permissions
                expandSelf((SelfPermission)p,
                        entry.getPrincipals(),
                        accPs,
                        perms);
            } else {
                perms.add(p);
            }
        }
    }

    /**
     * This method returns, true, if the principal in the policy entry,
     * pppe, is part of the current thread's principal array, pList.
     * This method also returns, true, if the policy entry's principal
     * is appropriately wildcarded.
     *
     * Note that the provided <i>pppe</i> argument may have
     * wildcards (*) for both the <code>Principal</code> class and name.
     *
     * @param pList an array of principals from the current thread's
     *          AccessControlContext.
     *
     * @param pppe a Principal specified in a policy grant entry.
     *
     * @return true if the current thread's pList "contains" the
     *          principal in the policy entry, pppe.  This method
     *          also returns true if the policy entry's principal
     *          appropriately wildcarded.
     */
    private boolean checkEntryPs(Principal[] pList,
                                PolicyParser.PrincipalEntry pppe) {

        for (int i = 0; i < pList.length; i++) {

            if (pppe.principalClass.equals
                        (PolicyParser.PrincipalEntry.WILDCARD_CLASS) ||
                pppe.principalClass.equals
                        (pList[i].getClass().getName())) {

                if (pppe.principalName.equals
                        (PolicyParser.PrincipalEntry.WILDCARD_NAME) ||
                    pppe.principalName.equals
                        (pList[i].getName())) {

                    return true;
                }
            }
        }
        return false;
    }

    /**
     * <p>
     *
     * @param sp the SelfPermission that needs to be expanded <p>
     *
     * @param entryPs list of principals for the Policy entry.
     *
     * @param pdp Principal array from the current ProtectionDomain.
     *
     * @param perms the PermissionCollection where the individual
     *                  Permissions will be added after expansion.
     */

    private void expandSelf(SelfPermission sp,
                            List<PolicyParser.PrincipalEntry> entryPs,
                            Principal[] pdp,
                            Permissions perms) {

        if (entryPs == null || entryPs.size() == 0) {
            // No principals in the grant to substitute
            if (debug != null) {
                debug.println("Ignoring permission "
                                + sp.getSelfType()
                                + " with target name ("
                                + sp.getSelfName() + ").  "
                                + "No Principal(s) specified "
                                + "in the grant clause.  "
                                + "SELF-based target names are "
                                + "only valid in the context "
                                + "of a Principal-based grant entry."
                             );
            }
            return;
        }
        int startIndex = 0;
        int v;
        StringBuilder sb = new StringBuilder();
        while ((v = sp.getSelfName().indexOf(SELF, startIndex)) != -1) {

            // add non-SELF string
            sb.append(sp.getSelfName().substring(startIndex, v));

            // expand SELF
            ListIterator<PolicyParser.PrincipalEntry> pli =
                                                entryPs.listIterator();
            while (pli.hasNext()) {
                PolicyParser.PrincipalEntry pppe = pli.next();
                String[][] principalInfo = getPrincipalInfo(pppe,pdp);
                for (int i = 0; i < principalInfo.length; i++) {
                    if (i != 0) {
                        sb.append(", ");
                    }
                    sb.append(principalInfo[i][0] + " " +
                        "\"" + principalInfo[i][1] + "\"");
                }
                if (pli.hasNext()) {
                    sb.append(", ");
                }
            }
            startIndex = v + SELF.length();
        }
        // add remaining string (might be the entire string)
        sb.append(sp.getSelfName().substring(startIndex));

        if (debug != null) {
            debug.println("  expanded:\n\t" + sp.getSelfName()
                        + "\n  into:\n\t" + sb.toString());
        }
        try {
            // first try to instantiate the permission
            perms.add(getInstance(sp.getSelfType(),
                                sb.toString(),
                                sp.getSelfActions()));
        } catch (ClassNotFoundException cnfe) {
            // ok, the permission is not in the bootclasspath.
            // before we add an UnresolvedPermission, check to see
            // whether this perm already belongs to the collection.
            // if so, use that perm's ClassLoader to create a new
            // one.
            Class<?> pc = null;
            synchronized (perms) {
                Enumeration<Permission> e = perms.elements();
                while (e.hasMoreElements()) {
                    Permission pElement = e.nextElement();
                    if (pElement.getClass().getName().equals(sp.getSelfType())) {
                        pc = pElement.getClass();
                        break;
                    }
                }
            }
            if (pc == null) {
                // create an UnresolvedPermission
                perms.add(new UnresolvedPermission(sp.getSelfType(),
                                                        sb.toString(),
                                                        sp.getSelfActions(),
                                                        sp.getCerts()));
            } else {
                try {
                    // we found an instantiated permission.
                    // use its class loader to instantiate a new permission.
                    Constructor<?> c;
                    // name parameter can not be null
                    if (sp.getSelfActions() == null) {
                        try {
                            c = pc.getConstructor(PARAMS1);
                            perms.add((Permission)c.newInstance
                                 (new Object[] {sb.toString()}));
                        } catch (NoSuchMethodException ne) {
                            c = pc.getConstructor(PARAMS2);
                            perms.add((Permission)c.newInstance
                                 (new Object[] {sb.toString(),
                                                sp.getSelfActions() }));
                        }
                    } else {
                        c = pc.getConstructor(PARAMS2);
                        perms.add((Permission)c.newInstance
                           (new Object[] {sb.toString(),
                                          sp.getSelfActions()}));
                    }
                } catch (Exception nme) {
                    if (debug != null) {
                        debug.println("self entry expansion " +
                        " instantiation failed: "
                        +  nme.toString());
                    }
                }
            }
        } catch (Exception e) {
            if (debug != null) {
                debug.println(e.toString());
            }
        }
    }

    /**
     * return the principal class/name pair in the 2D array.
     * array[x][y]:     x corresponds to the array length.
     *                  if (y == 0), it's the principal class.
     *                  if (y == 1), it's the principal name.
     */
    private String[][] getPrincipalInfo
        (PolicyParser.PrincipalEntry pe, Principal[] pdp) {

        // there are 3 possibilities:
        // 1) the entry's Principal class and name are not wildcarded
        // 2) the entry's Principal name is wildcarded only
        // 3) the entry's Principal class and name are wildcarded

        if (!pe.principalClass.equals
            (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
            !pe.principalName.equals
            (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {

            // build an info array for the principal
            // from the Policy entry
            String[][] info = new String[1][2];
            info[0][0] = pe.principalClass;
            info[0][1] = pe.principalName;
            return info;

        } else if (!pe.principalClass.equals
                   (PolicyParser.PrincipalEntry.WILDCARD_CLASS) &&
                   pe.principalName.equals
                   (PolicyParser.PrincipalEntry.WILDCARD_NAME)) {

            // build an info array for every principal
            // in the current domain which has a principal class
            // that is equal to policy entry principal class name
            List<Principal> plist = new ArrayList<Principal>();
            for (int i = 0; i < pdp.length; i++) {
                if(pe.principalClass.equals(pdp[i].getClass().getName()))
                    plist.add(pdp[i]);
            }
            String[][] info = new String[plist.size()][2];
            int i = 0;
            java.util.Iterator<Principal> pIterator = plist.iterator();
            while (pIterator.hasNext()) {
                Principal p = pIterator.next();
                info[i][0] = p.getClass().getName();
                info[i][1] = p.getName();
                i++;
            }
            return info;

        } else {

            // build an info array for every
            // one of the current Domain's principals

            String[][] info = new String[pdp.length][2];

            for (int i = 0; i < pdp.length; i++) {
                info[i][0] = pdp[i].getClass().getName();
                info[i][1] = pdp[i].getName();
            }
            return info;
        }
    }

    /*
     * Returns the signer certificates from the list of certificates
     * associated with the given code source.
     *
     * The signer certificates are those certificates that were used
     * to verifysigned code originating from the codesource location.
     *
     * This method assumes that in the given code source, each signer
     * certificate is followed by its supporting certificate chain
     * (which may be empty), and that the signer certificate and its
     * supporting certificate chain are ordered bottom-to-top
     * (i.e., with the signer certificate first and the (root) certificate
     * authority last).
     */
    protected Certificate[] getSignerCertificates(CodeSource cs) {
        Certificate[] certs = null;
        if ((certs = cs.getCertificates()) == null)
            return null;
        for (int i=0; i<certs.length; i++) {
            if (!(certs[i] instanceof X509Certificate))
                return cs.getCertificates();
        }

        // Do we have to do anything?
        int i = 0;
        int count = 0;
        while (i < certs.length) {
            count++;
            while (((i+1) < certs.length)
                   && ((X509Certificate)certs[i]).getIssuerDN().equals(
                           ((X509Certificate)certs[i+1]).getSubjectDN())) {
                i++;
            }
            i++;
        }
        if (count == certs.length)
            // Done
            return certs;

        ArrayList<Certificate> userCertList = new ArrayList<Certificate>();
        i = 0;
        while (i < certs.length) {
            userCertList.add(certs[i]);
            while (((i+1) < certs.length)
                   && ((X509Certificate)certs[i]).getIssuerDN().equals(
                           ((X509Certificate)certs[i+1]).getSubjectDN())) {
                i++;
            }
            i++;
        }
        Certificate[] userCerts = new Certificate[userCertList.size()];
        userCertList.toArray(userCerts);
        return userCerts;
    }

    private CodeSource canonicalizeCodebase(CodeSource cs,
                                            boolean extractSignerCerts) {

        String path = null;

        CodeSource canonCs = cs;
        URL u = cs.getLocation();
        if (u != null && u.getProtocol().equals("file")) {
            boolean isLocalFile = false;
            String host = u.getHost();
            isLocalFile = (host == null || host.equals("") ||
                host.equals("~") || host.equalsIgnoreCase("localhost"));

            if (isLocalFile) {
                path = u.getFile().replace('/', File.separatorChar);
                path = ParseUtil.decode(path);
            }
        }

        if (path != null) {
            try {
                URL csUrl = null;
                path = canonPath(path);
                csUrl = ParseUtil.fileToEncodedURL(new File(path));

                if (extractSignerCerts) {
                    canonCs = new CodeSource(csUrl,
                                             getSignerCertificates(cs));
                } else {
                    canonCs = new CodeSource(csUrl,
                                             cs.getCertificates());
                }
            } catch (IOException ioe) {
                // leave codesource as it is, unless we have to extract its
                // signer certificates
                if (extractSignerCerts) {
                    canonCs = new CodeSource(cs.getLocation(),
                                             getSignerCertificates(cs));
                }
            }
        } else {
            if (extractSignerCerts) {
                canonCs = new CodeSource(cs.getLocation(),
                                         getSignerCertificates(cs));
            }
        }
        return canonCs;
    }

    // Wrapper to return a canonical path that avoids calling getCanonicalPath()
    // with paths that are intended to match all entries in the directory
    private static String canonPath(String path) throws IOException {
        if (path.endsWith("*")) {
            path = path.substring(0, path.length()-1) + "-";
            path = new File(path).getCanonicalPath();
            return path.substring(0, path.length()-1) + "*";
        } else {
            return new File(path).getCanonicalPath();
        }
    }

    private String printPD(ProtectionDomain pd) {
        Principal[] principals = pd.getPrincipals();
        String pals = "<no principals>";
        if (principals != null && principals.length > 0) {
            StringBuilder palBuf = new StringBuilder("(principals ");
            for (int i = 0; i < principals.length; i++) {
                palBuf.append(principals[i].getClass().getName() +
                              " \"" + principals[i].getName() +
                              "\"");
                if (i < principals.length-1)
                    palBuf.append(", ");
                else
                    palBuf.append(")");
            }
            pals = palBuf.toString();
        }
        return "PD CodeSource: "
                + pd.getCodeSource()
                +"\n\t" + "PD ClassLoader: "
                + pd.getClassLoader()
                +"\n\t" + "PD Principals: "
                + pals;
    }

    /**
     * return true if no replacement was performed,
     * or if replacement succeeded.
     */
    private boolean replacePrincipals(
        List<PolicyParser.PrincipalEntry> principals, KeyStore keystore) {

        if (principals == null || principals.size() == 0 || keystore == null)
            return true;

        ListIterator<PolicyParser.PrincipalEntry> i = principals.listIterator();
        while (i.hasNext()) {
            PolicyParser.PrincipalEntry pppe = i.next();
            if (pppe.principalClass.equals(PolicyParser.REPLACE_NAME)) {

                // perform replacement
                // (only X509 replacement is possible now)
                String name;
                if ((name = getDN(pppe.principalName, keystore)) == null) {
                    return false;
                }

                if (debug != null) {
                    debug.println("  Replacing \"" +
                        pppe.principalName +
                        "\" with " +
                        X500PRINCIPAL + "/\"" +
                        name +
                        "\"");
                }

                pppe.principalClass = X500PRINCIPAL;
                pppe.principalName = name;
            }
        }
        // return true if no replacement was performed,
        // or if replacement succeeded
        return true;
    }

    private void expandPermissionName(PolicyParser.PermissionEntry pe,
                                        KeyStore keystore) throws Exception {
        // short cut the common case
        if (pe.name == null || pe.name.indexOf("${{", 0) == -1) {
            return;
        }

        int startIndex = 0;
        int b, e;
        StringBuilder sb = new StringBuilder();
        while ((b = pe.name.indexOf("${{", startIndex)) != -1) {
            e = pe.name.indexOf("}}", b);
            if (e < 1) {
                break;
            }
            sb.append(pe.name.substring(startIndex, b));

            // get the value in ${{...}}
            String value = pe.name.substring(b+3, e);

            // parse up to the first ':'
            int colonIndex;
            String prefix = value;
            String suffix;
            if ((colonIndex = value.indexOf(":")) != -1) {
                prefix = value.substring(0, colonIndex);
            }

            // handle different prefix possibilities
            if (prefix.equalsIgnoreCase("self")) {
                // do nothing - handled later
                sb.append(pe.name.substring(b, e+2));
                startIndex = e+2;
                continue;
            } else if (prefix.equalsIgnoreCase("alias")) {
                // get the suffix and perform keystore alias replacement
                if (colonIndex == -1) {
                    MessageFormat form = new MessageFormat
                        (ResourcesMgr.getString
                        ("alias name not provided (pe.name)"));
                    Object[] source = {pe.name};
                    throw new Exception(form.format(source));
                }
                suffix = value.substring(colonIndex+1);
                if ((suffix = getDN(suffix, keystore)) == null) {
                    MessageFormat form = new MessageFormat
                        (ResourcesMgr.getString
                        ("unable to perform substitution on alias, suffix"));
                    Object[] source = {value.substring(colonIndex+1)};
                    throw new Exception(form.format(source));
                }

                sb.append(X500PRINCIPAL + " \"" + suffix + "\"");
                startIndex = e+2;
            } else {
                MessageFormat form = new MessageFormat
                        (ResourcesMgr.getString
                        ("substitution value, prefix, unsupported"));
                Object[] source = {prefix};
                throw new Exception(form.format(source));
            }
        }

        // copy the rest of the value
        sb.append(pe.name.substring(startIndex));

        // replace the name with expanded value
        if (debug != null) {
            debug.println("  Permission name expanded from:\n\t" +
                        pe.name + "\nto\n\t" + sb.toString());
        }
        pe.name = sb.toString();
    }

    private String getDN(String alias, KeyStore keystore) {
        Certificate cert = null;
        try {
            cert = keystore.getCertificate(alias);
        } catch (Exception e) {
            if (debug != null) {
                debug.println("  Error retrieving certificate for '" +
                                alias +
                                "': " +
                                e.toString());
            }
            return null;
        }

        if (cert == null || !(cert instanceof X509Certificate)) {
            if (debug != null) {
                debug.println("  -- No certificate for '" +
                                alias +
                                "' - ignoring entry");
            }
            return null;
        } else {
            X509Certificate x509Cert = (X509Certificate)cert;

            // 4702543:  X500 names with an EmailAddress
            // were encoded incorrectly.  create new
            // X500Principal name with correct encoding

            X500Principal p = new X500Principal
                (x509Cert.getSubjectX500Principal().toString());
            return p.getName();
        }
    }

    /**
     * Checks public key. If it is marked as trusted in
     * the identity database, add it to the policy
     * with the AllPermission.
     */
    private boolean checkForTrustedIdentity(final Certificate cert,
        PolicyInfo myInfo)
    {
        return false;
    }

    /**
     * Each entry in the policy configuration file is represented by a
     * PolicyEntry object.  <p>
     *
     * A PolicyEntry is a (CodeSource,Permission) pair.  The
     * CodeSource contains the (URL, PublicKey) that together identify
     * where the Java bytecodes come from and who (if anyone) signed
     * them.  The URL could refer to localhost.  The URL could also be
     * null, meaning that this policy entry is given to all comers, as
     * long as they match the signer field.  The signer could be null,
     * meaning the code is not signed. <p>
     *
     * The Permission contains the (Type, Name, Action) triplet. <p>
     *
     * For now, the Policy object retrieves the public key from the
     * X.509 certificate on disk that corresponds to the signedBy
     * alias specified in the Policy config file.  For reasons of
     * efficiency, the Policy object keeps a hashtable of certs already
     * read in.  This could be replaced by a secure internal key
     * store.
     *
     * <p>
     * For example, the entry
     * <pre>
     *          permission java.io.File "/tmp", "read,write",
     *          signedBy "Duke";
     * </pre>
     * is represented internally
     * <pre>
     *
     * FilePermission f = new FilePermission("/tmp", "read,write");
     * PublicKey p = publickeys.get("Duke");
     * URL u = InetAddress.getLocalHost();
     * CodeBase c = new CodeBase( p, u );
     * pe = new PolicyEntry(f, c);
     * </pre>
     *
     * @author Marianne Mueller
     * @author Roland Schemers
     * @see java.security.CodeSource
     * @see java.security.Policy
     * @see java.security.Permissions
     * @see java.security.ProtectionDomain
     */
    private static class PolicyEntry {

        private final CodeSource codesource;
        final List<Permission> permissions;
        private final List<PolicyParser.PrincipalEntry> principals;

        /**
         * Given a Permission and a CodeSource, create a policy entry.
         *
         * XXX Decide if/how to add validity fields and "purpose" fields to
         * XXX policy entries
         *
         * @param cs the CodeSource, which encapsulates the URL and the
         *        public key
         *        attributes from the policy config file. Validity checks
         *        are performed on the public key before PolicyEntry is
         *        called.
         *
         */
        PolicyEntry(CodeSource cs, List<PolicyParser.PrincipalEntry> principals)
        {
            this.codesource = cs;
            this.permissions = new ArrayList<Permission>();
            this.principals = principals; // can be null
        }

        PolicyEntry(CodeSource cs)
        {
            this(cs, null);
        }

        List<PolicyParser.PrincipalEntry> getPrincipals() {
            return principals; // can be null
        }

        /**
         * add a Permission object to this entry.
         * No need to sync add op because perms are added to entry only
         * while entry is being initialized
         */
        void add(Permission p) {
            permissions.add(p);
        }

        /**
         * Return the CodeSource for this policy entry
         */
        CodeSource getCodeSource() {
            return codesource;
        }

        @Override public String toString(){
            StringBuilder sb = new StringBuilder();
            sb.append(ResourcesMgr.getString("("));
            sb.append(getCodeSource());
            sb.append("\n");
            for (int j = 0; j < permissions.size(); j++) {
                Permission p = permissions.get(j);
                sb.append(ResourcesMgr.getString(" "));
                sb.append(ResourcesMgr.getString(" "));
                sb.append(p);
                sb.append(ResourcesMgr.getString("\n"));
            }
            sb.append(ResourcesMgr.getString(")"));
            sb.append(ResourcesMgr.getString("\n"));
            return sb.toString();
        }
    }

    private static class SelfPermission extends Permission {

        private static final long serialVersionUID = -8315562579967246806L;

        /**
         * The class name of the Permission class that will be
         * created when this self permission is expanded .
         *
         * @serial
         */
        private String type;

        /**
         * The permission name.
         *
         * @serial
         */
        private String name;

        /**
         * The actions of the permission.
         *
         * @serial
         */
        private String actions;

        /**
         * The certs of the permission.
         *
         * @serial
         */
        private Certificate certs[];

        /**
         * Creates a new SelfPermission containing the permission
         * information needed later to expand the self
         * @param type the class name of the Permission class that will be
         * created when this permission is expanded and if necessary resolved.
         * @param name the name of the permission.
         * @param actions the actions of the permission.
         * @param certs the certificates the permission's class was signed with.
         * This is a list of certificate chains, where each chain is composed of
         * a signer certificate and optionally its supporting certificate chain.
         * Each chain is ordered bottom-to-top (i.e., with the signer
         * certificate first and the (root) certificate authority last).
         */
        public SelfPermission(String type, String name, String actions,
                              Certificate certs[])
        {
            super(type);
            if (type == null) {
                throw new NullPointerException
                    (ResourcesMgr.getString("type can't be null"));
            }
            this.type = type;
            this.name = name;
            this.actions = actions;
            if (certs != null) {
                // Extract the signer certs from the list of certificates.
                for (int i=0; i<certs.length; i++) {
                    if (!(certs[i] instanceof X509Certificate)) {
                        // there is no concept of signer certs, so we store the
                        // entire cert array
                        this.certs = certs.clone();
                        break;
                    }
                }

                if (this.certs == null) {
                    // Go through the list of certs and see if all the certs are
                    // signer certs.
                    int i = 0;
                    int count = 0;
                    while (i < certs.length) {
                        count++;
                        while (((i+1) < certs.length) &&
                            ((X509Certificate)certs[i]).getIssuerDN().equals(
                            ((X509Certificate)certs[i+1]).getSubjectDN())) {
                            i++;
                        }
                        i++;
                    }
                    if (count == certs.length) {
                        // All the certs are signer certs, so we store the
                        // entire array
                        this.certs = certs.clone();
                    }

                    if (this.certs == null) {
                        // extract the signer certs
                        ArrayList<Certificate> signerCerts =
                            new ArrayList<Certificate>();
                        i = 0;
                        while (i < certs.length) {
                            signerCerts.add(certs[i]);
                            while (((i+1) < certs.length) &&
                                ((X509Certificate)certs[i]).getIssuerDN().equals(
                                ((X509Certificate)certs[i+1]).getSubjectDN())) {
                                i++;
                            }
                            i++;
                        }
                        this.certs = new Certificate[signerCerts.size()];
                        signerCerts.toArray(this.certs);
                    }
                }
            }
        }

        /**
         * This method always returns false for SelfPermission permissions.
         * That is, an SelfPermission never considered to
         * imply another permission.
         *
         * @param p the permission to check against.
         *
         * @return false.
         */
        @Override public boolean implies(Permission p) {
            return false;
        }

        /**
         * Checks two SelfPermission objects for equality.
         *
         * Checks that <i>obj</i> is an SelfPermission, and has
         * the same type (class) name, permission name, actions, and
         * certificates as this object.
         *
         * @param obj the object we are testing for equality with this object.
         *
         * @return true if obj is an SelfPermission, and has the same
         * type (class) name, permission name, actions, and
         * certificates as this object.
         */
        @Override public boolean equals(Object obj) {
            if (obj == this)
                return true;

            if (! (obj instanceof SelfPermission))
                return false;
            SelfPermission that = (SelfPermission) obj;

            if (!(this.type.equals(that.type) &&
                this.name.equals(that.name) &&
                this.actions.equals(that.actions)))
                return false;

            if (this.certs.length != that.certs.length)
                return false;

            int i,j;
            boolean match;

            for (i = 0; i < this.certs.length; i++) {
                match = false;
                for (j = 0; j < that.certs.length; j++) {
                    if (this.certs[i].equals(that.certs[j])) {
                        match = true;
                        break;
                    }
                }
                if (!match) return false;
            }

            for (i = 0; i < that.certs.length; i++) {
                match = false;
                for (j = 0; j < this.certs.length; j++) {
                    if (that.certs[i].equals(this.certs[j])) {
                        match = true;
                        break;
                    }
                }
                if (!match) return false;
            }
            return true;
        }

        /**
         * Returns the hash code value for this object.
         *
         * @return a hash code value for this object.
         */
        @Override public int hashCode() {
            int hash = type.hashCode();
            if (name != null)
                hash ^= name.hashCode();
            if (actions != null)
                hash ^= actions.hashCode();
            return hash;
        }

        /**
         * Returns the canonical string representation of the actions,
         * which currently is the empty string "", since there are no actions
         * for an SelfPermission. That is, the actions for the
         * permission that will be created when this SelfPermission
         * is resolved may be non-null, but an SelfPermission
         * itself is never considered to have any actions.
         *
         * @return the empty string "".
         */
        @Override public String getActions() {
            return "";
        }

        public String getSelfType() {
            return type;
        }

        public String getSelfName() {
            return name;
        }

        public String getSelfActions() {
            return actions;
        }

        public Certificate[] getCerts() {
            return certs;
        }

        /**
         * Returns a string describing this SelfPermission.  The convention
         * is to specify the class name, the permission name, and the actions,
         * in the following format: '(unresolved "ClassName" "name" "actions")'.
         *
         * @return information about this SelfPermission.
         */
        @Override public String toString() {
            return "(SelfPermission " + type + " " + name + " " + actions + ")";
        }
    }

    /**
     * holds policy information that we need to synch on
     */
    private static class PolicyInfo {
        private static final boolean verbose = false;

        // Stores grant entries in the policy
        final List<PolicyEntry> policyEntries;

        // Stores grant entries gotten from identity database
        // Use separate lists to avoid sync on policyEntries
        final List<PolicyEntry> identityPolicyEntries;

        // Maps aliases to certs
        final Map aliasMapping;

        // Maps ProtectionDomain to PermissionCollection
        private final ProtectionDomainCache[] pdMapping;
        private java.util.Random random;

        PolicyInfo(int numCaches) {
            policyEntries = new ArrayList<PolicyEntry>();
            identityPolicyEntries =
                Collections.synchronizedList(new ArrayList<PolicyEntry>(2));
            aliasMapping = Collections.synchronizedMap(new HashMap(11));

            pdMapping = new ProtectionDomainCache[numCaches];
            JavaSecurityProtectionDomainAccess jspda
                = SharedSecrets.getJavaSecurityProtectionDomainAccess();
            for (int i = 0; i < numCaches; i++) {
                pdMapping[i] = jspda.getProtectionDomainCache();
            }
            if (numCaches > 1) {
                random = new java.util.Random();
            }
        }
        ProtectionDomainCache getPdMapping() {
            if (pdMapping.length == 1) {
                return pdMapping[0];
            } else {
                int i = java.lang.Math.abs(random.nextInt() % pdMapping.length);
                return pdMapping[i];
            }
        }
    }
}
