6854712: Revocation checking enhancements (JEP-124)
authormullan
Wed, 30 May 2012 17:19:46 -0400
changeset 12860 9ffbd4e43413
parent 11673 5fe35861f07e
child 12861 7aa4d0b3a8c7
6854712: Revocation checking enhancements (JEP-124) 6637288: Add OCSP support to PKIX CertPathBuilder implementation 7126011: ReverseBuilder.getMatchingCACerts may throws NPE Reviewed-by: xuelei
jdk/src/share/classes/java/security/cert/CertPathBuilder.java
jdk/src/share/classes/java/security/cert/CertPathBuilderSpi.java
jdk/src/share/classes/java/security/cert/CertPathChecker.java
jdk/src/share/classes/java/security/cert/CertPathValidator.java
jdk/src/share/classes/java/security/cert/CertPathValidatorSpi.java
jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java
jdk/src/share/classes/java/security/cert/PKIXRevocationChecker.java
jdk/src/share/classes/java/security/cert/package.html
jdk/src/share/classes/sun/security/provider/certpath/AdjacencyList.java
jdk/src/share/classes/sun/security/provider/certpath/BasicChecker.java
jdk/src/share/classes/sun/security/provider/certpath/BuildStep.java
jdk/src/share/classes/sun/security/provider/certpath/Builder.java
jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java
jdk/src/share/classes/sun/security/provider/certpath/CollectionCertStore.java
jdk/src/share/classes/sun/security/provider/certpath/ConstraintsChecker.java
jdk/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java
jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java
jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java
jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java
jdk/src/share/classes/sun/security/provider/certpath/IndexedCollectionCertStore.java
jdk/src/share/classes/sun/security/provider/certpath/KeyChecker.java
jdk/src/share/classes/sun/security/provider/certpath/OCSP.java
jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java
jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java
jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java
jdk/src/share/classes/sun/security/provider/certpath/PKIX.java
jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java
jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java
jdk/src/share/classes/sun/security/provider/certpath/PolicyChecker.java
jdk/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java
jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java
jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java
jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java
jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java
jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderParameters.java
jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java
jdk/src/share/classes/sun/security/provider/certpath/Vertex.java
jdk/src/share/classes/sun/security/provider/certpath/X509CertPath.java
jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java
jdk/src/share/classes/sun/security/x509/X509CRLEntryImpl.java
jdk/test/java/security/cert/PKIXRevocationChecker/UnitTest.java
--- a/jdk/src/share/classes/java/security/cert/CertPathBuilder.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/java/security/cert/CertPathBuilder.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -45,15 +45,28 @@
  * one of the static <code>getInstance</code> methods, passing in the
  * algorithm name of the <code>CertPathBuilder</code> desired and optionally
  * the name of the provider desired.
- * <p>
- * Once a <code>CertPathBuilder</code> object has been created, certification
+ *
+ * <p>Once a <code>CertPathBuilder</code> object has been created, certification
  * paths can be constructed by calling the {@link #build build} method and
  * passing it an algorithm-specific set of parameters. If successful, the
  * result (including the <code>CertPath</code> that was built) is returned
  * in an object that implements the <code>CertPathBuilderResult</code>
  * interface.
  *
- * <p> Every implementation of the Java platform is required to support the
+ * <p>The {@link #getRevocationChecker} method allows an application to specify
+ * additional algorithm-specific parameters and options used by the
+ * {@code CertPathBuilder} when checking the revocation status of certificates.
+ * Here is an example demonstrating how it is used with the PKIX algorithm:
+ *
+ * <pre>
+ * CertPathBuilder cpb = CertPathBuilder.getInstance("PKIX");
+ * PKIXRevocationChecker rc = (PKIXRevocationChecker)cpb.getRevocationChecker();
+ * rc.setOptions(EnumSet.of(Option.PREFER_CRLS));
+ * params.addCertPathChecker(rc);
+ * CertPathBuilderResult cpbr = cpb.build(params);
+ * </pre>
+ *
+ * <p>Every implementation of the Java platform is required to support the
  * following standard <code>CertPathBuilder</code> algorithm:
  * <ul>
  * <li><tt>PKIX</tt></li>
@@ -96,10 +109,9 @@
      * </pre>
      */
     private static final String CPB_TYPE = "certpathbuilder.type";
-    private static final Debug debug = Debug.getInstance("certpath");
-    private CertPathBuilderSpi builderSpi;
-    private Provider provider;
-    private String algorithm;
+    private final CertPathBuilderSpi builderSpi;
+    private final Provider provider;
+    private final String algorithm;
 
     /**
      * Creates a <code>CertPathBuilder</code> object of the given algorithm,
@@ -290,15 +302,30 @@
      * if no such property exists.
      */
     public final static String getDefaultType() {
-        String cpbtype;
-        cpbtype = AccessController.doPrivileged(new PrivilegedAction<String>() {
-            public String run() {
-                return Security.getProperty(CPB_TYPE);
-            }
-        });
-        if (cpbtype == null) {
-            cpbtype = "PKIX";
-        }
-        return cpbtype;
+        String cpbtype =
+            AccessController.doPrivileged(new PrivilegedAction<String>() {
+                public String run() {
+                    return Security.getProperty(CPB_TYPE);
+                }
+            });
+        return (cpbtype == null) ? "PKIX" : cpbtype;
+    }
+
+    /**
+     * Returns a {@code CertPathChecker} that the encapsulated
+     * {@code CertPathBuilderSpi} implementation uses to check the revocation
+     * status of certificates. A PKIX implementation returns objects of
+     * type {@code PKIXRevocationChecker}.
+     *
+     * <p>The primary purpose of this method is to allow callers to specify
+     * additional input parameters and options specific to revocation checking.
+     * See the class description for an example.
+     *
+     * @throws UnsupportedOperationException if the service provider does not
+     *         support this method
+     * @since 1.8
+     */
+    public final CertPathChecker getRevocationChecker() {
+        return builderSpi.engineGetRevocationChecker();
     }
 }
--- a/jdk/src/share/classes/java/security/cert/CertPathBuilderSpi.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/java/security/cert/CertPathBuilderSpi.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -72,4 +72,25 @@
      */
     public abstract CertPathBuilderResult engineBuild(CertPathParameters params)
         throws CertPathBuilderException, InvalidAlgorithmParameterException;
+
+    /**
+     * Returns a {@code CertPathChecker} that this implementation uses to
+     * check the revocation status of certificates. A PKIX implementation
+     * returns objects of type {@code PKIXRevocationChecker}.
+     *
+     * <p>The primary purpose of this method is to allow callers to specify
+     * additional input parameters and options specific to revocation checking.
+     * See the class description of {@code CertPathBuilder} for an example.
+     *
+     * <p>This method was added to version 1.8 of the Java Platform Standard
+     * Edition. In order to maintain backwards compatibility with existing
+     * service providers, this method cannot be abstract and by default throws
+     * an {@code UnsupportedOperationException}.
+     *
+     * @throws UnsupportedOperationException if this method is not supported
+     * @since 1.8
+     */
+    public CertPathChecker engineGetRevocationChecker() {
+        throw new UnsupportedOperationException();
+    }
 }
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/security/cert/CertPathChecker.java	Wed May 30 17:19:46 2012 -0400
@@ -0,0 +1,77 @@
+/*
+ * Copyright (c) 2012, 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 java.security.cert;
+
+/**
+ * <p>Performs one or more checks on each {@code Certificate} of a
+ * {@code CertPath}.
+ *
+ * <p>A {@code CertPathChecker} implementation is typically created to extend
+ * a certification path validation algorithm. For example, an implementation
+ * may check for and process a critical private extension of each certificate
+ * in a certification path.
+ *
+ * @since 1.8
+ */
+public interface CertPathChecker {
+
+    /**
+     * Initializes the internal state of this {@code CertPathChecker}.
+     *
+     * <p>The {@code forward} flag specifies the order that certificates will
+     * be passed to the {@link #check check} method (forward or reverse).
+     *
+     * @param forward the order that certificates are presented to the
+     *        {@code check} method. If {@code true}, certificates are
+     *        presented from target to trust anchor (forward); if
+     *        {@code false}, from trust anchor to target (reverse).
+     * @throws CertPathValidatorException if this {@code CertPathChecker} is
+     *         unable to check certificates in the specified order
+     */
+    void init(boolean forward) throws CertPathValidatorException;
+
+    /**
+     * Indicates if forward checking is supported. Forward checking refers
+     * to the ability of the {@code CertPathChecker} to perform its checks
+     * when certificates are presented to the {@code check} method in the
+     * forward direction (from target to trust anchor).
+     *
+     * @return {@code true} if forward checking is supported, {@code false}
+     *         otherwise
+     */
+    boolean isForwardCheckingSupported();
+
+    /**
+     * Performs the check(s) on the specified certificate using its internal
+     * state. The certificates are presented in the order specified by the
+     * {@code init} method.
+     *
+     * @param cert the {@code Certificate} to be checked
+     * @throws CertPathValidatorException if the specified certificate does
+     *         not pass the check
+     */
+    void check(Certificate cert) throws CertPathValidatorException;
+}
--- a/jdk/src/share/classes/java/security/cert/CertPathValidator.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/java/security/cert/CertPathValidator.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -46,15 +46,29 @@
  * call one of the static <code>getInstance</code> methods, passing in the
  * algorithm name of the <code>CertPathValidator</code> desired and
  * optionally the name of the provider desired.
- * <p>
- * Once a <code>CertPathValidator</code> object has been created, it can
+ *
+ * <p>Once a <code>CertPathValidator</code> object has been created, it can
  * be used to validate certification paths by calling the {@link #validate
  * validate} method and passing it the <code>CertPath</code> to be validated
  * and an algorithm-specific set of parameters. If successful, the result is
  * returned in an object that implements the
  * <code>CertPathValidatorResult</code> interface.
  *
- * <p> Every implementation of the Java platform is required to support the
+ * <p>The {@link #getRevocationChecker} method allows an application to specify
+ * additional algorithm-specific parameters and options used by the
+ * {@code CertPathValidator} when checking the revocation status of
+ * certificates. Here is an example demonstrating how it is used with the PKIX
+ * algorithm:
+ *
+ * <pre>
+ * CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
+ * PKIXRevocationChecker rc = (PKIXRevocationChecker)cpv.getRevocationChecker();
+ * rc.setOptions(EnumSet.of(Option.SOFT_FAIL));
+ * params.addCertPathChecker(rc);
+ * CertPathValidatorResult cpvr = cpv.validate(path, params);
+ * </pre>
+ *
+ * <p>Every implementation of the Java platform is required to support the
  * following standard <code>CertPathValidator</code> algorithm:
  * <ul>
  * <li><tt>PKIX</tt></li>
@@ -96,10 +110,9 @@
      * </pre>
      */
     private static final String CPV_TYPE = "certpathvalidator.type";
-    private static final Debug debug = Debug.getInstance("certpath");
-    private CertPathValidatorSpi validatorSpi;
-    private Provider provider;
-    private String algorithm;
+    private final CertPathValidatorSpi validatorSpi;
+    private final Provider provider;
+    private final String algorithm;
 
     /**
      * Creates a <code>CertPathValidator</code> object of the given algorithm,
@@ -301,15 +314,30 @@
      * if no such property exists.
      */
     public final static String getDefaultType() {
-        String cpvtype;
-        cpvtype = AccessController.doPrivileged(new PrivilegedAction<String>() {
-            public String run() {
-                return Security.getProperty(CPV_TYPE);
-            }
-        });
-        if (cpvtype == null) {
-            cpvtype = "PKIX";
-        }
-        return cpvtype;
+        String cpvtype =
+            AccessController.doPrivileged(new PrivilegedAction<String>() {
+                public String run() {
+                    return Security.getProperty(CPV_TYPE);
+                }
+            });
+        return (cpvtype == null) ? "PKIX" : cpvtype;
+    }
+
+    /**
+     * Returns a {@code CertPathChecker} that the encapsulated
+     * {@code CertPathValidatorSpi} implementation uses to check the revocation
+     * status of certificates. A PKIX implementation returns objects of
+     * type {@code PKIXRevocationChecker}.
+     *
+     * <p>The primary purpose of this method is to allow callers to specify
+     * additional input parameters and options specific to revocation checking.
+     * See the class description for an example.
+     *
+     * @throws UnsupportedOperationException if the service provider does not
+     *         support this method
+     * @since 1.8
+     */
+    public final CertPathChecker getRevocationChecker() {
+        return validatorSpi.engineGetRevocationChecker();
     }
 }
--- a/jdk/src/share/classes/java/security/cert/CertPathValidatorSpi.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/java/security/cert/CertPathValidatorSpi.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2001, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -82,4 +82,25 @@
     public abstract CertPathValidatorResult
         engineValidate(CertPath certPath, CertPathParameters params)
         throws CertPathValidatorException, InvalidAlgorithmParameterException;
+
+    /**
+     * Returns a {@code CertPathChecker} that this implementation uses to
+     * check the revocation status of certificates. A PKIX implementation
+     * returns objects of type {@code PKIXRevocationChecker}.
+     *
+     * <p>The primary purpose of this method is to allow callers to specify
+     * additional input parameters and options specific to revocation checking.
+     * See the class description of {@code CertPathValidator} for an example.
+     *
+     * <p>This method was added to version 1.8 of the Java Platform Standard
+     * Edition. In order to maintain backwards compatibility with existing
+     * service providers, this method cannot be abstract and by default throws
+     * an {@code UnsupportedOperationException}.
+     *
+     * @throws UnsupportedOperationException if this method is not supported
+     * @since 1.8
+     */
+    public CertPathChecker engineGetRevocationChecker() {
+        throw new UnsupportedOperationException();
+    }
 }
--- a/jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/java/security/cert/PKIXCertPathChecker.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -87,7 +87,8 @@
  * @author      Yassir Elley
  * @author      Sean Mullan
  */
-public abstract class PKIXCertPathChecker implements Cloneable {
+public abstract class PKIXCertPathChecker
+    implements CertPathChecker, Cloneable {
 
     /**
      * Default constructor.
@@ -111,6 +112,7 @@
      * the specified order; it should never be thrown if the forward flag
      * is false since reverse checking must be supported
      */
+    @Override
     public abstract void init(boolean forward)
         throws CertPathValidatorException;
 
@@ -123,6 +125,7 @@
      * @return <code>true</code> if forward checking is supported,
      * <code>false</code> otherwise
      */
+    @Override
     public abstract boolean isForwardCheckingSupported();
 
     /**
@@ -163,6 +166,17 @@
             throws CertPathValidatorException;
 
     /**
+     * {@inheritDoc}
+     *
+     * <p>This implementation calls
+     * {@code check(cert, java.util.Collections.<String>emptySet())}.
+     */
+    @Override
+    public void check(Certificate cert) throws CertPathValidatorException {
+        check(cert, java.util.Collections.<String>emptySet());
+    }
+
+    /**
      * Returns a clone of this object. Calls the <code>Object.clone()</code>
      * method.
      * All subclasses which maintain state must support and
@@ -170,6 +184,7 @@
      *
      * @return a copy of this <code>PKIXCertPathChecker</code>
      */
+    @Override
     public Object clone() {
         try {
             return super.clone();
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/java/security/cert/PKIXRevocationChecker.java	Wed May 30 17:19:46 2012 -0400
@@ -0,0 +1,271 @@
+/*
+ * Copyright (c) 2012, 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 java.security.cert;
+
+import java.net.URI;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Map.Entry;
+import java.util.Set;
+
+/**
+ * A {@code PKIXCertPathChecker} for checking the revocation status of
+ * certificates with the PKIX algorithm.
+ *
+ * <p>A {@code PKIXRevocationChecker} checks the revocation status of
+ * certificates with the Online Certificate Status Protocol (OCSP) or
+ * Certificate Revocation Lists (CRLs). OCSP is described in RFC 2560 and
+ * is a network protocol for determining the status of a certificate. A CRL
+ * is a time-stamped list identifying revoked certificates, and RFC 5280
+ * describes an algorithm for determining the revocation status of certificates
+ * using CRLs.
+ *
+ * <p>Each {@code PKIXRevocationChecker} must be able to check the revocation
+ * status of certificates with OCSP and CRLs. By default, OCSP is the
+ * preferred mechanism for checking revocation status, with CRLs as the
+ * fallback mechanism. However, this preference can be switched to CRLs with
+ * the {@link Option.PREFER_CRLS} option.
+ *
+ * <p>A {@code PKIXRevocationChecker} is obtained by calling the
+ * {@link CertPathValidator#getRevocationChecker getRevocationChecker} method
+ * of a PKIX {@code CertPathValidator}. Additional parameters and options
+ * specific to revocation can be set (by calling {@link #setOCSPResponder}
+ * method for instance). The {@code PKIXRevocationChecker} is added to
+ * a {@code PKIXParameters} object using the
+ * {@link PKIXParameters#addCertPathChecker addCertPathChecker}
+ * or {@link PKIXParameters#setCertPathCheckers setCertPathCheckers} method,
+ * and then the {@code PKIXParameters} is passed along with the {@code CertPath}
+ * to be validated to the {@link CertPathValidator#validate validate} method
+ * of a PKIX {@code CertPathValidator}. When supplying a revocation checker in
+ * this manner, do not enable the default revocation checking mechanism (by
+ * calling {@link PKIXParameters#setRevocationEnabled}.
+ *
+ * <p>Note that when a {@code PKIXRevocationChecker} is added to
+ * {@code PKIXParameters}, it clones the {@code PKIXRevocationChecker};
+ * thus any subsequent modifications to the {@code PKIXRevocationChecker}
+ * have no effect.
+ *
+ * <p>Any parameter that is not set (or is set to {@code null}) will be set to
+ * the default value for that parameter.
+ *
+ * <p><b>Concurrent Access</b>
+ *
+ * <p>Unless otherwise specified, the methods defined in this class are not
+ * thread-safe. Multiple threads that need to access a single object
+ * concurrently should synchronize amongst themselves and provide the
+ * necessary locking. Multiple threads each manipulating separate objects
+ * need not synchronize.
+ *
+ * @since 1.8
+ */
+public abstract class PKIXRevocationChecker extends PKIXCertPathChecker {
+    private URI ocspResponder;
+    private X509Certificate ocspResponderCert;
+    private List<Extension> ocspExtensions = Collections.<Extension>emptyList();
+    private Map<X509Certificate, byte[]> ocspStapled = Collections.emptyMap();
+    private Set<Option> options = Collections.emptySet();
+
+    protected PKIXRevocationChecker() {}
+
+    /**
+     * Sets the URI that identifies the location of the OCSP responder. This
+     * overrides the {@code ocsp.responderURL} security property and any
+     * responder specified in a certificate's Authority Information Access
+     * Extension, as defined in RFC 5280.
+     *
+     * @param uri the responder URI
+     */
+    public void setOCSPResponder(URI uri) {
+        this.ocspResponder = uri;
+    }
+
+    /**
+     * Gets the URI that identifies the location of the OCSP responder. This
+     * overrides the {@code ocsp.responderURL} security property. If this
+     * parameter or the {@code ocsp.responderURL} property is not set, the
+     * location is determined from the certificate's Authority Information
+     * Access Extension, as defined in RFC 5280.
+     *
+     * @return the responder URI, or {@code null} if not set
+     */
+    public URI getOCSPResponder() {
+        return ocspResponder;
+    }
+
+    /**
+     * Sets the OCSP responder's certificate. This overrides the
+     * {@code ocsp.responderCertSubjectName},
+     * {@code ocsp.responderCertIssuerName},
+     * and {@code ocsp.responderCertSerialNumber} security properties.
+     *
+     * @param cert the responder's certificate
+     */
+    public void setOCSPResponderCert(X509Certificate cert) {
+        this.ocspResponderCert = cert;
+    }
+
+    /**
+     * Gets the OCSP responder's certificate. This overrides the
+     * {@code ocsp.responderCertSubjectName},
+     * {@code ocsp.responderCertIssuerName},
+     * and {@code ocsp.responderCertSerialNumber} security properties. If this
+     * parameter or the aforementioned properties are not set, then the
+     * responder's certificate is determined as specified in RFC 2560.
+     *
+     * @return the responder's certificate, or {@code null} if not set
+     */
+    public X509Certificate getOCSPResponderCert() {
+        return ocspResponderCert;
+    }
+
+    // request extensions; single extensions not supported
+    /**
+     * Sets the optional OCSP request extensions.
+     *
+     * @param extensions a list of extensions. The list is copied to protect
+     *        against subsequent modification.
+     */
+    public void setOCSPExtensions(List<Extension> extensions)
+    {
+        this.ocspExtensions = (extensions == null)
+                              ? Collections.<Extension>emptyList()
+                              : new ArrayList<Extension>(extensions);
+    }
+
+    /**
+     * Gets the optional OCSP request extensions.
+     *
+     * @return an unmodifiable list of extensions. Returns an empty list if no
+     *         extensions have been specified.
+     */
+    public List<Extension> getOCSPExtensions() {
+        return Collections.unmodifiableList(ocspExtensions);
+    }
+
+    /**
+     * Sets the stapled OCSP responses. These responses are used to determine
+     * the revocation status of the specified certificates when OCSP is used.
+     *
+     * @param responses a map of stapled OCSP responses. Each key is an
+     *        {@code X509Certificate} that maps to the corresponding
+     *        DER-encoded OCSP response for that certificate. A deep copy of
+     *        the map is performed to protect against subsequent modification.
+     */
+    public void setOCSPStapledResponses(Map<X509Certificate, byte[]> responses)
+    {
+        if (responses == null) {
+            this.ocspStapled = Collections.<X509Certificate, byte[]>emptyMap();
+        } else {
+            Map<X509Certificate, byte[]> copy = new HashMap<>(responses.size());
+            for (Map.Entry<X509Certificate, byte[]> e : responses.entrySet()) {
+                copy.put(e.getKey(), e.getValue().clone());
+            }
+            this.ocspStapled = copy;
+        }
+    }
+
+    /**
+     * Gets the stapled OCSP responses. These responses are used to determine
+     * the revocation status of the specified certificates when OCSP is used.
+     *
+     * @return a map of stapled OCSP responses. Each key is an
+     *        {@code X509Certificate} that maps to the corresponding
+     *        DER-encoded OCSP response for that certificate. A deep copy of
+     *        the map is returned to protect against subsequent modification.
+     *        Returns an empty map if no responses have been specified.
+     */
+    public Map<X509Certificate, byte[]> getOCSPStapledResponses() {
+        Map<X509Certificate, byte[]> copy = new HashMap<>(ocspStapled.size());
+        for (Map.Entry<X509Certificate, byte[]> e : ocspStapled.entrySet()) {
+            copy.put(e.getKey(), e.getValue().clone());
+        }
+        return copy;
+    }
+
+    /**
+     * Sets the revocation options.
+     *
+     * @param options a set of revocation options. The set is copied to protect
+     *        against subsequent modification.
+     */
+    public void setOptions(Set<Option> options) {
+        this.options = (options == null)
+                       ? Collections.<Option>emptySet()
+                       : new HashSet<Option>(options);
+    }
+
+    /**
+     * Gets the revocation options.
+     *
+     * @return an unmodifiable set of revocation options, or an empty set if
+     *         none are specified
+     */
+    public Set<Option> getOptions() {
+        return Collections.unmodifiableSet(options);
+    }
+
+    @Override
+    public Object clone() {
+        PKIXRevocationChecker copy = (PKIXRevocationChecker)super.clone();
+        copy.ocspExtensions = new ArrayList<>(ocspExtensions);
+        copy.ocspStapled = new HashMap<>(ocspStapled);
+        // deep-copy the encoded stapled responses, since they are mutable
+        for (Map.Entry<X509Certificate, byte[]> entry :
+                 copy.ocspStapled.entrySet())
+        {
+            byte[] encoded = entry.getValue();
+            entry.setValue(encoded.clone());
+        }
+        copy.options = new HashSet<>(options);
+        return copy;
+    }
+
+    /**
+     * Various revocation options that can be specified for the revocation
+     * checking mechanism.
+     */
+    public enum Option {
+        /**
+         * Only check the revocation status of end-entity certificates.
+         */
+        ONLY_END_ENTITY,
+        /**
+         * Prefer CRLs to OSCP. The default behavior is to prefer OCSP. Each
+         * PKIX implementation should document further details of their
+         * specific preference rules and fallback policies.
+         */
+        PREFER_CRLS,
+        /**
+         * Ignore network failures. The default behavior is to consider it a
+         * failure if the revocation status of a certificate cannot be obtained
+         * due to a network error. This option applies to both OCSP and CRLs.
+         */
+        SOFT_FAIL
+    }
+}
--- a/jdk/src/share/classes/java/security/cert/package.html	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/java/security/cert/package.html	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 <!--
- Copyright (c) 1998, 2011, Oracle and/or its affiliates. All rights reserved.
+ Copyright (c) 1998, 2012, 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
@@ -38,8 +38,10 @@
   <li><a href="{@docRoot}/../technotes/guides/security/crypto/CryptoSpec.html">
     <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
     Cryptography Architecture (JCA) Reference Guide</b></a>
-  <li>RFC 3280: Internet X.509 Public Key Infrastructure Certificate and 
+  <li>RFC 5280: Internet X.509 Public Key Infrastructure Certificate and 
     Certificate Revocation List (CRL) Profile
+  <li>RFC 2560: X.509 Internet Public Key Infrastructure Online Certificate
+    Status Protocol - OCSP
   <li><a href="{@docRoot}/../technotes/guides/security/StandardNames.html">
     <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
     Cryptography Architecture Standard Algorithm Name
@@ -50,8 +52,8 @@
 
 For information about X.509 certificates and CRLs, please see:
 <ul>
-  <li><a href="http://www.ietf.org/rfc/rfc3280.txt">
-    http://www.ietf.org/rfc/rfc3280.txt</a>
+  <li><a href="http://www.ietf.org/rfc/rfc5280.txt">
+    http://www.ietf.org/rfc/rfc5280.txt</a>
   <li><a href=
     "{@docRoot}/../technotes/guides/security/certpath/CertPathProgGuide.html">
     <b>Java<FONT SIZE=-2><SUP>TM</SUP></FONT>
--- a/jdk/src/share/classes/sun/security/provider/certpath/AdjacencyList.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/AdjacencyList.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -24,13 +24,11 @@
  */
 package sun.security.provider.certpath;
 
-
 import java.util.ArrayList;
 import java.util.Collections;
 import java.util.Iterator;
 import java.util.List;
 
-
 /**
  * An AdjacencyList is used to store the history of certification paths
  * attempted in constructing a path from an initiator to a target. The
@@ -123,124 +121,117 @@
      * at the start.
      */
     private boolean buildList(List<List<Vertex>> theList, int index,
-        BuildStep follow) {
+                              BuildStep follow) {
 
         // Each time this method is called, we're examining a new list
         // from the global list. So, we have to start by getting the list
         // that contains the set of Vertexes we're considering.
         List<Vertex> l = theList.get(index);
 
-        try {
-            // we're interested in the case where all indexes are -1...
-            boolean allNegOne = true;
-            // ...and in the case where every entry has a Throwable
-            boolean allXcps = true;
+        // we're interested in the case where all indexes are -1...
+        boolean allNegOne = true;
+        // ...and in the case where every entry has a Throwable
+        boolean allXcps = true;
+
+        for (Vertex v : l) {
+            if (v.getIndex() != -1) {
+                // count an empty list the same as an index of -1...this
+                // is to patch a bug somewhere in the builder
+                if (theList.get(v.getIndex()).size() != 0)
+                    allNegOne = false;
+            } else {
+                if (v.getThrowable() == null)
+                    allXcps = false;
+            }
+            // every entry, regardless of the final use for it, is always
+            // entered as a possible step before we take any actions
+            mStepList.add(new BuildStep(v, BuildStep.POSSIBLE));
+        }
+
+        if (allNegOne) {
+            // There are two cases that we could be looking at here. We
+            // may need to back up, or the build may have succeeded at
+            // this point. This is based on whether or not any
+            // exceptions were found in the list.
+            if (allXcps) {
+                // we need to go back...see if this is the last one
+                if (follow == null)
+                    mStepList.add(new BuildStep(null, BuildStep.FAIL));
+                else
+                    mStepList.add(new BuildStep(follow.getVertex(),
+                                                BuildStep.BACK));
+
+                return false;
+            } else {
+                // we succeeded...now the only question is which is the
+                // successful step? If there's only one entry without
+                // a throwable, then that's the successful step. Otherwise,
+                // we'll have to make some guesses...
+                List<Vertex> possibles = new ArrayList<>();
+                for (Vertex v : l) {
+                    if (v.getThrowable() == null)
+                        possibles.add(v);
+                }
+
+                if (possibles.size() == 1) {
+                    // real easy...we've found the final Vertex
+                    mStepList.add(new BuildStep(possibles.get(0),
+                                                BuildStep.SUCCEED));
+                } else {
+                    // ok...at this point, there is more than one Cert
+                    // which might be the succeed step...how do we know
+                    // which it is? I'm going to assume that our builder
+                    // algorithm is good enough to know which is the
+                    // correct one, and put it first...but a FIXME goes
+                    // here anyway, and we should be comparing to the
+                    // target/initiator Cert...
+                    mStepList.add(new BuildStep(possibles.get(0),
+                                                BuildStep.SUCCEED));
+                }
+
+                return true;
+            }
+        } else {
+            // There's at least one thing that we can try before we give
+            // up and go back. Run through the list now, and enter a new
+            // BuildStep for each path that we try to follow. If none of
+            // the paths we try produce a successful end, we're going to
+            // have to back out ourselves.
+            boolean success = false;
 
             for (Vertex v : l) {
+
+                // Note that we'll only find a SUCCEED case when we're
+                // looking at the last possible path, so we don't need to
+                // consider success in the while loop
+
                 if (v.getIndex() != -1) {
-                    // count an empty list the same as an index of -1...this
-                    // is to patch a bug somewhere in the builder
-                    if (theList.get(v.getIndex()).size() != 0)
-                        allNegOne = false;
+                    if (theList.get(v.getIndex()).size() != 0) {
+                        // If the entry we're looking at doesn't have an
+                        // index of -1, and doesn't lead to an empty list,
+                        // then it's something we follow!
+                        BuildStep bs = new BuildStep(v, BuildStep.FOLLOW);
+                        mStepList.add(bs);
+                        success = buildList(theList, v.getIndex(), bs);
+                    }
                 }
-                else
-                    if (v.getThrowable() == null)
-                        allXcps = false;
-
-                // every entry, regardless of the final use for it, is always
-                // entered as a possible step before we take any actions
-                mStepList.add(new BuildStep(v, BuildStep.POSSIBLE));
             }
 
-            if (allNegOne) {
-                // There are two cases that we could be looking at here. We
-                // may need to back up, or the build may have succeeded at
-                // this point. This is based on whether or not any
-                // exceptions were found in the list.
-                if (allXcps) {
-                    // we need to go back...see if this is the last one
-                    if (follow == null)
-                        mStepList.add(new BuildStep(null, BuildStep.FAIL));
-                    else
-                        mStepList.add(new BuildStep(follow.getVertex(),
-                                                    BuildStep.BACK));
-
-                    return false;
-                } else {
-                    // we succeeded...now the only question is which is the
-                    // successful step? If there's only one entry without
-                    // a throwable, then that's the successful step. Otherwise,
-                    // we'll have to make some guesses...
-                    List<Vertex> possibles = new ArrayList<Vertex>();
-                    for (Vertex v : l) {
-                        if (v.getThrowable() == null)
-                            possibles.add(v);
-                    }
-
-                    if (possibles.size() == 1) {
-                        // real easy...we've found the final Vertex
-                        mStepList.add(new BuildStep(possibles.get(0),
-                                                    BuildStep.SUCCEED));
-                    } else {
-                        // ok...at this point, there is more than one Cert
-                        // which might be the succeed step...how do we know
-                        // which it is? I'm going to assume that our builder
-                        // algorithm is good enough to know which is the
-                        // correct one, and put it first...but a FIXME goes
-                        // here anyway, and we should be comparing to the
-                        // target/initiator Cert...
-                        mStepList.add(new BuildStep(possibles.get(0),
-                                                    BuildStep.SUCCEED));
-                    }
+            if (success) {
+                // We're already finished!
+                return true;
+            } else {
+                // We failed, and we've exhausted all the paths that we
+                // could take. The only choice is to back ourselves out.
+                if (follow == null)
+                    mStepList.add(new BuildStep(null, BuildStep.FAIL));
+                else
+                    mStepList.add(new BuildStep(follow.getVertex(),
+                                                BuildStep.BACK));
 
-                    return true;
-                }
-            } else {
-                // There's at least one thing that we can try before we give
-                // up and go back. Run through the list now, and enter a new
-                // BuildStep for each path that we try to follow. If none of
-                // the paths we try produce a successful end, we're going to
-                // have to back out ourselves.
-                boolean success = false;
-
-                for (Vertex v : l) {
-
-                    // Note that we'll only find a SUCCEED case when we're
-                    // looking at the last possible path, so we don't need to
-                    // consider success in the while loop
-
-                    if (v.getIndex() != -1) {
-                        if (theList.get(v.getIndex()).size() != 0) {
-                            // If the entry we're looking at doesn't have an
-                            // index of -1, and doesn't lead to an empty list,
-                            // then it's something we follow!
-                            BuildStep bs = new BuildStep(v, BuildStep.FOLLOW);
-                            mStepList.add(bs);
-                            success = buildList(theList, v.getIndex(), bs);
-                        }
-                    }
-                }
-
-                if (success) {
-                    // We're already finished!
-                    return true;
-                } else {
-                    // We failed, and we've exhausted all the paths that we
-                    // could take. The only choice is to back ourselves out.
-                    if (follow == null)
-                        mStepList.add(new BuildStep(null, BuildStep.FAIL));
-                    else
-                        mStepList.add(new BuildStep(follow.getVertex(),
-                                                    BuildStep.BACK));
-
-                    return false;
-                }
+                return false;
             }
         }
-        catch (Exception e) {}
-
-        // we'll never get here, but you know java...
-        return false;
     }
 
     /**
@@ -248,23 +239,20 @@
      *
      * @return String representation
      */
+    @Override
     public String toString() {
-        String out = "[\n";
+        StringBuilder sb = new StringBuilder("[\n");
 
         int i = 0;
         for (List<Vertex> l : mOrigList) {
-            out = out + "LinkedList[" + i++ + "]:\n";
+            sb.append("LinkedList[").append(i++).append("]:\n");
 
             for (Vertex step : l) {
-                try {
-                    out = out + step.toString();
-                    out = out + "\n";
-                }
-                catch (Exception e) { out = out + "No Such Element\n"; }
+                sb.append(step.toString()).append("\n");
             }
         }
-        out = out + "]\n";
+        sb.append("]\n");
 
-        return out;
+        return sb.toString();
     }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/BasicChecker.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/BasicChecker.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -62,7 +62,7 @@
     private static final Debug debug = Debug.getInstance("certpath");
     private final PublicKey trustedPubKey;
     private final X500Principal caName;
-    private final Date testDate;
+    private final Date date;
     private final String sigProvider;
     private final boolean sigOnly;
     private X500Principal prevSubject;
@@ -73,14 +73,13 @@
      *
      * @param anchor the anchor selected to validate the target certificate
      * @param testDate the time for which the validity of the certificate
-     * should be determined
+     *        should be determined
      * @param sigProvider the name of the signature provider
      * @param sigOnly true if only signature checking is to be done;
      *        if false, all checks are done
      */
-    BasicChecker(TrustAnchor anchor, Date testDate, String sigProvider,
-        boolean sigOnly) throws CertPathValidatorException
-    {
+    BasicChecker(TrustAnchor anchor, Date date, String sigProvider,
+                 boolean sigOnly) {
         if (anchor.getTrustedCert() != null) {
             this.trustedPubKey = anchor.getTrustedCert().getPublicKey();
             this.caName = anchor.getTrustedCert().getSubjectX500Principal();
@@ -88,16 +87,16 @@
             this.trustedPubKey = anchor.getCAPublicKey();
             this.caName = anchor.getCA();
         }
-        this.testDate = testDate;
+        this.date = date;
         this.sigProvider = sigProvider;
         this.sigOnly = sigOnly;
-        init(false);
     }
 
     /**
      * Initializes the internal state of the checker from parameters
      * specified in the constructor.
      */
+    @Override
     public void init(boolean forward) throws CertPathValidatorException {
         if (!forward) {
             prevPubKey = trustedPubKey;
@@ -108,10 +107,12 @@
         }
     }
 
+    @Override
     public boolean isForwardCheckingSupported() {
         return false;
     }
 
+    @Override
     public Set<String> getSupportedExtensions() {
         return null;
     }
@@ -124,33 +125,31 @@
      * @param cert the Certificate
      * @param unresolvedCritExts a Collection of the unresolved critical
      * extensions
-     * @exception CertPathValidatorException Exception thrown if certificate
-     * does not verify.
+     * @throws CertPathValidatorException if certificate does not verify
      */
+    @Override
     public void check(Certificate cert, Collection<String> unresolvedCritExts)
         throws CertPathValidatorException
     {
-        X509Certificate currCert = (X509Certificate) cert;
+        X509Certificate currCert = (X509Certificate)cert;
 
         if (!sigOnly) {
-            verifyTimestamp(currCert, testDate);
-            verifyNameChaining(currCert, prevSubject);
+            verifyTimestamp(currCert);
+            verifyNameChaining(currCert);
         }
-        verifySignature(currCert, prevPubKey, sigProvider);
+        verifySignature(currCert);
 
         updateState(currCert);
     }
 
     /**
-     * Verifies the signature on the certificate using the previous public key
-     * @param cert the Certificate
-     * @param prevPubKey the previous PublicKey
-     * @param sigProvider a String containing the signature provider
-     * @exception CertPathValidatorException Exception thrown if certificate
-     * does not verify.
+     * Verifies the signature on the certificate using the previous public key.
+     *
+     * @param cert the X509Certificate
+     * @throws CertPathValidatorException if certificate does not verify
      */
-    private void verifySignature(X509Certificate cert, PublicKey prevPubKey,
-        String sigProvider) throws CertPathValidatorException
+    private void verifySignature(X509Certificate cert)
+        throws CertPathValidatorException
     {
         String msg = "signature";
         if (debug != null)
@@ -162,7 +161,7 @@
             throw new CertPathValidatorException
                 (msg + " check failed", e, null, -1,
                  BasicReason.INVALID_SIGNATURE);
-        } catch (Exception e) {
+        } catch (GeneralSecurityException e) {
             throw new CertPathValidatorException(msg + " check failed", e);
         }
 
@@ -173,7 +172,7 @@
     /**
      * Internal method to verify the timestamp on a certificate
      */
-    private void verifyTimestamp(X509Certificate cert, Date date)
+    private void verifyTimestamp(X509Certificate cert)
         throws CertPathValidatorException
     {
         String msg = "timestamp";
@@ -197,8 +196,8 @@
     /**
      * Internal method to check that cert has a valid DN to be next in a chain
      */
-    private void verifyNameChaining(X509Certificate cert,
-        X500Principal prevSubject) throws CertPathValidatorException
+    private void verifyNameChaining(X509Certificate cert)
+        throws CertPathValidatorException
     {
         if (prevSubject != null) {
 
@@ -207,8 +206,8 @@
                 debug.println("---checking " + msg + "...");
 
             X500Principal currIssuer = cert.getIssuerX500Principal();
+
             // reject null or empty issuer DNs
-
             if (X500Name.asX500Name(currIssuer).isEmpty()) {
                 throw new CertPathValidatorException
                     (msg + " check failed: " +
--- a/jdk/src/share/classes/sun/security/provider/certpath/BuildStep.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/BuildStep.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2005, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -25,7 +25,6 @@
 
 package sun.security.provider.certpath;
 
-import sun.security.util.Debug;
 import java.security.cert.X509Certificate;
 
 /**
@@ -39,7 +38,6 @@
  */
 public class BuildStep {
 
-    private static final Debug debug = Debug.getInstance("certpath");
     private Vertex          vertex;
     private X509Certificate cert;
     private Throwable       throwable;
@@ -86,7 +84,7 @@
     public BuildStep(Vertex vtx, int res) {
         vertex = vtx;
         if (vertex != null) {
-            cert = (X509Certificate)vertex.getCertificate();
+            cert = vertex.getCertificate();
             throwable = vertex.getThrowable();
         }
         result = res;
@@ -117,7 +115,7 @@
      * @returns String form of issuer name or null, if no certificate.
      */
     public String getIssuerName() {
-        return (cert == null ? null : cert.getIssuerX500Principal().toString());
+        return getIssuerName(null);
     }
 
     /**
@@ -142,7 +140,7 @@
      * @returns String form of subject name or null, if no certificate.
      */
     public String getSubjectName() {
-        return (cert == null ? null : cert.getSubjectX500Principal().toString());
+        return getSubjectName(null);
     }
 
     /**
@@ -191,21 +189,21 @@
     public String resultToString(int res) {
         String resultString = "";
         switch (res) {
-            case BuildStep.POSSIBLE:
+            case POSSIBLE:
                 resultString = "Certificate to be tried.\n";
                 break;
-            case BuildStep.BACK:
+            case BACK:
                 resultString = "Certificate backed out since path does not "
                     + "satisfy build requirements.\n";
                 break;
-            case BuildStep.FOLLOW:
+            case FOLLOW:
                 resultString = "Certificate satisfies conditions.\n";
                 break;
-            case BuildStep.FAIL:
+            case FAIL:
                 resultString = "Certificate backed out since path does not "
                     + "satisfy conditions.\n";
                 break;
-            case BuildStep.SUCCEED:
+            case SUCCEED:
                 resultString = "Certificate satisfies conditions.\n";
                 break;
             default:
@@ -220,6 +218,7 @@
      *
      * @returns String
      */
+    @Override
     public String toString() {
         String out = "Internal Error\n";
         switch (result) {
@@ -273,8 +272,6 @@
      * @returns String
      */
     public String fullToString() {
-        String out = resultToString(getResult());
-        out = out + vertex.toString();
-        return out;
+        return resultToString(getResult()) + vertex.toString();
     }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/Builder.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/Builder.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -31,9 +31,8 @@
 import java.security.cert.*;
 import java.util.*;
 
-import javax.security.auth.x500.X500Principal;
-
 import sun.security.action.GetBooleanAction;
+import sun.security.provider.certpath.PKIX.BuilderParams;
 import sun.security.util.Debug;
 import sun.security.x509.GeneralNames;
 import sun.security.x509.GeneralNameInterface;
@@ -56,9 +55,7 @@
 
     private static final Debug debug = Debug.getInstance("certpath");
     private Set<String> matchingPolicies;
-    final PKIXBuilderParameters buildParams;
-    final X500Principal targetSubjectDN;
-    final Date date;
+    final BuilderParams buildParams;
     final X509CertSelector targetCertConstraints;
 
     /**
@@ -74,14 +71,10 @@
      *
      * @param params the parameter set used to build a certification path
      */
-    Builder(PKIXBuilderParameters buildParams, X500Principal targetSubjectDN) {
+    Builder(BuilderParams buildParams) {
         this.buildParams = buildParams;
-        this.targetSubjectDN = targetSubjectDN;
-        // Initialize date if not specified
-        Date paramsDate = buildParams.getDate();
-        this.date = paramsDate != null ? paramsDate : new Date();
         this.targetCertConstraints =
-            (X509CertSelector) buildParams.getTargetCertConstraints();
+            (X509CertSelector)buildParams.targetCertConstraints();
     }
 
     /**
@@ -104,7 +97,8 @@
      * @param certPathList the certPathList generated thus far
      */
     abstract void verifyCert(X509Certificate cert, State currentState,
-        List<X509Certificate> certPathList) throws GeneralSecurityException;
+                             List<X509Certificate> certPathList)
+        throws GeneralSecurityException;
 
     /**
      * Verifies whether the input certificate completes the path.
@@ -123,7 +117,7 @@
      * @param certPathList the certification path list
      */
     abstract void addCertToPath(X509Certificate cert,
-        LinkedList<X509Certificate> certPathList);
+                                LinkedList<X509Certificate> certPathList);
 
     /**
      * Removes final certificate from the certPathList
@@ -147,7 +141,8 @@
      *         is a grandparent, etc.
      */
     static int distance(GeneralNameInterface base,
-        GeneralNameInterface test, int incomparable) {
+                        GeneralNameInterface test, int incomparable)
+    {
         switch (base.constrains(test)) {
         case GeneralNameInterface.NAME_DIFF_TYPE:
             if (debug != null) {
@@ -192,7 +187,8 @@
      *         some number of down hops.
      */
     static int hops(GeneralNameInterface base, GeneralNameInterface test,
-        int incomparable) {
+                    int incomparable)
+    {
         int baseRtest = base.constrains(test);
         switch (baseRtest) {
         case GeneralNameInterface.NAME_DIFF_TYPE:
@@ -282,9 +278,9 @@
      * @throws IOException if certificate does not get closer
      */
     static int targetDistance(NameConstraintsExtension constraints,
-            X509Certificate cert, GeneralNameInterface target)
-            throws IOException {
-
+                              X509Certificate cert, GeneralNameInterface target)
+            throws IOException
+    {
         /* ensure that certificate satisfies existing name constraints */
         if (constraints != null && !constraints.verify(cert)) {
             throw new IOException("certificate does not satisfy existing name "
@@ -295,7 +291,7 @@
         try {
             certImpl = X509CertImpl.toImpl(cert);
         } catch (CertificateException e) {
-            throw (IOException)new IOException("Invalid certificate").initCause(e);
+            throw new IOException("Invalid certificate", e);
         }
         /* see if certificate subject matches target */
         X500Name subject = X500Name.asX500Name(certImpl.getSubjectX500Principal());
@@ -398,13 +394,13 @@
      */
     Set<String> getMatchingPolicies() {
         if (matchingPolicies != null) {
-            Set<String> initialPolicies = buildParams.getInitialPolicies();
+            Set<String> initialPolicies = buildParams.initialPolicies();
             if ((!initialPolicies.isEmpty()) &&
                 (!initialPolicies.contains(PolicyChecker.ANY_POLICY)) &&
-                (buildParams.isPolicyMappingInhibited()))
+                (buildParams.policyMappingInhibited()))
             {
-                initialPolicies.add(PolicyChecker.ANY_POLICY);
-                matchingPolicies = initialPolicies;
+                matchingPolicies = new HashSet<>(initialPolicies);
+                matchingPolicies.add(PolicyChecker.ANY_POLICY);
             } else {
                 // we just return an empty set to make sure that there is
                 // at least a certificate policies extension in the cert
@@ -429,13 +425,15 @@
      * Returns true iff resultCerts changed (a cert was added to the collection)
      */
     boolean addMatchingCerts(X509CertSelector selector,
-            Collection<CertStore> certStores,
-            Collection<X509Certificate> resultCerts, boolean checkAll) {
+                             Collection<CertStore> certStores,
+                             Collection<X509Certificate> resultCerts,
+                             boolean checkAll)
+    {
         X509Certificate targetCert = selector.getCertificate();
         if (targetCert != null) {
             // no need to search CertStores
             if (selector.match(targetCert) && !X509CertImpl.isSelfSigned
-                (targetCert, buildParams.getSigProvider())) {
+                (targetCert, buildParams.sigProvider())) {
                 if (debug != null) {
                     debug.println("Builder.addMatchingCerts: adding target cert");
                 }
@@ -450,7 +448,7 @@
                                         store.getCertificates(selector);
                 for (Certificate cert : certs) {
                     if (!X509CertImpl.isSelfSigned
-                        ((X509Certificate)cert, buildParams.getSigProvider())) {
+                        ((X509Certificate)cert, buildParams.sigProvider())) {
                         if (resultCerts.add((X509Certificate)cert)) {
                             add = true;
                         }
@@ -471,16 +469,4 @@
         }
         return add;
     }
-
-    /**
-     * Returns true if CertStore is local. Currently, returns true if
-     * type is Collection or if it has been initialized with
-     * CollectionCertStoreParameters. A new API method should be added
-     * to CertStore that returns local or remote.
-     */
-    static boolean isLocalCertStore(CertStore certStore) {
-        return (certStore.getType().equals("Collection") ||
-                certStore.getCertStoreParameters() instanceof
-                CollectionCertStoreParameters);
-    }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CertStoreHelper.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, 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
@@ -83,9 +83,8 @@
                                 = (CertStoreHelper)c.newInstance();
                             cache.put(type, csh);
                             return csh;
-                        } catch (InstantiationException e) {
-                            throw new AssertionError(e);
-                        } catch (IllegalAccessException e) {
+                        } catch (InstantiationException |
+                                 IllegalAccessException e) {
                             throw new AssertionError(e);
                         }
                     }
--- a/jdk/src/share/classes/sun/security/provider/certpath/CollectionCertStore.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/CollectionCertStore.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -31,7 +31,6 @@
 import java.util.Collection;
 import java.util.ConcurrentModificationException;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.security.cert.CertSelector;
 import java.security.cert.CertStore;
 import java.security.cert.CertStoreException;
@@ -114,6 +113,7 @@
      *         match the specified selector
      * @throws CertStoreException if an exception occurs
      */
+    @Override
     public Collection<Certificate> engineGetCertificates
             (CertSelector selector) throws CertStoreException {
         if (coll == null) {
@@ -122,18 +122,15 @@
         // Tolerate a few ConcurrentModificationExceptions
         for (int c = 0; c < 10; c++) {
             try {
-                HashSet<Certificate> result = new HashSet<Certificate>();
-                Iterator<?> i = coll.iterator();
+                HashSet<Certificate> result = new HashSet<>();
                 if (selector != null) {
-                    while (i.hasNext()) {
-                        Object o = i.next();
+                    for (Object o : coll) {
                         if ((o instanceof Certificate) &&
                             selector.match((Certificate) o))
                             result.add((Certificate)o);
                     }
                 } else {
-                    while (i.hasNext()) {
-                        Object o = i.next();
+                    for (Object o : coll) {
                         if (o instanceof Certificate)
                             result.add((Certificate)o);
                     }
@@ -157,6 +154,7 @@
      *         match the specified selector
      * @throws CertStoreException if an exception occurs
      */
+    @Override
     public Collection<CRL> engineGetCRLs(CRLSelector selector)
         throws CertStoreException
     {
@@ -166,22 +164,19 @@
         // Tolerate a few ConcurrentModificationExceptions
         for (int c = 0; c < 10; c++) {
             try {
-                HashSet<CRL> result = new HashSet<CRL>();
-                Iterator<?> i = coll.iterator();
+                HashSet<CRL> result = new HashSet<>();
                 if (selector != null) {
-                    while (i.hasNext()) {
-                        Object o = i.next();
+                    for (Object o : coll) {
                         if ((o instanceof CRL) && selector.match((CRL) o))
                             result.add((CRL)o);
                     }
                 } else {
-                    while (i.hasNext()) {
-                        Object o = i.next();
+                    for (Object o : coll) {
                         if (o instanceof CRL)
                             result.add((CRL)o);
                     }
                 }
-                return(result);
+                return result;
             } catch (ConcurrentModificationException e) { }
         }
         throw new ConcurrentModificationException("Too many "
--- a/jdk/src/share/classes/sun/security/provider/certpath/ConstraintsChecker.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ConstraintsChecker.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -25,19 +25,20 @@
 
 package sun.security.provider.certpath;
 
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Set;
-import java.util.HashSet;
 import java.io.IOException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertPathValidatorException;
-import java.security.cert.X509Certificate;
 import java.security.cert.PKIXCertPathChecker;
 import java.security.cert.PKIXReason;
+import java.security.cert.X509Certificate;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Set;
+
 import sun.security.util.Debug;
-import sun.security.x509.PKIXExtensions;
+import static sun.security.x509.PKIXExtensions.*;
 import sun.security.x509.NameConstraintsExtension;
 import sun.security.x509.X509CertImpl;
 
@@ -66,13 +67,12 @@
      * Creates a ConstraintsChecker.
      *
      * @param certPathLength the length of the certification path
-     * @throws CertPathValidatorException if the checker cannot be initialized
      */
-    ConstraintsChecker(int certPathLength) throws CertPathValidatorException {
+    ConstraintsChecker(int certPathLength) {
         this.certPathLength = certPathLength;
-        init(false);
     }
 
+    @Override
     public void init(boolean forward) throws CertPathValidatorException {
         if (!forward) {
             i = 0;
@@ -84,15 +84,17 @@
         }
     }
 
+    @Override
     public boolean isForwardCheckingSupported() {
         return false;
     }
 
+    @Override
     public Set<String> getSupportedExtensions() {
         if (supportedExts == null) {
-            supportedExts = new HashSet<String>();
-            supportedExts.add(PKIXExtensions.BasicConstraints_Id.toString());
-            supportedExts.add(PKIXExtensions.NameConstraints_Id.toString());
+            supportedExts = new HashSet<String>(2);
+            supportedExts.add(BasicConstraints_Id.toString());
+            supportedExts.add(NameConstraints_Id.toString());
             supportedExts = Collections.unmodifiableSet(supportedExts);
         }
         return supportedExts;
@@ -104,14 +106,15 @@
      *
      * @param cert the <code>Certificate</code> to be checked
      * @param unresCritExts a <code>Collection</code> of OID strings
-     * representing the current set of unresolved critical extensions
+     *        representing the current set of unresolved critical extensions
      * @throws CertPathValidatorException if the specified certificate
-     * does not pass the check
+     *         does not pass the check
      */
+    @Override
     public void check(Certificate cert, Collection<String> unresCritExts)
         throws CertPathValidatorException
     {
-        X509Certificate currCert = (X509Certificate) cert;
+        X509Certificate currCert = (X509Certificate)cert;
 
         i++;
         // MUST run NC check second, since it depends on BC check to
@@ -120,8 +123,8 @@
         verifyNameConstraints(currCert);
 
         if (unresCritExts != null && !unresCritExts.isEmpty()) {
-            unresCritExts.remove(PKIXExtensions.BasicConstraints_Id.toString());
-            unresCritExts.remove(PKIXExtensions.NameConstraints_Id.toString());
+            unresCritExts.remove(BasicConstraints_Id.toString());
+            unresCritExts.remove(NameConstraints_Id.toString());
         }
     }
 
@@ -166,9 +169,9 @@
     /**
      * Helper to fold sets of name constraints together
      */
-    static NameConstraintsExtension
-        mergeNameConstraints(X509Certificate currCert,
-            NameConstraintsExtension prevNC) throws CertPathValidatorException
+    static NameConstraintsExtension mergeNameConstraints(
+        X509Certificate currCert, NameConstraintsExtension prevNC)
+        throws CertPathValidatorException
     {
         X509CertImpl currCertImpl;
         try {
@@ -197,7 +200,7 @@
                 // Make sure we do a clone here, because we're probably
                 // going to modify this object later and we don't want to
                 // be sharing it with a Certificate object!
-                return (NameConstraintsExtension) newConstraints.clone();
+                return (NameConstraintsExtension)newConstraints.clone();
             }
         } else {
             try {
--- a/jdk/src/share/classes/sun/security/provider/certpath/CrlRevocationChecker.java	Mon Jan 23 04:44:16 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,785 +0,0 @@
-/*
- * Copyright (c) 2000, 2011, 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.certpath;
-
-import java.math.BigInteger;
-import java.util.Arrays;
-import java.util.ArrayList;
-import java.util.Collection;
-import java.util.Collections;
-import java.util.Date;
-import java.util.List;
-import java.util.HashSet;
-import java.util.Set;
-import java.util.Iterator;
-import java.security.InvalidAlgorithmParameterException;
-import java.security.NoSuchAlgorithmException;
-import java.security.PublicKey;
-import java.security.cert.*;
-import java.security.cert.CertPathValidatorException.BasicReason;
-import java.security.interfaces.DSAPublicKey;
-import sun.security.util.Debug;
-import sun.security.x509.AccessDescription;
-import sun.security.x509.AuthorityInfoAccessExtension;
-import sun.security.x509.CRLDistributionPointsExtension;
-import sun.security.x509.DistributionPoint;
-import sun.security.x509.GeneralName;
-import sun.security.x509.GeneralNames;
-import sun.security.x509.PKIXExtensions;
-import sun.security.x509.X500Name;
-import sun.security.x509.X509CertImpl;
-import sun.security.x509.X509CRLEntryImpl;
-
-/**
- * CrlRevocationChecker is a <code>PKIXCertPathChecker</code> that checks
- * revocation status information on a PKIX certificate using CRLs obtained
- * from one or more <code>CertStores</code>. This is based on section 6.3
- * of RFC 3280 (http://www.ietf.org/rfc/rfc3280.txt).
- *
- * @since       1.4
- * @author      Seth Proctor
- * @author      Steve Hanna
- */
-class CrlRevocationChecker extends PKIXCertPathChecker {
-
-    private static final Debug debug = Debug.getInstance("certpath");
-    private final TrustAnchor mAnchor;
-    private final List<CertStore> mStores;
-    private final String mSigProvider;
-    private final Date mCurrentTime;
-    private PublicKey mPrevPubKey;
-    private boolean mCRLSignFlag;
-    private HashSet<X509CRL> mPossibleCRLs;
-    private HashSet<X509CRL> mApprovedCRLs;
-    private final PKIXParameters mParams;
-    private static final boolean [] mCrlSignUsage =
-        { false, false, false, false, false, false, true };
-    private static final boolean[] ALL_REASONS =
-        {true, true, true, true, true, true, true, true, true};
-    private boolean mOnlyEECert = false;
-
-    // Maximum clock skew in milliseconds (15 minutes) allowed when checking
-    // validity of CRLs
-    private static final long MAX_CLOCK_SKEW = 900000;
-
-    /**
-     * Creates a <code>CrlRevocationChecker</code>.
-     *
-     * @param anchor anchor selected to validate the target certificate
-     * @param params <code>PKIXParameters</code> to be used for
-     *               finding certificates and CRLs, etc.
-     */
-    CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params)
-        throws CertPathValidatorException
-    {
-        this(anchor, params, null);
-    }
-
-    /**
-     * Creates a <code>CrlRevocationChecker</code>, allowing
-     * extra certificates to be supplied beyond those contained
-     * in the <code>PKIXParameters</code>.
-     *
-     * @param anchor anchor selected to validate the target certificate
-     * @param params <code>PKIXParameters</code> to be used for
-     *               finding certificates and CRLs, etc.
-     * @param certs a <code>Collection</code> of certificates
-     *              that may be useful, beyond those available
-     *              through <code>params</code> (<code>null</code>
-     *              if none)
-     */
-    CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
-        Collection<X509Certificate> certs) throws CertPathValidatorException
-    {
-        this(anchor, params, certs, false);
-    }
-
-    CrlRevocationChecker(TrustAnchor anchor, PKIXParameters params,
-        Collection<X509Certificate> certs, boolean onlyEECert)
-        throws CertPathValidatorException {
-        mAnchor = anchor;
-        mParams = params;
-        mStores = new ArrayList<CertStore>(params.getCertStores());
-        mSigProvider = params.getSigProvider();
-        if (certs != null) {
-            try {
-                mStores.add(CertStore.getInstance("Collection",
-                    new CollectionCertStoreParameters(certs)));
-            } catch (Exception e) {
-                // should never occur but not necessarily fatal, so log it,
-                // ignore and continue
-                if (debug != null) {
-                    debug.println("CrlRevocationChecker: " +
-                        "error creating Collection CertStore: " + e);
-                }
-            }
-        }
-        Date testDate = params.getDate();
-        mCurrentTime = (testDate != null ? testDate : new Date());
-        mOnlyEECert = onlyEECert;
-        init(false);
-    }
-
-    /**
-     * Initializes the internal state of the checker from parameters
-     * specified in the constructor
-     */
-    public void init(boolean forward) throws CertPathValidatorException
-    {
-        if (!forward) {
-            if (mAnchor != null) {
-                if (mAnchor.getCAPublicKey() != null) {
-                    mPrevPubKey = mAnchor.getCAPublicKey();
-                } else {
-                    mPrevPubKey = mAnchor.getTrustedCert().getPublicKey();
-                }
-            } else {
-                mPrevPubKey = null;
-            }
-            mCRLSignFlag = true;
-        } else {
-            throw new CertPathValidatorException("forward checking "
-                                + "not supported");
-        }
-    }
-
-    public boolean isForwardCheckingSupported() {
-        return false;
-    }
-
-    public Set<String> getSupportedExtensions() {
-        return null;
-    }
-
-    /**
-     * Performs the revocation status check on the certificate using
-     * its internal state.
-     *
-     * @param cert the Certificate
-     * @param unresolvedCritExts a Collection of the unresolved critical
-     * extensions
-     * @exception CertPathValidatorException Exception thrown if
-     * certificate does not verify
-     */
-    public void check(Certificate cert, Collection<String> unresolvedCritExts)
-        throws CertPathValidatorException
-    {
-        X509Certificate currCert = (X509Certificate) cert;
-        verifyRevocationStatus(currCert, mPrevPubKey, mCRLSignFlag, true);
-
-        // Make new public key if parameters are missing
-        PublicKey cKey = currCert.getPublicKey();
-        if (cKey instanceof DSAPublicKey &&
-            ((DSAPublicKey)cKey).getParams() == null) {
-            // cKey needs to inherit DSA parameters from prev key
-            cKey = BasicChecker.makeInheritedParamsKey(cKey, mPrevPubKey);
-        }
-        mPrevPubKey = cKey;
-        mCRLSignFlag = certCanSignCrl(currCert);
-    }
-
-    /**
-     * Performs the revocation status check on the certificate using
-     * the provided state variables, as well as the constant internal
-     * data.
-     *
-     * @param currCert the Certificate
-     * @param prevKey the previous PublicKey in the chain
-     * @param signFlag a boolean as returned from the last call, or true
-     * if this is the first cert in the chain
-     * @return a boolean specifying if the cert is allowed to vouch for the
-     * validity of a CRL for the next iteration
-     * @exception CertPathValidatorException Exception thrown if
-     *            certificate does not verify.
-     */
-    public boolean check(X509Certificate currCert, PublicKey prevKey,
-        boolean signFlag) throws CertPathValidatorException
-    {
-        verifyRevocationStatus(currCert, prevKey, signFlag, true);
-        return certCanSignCrl(currCert);
-    }
-
-    /**
-     * Checks that a cert can be used to verify a CRL.
-     *
-     * @param currCert an X509Certificate to check
-     * @return a boolean specifying if the cert is allowed to vouch for the
-     * validity of a CRL
-     */
-    static boolean certCanSignCrl(X509Certificate currCert) {
-        // if the cert doesn't include the key usage ext, or
-        // the key usage ext asserts cRLSigning, return true,
-        // otherwise return false.
-        boolean[] kbools = currCert.getKeyUsage();
-        if (kbools != null) {
-            return kbools[6];
-        }
-        return false;
-    }
-
-    /**
-     * Internal method to start the verification of a cert
-     */
-    private void verifyRevocationStatus(X509Certificate currCert,
-        PublicKey prevKey, boolean signFlag, boolean allowSeparateKey)
-        throws CertPathValidatorException
-    {
-        verifyRevocationStatus(currCert, prevKey, signFlag,
-                   allowSeparateKey, null, mParams.getTrustAnchors());
-    }
-
-    /**
-     * Internal method to start the verification of a cert
-     * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
-     *                     whose revocation status depends on the
-     *                     non-revoked status of this cert. To avoid
-     *                     circular dependencies, we assume they're
-     *                     revoked while checking the revocation
-     *                     status of this cert.
-     * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s
-     */
-    private void verifyRevocationStatus(X509Certificate currCert,
-        PublicKey prevKey, boolean signFlag, boolean allowSeparateKey,
-        Set<X509Certificate> stackedCerts,
-        Set<TrustAnchor> trustAnchors) throws CertPathValidatorException {
-
-        String msg = "revocation status";
-        if (debug != null) {
-            debug.println("CrlRevocationChecker.verifyRevocationStatus()" +
-                " ---checking " + msg + "...");
-        }
-
-        if (mOnlyEECert && currCert.getBasicConstraints() != -1) {
-            if (debug != null) {
-                debug.println("Skipping revocation check, not end entity cert");
-            }
-            return;
-        }
-
-        // reject circular dependencies - RFC 3280 is not explicit on how
-        // to handle this, so we feel it is safest to reject them until
-        // the issue is resolved in the PKIX WG.
-        if ((stackedCerts != null) && stackedCerts.contains(currCert)) {
-            if (debug != null) {
-                debug.println("CrlRevocationChecker.verifyRevocationStatus()" +
-                    " circular dependency");
-            }
-            throw new CertPathValidatorException
-                ("Could not determine revocation status", null, null, -1,
-                 BasicReason.UNDETERMINED_REVOCATION_STATUS);
-        }
-
-        // init the state for this run
-        mPossibleCRLs = new HashSet<X509CRL>();
-        mApprovedCRLs = new HashSet<X509CRL>();
-        boolean[] reasonsMask = new boolean[9];
-
-        try {
-            X509CRLSelector sel = new X509CRLSelector();
-            sel.setCertificateChecking(currCert);
-            CertPathHelper.setDateAndTime(sel, mCurrentTime, MAX_CLOCK_SKEW);
-
-            for (CertStore mStore : mStores) {
-                for (java.security.cert.CRL crl : mStore.getCRLs(sel)) {
-                    mPossibleCRLs.add((X509CRL)crl);
-                }
-            }
-            DistributionPointFetcher store =
-                DistributionPointFetcher.getInstance();
-            // all CRLs returned by the DP Fetcher have also been verified
-            mApprovedCRLs.addAll(store.getCRLs(sel, signFlag, prevKey,
-                mSigProvider, mStores, reasonsMask, trustAnchors,
-                mParams.getDate()));
-        } catch (Exception e) {
-            if (debug != null) {
-                debug.println("CrlRevocationChecker.verifyRevocationStatus() "
-                    + "unexpected exception: " + e.getMessage());
-            }
-            throw new CertPathValidatorException(e);
-        }
-
-        if (debug != null) {
-            debug.println("CrlRevocationChecker.verifyRevocationStatus() " +
-                "crls.size() = " + mPossibleCRLs.size());
-        }
-        if (!mPossibleCRLs.isEmpty()) {
-            // Now that we have a list of possible CRLs, see which ones can
-            // be approved
-            mApprovedCRLs.addAll(verifyPossibleCRLs(mPossibleCRLs, currCert,
-                signFlag, prevKey, reasonsMask, trustAnchors));
-        }
-        if (debug != null) {
-            debug.println("CrlRevocationChecker.verifyRevocationStatus() " +
-                "approved crls.size() = " + mApprovedCRLs.size());
-        }
-
-        // make sure that we have at least one CRL that _could_ cover
-        // the certificate in question and all reasons are covered
-        if (mApprovedCRLs.isEmpty() ||
-            !Arrays.equals(reasonsMask, ALL_REASONS)) {
-            if (allowSeparateKey) {
-                verifyWithSeparateSigningKey(currCert, prevKey, signFlag,
-                                             stackedCerts);
-                return;
-            } else {
-                throw new CertPathValidatorException
-                ("Could not determine revocation status", null, null, -1,
-                 BasicReason.UNDETERMINED_REVOCATION_STATUS);
-            }
-        }
-
-        // See if the cert is in the set of approved crls.
-        if (debug != null) {
-            BigInteger sn = currCert.getSerialNumber();
-            debug.println("CrlRevocationChecker.verifyRevocationStatus() " +
-                            "starting the final sweep...");
-            debug.println("CrlRevocationChecker.verifyRevocationStatus" +
-                            " cert SN: " + sn.toString());
-        }
-
-        CRLReason reasonCode = CRLReason.UNSPECIFIED;
-        X509CRLEntryImpl entry = null;
-        for (X509CRL crl : mApprovedCRLs) {
-            X509CRLEntry e = crl.getRevokedCertificate(currCert);
-            if (e != null) {
-                try {
-                    entry = X509CRLEntryImpl.toImpl(e);
-                } catch (CRLException ce) {
-                    throw new CertPathValidatorException(ce);
-                }
-                if (debug != null) {
-                    debug.println("CrlRevocationChecker.verifyRevocationStatus"
-                        + " CRL entry: " + entry.toString());
-                }
-
-                /*
-                 * Abort CRL validation and throw exception if there are any
-                 * unrecognized critical CRL entry extensions (see section
-                 * 5.3 of RFC 3280).
-                 */
-                Set<String> unresCritExts = entry.getCriticalExtensionOIDs();
-                if (unresCritExts != null && !unresCritExts.isEmpty()) {
-                    /* remove any that we will process */
-                    unresCritExts.remove
-                        (PKIXExtensions.ReasonCode_Id.toString());
-                    unresCritExts.remove
-                        (PKIXExtensions.CertificateIssuer_Id.toString());
-                    if (!unresCritExts.isEmpty()) {
-                        if (debug != null) {
-                            debug.println("Unrecognized "
-                            + "critical extension(s) in revoked CRL entry: "
-                            + unresCritExts);
-                        }
-                        throw new CertPathValidatorException
-                        ("Could not determine revocation status", null, null,
-                         -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
-                    }
-                }
-
-                reasonCode = entry.getRevocationReason();
-                if (reasonCode == null) {
-                    reasonCode = CRLReason.UNSPECIFIED;
-                }
-                Throwable t = new CertificateRevokedException
-                    (entry.getRevocationDate(), reasonCode,
-                     crl.getIssuerX500Principal(), entry.getExtensions());
-                throw new CertPathValidatorException(t.getMessage(), t,
-                    null, -1, BasicReason.REVOKED);
-            }
-        }
-    }
-
-    /**
-     * We have a cert whose revocation status couldn't be verified by
-     * a CRL issued by the cert that issued the CRL. See if we can
-     * find a valid CRL issued by a separate key that can verify the
-     * revocation status of this certificate.
-     * <p>
-     * Note that this does not provide support for indirect CRLs,
-     * only CRLs signed with a different key (but the same issuer
-     * name) as the certificate being checked.
-     *
-     * @param currCert the <code>X509Certificate</code> to be checked
-     * @param prevKey the <code>PublicKey</code> that failed
-     * @param signFlag <code>true</code> if that key was trusted to sign CRLs
-     * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
-     *                     whose revocation status depends on the
-     *                     non-revoked status of this cert. To avoid
-     *                     circular dependencies, we assume they're
-     *                     revoked while checking the revocation
-     *                     status of this cert.
-     * @throws CertPathValidatorException if the cert's revocation status
-     *         cannot be verified successfully with another key
-     */
-    private void verifyWithSeparateSigningKey(X509Certificate currCert,
-        PublicKey prevKey, boolean signFlag, Set<X509Certificate> stackedCerts)
-        throws CertPathValidatorException {
-        String msg = "revocation status";
-        if (debug != null) {
-            debug.println(
-                "CrlRevocationChecker.verifyWithSeparateSigningKey()" +
-                " ---checking " + msg + "...");
-        }
-
-        // reject circular dependencies - RFC 3280 is not explicit on how
-        // to handle this, so we feel it is safest to reject them until
-        // the issue is resolved in the PKIX WG.
-        if ((stackedCerts != null) && stackedCerts.contains(currCert)) {
-            if (debug != null) {
-                debug.println(
-                    "CrlRevocationChecker.verifyWithSeparateSigningKey()" +
-                    " circular dependency");
-            }
-            throw new CertPathValidatorException
-                ("Could not determine revocation status", null, null,
-                 -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
-        }
-
-        // If prevKey wasn't trusted, maybe we just didn't have the right
-        // path to it. Don't rule that key out.
-        if (!signFlag) {
-            prevKey = null;
-        }
-
-        // Try to find another key that might be able to sign
-        // CRLs vouching for this cert.
-        buildToNewKey(currCert, prevKey, stackedCerts);
-    }
-
-    /**
-     * Tries to find a CertPath that establishes a key that can be
-     * used to verify the revocation status of a given certificate.
-     * Ignores keys that have previously been tried. Throws a
-     * CertPathValidatorException if no such key could be found.
-     *
-     * @param currCert the <code>X509Certificate</code> to be checked
-     * @param prevKey the <code>PublicKey</code> of the certificate whose key
-     *    cannot be used to vouch for the CRL and should be ignored
-     * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
-     *                     whose revocation status depends on the
-     *                     establishment of this path.
-     * @throws CertPathValidatorException on failure
-     */
-    private void buildToNewKey(X509Certificate currCert,
-        PublicKey prevKey, Set<X509Certificate> stackedCerts)
-        throws CertPathValidatorException {
-
-        if (debug != null) {
-            debug.println("CrlRevocationChecker.buildToNewKey()" +
-                          " starting work");
-        }
-        Set<PublicKey> badKeys = new HashSet<PublicKey>();
-        if (prevKey != null) {
-            badKeys.add(prevKey);
-        }
-        X509CertSelector certSel = new RejectKeySelector(badKeys);
-        certSel.setSubject(currCert.getIssuerX500Principal());
-        certSel.setKeyUsage(mCrlSignUsage);
-
-        Set<TrustAnchor> newAnchors =
-            (mAnchor == null ? mParams.getTrustAnchors() :
-                                Collections.singleton(mAnchor));
-
-        PKIXBuilderParameters builderParams;
-        if (mParams instanceof PKIXBuilderParameters) {
-            builderParams = (PKIXBuilderParameters) mParams.clone();
-            builderParams.setTargetCertConstraints(certSel);
-            // Policy qualifiers must be rejected, since we don't have
-            // any way to convey them back to the application.
-            builderParams.setPolicyQualifiersRejected(true);
-            try {
-                builderParams.setTrustAnchors(newAnchors);
-            } catch (InvalidAlgorithmParameterException iape) {
-                throw new RuntimeException(iape); // should never occur
-            }
-        } else {
-            // It's unfortunate that there's no easy way to make a
-            // PKIXBuilderParameters object from a PKIXParameters
-            // object. This might miss some things if parameters
-            // are added in the future or the validatorParams object
-            // is a custom class derived from PKIXValidatorParameters.
-            try {
-                builderParams = new PKIXBuilderParameters(newAnchors, certSel);
-            } catch (InvalidAlgorithmParameterException iape) {
-                throw new RuntimeException(iape); // should never occur
-            }
-            builderParams.setInitialPolicies(mParams.getInitialPolicies());
-            builderParams.setCertStores(mStores);
-            builderParams.setExplicitPolicyRequired
-                (mParams.isExplicitPolicyRequired());
-            builderParams.setPolicyMappingInhibited
-                (mParams.isPolicyMappingInhibited());
-            builderParams.setAnyPolicyInhibited(mParams.isAnyPolicyInhibited());
-            // Policy qualifiers must be rejected, since we don't have
-            // any way to convey them back to the application.
-            // That's the default, so no need to write code.
-            builderParams.setDate(mParams.getDate());
-            builderParams.setCertPathCheckers(mParams.getCertPathCheckers());
-            builderParams.setSigProvider(mParams.getSigProvider());
-        }
-
-        // Skip revocation during this build to detect circular
-        // references. But check revocation afterwards, using the
-        // key (or any other that works).
-        builderParams.setRevocationEnabled(false);
-
-        // check for AuthorityInformationAccess extension
-        if (Builder.USE_AIA == true) {
-            X509CertImpl currCertImpl = null;
-            try {
-                currCertImpl = X509CertImpl.toImpl(currCert);
-            } catch (CertificateException ce) {
-                // ignore but log it
-                if (debug != null) {
-                    debug.println("CrlRevocationChecker.buildToNewKey: " +
-                        "error decoding cert: " + ce);
-                }
-            }
-            AuthorityInfoAccessExtension aiaExt = null;
-            if (currCertImpl != null) {
-                aiaExt = currCertImpl.getAuthorityInfoAccessExtension();
-            }
-            if (aiaExt != null) {
-                List<AccessDescription> adList = aiaExt.getAccessDescriptions();
-                if (adList != null) {
-                    for (AccessDescription ad : adList) {
-                        CertStore cs = URICertStore.getInstance(ad);
-                        if (cs != null) {
-                            if (debug != null) {
-                                debug.println("adding AIAext CertStore");
-                            }
-                            builderParams.addCertStore(cs);
-                        }
-                    }
-                }
-            }
-        }
-
-        CertPathBuilder builder = null;
-        try {
-            builder = CertPathBuilder.getInstance("PKIX");
-        } catch (NoSuchAlgorithmException nsae) {
-            throw new CertPathValidatorException(nsae);
-        }
-        while (true) {
-            try {
-                if (debug != null) {
-                    debug.println("CrlRevocationChecker.buildToNewKey()" +
-                                  " about to try build ...");
-                }
-                PKIXCertPathBuilderResult cpbr =
-                    (PKIXCertPathBuilderResult) builder.build(builderParams);
-
-                if (debug != null) {
-                    debug.println("CrlRevocationChecker.buildToNewKey()" +
-                                  " about to check revocation ...");
-                }
-                // Now check revocation of all certs in path, assuming that
-                // the stackedCerts are revoked.
-                if (stackedCerts == null) {
-                    stackedCerts = new HashSet<X509Certificate>();
-                }
-                stackedCerts.add(currCert);
-                TrustAnchor ta = cpbr.getTrustAnchor();
-                PublicKey prevKey2 = ta.getCAPublicKey();
-                if (prevKey2 == null) {
-                    prevKey2 = ta.getTrustedCert().getPublicKey();
-                }
-                boolean signFlag = true;
-                List<? extends Certificate> cpList =
-                    cpbr.getCertPath().getCertificates();
-                try {
-                    for (int i = cpList.size()-1; i >= 0; i-- ) {
-                        X509Certificate cert = (X509Certificate) cpList.get(i);
-
-                        if (debug != null) {
-                            debug.println("CrlRevocationChecker.buildToNewKey()"
-                                + " index " + i + " checking " + cert);
-                        }
-                        verifyRevocationStatus(cert, prevKey2, signFlag, true,
-                                stackedCerts, newAnchors);
-                        signFlag = certCanSignCrl(cert);
-                        prevKey2 = cert.getPublicKey();
-                    }
-                } catch (CertPathValidatorException cpve) {
-                    // ignore it and try to get another key
-                    badKeys.add(cpbr.getPublicKey());
-                    continue;
-                }
-
-                if (debug != null) {
-                    debug.println("CrlRevocationChecker.buildToNewKey()" +
-                                  " got key " + cpbr.getPublicKey());
-                }
-                // Now check revocation on the current cert using that key.
-                // If it doesn't check out, try to find a different key.
-                // And if we can't find a key, then return false.
-                PublicKey newKey = cpbr.getPublicKey();
-                try {
-                    verifyRevocationStatus(currCert, newKey, true, false);
-                    // If that passed, the cert is OK!
-                    return;
-                } catch (CertPathValidatorException cpve) {
-                    // If it is revoked, rethrow exception
-                    if (cpve.getReason() == BasicReason.REVOKED) {
-                        throw cpve;
-                    }
-                    // Otherwise, ignore the exception and
-                    // try to get another key.
-                }
-                badKeys.add(newKey);
-            } catch (InvalidAlgorithmParameterException iape) {
-                throw new CertPathValidatorException(iape);
-            } catch (CertPathBuilderException cpbe) {
-                throw new CertPathValidatorException
-                    ("Could not determine revocation status", null, null,
-                     -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
-            }
-        }
-    }
-
-    /*
-     * This inner class extends the X509CertSelector to add an additional
-     * check to make sure the subject public key isn't on a particular list.
-     * This class is used by buildToNewKey() to make sure the builder doesn't
-     * end up with a CertPath to a public key that has already been rejected.
-     */
-    private static class RejectKeySelector extends X509CertSelector {
-        private final Set<PublicKey> badKeySet;
-
-        /**
-         * Creates a new <code>RejectKeySelector</code>.
-         *
-         * @param badPublicKeys a <code>Set</code> of
-         *                      <code>PublicKey</code>s that
-         *                      should be rejected (or <code>null</code>
-         *                      if no such check should be done)
-         */
-        RejectKeySelector(Set<PublicKey> badPublicKeys) {
-            this.badKeySet = badPublicKeys;
-        }
-
-        /**
-         * Decides whether a <code>Certificate</code> should be selected.
-         *
-         * @param cert the <code>Certificate</code> to be checked
-         * @return <code>true</code> if the <code>Certificate</code> should be
-         *         selected, <code>false</code> otherwise
-         */
-        public boolean match(Certificate cert) {
-            if (!super.match(cert))
-                return(false);
-
-            if (badKeySet.contains(cert.getPublicKey())) {
-                if (debug != null)
-                    debug.println("RejectCertSelector.match: bad key");
-                return false;
-            }
-
-            if (debug != null)
-                debug.println("RejectCertSelector.match: returning true");
-            return true;
-        }
-
-        /**
-         * Return a printable representation of the <code>CertSelector</code>.
-         *
-         * @return a <code>String</code> describing the contents of the
-         *         <code>CertSelector</code>
-         */
-        public String toString() {
-            StringBuilder sb = new StringBuilder();
-            sb.append("RejectCertSelector: [\n");
-            sb.append(super.toString());
-            sb.append(badKeySet);
-            sb.append("]");
-            return sb.toString();
-        }
-    }
-
-    /**
-     * Internal method that verifies a set of possible_crls,
-     * and sees if each is approved, based on the cert.
-     *
-     * @param crls a set of possible CRLs to test for acceptability
-     * @param cert the certificate whose revocation status is being checked
-     * @param signFlag <code>true</code> if prevKey was trusted to sign CRLs
-     * @param prevKey the public key of the issuer of cert
-     * @param reasonsMask the reason code mask
-     * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s>
-     * @return a collection of approved crls (or an empty collection)
-     */
-    private Collection<X509CRL> verifyPossibleCRLs(Set<X509CRL> crls,
-        X509Certificate cert, boolean signFlag, PublicKey prevKey,
-        boolean[] reasonsMask,
-        Set<TrustAnchor> trustAnchors) throws CertPathValidatorException {
-
-        try {
-            X509CertImpl certImpl = X509CertImpl.toImpl(cert);
-            if (debug != null) {
-                debug.println("CRLRevocationChecker.verifyPossibleCRLs: " +
-                        "Checking CRLDPs for "
-                        + certImpl.getSubjectX500Principal());
-            }
-            CRLDistributionPointsExtension ext =
-                certImpl.getCRLDistributionPointsExtension();
-            List<DistributionPoint> points = null;
-            if (ext == null) {
-                // assume a DP with reasons and CRLIssuer fields omitted
-                // and a DP name of the cert issuer.
-                // TODO add issuerAltName too
-                X500Name certIssuer = (X500Name)certImpl.getIssuerDN();
-                DistributionPoint point = new DistributionPoint
-                    (new GeneralNames().add(new GeneralName(certIssuer)),
-                     null, null);
-                points = Collections.singletonList(point);
-            } else {
-                points = ext.get(CRLDistributionPointsExtension.POINTS);
-            }
-            Set<X509CRL> results = new HashSet<X509CRL>();
-            DistributionPointFetcher dpf =
-                DistributionPointFetcher.getInstance();
-            for (Iterator<DistributionPoint> t = points.iterator();
-                 t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) {
-                DistributionPoint point = t.next();
-                for (X509CRL crl : crls) {
-                    if (dpf.verifyCRL(certImpl, point, crl, reasonsMask,
-                            signFlag, prevKey, mSigProvider,
-                            trustAnchors, mStores, mParams.getDate())) {
-                        results.add(crl);
-                    }
-                }
-            }
-            return results;
-        } catch (Exception e) {
-            if (debug != null) {
-                debug.println("Exception while verifying CRL: "+e.getMessage());
-                e.printStackTrace();
-            }
-            return Collections.emptySet();
-        }
-    }
-}
--- a/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/DistributionPointFetcher.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, 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
@@ -27,14 +27,14 @@
 
 import java.io.*;
 import java.net.URI;
-import java.util.*;
 import java.security.*;
 import java.security.cert.*;
 import javax.security.auth.x500.X500Principal;
+import java.util.*;
 
-import sun.security.action.GetBooleanAction;
 import sun.security.util.Debug;
 import sun.security.util.DerOutputStream;
+import static sun.security.x509.PKIXExtensions.*;
 import sun.security.x509.*;
 
 /**
@@ -58,44 +58,23 @@
         {true, true, true, true, true, true, true, true, true};
 
     /**
-     * Flag indicating whether support for the CRL distribution point
-     * extension shall be enabled. Currently disabled by default for
-     * compatibility and legal reasons.
-     */
-    private final static boolean USE_CRLDP = AccessController.doPrivileged
-        (new GetBooleanAction("com.sun.security.enableCRLDP"));
-
-    // singleton instance
-    private static final DistributionPointFetcher INSTANCE =
-        new DistributionPointFetcher();
-
-    /**
      * Private instantiation only.
      */
     private DistributionPointFetcher() {}
 
     /**
-     * Return a DistributionPointFetcher instance.
-     */
-    static DistributionPointFetcher getInstance() {
-        return INSTANCE;
-    }
-
-    /**
      * Return the X509CRLs matching this selector. The selector must be
      * an X509CRLSelector with certificateChecking set.
-     *
-     * If CRLDP support is disabled, this method always returns an
-     * empty set.
      */
-    Collection<X509CRL> getCRLs(X509CRLSelector selector, boolean signFlag,
-        PublicKey prevKey, String provider, List<CertStore> certStores,
-        boolean[] reasonsMask, Set<TrustAnchor> trustAnchors,
-        Date validity) throws CertStoreException {
-
-        if (USE_CRLDP == false) {
-            return Collections.emptySet();
-        }
+    static Collection<X509CRL> getCRLs(X509CRLSelector selector,
+                                       boolean signFlag, PublicKey prevKey,
+                                       String provider,
+                                       List<CertStore> certStores,
+                                       boolean[] reasonsMask,
+                                       Set<TrustAnchor> trustAnchors,
+                                       Date validity)
+        throws CertStoreException
+    {
         X509Certificate cert = selector.getCertificateChecking();
         if (cert == null) {
             return Collections.emptySet();
@@ -116,7 +95,7 @@
             }
             List<DistributionPoint> points =
                     ext.get(CRLDistributionPointsExtension.POINTS);
-            Set<X509CRL> results = new HashSet<X509CRL>();
+            Set<X509CRL> results = new HashSet<>();
             for (Iterator<DistributionPoint> t = points.iterator();
                  t.hasNext() && !Arrays.equals(reasonsMask, ALL_REASONS); ) {
                 DistributionPoint point = t.next();
@@ -129,9 +108,7 @@
                 debug.println("Returning " + results.size() + " CRLs");
             }
             return results;
-        } catch (CertificateException e) {
-            return Collections.emptySet();
-        } catch (IOException e) {
+        } catch (CertificateException | IOException e) {
             return Collections.emptySet();
         }
     }
@@ -140,7 +117,7 @@
      * Download CRLs from the given distribution point, verify and return them.
      * See the top of the class for current limitations.
      */
-    private Collection<X509CRL> getCRLs(X509CRLSelector selector,
+    private static Collection<X509CRL> getCRLs(X509CRLSelector selector,
         X509CertImpl certImpl, DistributionPoint point, boolean[] reasonsMask,
         boolean signFlag, PublicKey prevKey, String provider,
         List<CertStore> certStores, Set<TrustAnchor> trustAnchors,
@@ -200,7 +177,7 @@
                         certStores, validity)) {
                     crls.add(crl);
                 }
-            } catch (Exception e) {
+            } catch (IOException | CRLException e) {
                 // don't add the CRL
                 if (debug != null) {
                     debug.println("Exception verifying CRL: " + e.getMessage());
@@ -214,7 +191,7 @@
     /**
      * Download CRL from given URI.
      */
-    private X509CRL getCRL(URIName name) {
+    private static X509CRL getCRL(URIName name) {
         URI uri = name.getURI();
         if (debug != null) {
             debug.println("Trying to fetch CRL from DP " + uri);
@@ -240,7 +217,7 @@
     /**
      * Fetch CRLs from certStores.
      */
-    private Collection<X509CRL> getCRLs(X500Name name,
+    private static Collection<X509CRL> getCRLs(X500Name name,
         X500Principal certIssuer, List<CertStore> certStores)
     {
         if (debug != null) {
@@ -249,7 +226,7 @@
         X509CRLSelector xcs = new X509CRLSelector();
         xcs.addIssuer(name.asX500Principal());
         xcs.addIssuer(certIssuer);
-        Collection<X509CRL> crls = new ArrayList<X509CRL>();
+        Collection<X509CRL> crls = new ArrayList<>();
         for (CertStore store : certStores) {
             try {
                 for (CRL crl : store.getCRLs(xcs)) {
@@ -285,7 +262,7 @@
      *        certification path should be determined
      * @return true if ok, false if not
      */
-    boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,
+    static boolean verifyCRL(X509CertImpl certImpl, DistributionPoint point,
         X509CRL crl, boolean[] reasonsMask, boolean signFlag,
         PublicKey prevKey, String provider,
         Set<TrustAnchor> trustAnchors, List<CertStore> certStores,
@@ -340,9 +317,9 @@
         } else {
             // in case of self-issued indirect CRL issuer.
             byte[] certAKID = certImpl.getExtensionValue(
-                                PKIXExtensions.AuthorityKey_Id.toString());
+                                AuthorityKey_Id.toString());
             byte[] crlAKID = crlImpl.getExtensionValue(
-                                PKIXExtensions.AuthorityKey_Id.toString());
+                                AuthorityKey_Id.toString());
 
             if (certAKID == null || crlAKID == null) {
                 // cannot recognize indirect CRL without AKID
@@ -539,7 +516,7 @@
         // verify that interim reasons mask includes one or more reasons
         // not included in the reasons mask
         boolean oneOrMore = false;
-        for (int i=0; i < interimReasonsMask.length && !oneOrMore; i++) {
+        for (int i = 0; i < interimReasonsMask.length && !oneOrMore; i++) {
             if (!reasonsMask[i] && interimReasonsMask[i]) {
                 oneOrMore = true;
             }
@@ -615,7 +592,7 @@
                 PKIXCertPathBuilderResult result =
                     (PKIXCertPathBuilderResult) builder.build(params);
                 prevKey = result.getPublicKey();
-            } catch (Exception e) {
+            } catch (GeneralSecurityException e) {
                 throw new CRLException(e);
             }
         }
@@ -633,7 +610,7 @@
         // validate the signature on the CRL
         try {
             crl.verify(prevKey, provider);
-        } catch (Exception e) {
+        } catch (GeneralSecurityException e) {
             if (debug != null) {
                 debug.println("CRL signature failed to verify");
             }
@@ -644,22 +621,21 @@
         Set<String> unresCritExts = crl.getCriticalExtensionOIDs();
         // remove any that we have processed
         if (unresCritExts != null) {
-            unresCritExts.remove
-                (PKIXExtensions.IssuingDistributionPoint_Id.toString());
+            unresCritExts.remove(IssuingDistributionPoint_Id.toString());
             if (!unresCritExts.isEmpty()) {
                 if (debug != null) {
                     debug.println("Unrecognized critical extension(s) in CRL: "
                         + unresCritExts);
-                    Iterator<String> i = unresCritExts.iterator();
-                    while (i.hasNext())
-                        debug.println(i.next());
+                    for (String ext : unresCritExts) {
+                        debug.println(ext);
+                    }
                 }
                 return false;
             }
         }
 
         // update reasonsMask
-        for (int i=0; i < interimReasonsMask.length; i++) {
+        for (int i = 0; i < interimReasonsMask.length; i++) {
             if (!reasonsMask[i] && interimReasonsMask[i]) {
                 reasonsMask[i] = true;
             }
@@ -671,9 +647,10 @@
      * Append relative name to the issuer name and return a new
      * GeneralNames object.
      */
-    private GeneralNames getFullNames(X500Name issuer, RDN rdn)
-        throws IOException {
-        List<RDN> rdns = new ArrayList<RDN>(issuer.rdns());
+    private static GeneralNames getFullNames(X500Name issuer, RDN rdn)
+        throws IOException
+    {
+        List<RDN> rdns = new ArrayList<>(issuer.rdns());
         rdns.add(rdn);
         X500Name fullName = new X500Name(rdns.toArray(new RDN[0]));
         GeneralNames fullNames = new GeneralNames();
@@ -681,15 +658,16 @@
         return fullNames;
     }
 
-    /** Verifies whether a CRL is issued by a certain certificate
+    /**
+     * Verifies whether a CRL is issued by a certain certificate
      *
      * @param cert the certificate
      * @param crl the CRL to be verified
      * @param provider the name of the signature provider
      */
     private static boolean issues(X509CertImpl cert, X509CRLImpl crl,
-            String provider) throws IOException {
-
+                                  String provider) throws IOException
+    {
         boolean matched = false;
 
         AdaptableX509CertSelector issuerSelector =
@@ -727,7 +705,7 @@
             try {
                 crl.verify(cert.getPublicKey(), provider);
                 matched = true;
-            } catch (Exception e) {
+            } catch (GeneralSecurityException e) {
                 matched = false;
             }
         }
--- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardBuilder.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -26,10 +26,9 @@
 package sun.security.provider.certpath;
 
 import java.io.IOException;
-import java.util.*;
-
 import java.security.GeneralSecurityException;
 import java.security.InvalidKeyException;
+import java.security.PublicKey;
 import java.security.cert.CertificateException;
 import java.security.cert.CertPathValidatorException;
 import java.security.cert.PKIXReason;
@@ -40,12 +39,14 @@
 import java.security.cert.TrustAnchor;
 import java.security.cert.X509Certificate;
 import java.security.cert.X509CertSelector;
+import java.util.*;
 import javax.security.auth.x500.X500Principal;
 
+import sun.security.provider.certpath.PKIX.BuilderParams;
 import sun.security.util.Debug;
 import sun.security.x509.AccessDescription;
 import sun.security.x509.AuthorityInfoAccessExtension;
-import sun.security.x509.PKIXExtensions;
+import static sun.security.x509.PKIXExtensions.*;
 import sun.security.x509.PolicyMappingsExtension;
 import sun.security.x509.X500Name;
 import sun.security.x509.X509CertImpl;
@@ -72,21 +73,17 @@
     TrustAnchor trustAnchor;
     private Comparator<X509Certificate> comparator;
     private boolean searchAllCertStores = true;
-    private boolean onlyEECert = false;
 
     /**
      * Initialize the builder with the input parameters.
      *
      * @param params the parameter set used to build a certification path
      */
-    ForwardBuilder(PKIXBuilderParameters buildParams,
-        X500Principal targetSubjectDN, boolean searchAllCertStores,
-        boolean onlyEECert)
-    {
-        super(buildParams, targetSubjectDN);
+    ForwardBuilder(BuilderParams buildParams, boolean searchAllCertStores) {
+        super(buildParams);
 
         // populate sets of trusted certificates and subject DNs
-        trustAnchors = buildParams.getTrustAnchors();
+        trustAnchors = buildParams.trustAnchors();
         trustedCerts = new HashSet<X509Certificate>(trustAnchors.size());
         trustedSubjectDNs = new HashSet<X500Principal>(trustAnchors.size());
         for (TrustAnchor anchor : trustAnchors) {
@@ -100,7 +97,6 @@
         }
         comparator = new PKIXCertComparator(trustedSubjectDNs);
         this.searchAllCertStores = searchAllCertStores;
-        this.onlyEECert = onlyEECert;
     }
 
     /**
@@ -112,8 +108,9 @@
      *        Must be an instance of <code>ForwardState</code>
      * @param certStores list of CertStores
      */
-    Collection<X509Certificate> getMatchingCerts
-        (State currentState, List<CertStore> certStores)
+    @Override
+    Collection<X509Certificate> getMatchingCerts(State currentState,
+                                                 List<CertStore> certStores)
         throws CertStoreException, CertificateException, IOException
     {
         if (debug != null) {
@@ -127,7 +124,7 @@
          * As each cert is added, it is sorted based on the PKIXCertComparator
          * algorithm.
          */
-        Set<X509Certificate> certs = new TreeSet<X509Certificate>(comparator);
+        Set<X509Certificate> certs = new TreeSet<>(comparator);
 
         /*
          * Only look for EE certs if search has just started.
@@ -145,9 +142,10 @@
      * and requirements specified in the parameters and PKIX state.
      */
     private void getMatchingEECerts(ForwardState currentState,
-        List<CertStore> certStores, Collection<X509Certificate> eeCerts)
-        throws IOException {
-
+                                    List<CertStore> certStores,
+                                    Collection<X509Certificate> eeCerts)
+        throws IOException
+    {
         if (debug != null) {
             debug.println("ForwardBuilder.getMatchingEECerts()...");
         }
@@ -165,12 +163,12 @@
             /*
              * Match on certificate validity date
              */
-            eeSelector.setCertificateValid(date);
+            eeSelector.setCertificateValid(buildParams.date());
 
             /*
              * Policy processing optimizations
              */
-            if (buildParams.isExplicitPolicyRequired()) {
+            if (buildParams.explicitPolicyRequired()) {
                 eeSelector.setPolicy(getMatchingPolicies());
             }
             /*
@@ -188,9 +186,10 @@
      * and requirements specified in the parameters and PKIX state.
      */
     private void getMatchingCACerts(ForwardState currentState,
-        List<CertStore> certStores, Collection<X509Certificate> caCerts)
-        throws IOException {
-
+                                    List<CertStore> certStores,
+                                    Collection<X509Certificate> caCerts)
+        throws IOException
+    {
         if (debug != null) {
             debug.println("ForwardBuilder.getMatchingCACerts()...");
         }
@@ -216,8 +215,8 @@
             }
 
             if (caTargetSelector == null) {
-                caTargetSelector = (X509CertSelector)
-                    targetCertConstraints.clone();
+                caTargetSelector =
+                    (X509CertSelector) targetCertConstraints.clone();
 
                 /*
                  * Since we don't check the validity period of trusted
@@ -229,7 +228,7 @@
                 /*
                  * Policy processing optimizations
                  */
-                if (buildParams.isExplicitPolicyRequired())
+                if (buildParams.explicitPolicyRequired())
                     caTargetSelector.setPolicy(getMatchingPolicies());
             }
 
@@ -249,7 +248,7 @@
                 /*
                  * Policy processing optimizations
                  */
-                if (buildParams.isExplicitPolicyRequired())
+                if (buildParams.explicitPolicyRequired())
                     caSelector.setPolicy(getMatchingPolicies());
             }
 
@@ -278,7 +277,7 @@
              * check the validity period
              */
             caSelector.setValidityPeriod(currentState.cert.getNotBefore(),
-                                            currentState.cert.getNotAfter());
+                                         currentState.cert.getNotAfter());
 
             sel = caSelector;
         }
@@ -307,7 +306,7 @@
          * The trusted certificate matching is completed. We need to match
          * on certificate validity date.
          */
-        sel.setCertificateValid(date);
+        sel.setCertificateValid(buildParams.date());
 
         /*
          * Require CA certs with a pathLenConstraint that allows
@@ -323,11 +322,12 @@
          * certificate pairs.
          */
         if (currentState.isInitial() ||
-           (buildParams.getMaxPathLength() == -1) ||
-           (buildParams.getMaxPathLength() > currentState.traversedCACerts))
+           (buildParams.maxPathLength() == -1) ||
+           (buildParams.maxPathLength() > currentState.traversedCACerts))
         {
             if (addMatchingCerts(sel, certStores,
-                    caCerts, searchAllCertStores) && !searchAllCertStores) {
+                                 caCerts, searchAllCertStores)
+                && !searchAllCertStores) {
                 return;
             }
         }
@@ -356,7 +356,8 @@
     // because of the selector, so the cast is safe
     @SuppressWarnings("unchecked")
     private boolean getCerts(AuthorityInfoAccessExtension aiaExt,
-        Collection<X509Certificate> certs) {
+                             Collection<X509Certificate> certs)
+    {
         if (Builder.USE_AIA == false) {
             return false;
         }
@@ -449,6 +450,7 @@
          * @throws ClassCastException if either argument is not of type
          * X509Certificate
          */
+        @Override
         public int compare(X509Certificate oCert1, X509Certificate oCert2) {
 
             // if certs are the same, return 0
@@ -651,8 +653,10 @@
      * @param currentState the current state against which the cert is verified
      * @param certPathList the certPathList generated thus far
      */
+    @Override
     void verifyCert(X509Certificate cert, State currentState,
-        List<X509Certificate> certPathList) throws GeneralSecurityException
+                    List<X509Certificate> certPathList)
+        throws GeneralSecurityException
     {
         if (debug != null) {
             debug.println("ForwardBuilder.verifyCert(SN: "
@@ -683,7 +687,7 @@
                     debug.println("policyMappingFound = " + policyMappingFound);
                 }
                 if (cert.equals(cpListCert)) {
-                    if ((buildParams.isPolicyMappingInhibited()) ||
+                    if ((buildParams.policyMappingInhibited()) ||
                         (!policyMappingFound)) {
                         if (debug != null) {
                             debug.println("loop detected!!");
@@ -718,7 +722,7 @@
              * all extensions that all user checkers are capable of
              * processing.
              */
-            for (PKIXCertPathChecker checker : buildParams.getCertPathCheckers()) {
+            for (PKIXCertPathChecker checker : buildParams.certPathCheckers()) {
                 if (!checker.isForwardCheckingSupported()) {
                     Set<String> supportedExts = checker.getSupportedExtensions();
                     if (supportedExts != null) {
@@ -732,23 +736,15 @@
              * to check. If there are any left, throw an exception!
              */
             if (!unresCritExts.isEmpty()) {
-                unresCritExts.remove(
-                    PKIXExtensions.BasicConstraints_Id.toString());
-                unresCritExts.remove(
-                    PKIXExtensions.NameConstraints_Id.toString());
-                unresCritExts.remove(
-                    PKIXExtensions.CertificatePolicies_Id.toString());
-                unresCritExts.remove(
-                    PKIXExtensions.PolicyMappings_Id.toString());
-                unresCritExts.remove(
-                    PKIXExtensions.PolicyConstraints_Id.toString());
-                unresCritExts.remove(
-                    PKIXExtensions.InhibitAnyPolicy_Id.toString());
-                unresCritExts.remove(
-                    PKIXExtensions.SubjectAlternativeName_Id.toString());
-                unresCritExts.remove(PKIXExtensions.KeyUsage_Id.toString());
-                unresCritExts.remove(
-                    PKIXExtensions.ExtendedKeyUsage_Id.toString());
+                unresCritExts.remove(BasicConstraints_Id.toString());
+                unresCritExts.remove(NameConstraints_Id.toString());
+                unresCritExts.remove(CertificatePolicies_Id.toString());
+                unresCritExts.remove(PolicyMappings_Id.toString());
+                unresCritExts.remove(PolicyConstraints_Id.toString());
+                unresCritExts.remove(InhibitAnyPolicy_Id.toString());
+                unresCritExts.remove(SubjectAlternativeName_Id.toString());
+                unresCritExts.remove(KeyUsage_Id.toString());
+                unresCritExts.remove(ExtendedKeyUsage_Id.toString());
 
                 if (!unresCritExts.isEmpty())
                     throw new CertPathValidatorException
@@ -786,31 +782,12 @@
          */
 
         /*
-         * Check revocation for the previous cert
-         */
-        if (buildParams.isRevocationEnabled()) {
-
-            // first off, see if this cert can authorize revocation...
-            if (CrlRevocationChecker.certCanSignCrl(cert)) {
-                // And then check to be sure no key requiring key parameters
-                // has been encountered
-                if (!currState.keyParamsNeeded())
-                    // If all that checks out, we can check the
-                    // revocation status of the cert. Otherwise,
-                    // we'll just wait until the end.
-                    currState.crlChecker.check(currState.cert,
-                                               cert.getPublicKey(),
-                                               true);
-            }
-        }
-
-        /*
          * Check signature only if no key requiring key parameters has been
          * encountered.
          */
         if (!currState.keyParamsNeeded()) {
             (currState.cert).verify(cert.getPublicKey(),
-                                    buildParams.getSigProvider());
+                                    buildParams.sigProvider());
         }
     }
 
@@ -826,6 +803,7 @@
      * @param cert the certificate to test
      * @return a boolean value indicating whether the cert completes the path.
      */
+    @Override
     boolean isPathCompleted(X509Certificate cert) {
         for (TrustAnchor anchor : trustAnchors) {
             if (anchor.getTrustedCert() != null) {
@@ -837,7 +815,7 @@
                 }
             } else {
                 X500Principal principal = anchor.getCA();
-                java.security.PublicKey publicKey = anchor.getCAPublicKey();
+                PublicKey publicKey = anchor.getCAPublicKey();
 
                 if (principal != null && publicKey != null &&
                         principal.equals(cert.getSubjectX500Principal())) {
@@ -856,21 +834,6 @@
                 }
             }
 
-            /* Check revocation if it is enabled */
-            if (buildParams.isRevocationEnabled()) {
-                try {
-                    CrlRevocationChecker crlChecker = new CrlRevocationChecker
-                        (anchor, buildParams, null, onlyEECert);
-                    crlChecker.check(cert, anchor.getCAPublicKey(), true);
-                } catch (CertPathValidatorException cpve) {
-                    if (debug != null) {
-                        debug.println("ForwardBuilder.isPathCompleted() cpve");
-                        cpve.printStackTrace();
-                    }
-                    continue;
-                }
-            }
-
             /*
              * Check signature
              */
@@ -879,18 +842,17 @@
                 // parameters, yet there is no key to inherit the parameters
                 // from.  This is probably such a rare case that it is not worth
                 // trying to detect the situation earlier.
-                cert.verify(anchor.getCAPublicKey(),
-                            buildParams.getSigProvider());
+                cert.verify(anchor.getCAPublicKey(), buildParams.sigProvider());
             } catch (InvalidKeyException ike) {
                 if (debug != null) {
                     debug.println("ForwardBuilder.isPathCompleted() invalid "
-                        + "DSA key found");
+                                  + "DSA key found");
                 }
                 continue;
-            } catch (Exception e){
+            } catch (GeneralSecurityException e){
                 if (debug != null) {
                     debug.println("ForwardBuilder.isPathCompleted() " +
-                        "unexpected exception");
+                                  "unexpected exception");
                     e.printStackTrace();
                 }
                 continue;
@@ -908,8 +870,10 @@
      * @param cert the certificate to be added
      * @param certPathList the certification path list
      */
+    @Override
     void addCertToPath(X509Certificate cert,
-        LinkedList<X509Certificate> certPathList) {
+                       LinkedList<X509Certificate> certPathList)
+    {
         certPathList.addFirst(cert);
     }
 
@@ -917,6 +881,7 @@
      *
      * @param certPathList the certification path list
      */
+    @Override
     void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) {
         certPathList.removeFirst();
     }
--- a/jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ForwardState.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -34,7 +34,6 @@
 import java.security.interfaces.DSAPublicKey;
 import java.util.ArrayList;
 import java.util.HashSet;
-import java.util.Iterator;
 import java.util.List;
 import java.util.ListIterator;
 import javax.security.auth.x500.X500Principal;
@@ -76,9 +75,6 @@
     /* Flag indicating if state is initial (path is just starting) */
     private boolean init = true;
 
-    /* the checker used for revocation status */
-    public CrlRevocationChecker crlChecker;
-
     /* The list of user-defined checkers that support forward checking */
     ArrayList<PKIXCertPathChecker> forwardCheckers;
 
@@ -93,6 +89,7 @@
      *
      * @return boolean flag indicating if the state is initial (just starting)
      */
+    @Override
     public boolean isInitial() {
         return init;
     }
@@ -104,6 +101,7 @@
      * @return boolean true if key needing to inherit parameters has been
      * encountered; false otherwise.
      */
+    @Override
     public boolean keyParamsNeeded() {
         return keyParamsNeededFlag;
     }
@@ -111,23 +109,18 @@
     /**
      * Display state for debugging purposes
      */
+    @Override
     public String toString() {
-        StringBuffer sb = new StringBuffer();
-        try {
-            sb.append("State [");
-            sb.append("\n  issuerDN of last cert: " + issuerDN);
-            sb.append("\n  traversedCACerts: " + traversedCACerts);
-            sb.append("\n  init: " + String.valueOf(init));
-            sb.append("\n  keyParamsNeeded: "
-                + String.valueOf(keyParamsNeededFlag));
-            sb.append("\n  subjectNamesTraversed: \n" + subjectNamesTraversed);
-            sb.append("]\n");
-        } catch (Exception e) {
-            if (debug != null) {
-                debug.println("ForwardState.toString() unexpected exception");
-                e.printStackTrace();
-            }
-        }
+        StringBuilder sb = new StringBuilder();
+        sb.append("State [");
+        sb.append("\n  issuerDN of last cert: ").append(issuerDN);
+        sb.append("\n  traversedCACerts: ").append(traversedCACerts);
+        sb.append("\n  init: ").append(String.valueOf(init));
+        sb.append("\n  keyParamsNeeded: ").append
+                 (String.valueOf(keyParamsNeededFlag));
+        sb.append("\n  subjectNamesTraversed: \n").append
+                 (subjectNamesTraversed);
+        sb.append("]\n");
         return sb.toString();
     }
 
@@ -147,12 +140,10 @@
          * that supports forward checking and initialize the forwardCheckers
          */
         forwardCheckers = new ArrayList<PKIXCertPathChecker>();
-        if (certPathCheckers != null) {
-            for (PKIXCertPathChecker checker : certPathCheckers) {
-                if (checker.isForwardCheckingSupported()) {
-                    checker.init(true);
-                    forwardCheckers.add(checker);
-                }
+        for (PKIXCertPathChecker checker : certPathCheckers) {
+            if (checker.isForwardCheckingSupported()) {
+                checker.init(true);
+                forwardCheckers.add(checker);
             }
         }
 
@@ -164,6 +155,7 @@
      *
      * @param cert the certificate which is used to update the state
      */
+    @Override
     public void updateState(X509Certificate cert)
         throws CertificateException, IOException, CertPathValidatorException {
 
@@ -208,13 +200,11 @@
                 if (subjAltNameExt != null) {
                     GeneralNames gNames = subjAltNameExt.get(
                             SubjectAlternativeNameExtension.SUBJECT_NAME);
-                    for (Iterator<GeneralName> t = gNames.iterator();
-                                t.hasNext(); ) {
-                        GeneralNameInterface gName = t.next().getName();
-                        subjectNamesTraversed.add(gName);
+                    for (GeneralName gName : gNames.names()) {
+                        subjectNamesTraversed.add(gName.getName());
                     }
                 }
-            } catch (Exception e) {
+            } catch (IOException e) {
                 if (debug != null) {
                     debug.println("ForwardState.updateState() unexpected "
                         + "exception");
@@ -236,6 +226,7 @@
      * because some of them will
      * not have their contents modified by subsequent calls to updateState.
      */
+    @Override
     @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
     public Object clone() {
         try {
--- a/jdk/src/share/classes/sun/security/provider/certpath/IndexedCollectionCertStore.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/IndexedCollectionCertStore.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2002, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2002, 2012, 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
@@ -180,7 +180,7 @@
                 if (cert.equals(oldEntry)) {
                     return;
                 }
-                List<X509Certificate> list = new ArrayList<X509Certificate>(2);
+                List<X509Certificate> list = new ArrayList<>(2);
                 list.add(cert);
                 list.add((X509Certificate)oldEntry);
                 certSubjects.put(subject, list);
@@ -206,7 +206,7 @@
                 if (crl.equals(oldEntry)) {
                     return;
                 }
-                List<X509CRL> list = new ArrayList<X509CRL>(2);
+                List<X509CRL> list = new ArrayList<>(2);
                 list.add(crl);
                 list.add((X509CRL)oldEntry);
                 crlIssuers.put(issuer, list);
@@ -234,19 +234,20 @@
      *         match the specified selector
      * @throws CertStoreException if an exception occurs
      */
+    @Override
     public Collection<? extends Certificate> engineGetCertificates(CertSelector selector)
             throws CertStoreException {
 
         // no selector means match all
         if (selector == null) {
-            Set<Certificate> matches = new HashSet<Certificate>();
+            Set<Certificate> matches = new HashSet<>();
             matchX509Certs(new X509CertSelector(), matches);
             matches.addAll(otherCertificates);
             return matches;
         }
 
         if (selector instanceof X509CertSelector == false) {
-            Set<Certificate> matches = new HashSet<Certificate>();
+            Set<Certificate> matches = new HashSet<>();
             matchX509Certs(selector, matches);
             for (Certificate cert : otherCertificates) {
                 if (selector.match(cert)) {
@@ -285,7 +286,7 @@
                 // See certSubjects javadoc.
                 @SuppressWarnings("unchecked")
                 List<X509Certificate> list = (List<X509Certificate>)entry;
-                Set<X509Certificate> matches = new HashSet<X509Certificate>(16);
+                Set<X509Certificate> matches = new HashSet<>(16);
                 for (X509Certificate cert : list) {
                     if (x509Selector.match(cert)) {
                         matches.add(cert);
@@ -295,7 +296,7 @@
             }
         }
         // cannot use index, iterate all
-        Set<Certificate> matches = new HashSet<Certificate>(16);
+        Set<Certificate> matches = new HashSet<>(16);
         matchX509Certs(x509Selector, matches);
         return matches;
     }
@@ -338,18 +339,19 @@
      *         match the specified selector
      * @throws CertStoreException if an exception occurs
      */
+    @Override
     public Collection<CRL> engineGetCRLs(CRLSelector selector)
             throws CertStoreException {
 
         if (selector == null) {
-            Set<CRL> matches = new HashSet<CRL>();
+            Set<CRL> matches = new HashSet<>();
             matchX509CRLs(new X509CRLSelector(), matches);
             matches.addAll(otherCRLs);
             return matches;
         }
 
         if (selector instanceof X509CRLSelector == false) {
-            Set<CRL> matches = new HashSet<CRL>();
+            Set<CRL> matches = new HashSet<>();
             matchX509CRLs(selector, matches);
             for (CRL crl : otherCRLs) {
                 if (selector.match(crl)) {
@@ -366,7 +368,7 @@
         // see if the issuer is specified
         Collection<X500Principal> issuers = x509Selector.getIssuers();
         if (issuers != null) {
-            HashSet<CRL> matches = new HashSet<CRL>(16);
+            HashSet<CRL> matches = new HashSet<>(16);
             for (X500Principal issuer : issuers) {
                 Object entry = crlIssuers.get(issuer);
                 if (entry == null) {
@@ -390,7 +392,7 @@
             return matches;
         }
         // cannot use index, iterate all
-        Set<CRL> matches = new HashSet<CRL>(16);
+        Set<CRL> matches = new HashSet<>(16);
         matchX509CRLs(x509Selector, matches);
         return matches;
     }
--- a/jdk/src/share/classes/sun/security/provider/certpath/KeyChecker.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/KeyChecker.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2008, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -30,7 +30,7 @@
 import java.security.cert.PKIXReason;
 
 import sun.security.util.Debug;
-import sun.security.x509.PKIXExtensions;
+import static sun.security.x509.PKIXExtensions.*;
 
 /**
  * KeyChecker is a <code>PKIXCertPathChecker</code> that checks that the
@@ -45,33 +45,29 @@
 class KeyChecker extends PKIXCertPathChecker {
 
     private static final Debug debug = Debug.getInstance("certpath");
-    // the index of keyCertSign in the boolean KeyUsage array
-    private static final int keyCertSign = 5;
     private final int certPathLen;
-    private CertSelector targetConstraints;
+    private final CertSelector targetConstraints;
     private int remainingCerts;
 
     private Set<String> supportedExts;
 
     /**
-     * Default Constructor
+     * Creates a KeyChecker.
      *
      * @param certPathLen allowable cert path length
      * @param targetCertSel a CertSelector object specifying the constraints
      * on the target certificate
      */
-    KeyChecker(int certPathLen, CertSelector targetCertSel)
-        throws CertPathValidatorException
-    {
+    KeyChecker(int certPathLen, CertSelector targetCertSel) {
         this.certPathLen = certPathLen;
         this.targetConstraints = targetCertSel;
-        init(false);
     }
 
     /**
      * Initializes the internal state of the checker from parameters
      * specified in the constructor
      */
+    @Override
     public void init(boolean forward) throws CertPathValidatorException {
         if (!forward) {
             remainingCerts = certPathLen;
@@ -81,16 +77,18 @@
         }
     }
 
-    public final boolean isForwardCheckingSupported() {
+    @Override
+    public boolean isForwardCheckingSupported() {
         return false;
     }
 
+    @Override
     public Set<String> getSupportedExtensions() {
         if (supportedExts == null) {
-            supportedExts = new HashSet<String>();
-            supportedExts.add(PKIXExtensions.KeyUsage_Id.toString());
-            supportedExts.add(PKIXExtensions.ExtendedKeyUsage_Id.toString());
-            supportedExts.add(PKIXExtensions.SubjectAlternativeName_Id.toString());
+            supportedExts = new HashSet<String>(3);
+            supportedExts.add(KeyUsage_Id.toString());
+            supportedExts.add(ExtendedKeyUsage_Id.toString());
+            supportedExts.add(SubjectAlternativeName_Id.toString());
             supportedExts = Collections.unmodifiableSet(supportedExts);
         }
         return supportedExts;
@@ -102,20 +100,20 @@
      *
      * @param cert the Certificate
      * @param unresolvedCritExts the unresolved critical extensions
-     * @exception CertPathValidatorException Exception thrown if certificate
-     * does not verify
+     * @throws CertPathValidatorException if certificate does not verify
      */
+    @Override
     public void check(Certificate cert, Collection<String> unresCritExts)
         throws CertPathValidatorException
     {
-        X509Certificate currCert = (X509Certificate) cert;
+        X509Certificate currCert = (X509Certificate)cert;
 
         remainingCerts--;
 
         // if final certificate, check that target constraints are satisfied
         if (remainingCerts == 0) {
-            if ((targetConstraints != null) &&
-                (targetConstraints.match(currCert) == false)) {
+            if (targetConstraints != null &&
+                targetConstraints.match(currCert) == false) {
                 throw new CertPathValidatorException("target certificate " +
                     "constraints check failed");
             }
@@ -126,25 +124,26 @@
 
         // remove the extensions that we have checked
         if (unresCritExts != null && !unresCritExts.isEmpty()) {
-            unresCritExts.remove(PKIXExtensions.KeyUsage_Id.toString());
-            unresCritExts.remove(PKIXExtensions.ExtendedKeyUsage_Id.toString());
-            unresCritExts.remove(
-                PKIXExtensions.SubjectAlternativeName_Id.toString());
+            unresCritExts.remove(KeyUsage_Id.toString());
+            unresCritExts.remove(ExtendedKeyUsage_Id.toString());
+            unresCritExts.remove(SubjectAlternativeName_Id.toString());
         }
     }
 
+    // the index of keyCertSign in the boolean KeyUsage array
+    private static final int KEY_CERT_SIGN = 5;
     /**
-     * Static method to verify that the key usage and extended key usage
-     * extension in a CA cert. The key usage extension, if present, must
-     * assert the keyCertSign bit. The extended key usage extension, if
-     * present, must include anyExtendedKeyUsage.
+     * Verifies the key usage extension in a CA cert.
+     * The key usage extension, if present, must assert the keyCertSign bit.
+     * The extended key usage extension is not checked (see CR 4776794 for
+     * more information).
      */
     static void verifyCAKeyUsage(X509Certificate cert)
             throws CertPathValidatorException {
         String msg = "CA key usage";
         if (debug != null) {
             debug.println("KeyChecker.verifyCAKeyUsage() ---checking " + msg
-                + "...");
+                          + "...");
         }
 
         boolean[] keyUsageBits = cert.getKeyUsage();
@@ -156,7 +155,7 @@
         }
 
         // throw an exception if the keyCertSign bit is not set
-        if (!keyUsageBits[keyCertSign]) {
+        if (!keyUsageBits[KEY_CERT_SIGN]) {
             throw new CertPathValidatorException
                 (msg + " check failed: keyCertSign bit is not set", null,
                  null, -1, PKIXReason.INVALID_KEY_USAGE);
@@ -164,7 +163,7 @@
 
         if (debug != null) {
             debug.println("KeyChecker.verifyCAKeyUsage() " + msg
-                + " verified.");
+                          + " verified.");
         }
     }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSP.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2009, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2009, 2012, 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
@@ -43,6 +43,7 @@
 
 import static sun.security.provider.certpath.OCSPResponse.*;
 import sun.security.util.Debug;
+import sun.security.util.ObjectIdentifier;
 import sun.security.x509.AccessDescription;
 import sun.security.x509.AuthorityInfoAccessExtension;
 import sun.security.x509.GeneralName;
@@ -62,6 +63,9 @@
  */
 public final class OCSP {
 
+    static final ObjectIdentifier NONCE_EXTENSION_OID =
+        ObjectIdentifier.newInternal(new int[]{ 1, 3, 6, 1, 5, 5, 7, 48, 1, 2});
+
     private static final Debug debug = Debug.getInstance("certpath");
 
     private static final int CONNECT_TIMEOUT = 15000; // 15 seconds
@@ -83,7 +87,7 @@
      *    encoding the OCSP Request or validating the OCSP Response
      */
     public static RevocationStatus check(X509Certificate cert,
-        X509Certificate issuerCert)
+                                         X509Certificate issuerCert)
         throws IOException, CertPathValidatorException {
         CertId certId = null;
         URI responderURI = null;
@@ -95,16 +99,13 @@
                     ("No OCSP Responder URI in certificate");
             }
             certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
-        } catch (CertificateException ce) {
+        } catch (CertificateException | IOException e) {
             throw new CertPathValidatorException
-                ("Exception while encoding OCSPRequest", ce);
-        } catch (IOException ioe) {
-            throw new CertPathValidatorException
-                ("Exception while encoding OCSPRequest", ioe);
+                ("Exception while encoding OCSPRequest", e);
         }
         OCSPResponse ocspResponse = check(Collections.singletonList(certId),
-            responderURI, issuerCert, null);
-        return (RevocationStatus) ocspResponse.getSingleResponse(certId);
+            responderURI, issuerCert, null, Collections.<Extension>emptyList());
+        return (RevocationStatus)ocspResponse.getSingleResponse(certId);
     }
 
     /**
@@ -123,22 +124,34 @@
      *    encoding the OCSP Request or validating the OCSP Response
      */
     public static RevocationStatus check(X509Certificate cert,
-        X509Certificate issuerCert, URI responderURI, X509Certificate
-        responderCert, Date date)
-        throws IOException, CertPathValidatorException {
+                                         X509Certificate issuerCert,
+                                         URI responderURI,
+                                         X509Certificate responderCert,
+                                         Date date)
+        throws IOException, CertPathValidatorException
+    {
+        return check(cert, issuerCert, responderURI, responderCert, date,
+                     Collections.<Extension>emptyList());
+    }
+
+    // Called by com.sun.deploy.security.TrustDecider
+    public static RevocationStatus check(X509Certificate cert,
+                                         X509Certificate issuerCert,
+                                         URI responderURI,
+                                         X509Certificate responderCert,
+                                         Date date, List<Extension> extensions)
+        throws IOException, CertPathValidatorException
+    {
         CertId certId = null;
         try {
             X509CertImpl certImpl = X509CertImpl.toImpl(cert);
             certId = new CertId(issuerCert, certImpl.getSerialNumberObject());
-        } catch (CertificateException ce) {
+        } catch (CertificateException | IOException e) {
             throw new CertPathValidatorException
-                ("Exception while encoding OCSPRequest", ce);
-        } catch (IOException ioe) {
-            throw new CertPathValidatorException
-                ("Exception while encoding OCSPRequest", ioe);
+                ("Exception while encoding OCSPRequest", e);
         }
         OCSPResponse ocspResponse = check(Collections.singletonList(certId),
-            responderURI, responderCert, date);
+            responderURI, responderCert, date, extensions);
         return (RevocationStatus) ocspResponse.getSingleResponse(certId);
     }
 
@@ -157,12 +170,14 @@
      *    encoding the OCSP Request or validating the OCSP Response
      */
     static OCSPResponse check(List<CertId> certIds, URI responderURI,
-        X509Certificate responderCert, Date date)
-        throws IOException, CertPathValidatorException {
-
+                              X509Certificate responderCert, Date date,
+                              List<Extension> extensions)
+        throws IOException, CertPathValidatorException
+    {
         byte[] bytes = null;
+        OCSPRequest request = null;
         try {
-            OCSPRequest request = new OCSPRequest(certIds);
+            request = new OCSPRequest(certIds, extensions);
             bytes = request.encodeBytes();
         } catch (IOException ioe) {
             throw new CertPathValidatorException
@@ -214,6 +229,8 @@
                 }
             }
             response = Arrays.copyOf(response, total);
+        } catch (IOException ioe) {
+            throw new NetworkFailureException(ioe);
         } finally {
             if (in != null) {
                 try {
@@ -233,33 +250,15 @@
 
         OCSPResponse ocspResponse = null;
         try {
-            ocspResponse = new OCSPResponse(response, date, responderCert);
+            ocspResponse = new OCSPResponse(response);
         } catch (IOException ioe) {
             // response decoding exception
             throw new CertPathValidatorException(ioe);
         }
-        if (ocspResponse.getResponseStatus() != ResponseStatus.SUCCESSFUL) {
-            throw new CertPathValidatorException
-                ("OCSP response error: " + ocspResponse.getResponseStatus());
-        }
 
-        // Check that the response includes a response for all of the
-        // certs that were supplied in the request
-        for (CertId certId : certIds) {
-            SingleResponse sr = ocspResponse.getSingleResponse(certId);
-            if (sr == null) {
-                if (debug != null) {
-                    debug.println("No response found for CertId: " + certId);
-                }
-                throw new CertPathValidatorException(
-                    "OCSP response does not include a response for a " +
-                    "certificate supplied in the OCSP request");
-            }
-            if (debug != null) {
-                debug.println("Status of certificate (with serial number " +
-                    certId.getSerialNumber() + ") is: " + sr.getCertStatus());
-            }
-        }
+        // verify the response
+        ocspResponse.verify(certIds, responderCert, date, request.getNonce());
+
         return ocspResponse;
     }
 
@@ -271,6 +270,7 @@
      * @param cert the certificate
      * @return the URI of the OCSP Responder, or null if not specified
      */
+    // Called by com.sun.deploy.security.TrustDecider
     public static URI getResponderURI(X509Certificate cert) {
         try {
             return getResponderURI(X509CertImpl.toImpl(cert));
@@ -330,4 +330,12 @@
          */
         Map<String, Extension> getSingleExtensions();
     }
+
+    static class NetworkFailureException extends CertPathValidatorException {
+        private static final long serialVersionUID = 0l;
+
+        private NetworkFailureException(IOException ioe) {
+            super(ioe);
+        }
+    }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPChecker.java	Mon Jan 23 04:44:16 2012 -0800
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,446 +0,0 @@
-/*
- * Copyright (c) 2003, 2011, 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.certpath;
-
-import java.math.BigInteger;
-import java.util.*;
-import java.security.AccessController;
-import java.security.PrivilegedAction;
-import java.security.Security;
-import java.security.cert.*;
-import java.security.cert.CertPathValidatorException.BasicReason;
-import java.net.URI;
-import java.net.URISyntaxException;
-import javax.security.auth.x500.X500Principal;
-
-import static sun.security.provider.certpath.OCSP.*;
-import sun.security.util.Debug;
-import sun.security.x509.*;
-
-/**
- * OCSPChecker is a <code>PKIXCertPathChecker</code> that uses the
- * Online Certificate Status Protocol (OCSP) as specified in RFC 2560
- * <a href="http://www.ietf.org/rfc/rfc2560.txt">
- * http://www.ietf.org/rfc/rfc2560.txt</a>.
- *
- * @author      Ram Marti
- */
-class OCSPChecker extends PKIXCertPathChecker {
-
-    static final String OCSP_ENABLE_PROP = "ocsp.enable";
-    static final String OCSP_URL_PROP = "ocsp.responderURL";
-    static final String OCSP_CERT_SUBJECT_PROP =
-        "ocsp.responderCertSubjectName";
-    static final String OCSP_CERT_ISSUER_PROP = "ocsp.responderCertIssuerName";
-    static final String OCSP_CERT_NUMBER_PROP =
-        "ocsp.responderCertSerialNumber";
-
-    private static final String HEX_DIGITS = "0123456789ABCDEFabcdef";
-    private static final Debug DEBUG = Debug.getInstance("certpath");
-    private static final boolean dump = false;
-
-    private int remainingCerts;
-
-    private X509Certificate[] certs;
-
-    private CertPath cp;
-
-    private PKIXParameters pkixParams;
-
-    private boolean onlyEECert = false;
-
-    /**
-     * Default Constructor
-     *
-     * @param certPath the X509 certification path
-     * @param pkixParams the input PKIX parameter set
-     * @throws CertPathValidatorException if OCSPChecker can not be created
-     */
-    OCSPChecker(CertPath certPath, PKIXParameters pkixParams)
-        throws CertPathValidatorException {
-        this(certPath, pkixParams, false);
-    }
-
-    OCSPChecker(CertPath certPath, PKIXParameters pkixParams, boolean onlyEECert)
-        throws CertPathValidatorException {
-
-        this.cp = certPath;
-        this.pkixParams = pkixParams;
-        this.onlyEECert = onlyEECert;
-        List<? extends Certificate> tmp = cp.getCertificates();
-        certs = tmp.toArray(new X509Certificate[tmp.size()]);
-        init(false);
-    }
-
-    /**
-     * Initializes the internal state of the checker from parameters
-     * specified in the constructor
-     */
-    @Override
-    public void init(boolean forward) throws CertPathValidatorException {
-        if (!forward) {
-            remainingCerts = certs.length + 1;
-        } else {
-            throw new CertPathValidatorException(
-                "Forward checking not supported");
-        }
-    }
-
-    @Override public boolean isForwardCheckingSupported() {
-        return false;
-    }
-
-    @Override public Set<String> getSupportedExtensions() {
-        return Collections.<String>emptySet();
-    }
-
-    /**
-     * Sends an OCSPRequest for the certificate to the OCSP Server and
-     * processes the response back from the OCSP Server.
-     *
-     * @param cert the Certificate
-     * @param unresolvedCritExts the unresolved critical extensions
-     * @exception CertPathValidatorException Exception is thrown if the
-     *            certificate has been revoked.
-     */
-    @Override
-    public void check(Certificate cert, Collection<String> unresolvedCritExts)
-        throws CertPathValidatorException {
-
-        // Decrement the certificate counter
-        remainingCerts--;
-
-        X509CertImpl currCertImpl = null;
-        try {
-            currCertImpl = X509CertImpl.toImpl((X509Certificate)cert);
-        } catch (CertificateException ce) {
-            throw new CertPathValidatorException(ce);
-        }
-
-        if (onlyEECert && currCertImpl.getBasicConstraints() != -1) {
-            if (DEBUG != null) {
-                DEBUG.println("Skipping revocation check, not end entity cert");
-            }
-            return;
-        }
-
-        /*
-         * OCSP security property values, in the following order:
-         *   1. ocsp.responderURL
-         *   2. ocsp.responderCertSubjectName
-         *   3. ocsp.responderCertIssuerName
-         *   4. ocsp.responderCertSerialNumber
-         */
-        // should cache these properties to avoid calling every time?
-        String[] properties = getOCSPProperties();
-
-        // Check whether OCSP is feasible before seeking cert information
-        URI uri = getOCSPServerURI(currCertImpl, properties[0]);
-
-        // When responder's subject name is set then the issuer/serial
-        // properties are ignored
-        X500Principal responderSubjectName = null;
-        X500Principal responderIssuerName = null;
-        BigInteger responderSerialNumber = null;
-        if (properties[1] != null) {
-            responderSubjectName = new X500Principal(properties[1]);
-        } else if (properties[2] != null && properties[3] != null) {
-            responderIssuerName = new X500Principal(properties[2]);
-            // remove colon or space separators
-            String value = stripOutSeparators(properties[3]);
-            responderSerialNumber = new BigInteger(value, 16);
-        } else if (properties[2] != null || properties[3] != null) {
-            throw new CertPathValidatorException(
-                "Must specify both ocsp.responderCertIssuerName and " +
-                "ocsp.responderCertSerialNumber properties");
-        }
-
-        // If the OCSP responder cert properties are set then the
-        // identified cert must be located in the trust anchors or
-        // in the cert stores.
-        boolean seekResponderCert = false;
-        if (responderSubjectName != null || responderIssuerName != null) {
-            seekResponderCert = true;
-        }
-
-        // Set the issuer certificate to the next cert in the chain
-        // (unless we're processing the final cert).
-        X509Certificate issuerCert = null;
-        boolean seekIssuerCert = true;
-        X509Certificate responderCert = null;
-        if (remainingCerts < certs.length) {
-            issuerCert = certs[remainingCerts];
-            seekIssuerCert = false; // done
-
-            // By default, the OCSP responder's cert is the same as the
-            // issuer of the cert being validated.
-            if (!seekResponderCert) {
-                responderCert = issuerCert;
-                if (DEBUG != null) {
-                    DEBUG.println("Responder's certificate is the same " +
-                        "as the issuer of the certificate being validated");
-                }
-            }
-        }
-
-        // Check anchor certs for:
-        //    - the issuer cert (of the cert being validated)
-        //    - the OCSP responder's cert
-        if (seekIssuerCert || seekResponderCert) {
-
-            if (DEBUG != null && seekResponderCert) {
-                DEBUG.println("Searching trust anchors for responder's " +
-                    "certificate");
-            }
-
-            // Extract the anchor certs
-            Iterator<TrustAnchor> anchors
-                = pkixParams.getTrustAnchors().iterator();
-            if (!anchors.hasNext()) {
-                throw new CertPathValidatorException(
-                    "Must specify at least one trust anchor");
-            }
-
-            X500Principal certIssuerName =
-                currCertImpl.getIssuerX500Principal();
-            while (anchors.hasNext() && (seekIssuerCert || seekResponderCert)) {
-
-                TrustAnchor anchor = anchors.next();
-                X509Certificate anchorCert = anchor.getTrustedCert();
-                X500Principal anchorSubjectName =
-                    anchorCert.getSubjectX500Principal();
-
-                if (dump) {
-                    System.out.println("Issuer DN is " + certIssuerName);
-                    System.out.println("Subject DN is " + anchorSubjectName);
-                }
-
-                // Check if anchor cert is the issuer cert
-                if (seekIssuerCert &&
-                    certIssuerName.equals(anchorSubjectName)) {
-
-                    issuerCert = anchorCert;
-                    seekIssuerCert = false; // done
-
-                    // By default, the OCSP responder's cert is the same as
-                    // the issuer of the cert being validated.
-                    if (!seekResponderCert && responderCert == null) {
-                        responderCert = anchorCert;
-                        if (DEBUG != null) {
-                            DEBUG.println("Responder's certificate is the" +
-                                " same as the issuer of the certificate " +
-                                "being validated");
-                        }
-                    }
-                }
-
-                // Check if anchor cert is the responder cert
-                if (seekResponderCert) {
-                    // Satisfy the responder subject name property only, or
-                    // satisfy the responder issuer name and serial number
-                    // properties only
-                    if ((responderSubjectName != null &&
-                         responderSubjectName.equals(anchorSubjectName)) ||
-                        (responderIssuerName != null &&
-                         responderSerialNumber != null &&
-                         responderIssuerName.equals(
-                         anchorCert.getIssuerX500Principal()) &&
-                         responderSerialNumber.equals(
-                         anchorCert.getSerialNumber()))) {
-
-                        responderCert = anchorCert;
-                        seekResponderCert = false; // done
-                    }
-                }
-            }
-            if (issuerCert == null) {
-                throw new CertPathValidatorException(
-                    "No trusted certificate for " + currCertImpl.getIssuerDN());
-            }
-
-            // Check cert stores if responder cert has not yet been found
-            if (seekResponderCert) {
-                if (DEBUG != null) {
-                    DEBUG.println("Searching cert stores for responder's " +
-                        "certificate");
-                }
-                X509CertSelector filter = null;
-                if (responderSubjectName != null) {
-                    filter = new X509CertSelector();
-                    filter.setSubject(responderSubjectName);
-                } else if (responderIssuerName != null &&
-                    responderSerialNumber != null) {
-                    filter = new X509CertSelector();
-                    filter.setIssuer(responderIssuerName);
-                    filter.setSerialNumber(responderSerialNumber);
-                }
-                if (filter != null) {
-                    List<CertStore> certStores = pkixParams.getCertStores();
-                    for (CertStore certStore : certStores) {
-                        Iterator<? extends Certificate> i = null;
-                        try {
-                            i = certStore.getCertificates(filter).iterator();
-                        } catch (CertStoreException cse) {
-                            // ignore and try next certStore
-                            if (DEBUG != null) {
-                                DEBUG.println("CertStore exception:" + cse);
-                            }
-                            continue;
-                        }
-                        if (i.hasNext()) {
-                            responderCert = (X509Certificate) i.next();
-                            seekResponderCert = false; // done
-                            break;
-                        }
-                    }
-                }
-            }
-        }
-
-        // Could not find the certificate identified in the OCSP properties
-        if (seekResponderCert) {
-            throw new CertPathValidatorException(
-                "Cannot find the responder's certificate " +
-                "(set using the OCSP security properties).");
-        }
-
-        // The algorithm constraints of the OCSP trusted responder certificate
-        // does not need to be checked in this code. The constraints will be
-        // checked when the responder's certificate is validated.
-
-        CertId certId = null;
-        OCSPResponse response = null;
-        try {
-            certId = new CertId
-                (issuerCert, currCertImpl.getSerialNumberObject());
-            response = OCSP.check(Collections.singletonList(certId), uri,
-                responderCert, pkixParams.getDate());
-        } catch (Exception e) {
-            if (e instanceof CertPathValidatorException) {
-                throw (CertPathValidatorException) e;
-            } else {
-                // Wrap exceptions in CertPathValidatorException so that
-                // we can fallback to CRLs, if enabled.
-                throw new CertPathValidatorException(e);
-            }
-        }
-
-        RevocationStatus rs = (RevocationStatus) response.getSingleResponse(certId);
-        RevocationStatus.CertStatus certStatus = rs.getCertStatus();
-        if (certStatus == RevocationStatus.CertStatus.REVOKED) {
-            Throwable t = new CertificateRevokedException(
-                rs.getRevocationTime(), rs.getRevocationReason(),
-                responderCert.getSubjectX500Principal(),
-                rs.getSingleExtensions());
-            throw new CertPathValidatorException(t.getMessage(), t,
-                null, -1, BasicReason.REVOKED);
-        } else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) {
-            throw new CertPathValidatorException(
-                "Certificate's revocation status is unknown", null, cp,
-                remainingCerts, BasicReason.UNDETERMINED_REVOCATION_STATUS);
-        }
-    }
-
-    /*
-     * The OCSP security property values are in the following order:
-     *   1. ocsp.responderURL
-     *   2. ocsp.responderCertSubjectName
-     *   3. ocsp.responderCertIssuerName
-     *   4. ocsp.responderCertSerialNumber
-     */
-    private static URI getOCSPServerURI(X509CertImpl currCertImpl,
-        String responderURL) throws CertPathValidatorException {
-
-        if (responderURL != null) {
-            try {
-                return new URI(responderURL);
-            } catch (URISyntaxException e) {
-                throw new CertPathValidatorException(e);
-            }
-        }
-
-        // Examine the certificate's AuthorityInfoAccess extension
-        AuthorityInfoAccessExtension aia =
-            currCertImpl.getAuthorityInfoAccessExtension();
-        if (aia == null) {
-            throw new CertPathValidatorException(
-                "Must specify the location of an OCSP Responder");
-        }
-
-        List<AccessDescription> descriptions = aia.getAccessDescriptions();
-        for (AccessDescription description : descriptions) {
-            if (description.getAccessMethod().equals((Object)
-                AccessDescription.Ad_OCSP_Id)) {
-
-                GeneralName generalName = description.getAccessLocation();
-                if (generalName.getType() == GeneralNameInterface.NAME_URI) {
-                    URIName uri = (URIName) generalName.getName();
-                    return uri.getURI();
-                }
-            }
-        }
-
-        throw new CertPathValidatorException(
-            "Cannot find the location of the OCSP Responder");
-    }
-
-    /*
-     * Retrieves the values of the OCSP security properties.
-     */
-    private static String[] getOCSPProperties() {
-        final String[] properties = new String[4];
-
-        AccessController.doPrivileged(
-            new PrivilegedAction<Void>() {
-                public Void run() {
-                    properties[0] = Security.getProperty(OCSP_URL_PROP);
-                    properties[1] =
-                        Security.getProperty(OCSP_CERT_SUBJECT_PROP);
-                    properties[2] =
-                        Security.getProperty(OCSP_CERT_ISSUER_PROP);
-                    properties[3] =
-                        Security.getProperty(OCSP_CERT_NUMBER_PROP);
-                    return null;
-                }
-            });
-
-        return properties;
-    }
-
-    /*
-     * Removes any non-hexadecimal characters from a string.
-     */
-    private static String stripOutSeparators(String value) {
-        char[] chars = value.toCharArray();
-        StringBuilder hexNumber = new StringBuilder();
-        for (int i = 0; i < chars.length; i++) {
-            if (HEX_DIGITS.indexOf(chars[i]) != -1) {
-                hexNumber.append(chars[i]);
-            }
-        }
-        return hexNumber.toString();
-    }
-}
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPRequest.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -26,8 +26,10 @@
 package sun.security.provider.certpath;
 
 import java.io.IOException;
+import java.security.cert.Extension;
 import java.util.Collections;
 import java.util.List;
+
 import sun.misc.HexDumpEncoder;
 import sun.security.util.*;
 
@@ -74,22 +76,29 @@
 
 class OCSPRequest {
 
-    private static final Debug debug = Debug.getInstance("certpath");
     private static final boolean dump = false;
 
     // List of request CertIds
     private final List<CertId> certIds;
+    private final List<Extension> extensions;
+    private byte[] nonce;
 
     /*
      * Constructs an OCSPRequest. This constructor is used
      * to construct an unsigned OCSP Request for a single user cert.
      */
     OCSPRequest(CertId certId) {
-        this.certIds = Collections.singletonList(certId);
+        this(Collections.singletonList(certId));
     }
 
     OCSPRequest(List<CertId> certIds) {
         this.certIds = certIds;
+        this.extensions = Collections.<Extension>emptyList();
+    }
+
+    OCSPRequest(List<CertId> certIds, List<Extension> extensions) {
+        this.certIds = certIds;
+        this.extensions = extensions;
     }
 
     byte[] encodeBytes() throws IOException {
@@ -104,7 +113,20 @@
         }
 
         tmp.write(DerValue.tag_Sequence, requestsOut);
-        // No extensions supported
+        if (!extensions.isEmpty()) {
+            DerOutputStream extOut = new DerOutputStream();
+            for (Extension ext : extensions) {
+                ext.encode(extOut);
+                if (ext.getId().equals(OCSP.NONCE_EXTENSION_OID.toString())) {
+                    nonce = ext.getValue();
+                }
+            }
+            DerOutputStream extsOut = new DerOutputStream();
+            extsOut.write(DerValue.tag_Sequence, extOut);
+            tmp.write(DerValue.createTag(DerValue.TAG_CONTEXT,
+                                         true, (byte)2), extsOut);
+        }
+
         DerOutputStream tbsRequest = new DerOutputStream();
         tbsRequest.write(DerValue.tag_Sequence, tmp);
 
@@ -126,4 +148,8 @@
     List<CertId> getCertIds() {
         return certIds;
     }
+
+    byte[] getNonce() {
+        return nonce;
+    }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/OCSPResponse.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2003, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2003, 2012, 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
@@ -33,11 +33,15 @@
 import java.security.cert.CRLReason;
 import java.security.cert.TrustAnchor;
 import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.Arrays;
 import java.util.Collections;
 import java.util.Date;
 import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
+import javax.security.auth.x500.X500Principal;
+
 import sun.misc.HexDumpEncoder;
 import sun.security.x509.*;
 import sun.security.util.*;
@@ -125,13 +129,10 @@
     };
     private static ResponseStatus[] rsvalues = ResponseStatus.values();
 
-    private static final Debug DEBUG = Debug.getInstance("certpath");
+    private static final Debug debug = Debug.getInstance("certpath");
     private static final boolean dump = false;
     private static final ObjectIdentifier OCSP_BASIC_RESPONSE_OID =
         ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 1});
-    private static final ObjectIdentifier OCSP_NONCE_EXTENSION_OID =
-        ObjectIdentifier.newInternal(new int[] { 1, 3, 6, 1, 5, 5, 7, 48, 1, 2});
-
     private static final int CERT_STATUS_GOOD = 0;
     private static final int CERT_STATUS_REVOKED = 1;
     private static final int CERT_STATUS_UNKNOWN = 2;
@@ -143,9 +144,6 @@
     // Object identifier for the OCSPSigning key purpose
     private static final String KP_OCSP_SIGNING_OID = "1.3.6.1.5.5.7.3.9";
 
-    private final ResponseStatus responseStatus;
-    private final Map<CertId, SingleResponse> singleResponseMap;
-
     // Maximum clock skew in milliseconds (15 minutes) allowed when checking
     // validity of OCSP responses
     private static final long MAX_CLOCK_SKEW = 900000;
@@ -153,14 +151,20 @@
     // an array of all of the CRLReasons (used in SingleResponse)
     private static CRLReason[] values = CRLReason.values();
 
+    private final ResponseStatus responseStatus;
+    private final Map<CertId, SingleResponse> singleResponseMap;
+    private final List<X509CertImpl> certs;
+    private final AlgorithmId sigAlgId;
+    private final byte[] signature;
+    private final byte[] tbsResponseData;
+    private final X500Principal responderName;
+    private final byte[] responderKey;
+    private final byte[] responseNonce;
+
     /*
      * Create an OCSP response from its ASN.1 DER encoding.
      */
-    OCSPResponse(byte[] bytes, Date dateCheckedAgainst,
-        X509Certificate responderCert)
-        throws IOException, CertPathValidatorException {
-
-        // OCSPResponse
+    OCSPResponse(byte[] bytes) throws IOException {
         if (dump) {
             HexDumpEncoder hexEnc = new HexDumpEncoder();
             System.out.println("OCSPResponse bytes are...");
@@ -181,12 +185,19 @@
             // unspecified responseStatus
             throw new IOException("Unknown OCSPResponse status: " + status);
         }
-        if (DEBUG != null) {
-            DEBUG.println("OCSP response status: " + responseStatus);
+        if (debug != null) {
+            debug.println("OCSP response status: " + responseStatus);
         }
         if (responseStatus != ResponseStatus.SUCCESSFUL) {
             // no need to continue, responseBytes are not set.
             singleResponseMap = Collections.emptyMap();
+            certs = Collections.<X509CertImpl>emptyList();
+            sigAlgId = null;
+            signature = null;
+            tbsResponseData = null;
+            responderName = null;
+            responderKey = null;
+            responseNonce = null;
             return;
         }
 
@@ -206,15 +217,15 @@
         derIn = tmp.data;
         ObjectIdentifier responseType = derIn.getOID();
         if (responseType.equals((Object)OCSP_BASIC_RESPONSE_OID)) {
-            if (DEBUG != null) {
-                DEBUG.println("OCSP response type: basic");
+            if (debug != null) {
+                debug.println("OCSP response type: basic");
             }
         } else {
-            if (DEBUG != null) {
-                DEBUG.println("OCSP response type: " + responseType);
+            if (debug != null) {
+                debug.println("OCSP response type: " + responseType);
             }
             throw new IOException("Unsupported OCSP response type: " +
-                responseType);
+                                  responseType);
         }
 
         // BasicOCSPResponse
@@ -229,7 +240,7 @@
         DerValue responseData = seqTmp[0];
 
         // Need the DER encoded ResponseData to verify the signature later
-        byte[] responseDataDer = seqTmp[0].toByteArray();
+        tbsResponseData = seqTmp[0].toByteArray();
 
         // tbsResponseData
         if (responseData.tag != DerValue.tag_Sequence) {
@@ -257,12 +268,15 @@
         // responderID
         short tag = (byte)(seq.tag & 0x1f);
         if (tag == NAME_TAG) {
-            if (DEBUG != null) {
-                X500Name responderName = new X500Name(seq.getData());
-                DEBUG.println("OCSP Responder name: " + responderName);
+            responderName =
+                new X500Principal(new ByteArrayInputStream(seq.toByteArray()));
+            if (debug != null) {
+                debug.println("OCSP Responder name: " + responderName);
             }
+            responderKey = null;
         } else if (tag == KEY_TAG) {
-            // Ignore, for now
+            responderKey = seq.getOctetString();
+            responderName = null;
         } else {
             throw new IOException("Bad encoding in responderID element of " +
                 "OCSP response: expected ASN.1 context specific tag 0 or 1");
@@ -270,57 +284,55 @@
 
         // producedAt
         seq = seqDerIn.getDerValue();
-        if (DEBUG != null) {
+        if (debug != null) {
             Date producedAtDate = seq.getGeneralizedTime();
-            DEBUG.println("OCSP response produced at: " + producedAtDate);
+            debug.println("OCSP response produced at: " + producedAtDate);
         }
 
         // responses
         DerValue[] singleResponseDer = seqDerIn.getSequence(1);
-        singleResponseMap
-            = new HashMap<CertId, SingleResponse>(singleResponseDer.length);
-        if (DEBUG != null) {
-            DEBUG.println("OCSP number of SingleResponses: "
-                + singleResponseDer.length);
+        singleResponseMap = new HashMap<>(singleResponseDer.length);
+        if (debug != null) {
+            debug.println("OCSP number of SingleResponses: "
+                          + singleResponseDer.length);
         }
         for (int i = 0; i < singleResponseDer.length; i++) {
-            SingleResponse singleResponse
-                = new SingleResponse(singleResponseDer[i]);
+            SingleResponse singleResponse =
+                new SingleResponse(singleResponseDer[i]);
             singleResponseMap.put(singleResponse.getCertId(), singleResponse);
         }
 
         // responseExtensions
+        byte[] nonce = null;
         if (seqDerIn.available() > 0) {
             seq = seqDerIn.getDerValue();
             if (seq.isContextSpecific((byte)1)) {
                 DerValue[] responseExtDer = seq.data.getSequence(3);
                 for (int i = 0; i < responseExtDer.length; i++) {
-                    Extension responseExtension
-                        = new Extension(responseExtDer[i]);
-                    if (DEBUG != null) {
-                        DEBUG.println("OCSP extension: " + responseExtension);
+                    Extension ext = new Extension(responseExtDer[i]);
+                    if (debug != null) {
+                        debug.println("OCSP extension: " + ext);
                     }
-                    if (responseExtension.getExtensionId().equals((Object)
-                        OCSP_NONCE_EXTENSION_OID)) {
-                        /*
-                        ocspNonce =
-                            responseExtension[i].getExtensionValue();
-                         */
-                    } else if (responseExtension.isCritical())  {
+                    // Only the NONCE extension is recognized
+                    if (ext.getExtensionId().equals((Object)
+                        OCSP.NONCE_EXTENSION_OID))
+                    {
+                        nonce = ext.getExtensionValue();
+                    } else if (ext.isCritical())  {
                         throw new IOException(
                             "Unsupported OCSP critical extension: " +
-                            responseExtension.getExtensionId());
+                            ext.getExtensionId());
                     }
                 }
             }
         }
+        responseNonce = nonce;
 
         // signatureAlgorithmId
-        AlgorithmId sigAlgId = AlgorithmId.parse(seqTmp[1]);
+        sigAlgId = AlgorithmId.parse(seqTmp[1]);
 
         // signature
-        byte[] signature = seqTmp[2].getBitString();
-        X509CertImpl[] x509Certs = null;
+        signature = seqTmp[2].getBitString();
 
         // if seq[3] is available , then it is a sequence of certificates
         if (seqTmp.length > 3) {
@@ -330,30 +342,59 @@
                 throw new IOException("Bad encoding in certs element of " +
                     "OCSP response: expected ASN.1 context specific tag 0.");
             }
-            DerValue[] certs = seqCert.getData().getSequence(3);
-            x509Certs = new X509CertImpl[certs.length];
+            DerValue[] derCerts = seqCert.getData().getSequence(3);
+            certs = new ArrayList<X509CertImpl>(derCerts.length);
             try {
-                for (int i = 0; i < certs.length; i++) {
-                    x509Certs[i] = new X509CertImpl(certs[i].toByteArray());
+                for (int i = 0; i < derCerts.length; i++) {
+                    certs.add(new X509CertImpl(derCerts[i].toByteArray()));
                 }
             } catch (CertificateException ce) {
                 throw new IOException("Bad encoding in X509 Certificate", ce);
             }
+        } else {
+            certs = Collections.<X509CertImpl>emptyList();
         }
+    }
+
+    void verify(List<CertId> certIds, X509Certificate responderCert,
+                Date date, byte[] nonce)
+        throws CertPathValidatorException
+    {
+        if (responseStatus != ResponseStatus.SUCCESSFUL) {
+            throw new CertPathValidatorException
+                ("OCSP response error: " + responseStatus);
+        }
+
+        // Check that the response includes a response for all of the
+        // certs that were supplied in the request
+        for (CertId certId : certIds) {
+            SingleResponse sr = getSingleResponse(certId);
+            if (sr == null) {
+                if (debug != null) {
+                    debug.println("No response found for CertId: " + certId);
+                }
+                throw new CertPathValidatorException(
+                    "OCSP response does not include a response for a " +
+                    "certificate supplied in the OCSP request");
+            }
+            if (debug != null) {
+                debug.println("Status of certificate (with serial number " +
+                    certId.getSerialNumber() + ") is: " + sr.getCertStatus());
+            }
+        }
+
 
         // Check whether the cert returned by the responder is trusted
-        if (x509Certs != null && x509Certs[0] != null) {
-            X509CertImpl cert = x509Certs[0];
-
-            // First check if the cert matches the responder cert which
-            // was set locally.
+        if (!certs.isEmpty()) {
+            X509CertImpl cert = certs.get(0);
+            // First check if the cert matches the expected responder cert
             if (cert.equals(responderCert)) {
                 // cert is trusted, now verify the signed response
 
             // Next check if the cert was issued by the responder cert
             // which was set locally.
             } else if (cert.getIssuerX500Principal().equals(
-                responderCert.getSubjectX500Principal())) {
+                       responderCert.getSubjectX500Principal())) {
 
                 // Check for the OCSPSigning key purpose
                 try {
@@ -380,12 +421,12 @@
 
                 // check the validity
                 try {
-                    if (dateCheckedAgainst == null) {
+                    if (date == null) {
                         cert.checkValidity();
                     } else {
-                        cert.checkValidity(dateCheckedAgainst);
+                        cert.checkValidity(date);
                     }
-                } catch (GeneralSecurityException e) {
+                } catch (CertificateException e) {
                     throw new CertPathValidatorException(
                         "Responder's certificate not within the " +
                         "validity period", e);
@@ -401,8 +442,8 @@
                 Extension noCheck =
                     cert.getExtension(PKIXExtensions.OCSPNoCheck_Id);
                 if (noCheck != null) {
-                    if (DEBUG != null) {
-                        DEBUG.println("Responder's certificate includes " +
+                    if (debug != null) {
+                        debug.println("Responder's certificate includes " +
                             "the extension id-pkix-ocsp-nocheck.");
                     }
                 } else {
@@ -433,15 +474,44 @@
             // "jdk.certpath.disabledAlgorithms".
             AlgorithmChecker.check(responderCert.getPublicKey(), sigAlgId);
 
-            if (!verifyResponse(responseDataDer, responderCert,
-                sigAlgId, signature)) {
+            if (!verifySignature(responderCert)) {
                 throw new CertPathValidatorException(
-                    "Error verifying OCSP Responder's signature");
+                    "Error verifying OCSP Response's signature");
             }
         } else {
             // Need responder's cert in order to verify the signature
             throw new CertPathValidatorException(
-                "Unable to verify OCSP Responder's signature");
+                "Unable to verify OCSP Response's signature");
+        }
+
+        // Check freshness of OCSPResponse
+        if (nonce != null) {
+            if (responseNonce != null && !Arrays.equals(nonce, responseNonce)) {
+                throw new CertPathValidatorException("Nonces don't match");
+            }
+        }
+
+        long now = (date == null) ? System.currentTimeMillis() : date.getTime();
+        Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
+        Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
+        for (SingleResponse sr : singleResponseMap.values()) {
+            if (debug != null) {
+                String until = "";
+                if (sr.nextUpdate != null) {
+                    until = " until " + sr.nextUpdate;
+                }
+                debug.println("Response's validity interval is from " +
+                              sr.thisUpdate + until);
+            }
+
+            // Check that the test date is within the validity interval
+            if ((sr.thisUpdate != null && nowPlusSkew.before(sr.thisUpdate)) ||
+                (sr.nextUpdate != null && nowMinusSkew.after(sr.nextUpdate)))
+            {
+                throw new CertPathValidatorException(
+                                      "Response is unreliable: its validity " +
+                                      "interval is out-of-date");
+            }
         }
     }
 
@@ -456,34 +526,31 @@
      * Verify the signature of the OCSP response.
      * The responder's cert is implicitly trusted.
      */
-    private boolean verifyResponse(byte[] responseData, X509Certificate cert,
-        AlgorithmId sigAlgId, byte[] signBytes)
+    private boolean verifySignature(X509Certificate cert)
         throws CertPathValidatorException {
 
         try {
             Signature respSignature = Signature.getInstance(sigAlgId.getName());
             respSignature.initVerify(cert);
-            respSignature.update(responseData);
+            respSignature.update(tbsResponseData);
 
-            if (respSignature.verify(signBytes)) {
-                if (DEBUG != null) {
-                    DEBUG.println("Verified signature of OCSP Responder");
+            if (respSignature.verify(signature)) {
+                if (debug != null) {
+                    debug.println("Verified signature of OCSP Response");
                 }
                 return true;
 
             } else {
-                if (DEBUG != null) {
-                    DEBUG.println(
-                        "Error verifying signature of OCSP Responder");
+                if (debug != null) {
+                    debug.println(
+                        "Error verifying signature of OCSP Response");
                 }
                 return false;
             }
-        } catch (InvalidKeyException ike) {
-            throw new CertPathValidatorException(ike);
-        } catch (NoSuchAlgorithmException nsae) {
-            throw new CertPathValidatorException(nsae);
-        } catch (SignatureException se) {
-            throw new CertPathValidatorException(se);
+        } catch (InvalidKeyException | NoSuchAlgorithmException |
+                 SignatureException e)
+        {
+            throw new CertPathValidatorException(e);
         }
     }
 
@@ -537,9 +604,9 @@
                     revocationReason = CRLReason.UNSPECIFIED;
                 }
                 // RevokedInfo
-                if (DEBUG != null) {
-                    DEBUG.println("Revocation time: " + revocationTime);
-                    DEBUG.println("Revocation reason: " + revocationReason);
+                if (debug != null) {
+                    debug.println("Revocation time: " + revocationTime);
+                    debug.println("Revocation reason: " + revocationReason);
                 }
             } else {
                 revocationTime = null;
@@ -585,8 +652,8 @@
                             (singleExtDer.length);
                     for (int i = 0; i < singleExtDer.length; i++) {
                         Extension ext = new Extension(singleExtDer[i]);
-                        if (DEBUG != null) {
-                            DEBUG.println("OCSP single extension: " + ext);
+                        if (debug != null) {
+                            debug.println("OCSP single extension: " + ext);
                         }
                         // We don't support any extensions yet. Therefore, if it
                         // is critical we must throw an exception because we
@@ -604,29 +671,6 @@
             } else {
                 singleExtensions = Collections.emptyMap();
             }
-
-            long now = System.currentTimeMillis();
-            Date nowPlusSkew = new Date(now + MAX_CLOCK_SKEW);
-            Date nowMinusSkew = new Date(now - MAX_CLOCK_SKEW);
-            if (DEBUG != null) {
-                String until = "";
-                if (nextUpdate != null) {
-                    until = " until " + nextUpdate;
-                }
-                DEBUG.println("Response's validity interval is from " +
-                    thisUpdate + until);
-            }
-            // Check that the test date is within the validity interval
-            if ((thisUpdate != null && nowPlusSkew.before(thisUpdate)) ||
-                (nextUpdate != null && nowMinusSkew.after(nextUpdate))) {
-
-                if (DEBUG != null) {
-                    DEBUG.println("Response is unreliable: its validity " +
-                        "interval is out-of-date");
-                }
-                throw new IOException("Response is unreliable: its validity " +
-                    "interval is out-of-date");
-            }
         }
 
         /*
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIX.java	Wed May 30 17:19:46 2012 -0400
@@ -0,0 +1,289 @@
+/*
+ * Copyright (c) 2012, 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.certpath;
+
+import java.security.InvalidAlgorithmParameterException;
+import java.security.KeyStore;
+import java.security.cert.*;
+import java.util.*;
+import javax.security.auth.x500.X500Principal;
+
+import sun.security.util.Debug;
+
+/**
+ * Common utility methods and classes used by the PKIX CertPathValidator and
+ * CertPathBuilder implementation.
+ */
+class PKIX {
+
+    private static final Debug debug = Debug.getInstance("certpath");
+
+    private PKIX() { }
+
+    static ValidatorParams checkParams(CertPath cp, CertPathParameters params)
+        throws InvalidAlgorithmParameterException
+    {
+        if (!(params instanceof PKIXParameters)) {
+            throw new InvalidAlgorithmParameterException("inappropriate "
+                + "params, must be an instance of PKIXParameters");
+        }
+        return new ValidatorParams(cp, (PKIXParameters)params);
+    }
+
+    static BuilderParams checkBuilderParams(CertPathParameters params)
+        throws InvalidAlgorithmParameterException
+    {
+        if (!(params instanceof PKIXBuilderParameters)) {
+            throw new InvalidAlgorithmParameterException("inappropriate "
+                + "params, must be an instance of PKIXBuilderParameters");
+        }
+        return new BuilderParams((PKIXBuilderParameters)params);
+    }
+
+    /**
+     * PKIXParameters that are shared by the PKIX CertPathValidator
+     * implementation. Provides additional functionality and avoids
+     * unnecessary cloning.
+     */
+    static class ValidatorParams {
+        private final PKIXParameters params;
+        private CertPath certPath;
+        private List<PKIXCertPathChecker> checkers;
+        private List<CertStore> stores;
+        private boolean gotDate;
+        private Date date;
+        private Set<String> policies;
+        private boolean gotConstraints;
+        private CertSelector constraints;
+        private Set<TrustAnchor> anchors;
+        private List<X509Certificate> certs;
+
+        ValidatorParams(CertPath cp, PKIXParameters params)
+            throws InvalidAlgorithmParameterException
+        {
+            this(params);
+            if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) {
+                throw new InvalidAlgorithmParameterException("inappropriate "
+                    + "CertPath type specified, must be X.509 or X509");
+            }
+            this.certPath = cp;
+        }
+
+        ValidatorParams(PKIXParameters params)
+            throws InvalidAlgorithmParameterException
+        {
+            this.anchors = params.getTrustAnchors();
+            // Make sure that none of the trust anchors include name constraints
+            // (not supported).
+            for (TrustAnchor anchor : this.anchors) {
+                if (anchor.getNameConstraints() != null) {
+                    throw new InvalidAlgorithmParameterException
+                        ("name constraints in trust anchor not supported");
+                }
+            }
+            this.params = params;
+        }
+
+        CertPath certPath() {
+            return certPath;
+        }
+        // called by CertPathBuilder after path has been built
+        void setCertPath(CertPath cp) {
+            this.certPath = cp;
+        }
+        List<X509Certificate> certificates() {
+            if (certs == null) {
+                if (certPath == null) {
+                    certs = Collections.emptyList();
+                } else {
+                    // Reverse the ordering for validation so that the target
+                    // cert is the last certificate
+                    @SuppressWarnings("unchecked")
+                    List<X509Certificate> xc = new ArrayList<>
+                        ((List<X509Certificate>)certPath.getCertificates());
+                    Collections.reverse(xc);
+                    certs = xc;
+                }
+            }
+            return certs;
+        }
+        List<PKIXCertPathChecker> certPathCheckers() {
+            if (checkers == null)
+                checkers = params.getCertPathCheckers();
+            return checkers;
+        }
+        List<CertStore> certStores() {
+            if (stores == null)
+                stores = params.getCertStores();
+            return stores;
+        }
+        Date date() {
+            if (!gotDate) {
+                date = params.getDate();
+                if (date == null)
+                    date = new Date();
+                gotDate = true;
+            }
+            return date;
+        }
+        Set<String> initialPolicies() {
+            if (policies == null)
+                policies = params.getInitialPolicies();
+            return policies;
+        }
+        CertSelector targetCertConstraints() {
+            if (!gotConstraints) {
+                constraints = params.getTargetCertConstraints();
+                gotConstraints = true;
+            }
+            return constraints;
+        }
+        Set<TrustAnchor> trustAnchors() {
+            return anchors;
+        }
+        boolean revocationEnabled() {
+            return params.isRevocationEnabled();
+        }
+        boolean policyMappingInhibited() {
+            return params.isPolicyMappingInhibited();
+        }
+        boolean explicitPolicyRequired() {
+            return params.isExplicitPolicyRequired();
+        }
+        boolean policyQualifiersRejected() {
+            return params.getPolicyQualifiersRejected();
+        }
+        String sigProvider() { return params.getSigProvider(); }
+        boolean anyPolicyInhibited() { return params.isAnyPolicyInhibited(); }
+
+        // in rare cases we need access to the original params, for example
+        // in order to clone CertPathCheckers before building a new chain
+        PKIXParameters getPKIXParameters() {
+            return params;
+        }
+    }
+
+    static class BuilderParams extends ValidatorParams {
+        private PKIXBuilderParameters params;
+        private boolean buildForward = true;
+        private List<CertStore> stores;
+        private X500Principal targetSubject;
+
+        BuilderParams(PKIXBuilderParameters params)
+            throws InvalidAlgorithmParameterException
+        {
+            super(params);
+            checkParams(params);
+        }
+        private void checkParams(PKIXBuilderParameters params)
+            throws InvalidAlgorithmParameterException
+        {
+            CertSelector sel = targetCertConstraints();
+            if (!(sel instanceof X509CertSelector)) {
+                throw new InvalidAlgorithmParameterException("the "
+                    + "targetCertConstraints parameter must be an "
+                    + "X509CertSelector");
+            }
+            if (params instanceof SunCertPathBuilderParameters) {
+                buildForward =
+                    ((SunCertPathBuilderParameters)params).getBuildForward();
+            }
+            this.params = params;
+            this.targetSubject = getTargetSubject(
+                certStores(), (X509CertSelector)targetCertConstraints());
+        }
+        @Override List<CertStore> certStores() {
+            if (stores == null) {
+                // reorder CertStores so that local CertStores are tried first
+                stores = new ArrayList<>(params.getCertStores());
+                Collections.sort(stores, new CertStoreComparator());
+            }
+            return stores;
+        }
+        int maxPathLength() { return params.getMaxPathLength(); }
+        boolean buildForward() { return buildForward; }
+        PKIXBuilderParameters params() { return params; }
+        X500Principal targetSubject() { return targetSubject; }
+
+        /**
+         * Returns the target subject DN from the first X509Certificate that
+         * is fetched that matches the specified X509CertSelector.
+         */
+        private static X500Principal getTargetSubject(List<CertStore> stores,
+                                                      X509CertSelector sel)
+            throws InvalidAlgorithmParameterException
+        {
+            X500Principal subject = sel.getSubject();
+            if (subject != null) {
+                return subject;
+            }
+            X509Certificate cert = sel.getCertificate();
+            if (cert != null) {
+                subject = cert.getSubjectX500Principal();
+            }
+            if (subject != null) {
+                return subject;
+            }
+            for (CertStore store : stores) {
+                try {
+                    Collection<? extends Certificate> certs =
+                        (Collection<? extends Certificate>)
+                            store.getCertificates(sel);
+                    if (!certs.isEmpty()) {
+                        X509Certificate xc =
+                            (X509Certificate)certs.iterator().next();
+                        return xc.getSubjectX500Principal();
+                    }
+                } catch (CertStoreException e) {
+                    // ignore but log it
+                    if (debug != null) {
+                        debug.println("BuilderParams.getTargetSubjectDN: " +
+                            "non-fatal exception retrieving certs: " + e);
+                        e.printStackTrace();
+                    }
+                }
+            }
+            throw new InvalidAlgorithmParameterException
+                ("Could not determine unique target subject");
+        }
+    }
+
+    /**
+     * Comparator that orders CertStores so that local CertStores come before
+     * remote CertStores.
+     */
+    private static class CertStoreComparator implements Comparator<CertStore> {
+        @Override
+        public int compare(CertStore store1, CertStore store2) {
+            if (store1.getType().equals("Collection") ||
+                store1.getCertStoreParameters() instanceof
+                CollectionCertStoreParameters) {
+                return -1;
+            } else {
+                return 1;
+            }
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXCertPathValidator.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -25,55 +25,38 @@
 
 package sun.security.provider.certpath;
 
-import java.security.AccessController;
+import java.io.IOException;
 import java.security.InvalidAlgorithmParameterException;
-import java.security.cert.CertPath;
-import java.security.cert.CertPathParameters;
-import java.security.cert.CertPathValidatorException;
-import java.security.cert.CertPathValidatorSpi;
-import java.security.cert.CertPathValidatorResult;
-import java.security.cert.PKIXCertPathChecker;
-import java.security.cert.PKIXCertPathValidatorResult;
-import java.security.cert.PKIXParameters;
-import java.security.cert.PKIXReason;
-import java.security.cert.PolicyNode;
-import java.security.cert.TrustAnchor;
-import java.security.cert.X509Certificate;
-import java.util.Collections;
-import java.util.List;
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.Set;
-import sun.security.action.GetBooleanSecurityPropertyAction;
+import java.security.cert.*;
+import java.util.*;
+
+import sun.security.provider.certpath.PKIX.ValidatorParams;
+import sun.security.x509.X509CertImpl;
 import sun.security.util.Debug;
 
-import sun.security.x509.X509CertImpl;
-
-
 /**
  * This class implements the PKIX validation algorithm for certification
  * paths consisting exclusively of <code>X509Certificates</code>. It uses
  * the specified input parameter set (which must be a
- * <code>PKIXParameters</code> object) and signature provider (if any).
+ * <code>PKIXParameters</code> object).
  *
  * @since       1.4
  * @author      Yassir Elley
  */
-public class PKIXCertPathValidator extends CertPathValidatorSpi {
+public final class PKIXCertPathValidator extends CertPathValidatorSpi {
 
     private static final Debug debug = Debug.getInstance("certpath");
-    private Date testDate;
-    private List<PKIXCertPathChecker> userCheckers;
-    private String sigProvider;
-    private BasicChecker basicChecker;
-    private boolean ocspEnabled = false;
-    private boolean onlyEECert = false;
 
     /**
      * Default constructor.
      */
     public PKIXCertPathValidator() {}
 
+    @Override
+    public CertPathChecker engineGetRevocationChecker() {
+        return new RevocationChecker();
+    }
+
     /**
      * Validates a certification path consisting exclusively of
      * <code>X509Certificate</code>s using the PKIX validation algorithm,
@@ -81,98 +64,70 @@
      * The input parameter set must be a <code>PKIXParameters</code> object.
      *
      * @param cp the X509 certification path
-     * @param param the input PKIX parameter set
+     * @param params the input PKIX parameter set
      * @return the result
-     * @exception CertPathValidatorException Exception thrown if cert path
-     * does not validate.
-     * @exception InvalidAlgorithmParameterException if the specified
-     * parameters are inappropriate for this certification path validator
+     * @throws CertPathValidatorException if cert path does not validate.
+     * @throws InvalidAlgorithmParameterException if the specified
+     *         parameters are inappropriate for this CertPathValidator
      */
+    @Override
     public CertPathValidatorResult engineValidate(CertPath cp,
-        CertPathParameters param)
+                                                  CertPathParameters params)
         throws CertPathValidatorException, InvalidAlgorithmParameterException
     {
+        ValidatorParams valParams = PKIX.checkParams(cp, params);
+        return validate(valParams);
+    }
+
+    private static PKIXCertPathValidatorResult validate(ValidatorParams params)
+        throws CertPathValidatorException
+    {
         if (debug != null)
             debug.println("PKIXCertPathValidator.engineValidate()...");
 
-        if (!(param instanceof PKIXParameters)) {
-            throw new InvalidAlgorithmParameterException("inappropriate "
-                + "parameters, must be an instance of PKIXParameters");
-        }
-
-        if (!cp.getType().equals("X.509") && !cp.getType().equals("X509")) {
-            throw new InvalidAlgorithmParameterException("inappropriate "
-                + "certification path type specified, must be X.509 or X509");
-        }
-
-        PKIXParameters pkixParam = (PKIXParameters) param;
-
-        // Make sure that none of the trust anchors include name constraints
-        // (not supported).
-        Set<TrustAnchor> anchors = pkixParam.getTrustAnchors();
-        for (TrustAnchor anchor : anchors) {
-            if (anchor.getNameConstraints() != null) {
-                throw new InvalidAlgorithmParameterException
-                    ("name constraints in trust anchor not supported");
-            }
-        }
-
-        // the certpath which has been passed in (cp)
-        // has the target cert as the first certificate - we
-        // need to keep this cp so we can return it
-        // in case of an exception and for policy qualifier
-        // processing - however, for certpath validation,
-        // we need to create a reversed path, where we reverse the
-        // ordering so that the target cert is the last certificate
-
-        // Must copy elements of certList into a new modifiable List before
-        // calling Collections.reverse().
-        // If cp is not an X.509 or X509 certpath, an
-        // InvalidAlgorithmParameterException will have been thrown by now.
-        @SuppressWarnings("unchecked")
-        ArrayList<X509Certificate> certList = new ArrayList<X509Certificate>
-            ((List<X509Certificate>)cp.getCertificates());
-        if (debug != null) {
-            if (certList.isEmpty()) {
-                debug.println("PKIXCertPathValidator.engineValidate() "
-                    + "certList is empty");
-            }
-            debug.println("PKIXCertPathValidator.engineValidate() "
-                + "reversing certpath...");
-        }
-        Collections.reverse(certList);
-
-        // now certList has the target cert as the last cert and we
-        // can proceed with normal validation
-
-        populateVariables(pkixParam);
-
         // Retrieve the first certificate in the certpath
         // (to be used later in pre-screening)
-        X509Certificate firstCert = null;
+        AdaptableX509CertSelector selector = null;
+        List<X509Certificate> certList = params.certificates();
         if (!certList.isEmpty()) {
-            firstCert = certList.get(0);
+            selector = new AdaptableX509CertSelector();
+            X509Certificate firstCert = certList.get(0);
+            // check trusted certificate's subject
+            selector.setSubject(firstCert.getIssuerX500Principal());
+            // check the validity period
+            selector.setValidityPeriod(firstCert.getNotBefore(),
+                                       firstCert.getNotAfter());
+            /*
+             * Facilitate certification path construction with authority
+             * key identifier and subject key identifier.
+             */
+            try {
+                X509CertImpl firstCertImpl = X509CertImpl.toImpl(firstCert);
+                selector.parseAuthorityKeyIdentifierExtension(
+                            firstCertImpl.getAuthorityKeyIdentifierExtension());
+            } catch (CertificateException | IOException e) {
+                // ignore
+            }
         }
 
         CertPathValidatorException lastException = null;
 
         // We iterate through the set of trust anchors until we find
         // one that works at which time we stop iterating
-        for (TrustAnchor anchor : anchors) {
+        for (TrustAnchor anchor : params.trustAnchors()) {
             X509Certificate trustedCert = anchor.getTrustedCert();
             if (trustedCert != null) {
-                if (debug != null) {
-                    debug.println("PKIXCertPathValidator.engineValidate() "
-                        + "anchor.getTrustedCert() != null");
-                }
-
                 // if this trust anchor is not worth trying,
                 // we move on to the next one
-                if (!isWorthTrying(trustedCert, firstCert)) {
+                if (selector != null && !selector.match(trustedCert)) {
+                    if (debug != null) {
+                        debug.println("NO - don't try this trustedCert");
+                    }
                     continue;
                 }
 
                 if (debug != null) {
+                    debug.println("YES - try this trustedCert");
                     debug.println("anchor.getTrustedCert()."
                         + "getSubjectX500Principal() = "
                         + trustedCert.getSubjectX500Principal());
@@ -185,14 +140,7 @@
             }
 
             try {
-                PolicyNodeImpl rootNode = new PolicyNodeImpl(null,
-                    PolicyChecker.ANY_POLICY, null, false,
-                    Collections.singleton(PolicyChecker.ANY_POLICY), false);
-                PolicyNode policyTree =
-                    doValidate(anchor, cp, certList, pkixParam, rootNode);
-                // if this anchor works, return success
-                return new PKIXCertPathValidatorResult(anchor, policyTree,
-                    basicChecker.getPublicKey());
+                return validate(anchor, params);
             } catch (CertPathValidatorException cpe) {
                 // remember this exception
                 lastException = cpe;
@@ -210,144 +158,59 @@
              null, null, -1, PKIXReason.NO_TRUST_ANCHOR);
     }
 
-    /**
-     * Internal method to do some simple checks to see if a given cert is
-     * worth trying to validate in the chain.
-     */
-    private boolean isWorthTrying(X509Certificate trustedCert,
-          X509Certificate firstCert) {
-
-        boolean worthy = false;
-
-        if (debug != null) {
-            debug.println("PKIXCertPathValidator.isWorthTrying() checking "
-                + "if this trusted cert is worth trying ...");
-        }
-
-        if (firstCert == null) {
-            return true;
-        }
-
-        AdaptableX509CertSelector issuerSelector =
-                        new AdaptableX509CertSelector();
-
-        // check trusted certificate's subject
-        issuerSelector.setSubject(firstCert.getIssuerX500Principal());
+    private static PKIXCertPathValidatorResult validate(TrustAnchor anchor,
+                                                        ValidatorParams params)
+        throws CertPathValidatorException
+    {
+        int certPathLen = params.certificates().size();
 
-        // check the validity period
-        issuerSelector.setValidityPeriod(firstCert.getNotBefore(),
-                                                firstCert.getNotAfter());
+        // create PKIXCertPathCheckers
+        List<PKIXCertPathChecker> certPathCheckers = new ArrayList<>();
+        // add standard checkers that we will be using
+        certPathCheckers.add(new AlgorithmChecker(anchor));
+        certPathCheckers.add(new KeyChecker(certPathLen,
+                                            params.targetCertConstraints()));
+        certPathCheckers.add(new ConstraintsChecker(certPathLen));
+        PolicyNodeImpl rootNode =
+            new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null, false,
+                               Collections.singleton(PolicyChecker.ANY_POLICY),
+                               false);
+        PolicyChecker pc = new PolicyChecker(params.initialPolicies(),
+                                             certPathLen,
+                                             params.explicitPolicyRequired(),
+                                             params.policyMappingInhibited(),
+                                             params.anyPolicyInhibited(),
+                                             params.policyQualifiersRejected(),
+                                             rootNode);
+        certPathCheckers.add(pc);
+        // default value for date is current time
+        BasicChecker bc = new BasicChecker(anchor, params.date(),
+                                           params.sigProvider(), false);
+        certPathCheckers.add(bc);
 
-        /*
-         * Facilitate certification path construction with authority
-         * key identifier and subject key identifier.
-         */
-        try {
-            X509CertImpl firstCertImpl = X509CertImpl.toImpl(firstCert);
-            issuerSelector.parseAuthorityKeyIdentifierExtension(
-                        firstCertImpl.getAuthorityKeyIdentifierExtension());
-
-            worthy = issuerSelector.match(trustedCert);
-        } catch (Exception e) {
-            // It is not worth trying.
-        }
-
-        if (debug != null) {
-            if (worthy) {
-                debug.println("YES - try this trustedCert");
-            } else {
-                debug.println("NO - don't try this trustedCert");
+        boolean revCheckerAdded = false;
+        List<PKIXCertPathChecker> checkers = params.certPathCheckers();
+        for (PKIXCertPathChecker checker : checkers) {
+            if (checker instanceof PKIXRevocationChecker) {
+                revCheckerAdded = true;
+                // if it's our own, initialize it
+                if (checker instanceof RevocationChecker)
+                    ((RevocationChecker)checker).init(anchor, params);
             }
         }
-
-        return worthy;
-    }
-
-    /**
-     * Internal method to setup the internal state
-     */
-    private void populateVariables(PKIXParameters pkixParam)
-    {
-        // default value for testDate is current time
-        testDate = pkixParam.getDate();
-        if (testDate == null) {
-            testDate = new Date(System.currentTimeMillis());
+        // only add a RevocationChecker if revocation is enabled and
+        // a PKIXRevocationChecker has not already been added
+        if (params.revocationEnabled() && !revCheckerAdded) {
+            certPathCheckers.add(new RevocationChecker(anchor, params));
         }
-
-        userCheckers = pkixParam.getCertPathCheckers();
-        sigProvider = pkixParam.getSigProvider();
-
-        if (pkixParam.isRevocationEnabled()) {
-            // Examine OCSP security property
-            ocspEnabled = AccessController.doPrivileged(
-                new GetBooleanSecurityPropertyAction
-                    (OCSPChecker.OCSP_ENABLE_PROP));
-            onlyEECert = AccessController.doPrivileged(
-                new GetBooleanSecurityPropertyAction
-                    ("com.sun.security.onlyCheckRevocationOfEECert"));
-        }
-    }
-
-    /**
-     * Internal method to actually validate a constructed path.
-     *
-     * @return the valid policy tree
-     */
-    private PolicyNode doValidate(
-            TrustAnchor anchor, CertPath cpOriginal,
-            ArrayList<X509Certificate> certList, PKIXParameters pkixParam,
-            PolicyNodeImpl rootNode) throws CertPathValidatorException
-    {
-        int certPathLen = certList.size();
+        // add user-specified checkers
+        certPathCheckers.addAll(checkers);
 
-        basicChecker = new BasicChecker(anchor, testDate, sigProvider, false);
-        AlgorithmChecker algorithmChecker = new AlgorithmChecker(anchor);
-        KeyChecker keyChecker = new KeyChecker(certPathLen,
-            pkixParam.getTargetCertConstraints());
-        ConstraintsChecker constraintsChecker =
-            new ConstraintsChecker(certPathLen);
-
-        PolicyChecker policyChecker =
-            new PolicyChecker(pkixParam.getInitialPolicies(), certPathLen,
-                              pkixParam.isExplicitPolicyRequired(),
-                              pkixParam.isPolicyMappingInhibited(),
-                              pkixParam.isAnyPolicyInhibited(),
-                              pkixParam.getPolicyQualifiersRejected(),
-                              rootNode);
-
-        ArrayList<PKIXCertPathChecker> certPathCheckers =
-            new ArrayList<PKIXCertPathChecker>();
-        // add standard checkers that we will be using
-        certPathCheckers.add(algorithmChecker);
-        certPathCheckers.add(keyChecker);
-        certPathCheckers.add(constraintsChecker);
-        certPathCheckers.add(policyChecker);
-        certPathCheckers.add(basicChecker);
+        PKIXMasterCertPathValidator.validate(params.certPath(),
+                                             params.certificates(),
+                                             certPathCheckers);
 
-        // only add a revocationChecker if revocation is enabled
-        if (pkixParam.isRevocationEnabled()) {
-
-            // Use OCSP if it has been enabled
-            if (ocspEnabled) {
-                OCSPChecker ocspChecker =
-                    new OCSPChecker(cpOriginal, pkixParam, onlyEECert);
-                certPathCheckers.add(ocspChecker);
-            }
-
-            // Always use CRLs
-            CrlRevocationChecker revocationChecker = new
-                CrlRevocationChecker(anchor, pkixParam, certList, onlyEECert);
-            certPathCheckers.add(revocationChecker);
-        }
-
-        // add user-specified checkers
-        certPathCheckers.addAll(userCheckers);
-
-        PKIXMasterCertPathValidator masterValidator =
-            new PKIXMasterCertPathValidator(certPathCheckers);
-
-        masterValidator.validate(cpOriginal, certList);
-
-        return policyChecker.getPolicyTree();
+        return new PKIXCertPathValidatorResult(anchor, pc.getPolicyTree(),
+                                               bc.getPublicKey());
     }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PKIXMasterCertPathValidator.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2009, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -30,10 +30,8 @@
 import java.util.Collections;
 import java.util.List;
 import java.util.Set;
-import java.security.cert.CertificateRevokedException;
 import java.security.cert.CertPath;
 import java.security.cert.CertPathValidatorException;
-import java.security.cert.CertPathValidatorException.BasicReason;
 import java.security.cert.PKIXCertPathChecker;
 import java.security.cert.PKIXReason;
 import java.security.cert.X509Certificate;
@@ -49,32 +47,22 @@
 class PKIXMasterCertPathValidator {
 
     private static final Debug debug = Debug.getInstance("certpath");
-    private List<PKIXCertPathChecker> certPathCheckers;
-
-    /**
-     * Initializes the list of PKIXCertPathCheckers whose checks
-     * will be performed on each certificate in the certpath.
-     *
-     * @param certPathCheckers a List of checkers to use
-     */
-    PKIXMasterCertPathValidator(List<PKIXCertPathChecker> certPathCheckers) {
-        this.certPathCheckers = certPathCheckers;
-    }
 
     /**
      * Validates a certification path consisting exclusively of
-     * <code>X509Certificate</code>s using the
-     * <code>PKIXCertPathChecker</code>s specified
-     * in the constructor. It is assumed that the
+     * <code>X509Certificate</code>s using the specified
+     * <code>PKIXCertPathChecker</code>s. It is assumed that the
      * <code>PKIXCertPathChecker</code>s
      * have been initialized with any input parameters they may need.
      *
      * @param cpOriginal the original X509 CertPath passed in by the user
      * @param reversedCertList the reversed X509 CertPath (as a List)
-     * @exception CertPathValidatorException Exception thrown if cert
-     * path does not validate.
+     * @param certPathCheckers the PKIXCertPathCheckers
+     * @throws CertPathValidatorException if cert path does not validate
      */
-    void validate(CertPath cpOriginal, List<X509Certificate> reversedCertList)
+    static void validate(CertPath cpOriginal,
+                         List<X509Certificate> reversedCertList,
+                         List<PKIXCertPathChecker> certPathCheckers)
         throws CertPathValidatorException
     {
         // we actually process reversedCertList, but we keep cpOriginal because
@@ -104,20 +92,18 @@
                 debug.println("Checking cert" + (i+1) + " ...");
 
             X509Certificate currCert = reversedCertList.get(i);
-            Set<String> unresolvedCritExts =
-                                        currCert.getCriticalExtensionOIDs();
-            if (unresolvedCritExts == null) {
-                unresolvedCritExts = Collections.<String>emptySet();
+            Set<String> unresCritExts = currCert.getCriticalExtensionOIDs();
+            if (unresCritExts == null) {
+                unresCritExts = Collections.<String>emptySet();
             }
 
-            if (debug != null && !unresolvedCritExts.isEmpty()) {
+            if (debug != null && !unresCritExts.isEmpty()) {
                 debug.println("Set of critical extensions:");
-                for (String oid : unresolvedCritExts) {
+                for (String oid : unresCritExts) {
                     debug.println(oid);
                 }
             }
 
-            CertPathValidatorException ocspCause = null;
             for (int j = 0; j < certPathCheckers.size(); j++) {
 
                 PKIXCertPathChecker currChecker = certPathCheckers.get(j);
@@ -130,65 +116,21 @@
                     currChecker.init(false);
 
                 try {
-                    currChecker.check(currCert, unresolvedCritExts);
+                    currChecker.check(currCert, unresCritExts);
 
-                    // OCSP has validated the cert so skip the CRL check
-                    if (isRevocationCheck(currChecker, j, certPathCheckers)) {
-                        if (debug != null) {
-                            debug.println("-checker" + (j + 1) +
-                                " validation succeeded");
-                        }
-                        j++;
-                        continue; // skip
+                    if (debug != null) {
+                        debug.println("-checker" + (j + 1) +
+                            " validation succeeded");
                     }
 
                 } catch (CertPathValidatorException cpve) {
-                    // Throw the saved OCSP exception unless the CRL
-                    // checker has determined that the cert is revoked
-                    if (ocspCause != null &&
-                            currChecker instanceof CrlRevocationChecker) {
-                        if (cpve.getReason() == BasicReason.REVOKED) {
-                            throw cpve;
-                        } else {
-                            throw ocspCause;
-                        }
-                    }
-                    /*
-                     * Handle failover from OCSP to CRLs
-                     */
-                    CertPathValidatorException currentCause =
-                        new CertPathValidatorException(cpve.getMessage(),
-                            cpve.getCause(), cpOriginal, cpSize - (i + 1),
-                            cpve.getReason());
-
-                    // Check if OCSP has confirmed that the cert was revoked
-                    if (cpve.getReason() == BasicReason.REVOKED) {
-                        throw currentCause;
-                    }
-                    // Check if it is appropriate to failover
-                    if (! isRevocationCheck(currChecker, j, certPathCheckers)) {
-                        // no failover
-                        throw currentCause;
-                    }
-                    // Save the current exception
-                    // (in case the CRL check also fails)
-                    ocspCause = currentCause;
-
-                    // Otherwise, failover to CRLs
-                    if (debug != null) {
-                        debug.println(cpve.getMessage());
-                        debug.println(
-                            "preparing to failover (from OCSP to CRLs)");
-                    }
+                    throw new CertPathValidatorException(cpve.getMessage(),
+                        cpve.getCause(), cpOriginal, cpSize - (i + 1),
+                        cpve.getReason());
                 }
-
-                if (debug != null)
-                    debug.println("-checker" + (j+1) + " validation succeeded");
             }
 
-            if (debug != null)
-                debug.println("checking for unresolvedCritExts");
-            if (!unresolvedCritExts.isEmpty()) {
+            if (!unresCritExts.isEmpty()) {
                 throw new CertPathValidatorException("unrecognized " +
                     "critical extension(s)", null, cpOriginal, cpSize-(i+1),
                     PKIXReason.UNRECOGNIZED_CRIT_EXT);
@@ -200,26 +142,9 @@
 
         if (debug != null) {
             debug.println("Cert path validation succeeded. (PKIX validation "
-                    + "algorithm)");
+                          + "algorithm)");
             debug.println("-------------------------------------------------"
-                    + "-------------");
+                          + "-------------");
         }
     }
-
-    /*
-     * Examines the list of PKIX cert path checkers to determine whether
-     * both the current checker and the next checker are revocation checkers.
-     * OCSPChecker and CrlRevocationChecker are both revocation checkers.
-     */
-    private static boolean isRevocationCheck(PKIXCertPathChecker checker,
-        int index, List<PKIXCertPathChecker> checkers) {
-
-        if (checker instanceof OCSPChecker && index + 1 < checkers.size()) {
-            PKIXCertPathChecker nextChecker = checkers.get(index + 1);
-            if (nextChecker instanceof CrlRevocationChecker) {
-                return true;
-            }
-        }
-        return false;
-    }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/PolicyChecker.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PolicyChecker.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -25,9 +25,8 @@
 
 package sun.security.provider.certpath;
 
-import java.util.*;
 import java.io.IOException;
-
+import java.security.GeneralSecurityException;
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertPathValidatorException;
@@ -36,13 +35,14 @@
 import java.security.cert.PolicyNode;
 import java.security.cert.PolicyQualifierInfo;
 import java.security.cert.X509Certificate;
+import java.util.*;
 
 import sun.security.util.Debug;
 import sun.security.x509.CertificatePoliciesExtension;
 import sun.security.x509.PolicyConstraintsExtension;
 import sun.security.x509.PolicyMappingsExtension;
 import sun.security.x509.CertificatePolicyMap;
-import sun.security.x509.PKIXExtensions;
+import static sun.security.x509.PKIXExtensions.*;
 import sun.security.x509.PolicyInformation;
 import sun.security.x509.X509CertImpl;
 import sun.security.x509.InhibitAnyPolicyExtension;
@@ -88,7 +88,7 @@
     PolicyChecker(Set<String> initialPolicies, int certPathLen,
         boolean expPolicyRequired, boolean polMappingInhibited,
         boolean anyPolicyInhibited, boolean rejectPolicyQualifiers,
-        PolicyNodeImpl rootNode) throws CertPathValidatorException
+        PolicyNodeImpl rootNode)
     {
         if (initialPolicies.isEmpty()) {
             // if no initialPolicies are specified by user, set
@@ -104,18 +104,18 @@
         this.anyPolicyInhibited = anyPolicyInhibited;
         this.rejectPolicyQualifiers = rejectPolicyQualifiers;
         this.rootNode = rootNode;
-        init(false);
     }
 
     /**
      * Initializes the internal state of the checker from parameters
      * specified in the constructor
      *
-     * @param forward a boolean indicating whether this checker should
-     * be initialized capable of building in the forward direction
-     * @exception CertPathValidatorException Exception thrown if user
-     * wants to enable forward checking and forward checking is not supported.
+     * @param forward a boolean indicating whether this checker should be
+     *        initialized capable of building in the forward direction
+     * @throws CertPathValidatorException if user wants to enable forward
+     *         checking and forward checking is not supported.
      */
+    @Override
     public void init(boolean forward) throws CertPathValidatorException {
         if (forward) {
             throw new CertPathValidatorException
@@ -136,6 +136,7 @@
      *
      * @return true if forward checking is supported, false otherwise
      */
+    @Override
     public boolean isForwardCheckingSupported() {
         return false;
     }
@@ -150,13 +151,14 @@
      * @return the Set of extensions supported by this PKIXCertPathChecker,
      * or null if no extensions are supported
      */
+    @Override
     public Set<String> getSupportedExtensions() {
         if (supportedExts == null) {
-            supportedExts = new HashSet<String>();
-            supportedExts.add(PKIXExtensions.CertificatePolicies_Id.toString());
-            supportedExts.add(PKIXExtensions.PolicyMappings_Id.toString());
-            supportedExts.add(PKIXExtensions.PolicyConstraints_Id.toString());
-            supportedExts.add(PKIXExtensions.InhibitAnyPolicy_Id.toString());
+            supportedExts = new HashSet<String>(4);
+            supportedExts.add(CertificatePolicies_Id.toString());
+            supportedExts.add(PolicyMappings_Id.toString());
+            supportedExts.add(PolicyConstraints_Id.toString());
+            supportedExts.add(InhibitAnyPolicy_Id.toString());
             supportedExts = Collections.unmodifiableSet(supportedExts);
         }
         return supportedExts;
@@ -168,9 +170,9 @@
      *
      * @param cert the Certificate to be processed
      * @param unresCritExts the unresolved critical extensions
-     * @exception CertPathValidatorException Exception thrown if
-     * the certificate does not verify.
+     * @throws CertPathValidatorException if the certificate does not verify
      */
+    @Override
     public void check(Certificate cert, Collection<String> unresCritExts)
         throws CertPathValidatorException
     {
@@ -178,10 +180,10 @@
         checkPolicy((X509Certificate) cert);
 
         if (unresCritExts != null && !unresCritExts.isEmpty()) {
-            unresCritExts.remove(PKIXExtensions.CertificatePolicies_Id.toString());
-            unresCritExts.remove(PKIXExtensions.PolicyMappings_Id.toString());
-            unresCritExts.remove(PKIXExtensions.PolicyConstraints_Id.toString());
-            unresCritExts.remove(PKIXExtensions.InhibitAnyPolicy_Id.toString());
+            unresCritExts.remove(CertificatePolicies_Id.toString());
+            unresCritExts.remove(PolicyMappings_Id.toString());
+            unresCritExts.remove(PolicyConstraints_Id.toString());
+            unresCritExts.remove(InhibitAnyPolicy_Id.toString());
         }
     }
 
@@ -290,7 +292,7 @@
                 if (require == 0)
                     explicitPolicy = require;
             }
-        } catch (Exception e) {
+        } catch (IOException e) {
             if (debug != null) {
                 debug.println("PolicyChecker.mergeExplicitPolicy "
                               + "unexpected exception");
@@ -339,7 +341,7 @@
                     policyMapping = inhibit;
                 }
             }
-        } catch (Exception e) {
+        } catch (IOException e) {
             if (debug != null) {
                 debug.println("PolicyChecker.mergePolicyMapping "
                               + "unexpected exception");
@@ -372,7 +374,7 @@
 
         try {
             InhibitAnyPolicyExtension inhAnyPolExt = (InhibitAnyPolicyExtension)
-                currCert.getExtension(PKIXExtensions.InhibitAnyPolicy_Id);
+                currCert.getExtension(InhibitAnyPolicy_Id);
             if (inhAnyPolExt == null)
                 return inhibitAnyPolicy;
 
@@ -387,7 +389,7 @@
                     inhibitAnyPolicy = skipCerts;
                 }
             }
-        } catch (Exception e) {
+        } catch (IOException e) {
             if (debug != null) {
                 debug.println("PolicyChecker.mergeInhibitAnyPolicy "
                               + "unexpected exception");
@@ -429,7 +431,7 @@
         boolean policiesCritical = false;
         List<PolicyInformation> policyInfo;
         PolicyNodeImpl rootNode = null;
-        Set<PolicyQualifierInfo> anyQuals = new HashSet<PolicyQualifierInfo>();
+        Set<PolicyQualifierInfo> anyQuals = new HashSet<>();
 
         if (origRootNode == null)
             rootNode = null;
@@ -600,7 +602,7 @@
         PolicyNodeImpl parentNode = (PolicyNodeImpl)anyNode.getParent();
         parentNode.deleteChild(anyNode);
         // see if there are any initialPolicies not represented by leaf nodes
-        Set<String> initial = new HashSet<String>(initPolicies);
+        Set<String> initial = new HashSet<>(initPolicies);
         for (PolicyNodeImpl node : rootNode.getPolicyNodes(certIndex)) {
             initial.remove(node.getValidPolicy());
         }
@@ -697,7 +699,7 @@
                         }
                     }
 
-                    Set<String> expPols = new HashSet<String>();
+                    Set<String> expPols = new HashSet<>();
                     expPols.add(curParExpPol);
 
                     curNode = new PolicyNodeImpl
@@ -762,8 +764,7 @@
         }
 
         boolean childDeleted = false;
-        for (int j = 0; j < maps.size(); j++) {
-            CertificatePolicyMap polMap = maps.get(j);
+        for (CertificatePolicyMap polMap : maps) {
             String issuerDomain
                 = polMap.getIssuerIdentifier().getIdentifier().toString();
             String subjectDomain
@@ -816,7 +817,7 @@
                         PolicyNodeImpl curAnyNodeParent =
                             (PolicyNodeImpl) curAnyNode.getParent();
 
-                        Set<String> expPols = new HashSet<String>();
+                        Set<String> expPols = new HashSet<>();
                         expPols.add(subjectDomain);
 
                         PolicyNodeImpl curNode = new PolicyNodeImpl
--- a/jdk/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/PolicyNodeImpl.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2006, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -134,30 +134,37 @@
              node.mCriticalityIndicator, node.mExpectedPolicySet, false);
     }
 
+    @Override
     public PolicyNode getParent() {
         return mParent;
     }
 
+    @Override
     public Iterator<PolicyNodeImpl> getChildren() {
         return Collections.unmodifiableSet(mChildren).iterator();
     }
 
+    @Override
     public int getDepth() {
         return mDepth;
     }
 
+    @Override
     public String getValidPolicy() {
         return mValidPolicy;
     }
 
+    @Override
     public Set<PolicyQualifierInfo> getPolicyQualifiers() {
         return Collections.unmodifiableSet(mQualifierSet);
     }
 
+    @Override
     public Set<String> getExpectedPolicies() {
         return Collections.unmodifiableSet(mExpectedPolicySet);
     }
 
+    @Override
     public boolean isCritical() {
         return mCriticalityIndicator;
     }
@@ -169,12 +176,12 @@
      *
      * @return a String describing the contents of the Policy Node
      */
+    @Override
     public String toString() {
-        StringBuffer buffer = new StringBuffer(this.asString());
+        StringBuilder buffer = new StringBuilder(this.asString());
 
-        Iterator<PolicyNodeImpl> it = getChildren();
-        while (it.hasNext()) {
-            buffer.append(it.next());
+        for (PolicyNodeImpl node : mChildren) {
+            buffer.append(node);
         }
         return buffer.toString();
     }
@@ -293,7 +300,7 @@
      * @return a <code>Set</code> of all nodes at the specified depth
      */
     Set<PolicyNodeImpl> getPolicyNodes(int depth) {
-        Set<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>();
+        Set<PolicyNodeImpl> set = new HashSet<>();
         getPolicyNodes(depth, set);
         return set;
     }
@@ -337,7 +344,7 @@
     private Set<PolicyNodeImpl> getPolicyNodesExpectedHelper(int depth,
         String expectedOID, boolean matchAny) {
 
-        HashSet<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>();
+        HashSet<PolicyNodeImpl> set = new HashSet<>();
 
         if (mDepth < depth) {
             for (PolicyNodeImpl node : mChildren) {
@@ -367,7 +374,7 @@
      * @return a Set of matched <code>PolicyNode</code>s
      */
     Set<PolicyNodeImpl> getPolicyNodesValid(int depth, String validOID) {
-        HashSet<PolicyNodeImpl> set = new HashSet<PolicyNodeImpl>();
+        HashSet<PolicyNodeImpl> set = new HashSet<>();
 
         if (mDepth < depth) {
             for (PolicyNodeImpl node : mChildren) {
@@ -396,7 +403,7 @@
         if (mParent == null) {
             return "anyPolicy  ROOT\n";
         } else {
-            StringBuffer sb = new StringBuffer();
+            StringBuilder sb = new StringBuilder();
             for (int i = 0, n = getDepth(); i < n; i++) {
                 sb.append("  ");
             }
--- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseBuilder.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -51,9 +51,10 @@
 
 import javax.security.auth.x500.X500Principal;
 
+import sun.security.provider.certpath.PKIX.BuilderParams;
 import sun.security.util.Debug;
 import sun.security.x509.Extension;
-import sun.security.x509.PKIXExtensions;
+import static sun.security.x509.PKIXExtensions.*;
 import sun.security.x509.X500Name;
 import sun.security.x509.X509CertImpl;
 import sun.security.x509.PolicyMappingsExtension;
@@ -72,28 +73,24 @@
 
     private Debug debug = Debug.getInstance("certpath");
 
-    Set<String> initPolicies;
+    private final Set<String> initPolicies;
 
     /**
      * Initialize the builder with the input parameters.
      *
      * @param params the parameter set used to build a certification path
      */
-    ReverseBuilder(PKIXBuilderParameters buildParams,
-        X500Principal targetSubjectDN) {
+    ReverseBuilder(BuilderParams buildParams) {
+        super(buildParams);
 
-        super(buildParams, targetSubjectDN);
-
-        Set<String> initialPolicies = buildParams.getInitialPolicies();
+        Set<String> initialPolicies = buildParams.initialPolicies();
         initPolicies = new HashSet<String>();
         if (initialPolicies.isEmpty()) {
             // if no initialPolicies are specified by user, set
             // initPolicies to be anyPolicy by default
             initPolicies.add(PolicyChecker.ANY_POLICY);
         } else {
-            for (String policy : initialPolicies) {
-                initPolicies.add(policy);
-            }
+            initPolicies.addAll(initialPolicies);
         }
     }
 
@@ -106,6 +103,7 @@
      *        Must be an instance of <code>ReverseState</code>
      * @param certStores list of CertStores
      */
+    @Override
     Collection<X509Certificate> getMatchingCerts
         (State currState, List<CertStore> certStores)
         throws CertStoreException, CertificateException, IOException
@@ -138,56 +136,56 @@
         (ReverseState currentState, List<CertStore> certStores)
         throws CertStoreException, CertificateException, IOException {
 
-      /*
-       * Compose a CertSelector to filter out
-       * certs which do not satisfy requirements.
-       *
-       * First, retrieve clone of current target cert constraints,
-       * and then add more selection criteria based on current validation state.
-       */
-      X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone();
+        /*
+         * Compose a CertSelector to filter out
+         * certs which do not satisfy requirements.
+         *
+         * First, retrieve clone of current target cert constraints, and
+         * then add more selection criteria based on current validation state.
+         */
+        X509CertSelector sel = (X509CertSelector) targetCertConstraints.clone();
 
-      /*
-       * Match on issuer (subject of previous cert)
-       */
-      sel.setIssuer(currentState.subjectDN);
+        /*
+         * Match on issuer (subject of previous cert)
+         */
+        sel.setIssuer(currentState.subjectDN);
 
-      /*
-       * Match on certificate validity date.
-       */
-      sel.setCertificateValid(date);
+        /*
+         * Match on certificate validity date.
+         */
+        sel.setCertificateValid(buildParams.date());
 
-      /*
-       * Policy processing optimizations
-       */
-      if (currentState.explicitPolicy == 0)
-          sel.setPolicy(getMatchingPolicies());
+        /*
+         * Policy processing optimizations
+         */
+        if (currentState.explicitPolicy == 0)
+            sel.setPolicy(getMatchingPolicies());
 
-      /*
-       * If previous cert has a subject key identifier extension,
-       * use it to match on authority key identifier extension.
-       */
-      /*if (currentState.subjKeyId != null) {
-        AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
+        /*
+         * If previous cert has a subject key identifier extension,
+         * use it to match on authority key identifier extension.
+         */
+        /*if (currentState.subjKeyId != null) {
+          AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
                 (KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID),
                 null, null);
         sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
-      }*/
+        }*/
 
-      /*
-       * Require EE certs
-       */
-      sel.setBasicConstraints(-2);
+        /*
+         * Require EE certs
+         */
+        sel.setBasicConstraints(-2);
 
-      /* Retrieve matching certs from CertStores */
-      HashSet<X509Certificate> eeCerts = new HashSet<X509Certificate>();
-      addMatchingCerts(sel, certStores, eeCerts, true);
+        /* Retrieve matching certs from CertStores */
+        HashSet<X509Certificate> eeCerts = new HashSet<>();
+        addMatchingCerts(sel, certStores, eeCerts, true);
 
-      if (debug != null) {
-        debug.println("ReverseBuilder.getMatchingEECerts got " + eeCerts.size()
-                    + " certs.");
-      }
-      return eeCerts;
+        if (debug != null) {
+            debug.println("ReverseBuilder.getMatchingEECerts got "
+                          + eeCerts.size() + " certs.");
+        }
+        return eeCerts;
     }
 
     /*
@@ -198,63 +196,71 @@
         (ReverseState currentState, List<CertStore> certStores)
         throws CertificateException, CertStoreException, IOException {
 
-      /*
-       * Compose a CertSelector to filter out
-       * certs which do not satisfy requirements.
-       */
-      X509CertSelector sel = new X509CertSelector();
+        /*
+         * Compose a CertSelector to filter out
+         * certs which do not satisfy requirements.
+         */
+        X509CertSelector sel = new X509CertSelector();
 
-      /*
-       * Match on issuer (subject of previous cert)
-       */
-      sel.setIssuer(currentState.subjectDN);
+        /*
+         * Match on issuer (subject of previous cert)
+         */
+        sel.setIssuer(currentState.subjectDN);
 
-      /*
-       * Match on certificate validity date.
-       */
-      sel.setCertificateValid(date);
+        /*
+         * Match on certificate validity date.
+         */
+        sel.setCertificateValid(buildParams.date());
 
-      /*
-       * Match on target subject name (checks that current cert's
-       * name constraints permit it to certify target).
-       * (4 is the integer type for DIRECTORY name).
-       */
-      sel.addPathToName(4, targetCertConstraints.getSubjectAsBytes());
+        /*
+         * Match on target subject name (checks that current cert's
+         * name constraints permit it to certify target).
+         * (4 is the integer type for DIRECTORY name).
+         */
+        byte[] subject = targetCertConstraints.getSubjectAsBytes();
+        if (subject != null) {
+            sel.addPathToName(4, subject);
+        } else {
+            X509Certificate cert = targetCertConstraints.getCertificate();
+            if (cert != null) {
+                sel.addPathToName(4,
+                                  cert.getSubjectX500Principal().getEncoded());
+            }
+        }
 
-      /*
-       * Policy processing optimizations
-       */
-      if (currentState.explicitPolicy == 0)
-          sel.setPolicy(getMatchingPolicies());
+        /*
+         * Policy processing optimizations
+         */
+        if (currentState.explicitPolicy == 0)
+            sel.setPolicy(getMatchingPolicies());
 
-      /*
-       * If previous cert has a subject key identifier extension,
-       * use it to match on authority key identifier extension.
-       */
-      /*if (currentState.subjKeyId != null) {
-        AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
+        /*
+         * If previous cert has a subject key identifier extension,
+         * use it to match on authority key identifier extension.
+         */
+        /*if (currentState.subjKeyId != null) {
+          AuthorityKeyIdentifierExtension authKeyId = new AuthorityKeyIdentifierExtension(
                 (KeyIdentifier) currentState.subjKeyId.get(SubjectKeyIdentifierExtension.KEY_ID),
                                 null, null);
-        sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
-      }*/
+          sel.setAuthorityKeyIdentifier(authKeyId.getExtensionValue());
+        }*/
 
-      /*
-       * Require CA certs
-       */
-      sel.setBasicConstraints(0);
+        /*
+         * Require CA certs
+         */
+        sel.setBasicConstraints(0);
 
-      /* Retrieve matching certs from CertStores */
-      ArrayList<X509Certificate> reverseCerts =
-          new ArrayList<X509Certificate>();
-      addMatchingCerts(sel, certStores, reverseCerts, true);
+        /* Retrieve matching certs from CertStores */
+        ArrayList<X509Certificate> reverseCerts = new ArrayList<>();
+        addMatchingCerts(sel, certStores, reverseCerts, true);
 
-      /* Sort remaining certs using name constraints */
-      Collections.sort(reverseCerts, new PKIXCertComparator());
+        /* Sort remaining certs using name constraints */
+        Collections.sort(reverseCerts, new PKIXCertComparator());
 
-      if (debug != null)
-        debug.println("ReverseBuilder.getMatchingCACerts got " +
-                    reverseCerts.size() + " certs.");
-      return reverseCerts;
+        if (debug != null)
+            debug.println("ReverseBuilder.getMatchingCACerts got " +
+                          reverseCerts.size() + " certs.");
+        return reverseCerts;
     }
 
     /*
@@ -269,23 +275,25 @@
 
         private Debug debug = Debug.getInstance("certpath");
 
+        @Override
         public int compare(X509Certificate cert1, X509Certificate cert2) {
 
             /*
              * if either cert certifies the target, always
              * put at head of list.
              */
-            if (cert1.getSubjectX500Principal().equals(targetSubjectDN)) {
+            X500Principal targetSubject = buildParams.targetSubject();
+            if (cert1.getSubjectX500Principal().equals(targetSubject)) {
                 return -1;
             }
-            if (cert2.getSubjectX500Principal().equals(targetSubjectDN)) {
+            if (cert2.getSubjectX500Principal().equals(targetSubject)) {
                 return 1;
             }
 
             int targetDist1;
             int targetDist2;
             try {
-                X500Name targetSubjectName = X500Name.asX500Name(targetSubjectDN);
+                X500Name targetSubjectName = X500Name.asX500Name(targetSubject);
                 targetDist1 = Builder.targetDistance(
                     null, cert1, targetSubjectName);
                 targetDist2 = Builder.targetDistance(
@@ -330,6 +338,7 @@
      * @param currentState the current state against which the cert is verified
      * @param certPathList the certPathList generated thus far
      */
+    @Override
     void verifyCert(X509Certificate cert, State currState,
         List<X509Certificate> certPathList)
         throws GeneralSecurityException
@@ -358,8 +367,7 @@
          * of the same certificate, we reverse the certpathlist first
          */
         if ((certPathList != null) && (!certPathList.isEmpty())) {
-            List<X509Certificate> reverseCertList =
-                new ArrayList<X509Certificate>();
+            List<X509Certificate> reverseCertList = new ArrayList<>();
             for (X509Certificate c : certPathList) {
                 reverseCertList.add(0, c);
             }
@@ -374,8 +382,8 @@
                 }
                 if (debug != null)
                     debug.println("policyMappingFound = " + policyMappingFound);
-                if (cert.equals(cpListCert)){
-                    if ((buildParams.isPolicyMappingInhibited()) ||
+                if (cert.equals(cpListCert)) {
+                    if ((buildParams.policyMappingInhibited()) ||
                         (!policyMappingFound)){
                         if (debug != null)
                             debug.println("loop detected!!");
@@ -386,7 +394,7 @@
         }
 
         /* check if target cert */
-        boolean finalCert = cert.getSubjectX500Principal().equals(targetSubjectDN);
+        boolean finalCert = cert.getSubjectX500Principal().equals(buildParams.targetSubject());
 
         /* check if CA cert */
         boolean caCert = (cert.getBasicConstraints() != -1 ? true : false);
@@ -427,23 +435,20 @@
         /*
          * Check revocation.
          */
-        if (buildParams.isRevocationEnabled()) {
-
-            currentState.crlChecker.check(cert,
-                                          currentState.pubKey,
-                                          currentState.crlSign);
+        if (buildParams.revocationEnabled() && currentState.revChecker != null) {
+            currentState.revChecker.check(cert, Collections.<String>emptySet());
         }
 
         /* Check name constraints if this is not a self-issued cert */
         if (finalCert || !X509CertImpl.isSelfIssued(cert)){
-            if (currentState.nc != null){
+            if (currentState.nc != null) {
                 try {
                     if (!currentState.nc.verify(cert)){
                         throw new CertPathValidatorException
                             ("name constraints check failed", null, null, -1,
                              PKIXReason.INVALID_NAME);
                     }
-                } catch (IOException ioe){
+                } catch (IOException ioe) {
                     throw new CertPathValidatorException(ioe);
                 }
             }
@@ -457,7 +462,7 @@
             (currentState.certIndex, initPolicies,
             currentState.explicitPolicy, currentState.policyMapping,
             currentState.inhibitAnyPolicy,
-            buildParams.getPolicyQualifiersRejected(), currentState.rootNode,
+            buildParams.policyQualifiersRejected(), currentState.rootNode,
             certImpl, finalCert);
 
         /*
@@ -482,15 +487,15 @@
          * already checked. If there are any left, throw an exception!
          */
         if (!unresolvedCritExts.isEmpty()) {
-            unresolvedCritExts.remove(PKIXExtensions.BasicConstraints_Id.toString());
-            unresolvedCritExts.remove(PKIXExtensions.NameConstraints_Id.toString());
-            unresolvedCritExts.remove(PKIXExtensions.CertificatePolicies_Id.toString());
-            unresolvedCritExts.remove(PKIXExtensions.PolicyMappings_Id.toString());
-            unresolvedCritExts.remove(PKIXExtensions.PolicyConstraints_Id.toString());
-            unresolvedCritExts.remove(PKIXExtensions.InhibitAnyPolicy_Id.toString());
-            unresolvedCritExts.remove(PKIXExtensions.SubjectAlternativeName_Id.toString());
-            unresolvedCritExts.remove(PKIXExtensions.KeyUsage_Id.toString());
-            unresolvedCritExts.remove(PKIXExtensions.ExtendedKeyUsage_Id.toString());
+            unresolvedCritExts.remove(BasicConstraints_Id.toString());
+            unresolvedCritExts.remove(NameConstraints_Id.toString());
+            unresolvedCritExts.remove(CertificatePolicies_Id.toString());
+            unresolvedCritExts.remove(PolicyMappings_Id.toString());
+            unresolvedCritExts.remove(PolicyConstraints_Id.toString());
+            unresolvedCritExts.remove(InhibitAnyPolicy_Id.toString());
+            unresolvedCritExts.remove(SubjectAlternativeName_Id.toString());
+            unresolvedCritExts.remove(KeyUsage_Id.toString());
+            unresolvedCritExts.remove(ExtendedKeyUsage_Id.toString());
 
             if (!unresolvedCritExts.isEmpty())
                 throw new CertPathValidatorException
@@ -501,8 +506,8 @@
         /*
          * Check signature.
          */
-        if (buildParams.getSigProvider() != null) {
-            cert.verify(currentState.pubKey, buildParams.getSigProvider());
+        if (buildParams.sigProvider() != null) {
+            cert.verify(currentState.pubKey, buildParams.sigProvider());
         } else {
             cert.verify(currentState.pubKey);
         }
@@ -515,8 +520,9 @@
      * @param cert the certificate to test
      * @return a boolean value indicating whether the cert completes the path.
      */
+    @Override
     boolean isPathCompleted(X509Certificate cert) {
-        return cert.getSubjectX500Principal().equals(targetSubjectDN);
+        return cert.getSubjectX500Principal().equals(buildParams.targetSubject());
     }
 
     /** Adds the certificate to the certPathList
@@ -524,6 +530,7 @@
      * @param cert the certificate to be added
      * @param certPathList the certification path list
      */
+    @Override
     void addCertToPath(X509Certificate cert,
         LinkedList<X509Certificate> certPathList) {
         certPathList.addLast(cert);
@@ -533,6 +540,7 @@
      *
      * @param certPathList the certification path list
      */
+    @Override
     void removeFinalCertFromPath(LinkedList<X509Certificate> certPathList) {
         certPathList.removeLast();
     }
--- a/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/ReverseState.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -40,6 +40,7 @@
 import java.util.Set;
 import javax.security.auth.x500.X500Principal;
 
+import sun.security.provider.certpath.PKIX.BuilderParams;
 import sun.security.util.Debug;
 import sun.security.x509.NameConstraintsExtension;
 import sun.security.x509.SubjectKeyIdentifierExtension;
@@ -94,7 +95,7 @@
     private boolean init = true;
 
     /* the checker used for revocation status */
-    public CrlRevocationChecker crlChecker;
+    RevocationChecker revChecker;
 
     /* the algorithm checker */
     AlgorithmChecker algorithmChecker;
@@ -105,7 +106,7 @@
     /* Flag indicating if current cert can vouch for the CRL for
      * the next cert
      */
-    public boolean crlSign = true;
+    boolean crlSign = true;
 
     /**
      * Returns a boolean flag indicating if the state is initial
@@ -113,6 +114,7 @@
      *
      * @return boolean flag indicating if the state is initial (just starting)
      */
+    @Override
     public boolean isInitial() {
         return init;
     }
@@ -120,44 +122,32 @@
     /**
      * Display state for debugging purposes
      */
+    @Override
     public String toString() {
-        StringBuffer sb = new StringBuffer();
-        try {
-            sb.append("State [");
-            sb.append("\n  subjectDN of last cert: " + subjectDN);
-            sb.append("\n  subjectKeyIdentifier: " + String.valueOf(subjKeyId));
-            sb.append("\n  nameConstraints: " + String.valueOf(nc));
-            sb.append("\n  certIndex: " + certIndex);
-            sb.append("\n  explicitPolicy: " + explicitPolicy);
-            sb.append("\n  policyMapping:  " + policyMapping);
-            sb.append("\n  inhibitAnyPolicy:  " + inhibitAnyPolicy);
-            sb.append("\n  rootNode: " + rootNode);
-            sb.append("\n  remainingCACerts: " + remainingCACerts);
-            sb.append("\n  crlSign: " + crlSign);
-            sb.append("\n  init: " + init);
-            sb.append("\n]\n");
-        } catch (Exception e) {
-            if (debug != null) {
-                debug.println("ReverseState.toString() unexpected exception");
-                e.printStackTrace();
-            }
-        }
+        StringBuilder sb = new StringBuilder();
+        sb.append("State [");
+        sb.append("\n  subjectDN of last cert: ").append(subjectDN);
+        sb.append("\n  subjectKeyIdentifier: ").append
+                 (String.valueOf(subjKeyId));
+        sb.append("\n  nameConstraints: ").append(String.valueOf(nc));
+        sb.append("\n  certIndex: ").append(certIndex);
+        sb.append("\n  explicitPolicy: ").append(explicitPolicy);
+        sb.append("\n  policyMapping:  ").append(policyMapping);
+        sb.append("\n  inhibitAnyPolicy:  ").append(inhibitAnyPolicy);
+        sb.append("\n  rootNode: ").append(rootNode);
+        sb.append("\n  remainingCACerts: ").append(remainingCACerts);
+        sb.append("\n  crlSign: ").append(crlSign);
+        sb.append("\n  init: ").append(init);
+        sb.append("\n]\n");
         return sb.toString();
     }
 
     /**
      * Initialize the state.
      *
-     * @param maxPathLen The maximum number of CA certs in a path, where -1
-     * means unlimited and 0 means only a single EE cert is allowed.
-     * @param explicitPolicyRequired True, if explicit policy is required.
-     * @param policyMappingInhibited True, if policy mapping is inhibited.
-     * @param anyPolicyInhibited True, if any policy is inhibited.
-     * @param certPathCheckers the list of user-defined PKIXCertPathCheckers
+     * @param buildParams builder parameters
      */
-    public void initState(int maxPathLen, boolean explicitPolicyRequired,
-        boolean policyMappingInhibited, boolean anyPolicyInhibited,
-        List<PKIXCertPathChecker> certPathCheckers)
+    public void initState(BuilderParams buildParams)
         throws CertPathValidatorException
     {
         /*
@@ -165,60 +155,52 @@
          * Note that -1 maxPathLen implies unlimited.
          * 0 implies only an EE cert is acceptable.
          */
-        remainingCACerts = (maxPathLen == -1 ? Integer.MAX_VALUE : maxPathLen);
+        int maxPathLen = buildParams.maxPathLength();
+        remainingCACerts = (maxPathLen == -1) ? Integer.MAX_VALUE
+                                              : maxPathLen;
 
         /* Initialize explicit policy state variable */
-        if (explicitPolicyRequired) {
+        if (buildParams.explicitPolicyRequired()) {
             explicitPolicy = 0;
         } else {
             // unconstrained if maxPathLen is -1,
             // otherwise, we want to initialize this to the value of the
             // longest possible path + 1 (i.e. maxpathlen + finalcert + 1)
-            explicitPolicy = (maxPathLen == -1)
-                ? maxPathLen
-                : maxPathLen + 2;
+            explicitPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
         }
 
         /* Initialize policy mapping state variable */
-        if (policyMappingInhibited) {
+        if (buildParams.policyMappingInhibited()) {
             policyMapping = 0;
         } else {
-            policyMapping = (maxPathLen == -1)
-                ? maxPathLen
-                : maxPathLen + 2;
+            policyMapping = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
         }
 
         /* Initialize inhibit any policy state variable */
-        if (anyPolicyInhibited) {
+        if (buildParams.anyPolicyInhibited()) {
             inhibitAnyPolicy = 0;
         } else {
-            inhibitAnyPolicy = (maxPathLen == -1)
-                ? maxPathLen
-                : maxPathLen + 2;
+            inhibitAnyPolicy = (maxPathLen == -1) ? maxPathLen : maxPathLen + 2;
         }
 
         /* Initialize certIndex */
         certIndex = 1;
 
         /* Initialize policy tree */
-        Set<String> initExpPolSet = new HashSet<String>(1);
+        Set<String> initExpPolSet = new HashSet<>(1);
         initExpPolSet.add(PolicyChecker.ANY_POLICY);
 
-        rootNode = new PolicyNodeImpl
-            (null, PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false);
+        rootNode = new PolicyNodeImpl(null, PolicyChecker.ANY_POLICY, null,
+                                      false, initExpPolSet, false);
 
         /*
          * Initialize each user-defined checker
+         * Shallow copy the checkers
          */
-        if (certPathCheckers != null) {
-            /* Shallow copy the checkers */
-            userCheckers = new ArrayList<PKIXCertPathChecker>(certPathCheckers);
-            /* initialize each checker (just in case) */
-            for (PKIXCertPathChecker checker : certPathCheckers) {
-                checker.init(false);
-            }
-        } else {
-            userCheckers = new ArrayList<PKIXCertPathChecker>();
+        userCheckers = new ArrayList<>(buildParams.certPathCheckers());
+        /* initialize each checker (just in case) */
+        for (PKIXCertPathChecker checker : userCheckers) {
+            checker.init(false);
         }
 
         /* Start by trusting the cert to sign CRLs */
@@ -231,8 +213,9 @@
      * Update the state with the specified trust anchor.
      *
      * @param anchor the most-trusted CA
+     * @param buildParams builder parameters
      */
-    public void updateState(TrustAnchor anchor)
+    public void updateState(TrustAnchor anchor, BuilderParams buildParams)
         throws CertificateException, IOException, CertPathValidatorException
     {
         trustAnchor = anchor;
@@ -244,14 +227,26 @@
             updateState(anchor.getCAPublicKey(), caName);
         }
 
-        // The user specified AlgorithmChecker may not be
+        // The user specified AlgorithmChecker and RevocationChecker may not be
         // able to set the trust anchor until now.
+        boolean revCheckerAdded = false;
         for (PKIXCertPathChecker checker : userCheckers) {
             if (checker instanceof AlgorithmChecker) {
                 ((AlgorithmChecker)checker).trySetTrustAnchor(anchor);
+            } else if (checker instanceof RevocationChecker) {
+                ((RevocationChecker)checker).init(anchor, buildParams);
+                ((RevocationChecker)checker).init(false);
+                revCheckerAdded = true;
             }
         }
 
+        // only create a RevocationChecker if revocation is enabled and
+        // a PKIXRevocationChecker has not already been added
+        if (buildParams.revocationEnabled() && !revCheckerAdded) {
+            revChecker = new RevocationChecker(anchor, buildParams);
+            revChecker.init(false);
+        }
+
         init = false;
     }
 
@@ -310,7 +305,7 @@
         subjKeyId = icert.getSubjectKeyIdentifierExtension();
 
         /* update crlSign */
-        crlSign = CrlRevocationChecker.certCanSignCrl(cert);
+        crlSign = RevocationChecker.certCanSignCrl(cert);
 
         /* update current name constraints */
         if (nc != null) {
@@ -349,6 +344,7 @@
      *
      * @return boolean flag indicating if key lacking parameters encountered.
      */
+    @Override
     public boolean keyParamsNeeded() {
         /* when building in reverse, we immediately get parameters needed
          * or else throw an exception
@@ -365,6 +361,7 @@
      * because some of them (e.g., subjKeyId) will
      * not have their contents modified by subsequent calls to updateState.
      */
+    @Override
     @SuppressWarnings("unchecked") // Safe casts assuming clone() works correctly
     public Object clone() {
         try {
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/src/share/classes/sun/security/provider/certpath/RevocationChecker.java	Wed May 30 17:19:46 2012 -0400
@@ -0,0 +1,1095 @@
+/*
+ * Copyright (c) 2012, 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.certpath;
+
+import java.io.IOException;
+import java.math.BigInteger;
+import java.net.URI;
+import java.net.URISyntaxException;
+import java.security.AccessController;
+import java.security.InvalidAlgorithmParameterException;
+import java.security.NoSuchAlgorithmException;
+import java.security.PrivilegedAction;
+import java.security.PublicKey;
+import java.security.Security;
+import java.security.cert.CertPathValidatorException.BasicReason;
+import java.security.cert.Extension;
+import java.security.cert.*;
+import java.security.interfaces.DSAPublicKey;
+import java.util.Arrays;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+import javax.security.auth.x500.X500Principal;
+
+import static sun.security.provider.certpath.OCSP.*;
+import sun.security.provider.certpath.PKIX.ValidatorParams;
+import sun.security.action.GetPropertyAction;
+import sun.security.x509.*;
+import static sun.security.x509.PKIXExtensions.*;
+import sun.security.util.Debug;
+
+class RevocationChecker extends PKIXRevocationChecker {
+
+    private static final Debug debug = Debug.getInstance("certpath");
+
+    private TrustAnchor anchor;
+    private ValidatorParams params;
+    private boolean onlyEE;
+    private boolean softFail;
+    private boolean crlDP;
+    private URI responderURI;
+    private X509Certificate responderCert;
+    private List<CertStore> certStores;
+    private Map<X509Certificate, byte[]> ocspStapled;
+    private List<Extension> ocspExtensions;
+    private boolean legacy;
+
+    // state variables
+    private X509Certificate issuerCert;
+    private PublicKey prevPubKey;
+    private boolean crlSignFlag;
+
+    private enum Mode { PREFER_OCSP, PREFER_CRLS, ONLY_CRLS };
+    private Mode mode = Mode.PREFER_OCSP;
+
+    private static class RevocationProperties {
+        boolean onlyEE;
+        boolean ocspEnabled;
+        boolean crlDPEnabled;
+        String ocspUrl;
+        String ocspSubject;
+        String ocspIssuer;
+        String ocspSerial;
+    }
+
+    RevocationChecker() {
+        legacy = false;
+    }
+
+    RevocationChecker(TrustAnchor anchor, ValidatorParams params)
+        throws CertPathValidatorException
+    {
+        legacy = true;
+        init(anchor, params);
+    }
+
+    void init(TrustAnchor anchor, ValidatorParams params)
+        throws CertPathValidatorException
+    {
+        RevocationProperties rp = getRevocationProperties();
+        URI uri = getOCSPResponder();
+        responderURI = (uri == null) ? toURI(rp.ocspUrl) : uri;
+        X509Certificate cert = getOCSPResponderCert();
+        responderCert = (cert == null)
+                        ? getResponderCert(rp, params.trustAnchors(),
+                                           params.certStores())
+                        : cert;
+        Set<Option> options = getOptions();
+        for (Option option : options) {
+            switch (option) {
+            case ONLY_END_ENTITY:
+            case PREFER_CRLS:
+            case SOFT_FAIL:
+                break;
+            default:
+                throw new CertPathValidatorException(
+                    "Unrecognized revocation parameter option: " + option);
+            }
+        }
+
+        // set mode, only end entity flag
+        if (legacy) {
+            mode = (rp.ocspEnabled) ? Mode.PREFER_OCSP : Mode.ONLY_CRLS;
+            onlyEE = rp.onlyEE;
+        } else {
+            if (options.contains(Option.PREFER_CRLS)) {
+                mode = Mode.PREFER_CRLS;
+            }
+            onlyEE = options.contains(Option.ONLY_END_ENTITY);
+        }
+        softFail = options.contains(Option.SOFT_FAIL);
+        if (legacy) {
+            crlDP = rp.crlDPEnabled;
+        } else {
+            crlDP = true;
+        }
+        ocspStapled = getOCSPStapledResponses();
+        ocspExtensions = getOCSPExtensions();
+
+        this.anchor = anchor;
+        this.params = params;
+        this.certStores = new ArrayList<>(params.certStores());
+        try {
+            this.certStores.add(CertStore.getInstance("Collection",
+                new CollectionCertStoreParameters(params.certificates())));
+        } catch (InvalidAlgorithmParameterException |
+                 NoSuchAlgorithmException e) {
+            // should never occur but not necessarily fatal, so log it,
+            // ignore and continue
+            if (debug != null) {
+                debug.println("RevocationChecker: " +
+                              "error creating Collection CertStore: " + e);
+            }
+        }
+    }
+
+    private static URI toURI(String uriString)
+        throws CertPathValidatorException
+    {
+        try {
+            if (uriString != null) {
+                return new URI(uriString);
+            }
+            return null;
+        } catch (URISyntaxException e) {
+            throw new CertPathValidatorException(
+                "cannot parse ocsp.responderURL property", e);
+        }
+    }
+
+    private static RevocationProperties getRevocationProperties() {
+        return AccessController.doPrivileged(
+            new PrivilegedAction<RevocationProperties>() {
+                public RevocationProperties run() {
+                    RevocationProperties rp = new RevocationProperties();
+                    String onlyEE = Security.getProperty(
+                        "com.sun.security.onlyCheckRevocationOfEECert");
+                    rp.onlyEE = onlyEE != null
+                                && onlyEE.equalsIgnoreCase("true");
+                    String ocspEnabled = Security.getProperty("ocsp.enable");
+                    rp.ocspEnabled = ocspEnabled != null
+                                     && ocspEnabled.equalsIgnoreCase("true");
+                    rp.ocspUrl = Security.getProperty("ocsp.responderURL");
+                    rp.ocspSubject
+                        = Security.getProperty("ocsp.responderCertSubjectName");
+                    rp.ocspIssuer
+                        = Security.getProperty("ocsp.responderCertIssuerName");
+                    rp.ocspSerial
+                        = Security.getProperty("ocsp.responderCertSerialNumber");
+                    rp.crlDPEnabled
+                        = Boolean.getBoolean("com.sun.security.enableCRLDP");
+                    return rp;
+                }
+            }
+        );
+    }
+
+    private static X509Certificate getResponderCert(RevocationProperties rp,
+                                                    Set<TrustAnchor> anchors,
+                                                    List<CertStore> stores)
+        throws CertPathValidatorException
+    {
+        if (rp.ocspSubject != null) {
+            return getResponderCert(rp.ocspSubject, anchors, stores);
+        } else if (rp.ocspIssuer != null && rp.ocspSerial != null) {
+            return getResponderCert(rp.ocspIssuer, rp.ocspSerial,
+                                    anchors, stores);
+        } else if (rp.ocspIssuer != null || rp.ocspSerial != null) {
+            throw new CertPathValidatorException(
+                "Must specify both ocsp.responderCertIssuerName and " +
+                "ocsp.responderCertSerialNumber properties");
+        }
+        return null;
+    }
+
+    private static X509Certificate getResponderCert(String subject,
+                                                    Set<TrustAnchor> anchors,
+                                                    List<CertStore> stores)
+        throws CertPathValidatorException
+    {
+        X509CertSelector sel = new X509CertSelector();
+        try {
+            sel.setSubject(new X500Principal(subject));
+        } catch (IllegalArgumentException e) {
+            throw new CertPathValidatorException(
+                "cannot parse ocsp.responderCertSubjectName property", e);
+        }
+        return getResponderCert(sel, anchors, stores);
+    }
+
+    private static X509Certificate getResponderCert(String issuer,
+                                                    String serial,
+                                                    Set<TrustAnchor> anchors,
+                                                    List<CertStore> stores)
+        throws CertPathValidatorException
+    {
+        X509CertSelector sel = new X509CertSelector();
+        try {
+            sel.setIssuer(new X500Principal(issuer));
+        } catch (IllegalArgumentException e) {
+            throw new CertPathValidatorException(
+                "cannot parse ocsp.responderCertIssuerName property", e);
+        }
+        try {
+            sel.setSerialNumber(new BigInteger(stripOutSeparators(serial), 16));
+        } catch (NumberFormatException e) {
+            throw new CertPathValidatorException(
+                "cannot parse ocsp.responderCertSerialNumber property", e);
+        }
+        return getResponderCert(sel, anchors, stores);
+    }
+
+    private static X509Certificate getResponderCert(X509CertSelector sel,
+                                                    Set<TrustAnchor> anchors,
+                                                    List<CertStore> stores)
+        throws CertPathValidatorException
+    {
+        // first check TrustAnchors
+        for (TrustAnchor anchor : anchors) {
+            X509Certificate cert = anchor.getTrustedCert();
+            if (cert == null) {
+                continue;
+            }
+            if (sel.match(cert)) {
+                return cert;
+            }
+        }
+        // now check CertStores
+        for (CertStore store : stores) {
+            try {
+                Collection<? extends Certificate> certs =
+                    store.getCertificates(sel);
+                if (!certs.isEmpty()) {
+                    return (X509Certificate)certs.iterator().next();
+                }
+            } catch (CertStoreException e) {
+                // ignore and try next CertStore
+                if (debug != null) {
+                    debug.println("CertStore exception:" + e);
+                }
+                continue;
+            }
+        }
+        throw new CertPathValidatorException(
+            "Cannot find the responder's certificate " +
+            "(set using the OCSP security properties).");
+    }
+
+    @Override
+    public void init(boolean forward) throws CertPathValidatorException {
+        if (forward) {
+            throw new
+                CertPathValidatorException("forward checking not supported");
+        } else {
+            if (anchor != null) {
+                issuerCert = anchor.getTrustedCert();
+                prevPubKey = (issuerCert != null) ? issuerCert.getPublicKey()
+                                                  : anchor.getCAPublicKey();
+            }
+            crlSignFlag = true;
+        }
+    }
+
+    @Override
+    public boolean isForwardCheckingSupported() {
+        return false;
+    }
+
+    @Override
+    public Set<String> getSupportedExtensions() {
+        return null;
+    }
+
+    @Override
+    public void check(Certificate cert, Collection<String> unresolvedCritExts)
+        throws CertPathValidatorException
+    {
+        X509Certificate xcert = (X509Certificate)cert;
+        if (onlyEE && xcert.getBasicConstraints() != -1) {
+            if (debug != null) {
+                debug.println("Skipping revocation check, not end entity cert");
+            }
+        } else {
+            check(xcert, unresolvedCritExts, prevPubKey, crlSignFlag);
+        }
+        updateState(xcert);
+    }
+
+    void check(X509Certificate xcert, Collection<String> unresolvedCritExts,
+               PublicKey pubKey, boolean crlSignFlag)
+        throws CertPathValidatorException
+    {
+        try {
+            switch (mode) {
+                case PREFER_OCSP:
+                    checkOCSP(xcert, unresolvedCritExts);
+                    break;
+                case PREFER_CRLS:
+                case ONLY_CRLS:
+                    checkCRLs(xcert, unresolvedCritExts, null,
+                              pubKey, crlSignFlag);
+                    break;
+            }
+        } catch (CertPathValidatorException e) {
+            if (e.getReason() == BasicReason.REVOKED) {
+                throw e;
+            }
+            CertPathValidatorException cause = e;
+            if (softFail && e instanceof NetworkFailureException) {
+                if (mode == Mode.ONLY_CRLS) return;
+            }
+            // Rethrow the exception if ONLY_CRLS
+            if (mode == Mode.ONLY_CRLS) {
+                throw e;
+            }
+            // Otherwise, failover
+            if (debug != null) {
+                debug.println("RevocationChecker.check() " + e.getMessage());
+                debug.println("RevocationChecker.check() preparing to failover");
+            }
+            try {
+                switch (mode) {
+                    case PREFER_OCSP:
+                        checkCRLs(xcert, unresolvedCritExts, null,
+                                  pubKey, crlSignFlag);
+                        break;
+                    case PREFER_CRLS:
+                        checkOCSP(xcert, unresolvedCritExts);
+                        break;
+                }
+            } catch (CertPathValidatorException x) {
+                if (debug != null) {
+                    debug.println("RevocationChecker.check() failover failed");
+                    debug.println("RevocationChecker.check() " + x.getMessage());
+                }
+                if (x.getReason() == BasicReason.REVOKED) {
+                    throw x;
+                }
+                if (cause != null) {
+                    if (softFail && cause instanceof NetworkFailureException) {
+                        return;
+                    } else {
+                        cause.addSuppressed(x);
+                        throw cause;
+                    }
+                }
+                if (softFail && x instanceof NetworkFailureException) {
+                    return;
+                }
+                throw x;
+            }
+        }
+    }
+
+    private void updateState(X509Certificate cert)
+        throws CertPathValidatorException
+    {
+        issuerCert = cert;
+
+        // Make new public key if parameters are missing
+        PublicKey pubKey = cert.getPublicKey();
+        if (pubKey instanceof DSAPublicKey &&
+            ((DSAPublicKey)pubKey).getParams() == null) {
+            // pubKey needs to inherit DSA parameters from prev key
+            pubKey = BasicChecker.makeInheritedParamsKey(pubKey, prevPubKey);
+        }
+        prevPubKey = pubKey;
+        crlSignFlag = certCanSignCrl(cert);
+    }
+
+    // Maximum clock skew in milliseconds (15 minutes) allowed when checking
+    // validity of CRLs
+    private static final long MAX_CLOCK_SKEW = 900000;
+    private void checkCRLs(X509Certificate cert,
+                           Collection<String> unresolvedCritExts,
+                           Set<X509Certificate> stackedCerts,
+                           PublicKey pubKey, boolean signFlag)
+        throws CertPathValidatorException
+    {
+        checkCRLs(cert, pubKey, signFlag, true,
+                  stackedCerts, params.trustAnchors());
+    }
+
+    private void checkCRLs(X509Certificate cert, PublicKey prevKey,
+                           boolean signFlag, boolean allowSeparateKey,
+                           Set<X509Certificate> stackedCerts,
+                           Set<TrustAnchor> anchors)
+        throws CertPathValidatorException
+    {
+        if (debug != null) {
+            debug.println("RevocationChecker.checkCRLs()" +
+                          " ---checking revocation status ...");
+        }
+
+        // reject circular dependencies - RFC 3280 is not explicit on how
+        // to handle this, so we feel it is safest to reject them until
+        // the issue is resolved in the PKIX WG.
+        if (stackedCerts != null && stackedCerts.contains(cert)) {
+            if (debug != null) {
+                debug.println("RevocationChecker.checkCRLs()" +
+                              " circular dependency");
+            }
+            throw new CertPathValidatorException
+                ("Could not determine revocation status", null, null, -1,
+                 BasicReason.UNDETERMINED_REVOCATION_STATUS);
+        }
+
+        Set<X509CRL> possibleCRLs = new HashSet<>();
+        Set<X509CRL> approvedCRLs = new HashSet<>();
+        X509CRLSelector sel = new X509CRLSelector();
+        sel.setCertificateChecking(cert);
+        CertPathHelper.setDateAndTime(sel, params.date(), MAX_CLOCK_SKEW);
+
+        // First, check cached CRLs
+        for (CertStore store : certStores) {
+            try {
+                for (CRL crl : store.getCRLs(sel)) {
+                    possibleCRLs.add((X509CRL)crl);
+                }
+            } catch (CertStoreException e) {
+                // XXX ignore?
+            }
+        }
+
+        if (debug != null) {
+            debug.println("RevocationChecker.checkCRLs() " +
+                          "possible crls.size() = " + possibleCRLs.size());
+        }
+        boolean[] reasonsMask = new boolean[9];
+        if (!possibleCRLs.isEmpty()) {
+            // Now that we have a list of possible CRLs, see which ones can
+            // be approved
+            approvedCRLs.addAll(verifyPossibleCRLs(possibleCRLs, cert, prevKey,
+                                                   signFlag, reasonsMask,
+                                                   anchors));
+        }
+
+        if (debug != null) {
+            debug.println("RevocationChecker.checkCRLs() " +
+                          "approved crls.size() = " + approvedCRLs.size());
+        }
+
+        // make sure that we have at least one CRL that _could_ cover
+        // the certificate in question and all reasons are covered
+        if (!approvedCRLs.isEmpty() &&
+            Arrays.equals(reasonsMask, ALL_REASONS))
+        {
+            checkApprovedCRLs(cert, approvedCRLs);
+        } else {
+            // Check Distribution Points
+            // all CRLs returned by the DP Fetcher have also been verified
+            try {
+                if (crlDP) {
+                    approvedCRLs.addAll(DistributionPointFetcher.getCRLs(
+                                        sel, signFlag, prevKey,
+                                        params.sigProvider(), certStores,
+                                        reasonsMask, anchors, params.date()));
+                }
+            } catch (CertStoreException e) {
+                if (debug != null) {
+                    debug.println("RevocationChecker.checkCRLs() " +
+                                  "unexpected exception: " + e.getMessage());
+                }
+                throw new CertPathValidatorException(e);
+            }
+            if (!approvedCRLs.isEmpty() &&
+                Arrays.equals(reasonsMask, ALL_REASONS))
+            {
+                checkApprovedCRLs(cert, approvedCRLs);
+            } else {
+                if (allowSeparateKey) {
+                    verifyWithSeparateSigningKey(cert, prevKey, signFlag,
+                                                 stackedCerts);
+                    return;
+                } else {
+                    throw new CertPathValidatorException
+                    ("Could not determine revocation status", null, null, -1,
+                     BasicReason.UNDETERMINED_REVOCATION_STATUS);
+                }
+            }
+        }
+    }
+
+    private void checkApprovedCRLs(X509Certificate cert,
+                                   Set<X509CRL> approvedCRLs)
+        throws CertPathValidatorException
+    {
+        // See if the cert is in the set of approved crls.
+        if (debug != null) {
+            BigInteger sn = cert.getSerialNumber();
+            debug.println("RevocationChecker.checkApprovedCRLs() " +
+                          "starting the final sweep...");
+            debug.println("RevocationChecker.checkApprovedCRLs()" +
+                          " cert SN: " + sn.toString());
+        }
+
+        CRLReason reasonCode = CRLReason.UNSPECIFIED;
+        X509CRLEntryImpl entry = null;
+        for (X509CRL crl : approvedCRLs) {
+            X509CRLEntry e = crl.getRevokedCertificate(cert);
+            if (e != null) {
+                try {
+                    entry = X509CRLEntryImpl.toImpl(e);
+                } catch (CRLException ce) {
+                    throw new CertPathValidatorException(ce);
+                }
+                if (debug != null) {
+                    debug.println("RevocationChecker.checkApprovedCRLs()"
+                        + " CRL entry: " + entry.toString());
+                }
+
+                /*
+                 * Abort CRL validation and throw exception if there are any
+                 * unrecognized critical CRL entry extensions (see section
+                 * 5.3 of RFC 3280).
+                 */
+                Set<String> unresCritExts = entry.getCriticalExtensionOIDs();
+                if (unresCritExts != null && !unresCritExts.isEmpty()) {
+                    /* remove any that we will process */
+                    unresCritExts.remove(ReasonCode_Id.toString());
+                    unresCritExts.remove(CertificateIssuer_Id.toString());
+                    if (!unresCritExts.isEmpty()) {
+                        if (debug != null) {
+                            debug.println("Unrecognized "
+                            + "critical extension(s) in revoked CRL entry: "
+                            + unresCritExts);
+                        }
+                        throw new CertPathValidatorException
+                        ("Could not determine revocation status", null, null,
+                         -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
+                    }
+                }
+
+                reasonCode = entry.getRevocationReason();
+                if (reasonCode == null) {
+                    reasonCode = CRLReason.UNSPECIFIED;
+                }
+                Throwable t = new CertificateRevokedException
+                    (entry.getRevocationDate(), reasonCode,
+                     crl.getIssuerX500Principal(), entry.getExtensions());
+                throw new CertPathValidatorException(t.getMessage(), t,
+                    null, -1, BasicReason.REVOKED);
+            }
+        }
+    }
+
+    private void checkOCSP(X509Certificate cert,
+                           Collection<String> unresolvedCritExts)
+        throws CertPathValidatorException
+    {
+        X509CertImpl currCert = null;
+        try {
+            currCert = X509CertImpl.toImpl(cert);
+        } catch (CertificateException ce) {
+            throw new CertPathValidatorException(ce);
+        }
+
+        URI responderURI = (this.responderURI != null)
+                           ? this.responderURI : getOCSPServerURI(currCert);
+
+        X509Certificate respCert = (responderCert == null) ? issuerCert
+                                                           : responderCert;
+
+        // The algorithm constraints of the OCSP trusted responder certificate
+        // does not need to be checked in this code. The constraints will be
+        // checked when the responder's certificate is validated.
+
+        OCSPResponse response = null;
+        CertId certId = null;
+        try {
+            certId = new CertId(issuerCert, currCert.getSerialNumberObject());
+
+            // check if there is a stapled OCSP response available
+            byte[] responseBytes = ocspStapled.get(cert);
+            if (responseBytes != null) {
+                if (debug != null) {
+                    debug.println("Found stapled OCSP response");
+                }
+                response = new OCSPResponse(responseBytes);
+
+                // verify the response
+                byte[] nonce = null;
+                for (Extension ext : ocspExtensions) {
+                    if (ext.getId().equals("1.3.6.1.5.5.7.48.1.2")) {
+                        nonce = ext.getValue();
+                    }
+                }
+                response.verify(Collections.singletonList(certId), respCert,
+                                params.date(), nonce);
+
+            } else {
+                response = OCSP.check(Collections.singletonList(certId),
+                                      responderURI, respCert, params.date(),
+                                      ocspExtensions);
+            }
+        } catch (IOException e) {
+            throw new CertPathValidatorException(e);
+        }
+
+        RevocationStatus rs =
+            (RevocationStatus)response.getSingleResponse(certId);
+        RevocationStatus.CertStatus certStatus = rs.getCertStatus();
+        if (certStatus == RevocationStatus.CertStatus.REVOKED) {
+            Throwable t = new CertificateRevokedException(
+                rs.getRevocationTime(), rs.getRevocationReason(),
+                respCert.getSubjectX500Principal(), rs.getSingleExtensions());
+            throw new CertPathValidatorException(t.getMessage(), t, null,
+                                                 -1, BasicReason.REVOKED);
+        } else if (certStatus == RevocationStatus.CertStatus.UNKNOWN) {
+            throw new CertPathValidatorException(
+                "Certificate's revocation status is unknown", null,
+                params.certPath(), -1,
+                BasicReason.UNDETERMINED_REVOCATION_STATUS);
+        }
+    }
+
+    /*
+     * Removes any non-hexadecimal characters from a string.
+     */
+    private static final String HEX_DIGITS = "0123456789ABCDEFabcdef";
+    private static String stripOutSeparators(String value) {
+        char[] chars = value.toCharArray();
+        StringBuilder hexNumber = new StringBuilder();
+        for (int i = 0; i < chars.length; i++) {
+            if (HEX_DIGITS.indexOf(chars[i]) != -1) {
+                hexNumber.append(chars[i]);
+            }
+        }
+        return hexNumber.toString();
+    }
+
+    private static URI getOCSPServerURI(X509CertImpl cert)
+        throws CertPathValidatorException
+    {
+        // Examine the certificate's AuthorityInfoAccess extension
+        AuthorityInfoAccessExtension aia =
+            cert.getAuthorityInfoAccessExtension();
+        if (aia == null) {
+            throw new CertPathValidatorException(
+                "Must specify the location of an OCSP Responder");
+        }
+
+        List<AccessDescription> descriptions = aia.getAccessDescriptions();
+        for (AccessDescription description : descriptions) {
+            if (description.getAccessMethod().equals((Object)
+                AccessDescription.Ad_OCSP_Id)) {
+
+                GeneralName generalName = description.getAccessLocation();
+                if (generalName.getType() == GeneralNameInterface.NAME_URI) {
+                    URIName uri = (URIName)generalName.getName();
+                    return uri.getURI();
+                }
+            }
+        }
+
+        throw new CertPathValidatorException(
+            "Cannot find the location of the OCSP Responder");
+    }
+
+    /**
+     * Checks that a cert can be used to verify a CRL.
+     *
+     * @param cert an X509Certificate to check
+     * @return a boolean specifying if the cert is allowed to vouch for the
+     *         validity of a CRL
+     */
+    static boolean certCanSignCrl(X509Certificate cert) {
+        // if the cert doesn't include the key usage ext, or
+        // the key usage ext asserts cRLSigning, return true,
+        // otherwise return false.
+        boolean[] keyUsage = cert.getKeyUsage();
+        if (keyUsage != null) {
+            return keyUsage[6];
+        }
+        return false;
+    }
+
+    /**
+     * Internal method that verifies a set of possible_crls,
+     * and sees if each is approved, based on the cert.
+     *
+     * @param crls a set of possible CRLs to test for acceptability
+     * @param cert the certificate whose revocation status is being checked
+     * @param signFlag <code>true</code> if prevKey was trusted to sign CRLs
+     * @param prevKey the public key of the issuer of cert
+     * @param reasonsMask the reason code mask
+     * @param trustAnchors a <code>Set</code> of <code>TrustAnchor</code>s>
+     * @return a collection of approved crls (or an empty collection)
+     */
+    private static final boolean[] ALL_REASONS =
+        {true, true, true, true, true, true, true, true, true};
+    private Collection<X509CRL> verifyPossibleCRLs(Set<X509CRL> crls,
+                                                   X509Certificate cert,
+                                                   PublicKey prevKey,
+                                                   boolean signFlag,
+                                                   boolean[] reasonsMask,
+                                                   Set<TrustAnchor> anchors)
+        throws CertPathValidatorException
+    {
+        try {
+            X509CertImpl certImpl = X509CertImpl.toImpl(cert);
+            if (debug != null) {
+                debug.println("RevocationChecker.verifyPossibleCRLs: " +
+                              "Checking CRLDPs for "
+                              + certImpl.getSubjectX500Principal());
+            }
+            CRLDistributionPointsExtension ext =
+                certImpl.getCRLDistributionPointsExtension();
+            List<DistributionPoint> points = null;
+            if (ext == null) {
+                // assume a DP with reasons and CRLIssuer fields omitted
+                // and a DP name of the cert issuer.
+                // TODO add issuerAltName too
+                X500Name certIssuer = (X500Name)certImpl.getIssuerDN();
+                DistributionPoint point = new DistributionPoint(
+                     new GeneralNames().add(new GeneralName(certIssuer)),
+                     null, null);
+                points = Collections.singletonList(point);
+            } else {
+                points = ext.get(CRLDistributionPointsExtension.POINTS);
+            }
+            Set<X509CRL> results = new HashSet<>();
+            for (DistributionPoint point : points) {
+                for (X509CRL crl : crls) {
+                    if (DistributionPointFetcher.verifyCRL(
+                            certImpl, point, crl, reasonsMask, signFlag,
+                            prevKey, params.sigProvider(), anchors,
+                            certStores, params.date()))
+                    {
+                        results.add(crl);
+                    }
+                }
+                if (Arrays.equals(reasonsMask, ALL_REASONS))
+                    break;
+            }
+            return results;
+        } catch (CertificateException | CRLException | IOException e) {
+            if (debug != null) {
+                debug.println("Exception while verifying CRL: "+e.getMessage());
+                e.printStackTrace();
+            }
+            return Collections.emptySet();
+        }
+    }
+
+    /**
+     * We have a cert whose revocation status couldn't be verified by
+     * a CRL issued by the cert that issued the CRL. See if we can
+     * find a valid CRL issued by a separate key that can verify the
+     * revocation status of this certificate.
+     * <p>
+     * Note that this does not provide support for indirect CRLs,
+     * only CRLs signed with a different key (but the same issuer
+     * name) as the certificate being checked.
+     *
+     * @param currCert the <code>X509Certificate</code> to be checked
+     * @param prevKey the <code>PublicKey</code> that failed
+     * @param signFlag <code>true</code> if that key was trusted to sign CRLs
+     * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
+     *                     whose revocation status depends on the
+     *                     non-revoked status of this cert. To avoid
+     *                     circular dependencies, we assume they're
+     *                     revoked while checking the revocation
+     *                     status of this cert.
+     * @throws CertPathValidatorException if the cert's revocation status
+     *         cannot be verified successfully with another key
+     */
+    private void verifyWithSeparateSigningKey(X509Certificate cert,
+                                              PublicKey prevKey,
+                                              boolean signFlag,
+                                              Set<X509Certificate> stackedCerts)
+        throws CertPathValidatorException
+    {
+        String msg = "revocation status";
+        if (debug != null) {
+            debug.println(
+                "RevocationChecker.verifyWithSeparateSigningKey()" +
+                " ---checking " + msg + "...");
+        }
+
+        // reject circular dependencies - RFC 3280 is not explicit on how
+        // to handle this, so we feel it is safest to reject them until
+        // the issue is resolved in the PKIX WG.
+        if ((stackedCerts != null) && stackedCerts.contains(cert)) {
+            if (debug != null) {
+                debug.println(
+                    "RevocationChecker.verifyWithSeparateSigningKey()" +
+                    " circular dependency");
+            }
+            throw new CertPathValidatorException
+                ("Could not determine revocation status", null, null,
+                 -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
+        }
+
+        // Try to find another key that might be able to sign
+        // CRLs vouching for this cert.
+        // If prevKey wasn't trusted, maybe we just didn't have the right
+        // path to it. Don't rule that key out.
+        if (!signFlag) {
+            buildToNewKey(cert, null, stackedCerts);
+        } else {
+            buildToNewKey(cert, prevKey, stackedCerts);
+        }
+    }
+
+    /**
+     * Tries to find a CertPath that establishes a key that can be
+     * used to verify the revocation status of a given certificate.
+     * Ignores keys that have previously been tried. Throws a
+     * CertPathValidatorException if no such key could be found.
+     *
+     * @param currCert the <code>X509Certificate</code> to be checked
+     * @param prevKey the <code>PublicKey</code> of the certificate whose key
+     *    cannot be used to vouch for the CRL and should be ignored
+     * @param stackedCerts a <code>Set</code> of <code>X509Certificate</code>s>
+     *                     whose revocation status depends on the
+     *                     establishment of this path.
+     * @throws CertPathValidatorException on failure
+     */
+    private static final boolean [] CRL_SIGN_USAGE =
+        { false, false, false, false, false, false, true };
+    private void buildToNewKey(X509Certificate currCert,
+                               PublicKey prevKey,
+                               Set<X509Certificate> stackedCerts)
+        throws CertPathValidatorException
+    {
+
+        if (debug != null) {
+            debug.println("RevocationChecker.buildToNewKey()" +
+                          " starting work");
+        }
+        Set<PublicKey> badKeys = new HashSet<>();
+        if (prevKey != null) {
+            badKeys.add(prevKey);
+        }
+        X509CertSelector certSel = new RejectKeySelector(badKeys);
+        certSel.setSubject(currCert.getIssuerX500Principal());
+        certSel.setKeyUsage(CRL_SIGN_USAGE);
+
+        Set<TrustAnchor> newAnchors = anchor == null ?
+                                      params.trustAnchors() :
+                                      Collections.singleton(anchor);
+
+        PKIXBuilderParameters builderParams;
+        try {
+            builderParams = new PKIXBuilderParameters(newAnchors, certSel);
+        } catch (InvalidAlgorithmParameterException iape) {
+            throw new RuntimeException(iape); // should never occur
+        }
+        builderParams.setInitialPolicies(params.initialPolicies());
+        builderParams.setCertStores(certStores);
+        builderParams.setExplicitPolicyRequired
+            (params.explicitPolicyRequired());
+        builderParams.setPolicyMappingInhibited
+            (params.policyMappingInhibited());
+        builderParams.setAnyPolicyInhibited(params.anyPolicyInhibited());
+        // Policy qualifiers must be rejected, since we don't have
+        // any way to convey them back to the application.
+        // That's the default, so no need to write code.
+        builderParams.setDate(params.date());
+        // CertPathCheckers need to be cloned to start from fresh state
+        builderParams.setCertPathCheckers(
+            params.getPKIXParameters().getCertPathCheckers());
+        builderParams.setSigProvider(params.sigProvider());
+
+        // Skip revocation during this build to detect circular
+        // references. But check revocation afterwards, using the
+        // key (or any other that works).
+        builderParams.setRevocationEnabled(false);
+
+        // check for AuthorityInformationAccess extension
+        if (Builder.USE_AIA == true) {
+            X509CertImpl currCertImpl = null;
+            try {
+                currCertImpl = X509CertImpl.toImpl(currCert);
+            } catch (CertificateException ce) {
+                // ignore but log it
+                if (debug != null) {
+                    debug.println("RevocationChecker.buildToNewKey: " +
+                                  "error decoding cert: " + ce);
+                }
+            }
+            AuthorityInfoAccessExtension aiaExt = null;
+            if (currCertImpl != null) {
+                aiaExt = currCertImpl.getAuthorityInfoAccessExtension();
+            }
+            if (aiaExt != null) {
+                List<AccessDescription> adList = aiaExt.getAccessDescriptions();
+                if (adList != null) {
+                    for (AccessDescription ad : adList) {
+                        CertStore cs = URICertStore.getInstance(ad);
+                        if (cs != null) {
+                            if (debug != null) {
+                                debug.println("adding AIAext CertStore");
+                            }
+                            builderParams.addCertStore(cs);
+                        }
+                    }
+                }
+            }
+        }
+
+        CertPathBuilder builder = null;
+        try {
+            builder = CertPathBuilder.getInstance("PKIX");
+        } catch (NoSuchAlgorithmException nsae) {
+            throw new CertPathValidatorException(nsae);
+        }
+        while (true) {
+            try {
+                if (debug != null) {
+                    debug.println("RevocationChecker.buildToNewKey()" +
+                                  " about to try build ...");
+                }
+                PKIXCertPathBuilderResult cpbr =
+                    (PKIXCertPathBuilderResult)builder.build(builderParams);
+
+                if (debug != null) {
+                    debug.println("RevocationChecker.buildToNewKey()" +
+                                  " about to check revocation ...");
+                }
+                // Now check revocation of all certs in path, assuming that
+                // the stackedCerts are revoked.
+                if (stackedCerts == null) {
+                    stackedCerts = new HashSet<X509Certificate>();
+                }
+                stackedCerts.add(currCert);
+                TrustAnchor ta = cpbr.getTrustAnchor();
+                PublicKey prevKey2 = ta.getCAPublicKey();
+                if (prevKey2 == null) {
+                    prevKey2 = ta.getTrustedCert().getPublicKey();
+                }
+                boolean signFlag = true;
+                List<? extends Certificate> cpList =
+                    cpbr.getCertPath().getCertificates();
+                try {
+                    for (int i = cpList.size()-1; i >= 0; i-- ) {
+                        X509Certificate cert = (X509Certificate)cpList.get(i);
+
+                        if (debug != null) {
+                            debug.println("RevocationChecker.buildToNewKey()"
+                                          + " index " + i + " checking "
+                                          + cert);
+                        }
+                        checkCRLs(cert, prevKey2, signFlag, true,
+                                  stackedCerts, newAnchors);
+                        signFlag = certCanSignCrl(cert);
+                        prevKey2 = cert.getPublicKey();
+                    }
+                } catch (CertPathValidatorException cpve) {
+                    // ignore it and try to get another key
+                    badKeys.add(cpbr.getPublicKey());
+                    continue;
+                }
+
+                if (debug != null) {
+                    debug.println("RevocationChecker.buildToNewKey()" +
+                                  " got key " + cpbr.getPublicKey());
+                }
+                // Now check revocation on the current cert using that key.
+                // If it doesn't check out, try to find a different key.
+                // And if we can't find a key, then return false.
+                PublicKey newKey = cpbr.getPublicKey();
+                try {
+                    checkCRLs(currCert, newKey, true, false, null,
+                              params.trustAnchors());
+                    // If that passed, the cert is OK!
+                    return;
+                } catch (CertPathValidatorException cpve) {
+                    // If it is revoked, rethrow exception
+                    if (cpve.getReason() == BasicReason.REVOKED) {
+                        throw cpve;
+                    }
+                    // Otherwise, ignore the exception and
+                    // try to get another key.
+                }
+                badKeys.add(newKey);
+            } catch (InvalidAlgorithmParameterException iape) {
+                throw new CertPathValidatorException(iape);
+            } catch (CertPathBuilderException cpbe) {
+                throw new CertPathValidatorException
+                    ("Could not determine revocation status", null, null,
+                     -1, BasicReason.UNDETERMINED_REVOCATION_STATUS);
+            }
+        }
+    }
+
+    /*
+     * This inner class extends the X509CertSelector to add an additional
+     * check to make sure the subject public key isn't on a particular list.
+     * This class is used by buildToNewKey() to make sure the builder doesn't
+     * end up with a CertPath to a public key that has already been rejected.
+     */
+    private static class RejectKeySelector extends X509CertSelector {
+        private final Set<PublicKey> badKeySet;
+
+        /**
+         * Creates a new <code>RejectKeySelector</code>.
+         *
+         * @param badPublicKeys a <code>Set</code> of
+         *                      <code>PublicKey</code>s that
+         *                      should be rejected (or <code>null</code>
+         *                      if no such check should be done)
+         */
+        RejectKeySelector(Set<PublicKey> badPublicKeys) {
+            this.badKeySet = badPublicKeys;
+        }
+
+        /**
+         * Decides whether a <code>Certificate</code> should be selected.
+         *
+         * @param cert the <code>Certificate</code> to be checked
+         * @return <code>true</code> if the <code>Certificate</code> should be
+         *         selected, <code>false</code> otherwise
+         */
+        @Override
+        public boolean match(Certificate cert) {
+            if (!super.match(cert))
+                return(false);
+
+            if (badKeySet.contains(cert.getPublicKey())) {
+                if (debug != null)
+                    debug.println("RejectKeySelector.match: bad key");
+                return false;
+            }
+
+            if (debug != null)
+                debug.println("RejectKeySelector.match: returning true");
+            return true;
+        }
+
+        /**
+         * Return a printable representation of the <code>CertSelector</code>.
+         *
+         * @return a <code>String</code> describing the contents of the
+         *         <code>CertSelector</code>
+         */
+        @Override
+        public String toString() {
+            StringBuilder sb = new StringBuilder();
+            sb.append("RejectKeySelector: [\n");
+            sb.append(super.toString());
+            sb.append(badKeySet);
+            sb.append("]");
+            return sb.toString();
+        }
+    }
+}
--- a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilder.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -26,10 +26,8 @@
 package sun.security.provider.certpath;
 
 import java.io.IOException;
-import java.security.AccessController;
 import java.security.GeneralSecurityException;
 import java.security.InvalidAlgorithmParameterException;
-import java.security.Principal;
 import java.security.PublicKey;
 import java.security.cert.*;
 import java.security.cert.PKIXReason;
@@ -37,7 +35,6 @@
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
@@ -45,9 +42,8 @@
 import java.util.Set;
 import javax.security.auth.x500.X500Principal;
 
-import sun.security.action.GetBooleanSecurityPropertyAction;
-import sun.security.x509.X500Name;
-import sun.security.x509.PKIXExtensions;
+import sun.security.provider.certpath.PKIX.BuilderParams;
+import static sun.security.x509.PKIXExtensions.*;
 import sun.security.util.Debug;
 
 /**
@@ -78,16 +74,12 @@
     /*
      * private objects shared by methods
      */
-    private PKIXBuilderParameters buildParams;
+    private BuilderParams buildParams;
     private CertificateFactory cf;
     private boolean pathCompleted = false;
-    private X500Principal targetSubjectDN;
     private PolicyNode policyTreeResult;
     private TrustAnchor trustAnchor;
     private PublicKey finalPublicKey;
-    private X509CertSelector targetSel;
-    private List<CertStore> orderedCertStores;
-    private boolean onlyEECert = false;
 
     /**
      * Create an instance of <code>SunCertPathBuilder</code>.
@@ -100,9 +92,11 @@
         } catch (CertificateException e) {
             throw new CertPathBuilderException(e);
         }
-        onlyEECert = AccessController.doPrivileged(
-            new GetBooleanSecurityPropertyAction
-                ("com.sun.security.onlyCheckRevocationOfEECert"));
+    }
+
+    @Override
+    public CertPathChecker engineGetRevocationChecker() {
+        return new RevocationChecker();
     }
 
     /**
@@ -125,6 +119,7 @@
      * @throws InvalidAlgorithmParameterException if the given parameters are
      *  inappropriate for this certification path builder.
      */
+    @Override
     public CertPathBuilderResult engineBuild(CertPathParameters params)
         throws CertPathBuilderException, InvalidAlgorithmParameterException {
 
@@ -132,66 +127,20 @@
             debug.println("SunCertPathBuilder.engineBuild(" + params + ")");
         }
 
-        if (!(params instanceof PKIXBuilderParameters)) {
-            throw new InvalidAlgorithmParameterException("inappropriate " +
-                "parameter type, must be an instance of PKIXBuilderParameters");
-        }
-
-        boolean buildForward = true;
-        if (params instanceof SunCertPathBuilderParameters) {
-            buildForward =
-                ((SunCertPathBuilderParameters)params).getBuildForward();
-        }
-
-        buildParams = (PKIXBuilderParameters)params;
-
-        /* Check mandatory parameters */
-
-        // Make sure that none of the trust anchors include name constraints
-        // (not supported).
-        for (TrustAnchor anchor : buildParams.getTrustAnchors()) {
-            if (anchor.getNameConstraints() != null) {
-                throw new InvalidAlgorithmParameterException
-                    ("name constraints in trust anchor not supported");
-            }
-        }
+        buildParams = PKIX.checkBuilderParams(params);
+        return build();
+    }
 
-        CertSelector sel = buildParams.getTargetCertConstraints();
-        if (!(sel instanceof X509CertSelector)) {
-            throw new InvalidAlgorithmParameterException("the "
-                + "targetCertConstraints parameter must be an "
-                + "X509CertSelector");
-        }
-        targetSel = (X509CertSelector)sel;
-        targetSubjectDN = targetSel.getSubject();
-        if (targetSubjectDN == null) {
-            X509Certificate targetCert = targetSel.getCertificate();
-            if (targetCert != null) {
-                targetSubjectDN = targetCert.getSubjectX500Principal();
-            }
-        }
-        // reorder CertStores so that local CertStores are tried first
-        orderedCertStores =
-            new ArrayList<CertStore>(buildParams.getCertStores());
-        Collections.sort(orderedCertStores, new CertStoreComparator());
-        if (targetSubjectDN == null) {
-            targetSubjectDN = getTargetSubjectDN(orderedCertStores, targetSel);
-        }
-        if (targetSubjectDN == null) {
-            throw new InvalidAlgorithmParameterException
-                ("Could not determine unique target subject");
-        }
-
-        List<List<Vertex>> adjList = new ArrayList<List<Vertex>>();
-        CertPathBuilderResult result =
-            buildCertPath(buildForward, false, adjList);
+    private PKIXCertPathBuilderResult build() throws CertPathBuilderException {
+        List<List<Vertex>> adjList = new ArrayList<>();
+        PKIXCertPathBuilderResult result = buildCertPath(false, adjList);
         if (result == null) {
             if (debug != null) {
                 debug.println("SunCertPathBuilder.engineBuild: 2nd pass");
             }
             // try again
             adjList.clear();
-            result = buildCertPath(buildForward, true, adjList);
+            result = buildCertPath(true, adjList);
             if (result == null) {
                 throw new SunCertPathBuilderException("unable to find valid "
                     + "certification path to requested target",
@@ -201,24 +150,23 @@
         return result;
     }
 
-    private CertPathBuilderResult buildCertPath(boolean buildForward,
-        boolean searchAllCertStores, List<List<Vertex>> adjList)
-        throws CertPathBuilderException {
-
+    private PKIXCertPathBuilderResult buildCertPath(boolean searchAllCertStores,
+                                                    List<List<Vertex>> adjList)
+        throws CertPathBuilderException
+    {
         // Init shared variables and build certification path
         pathCompleted = false;
         trustAnchor = null;
         finalPublicKey = null;
         policyTreeResult = null;
-        LinkedList<X509Certificate> certPathList =
-            new LinkedList<X509Certificate>();
+        LinkedList<X509Certificate> certPathList = new LinkedList<>();
         try {
-            if (buildForward) {
+            if (buildParams.buildForward()) {
                 buildForward(adjList, certPathList, searchAllCertStores);
             } else {
                 buildReverse(adjList, certPathList);
             }
-        } catch (Exception e) {
+        } catch (GeneralSecurityException | IOException e) {
             if (debug != null) {
                 debug.println("SunCertPathBuilder.engineBuild() exception in "
                     + "build");
@@ -242,11 +190,11 @@
                 Collections.reverse(certPathList);
 
                 return new SunCertPathBuilderResult(
-                    cf.generateCertPath(certPathList), this.trustAnchor,
+                    cf.generateCertPath(certPathList), trustAnchor,
                     policyTreeResult, finalPublicKey,
                     new AdjacencyList(adjList));
             }
-        } catch (Exception e) {
+        } catch (CertificateException e) {
             if (debug != null) {
                 debug.println("SunCertPathBuilder.engineBuild() exception "
                               + "in wrap-up");
@@ -264,12 +212,13 @@
      * Private build reverse method.
      */
     private void buildReverse(List<List<Vertex>> adjacencyList,
-        LinkedList<X509Certificate> certPathList) throws Exception
+                              LinkedList<X509Certificate> certPathList)
+        throws GeneralSecurityException, IOException
     {
         if (debug != null) {
             debug.println("SunCertPathBuilder.buildReverse()...");
             debug.println("SunCertPathBuilder.buildReverse() InitialPolicies: "
-                + buildParams.getInitialPolicies());
+                + buildParams.initialPolicies());
         }
 
         ReverseState currentState = new ReverseState();
@@ -281,11 +230,11 @@
          * Perform a search using each trust anchor, until a valid
          * path is found
          */
-        Iterator<TrustAnchor> iter = buildParams.getTrustAnchors().iterator();
+        Iterator<TrustAnchor> iter = buildParams.trustAnchors().iterator();
         while (iter.hasNext()) {
             TrustAnchor anchor = iter.next();
             /* check if anchor satisfies target constraints */
-            if (anchorIsTarget(anchor, targetSel)) {
+            if (anchorIsTarget(anchor, buildParams.targetCertConstraints())) {
                 this.trustAnchor = anchor;
                 this.pathCompleted = true;
                 this.finalPublicKey = anchor.getTrustedCert().getPublicKey();
@@ -293,21 +242,15 @@
             }
 
             /* Initialize current state */
-            currentState.initState(buildParams.getMaxPathLength(),
-                       buildParams.isExplicitPolicyRequired(),
-                       buildParams.isPolicyMappingInhibited(),
-                       buildParams.isAnyPolicyInhibited(),
-                       buildParams.getCertPathCheckers());
-            currentState.updateState(anchor);
-            // init the crl checker
-            currentState.crlChecker =
-                new CrlRevocationChecker(null, buildParams, null, onlyEECert);
+            currentState.initState(buildParams);
+            currentState.updateState(anchor, buildParams);
+
             currentState.algorithmChecker = new AlgorithmChecker(anchor);
             try {
                 depthFirstSearchReverse(null, currentState,
-                new ReverseBuilder(buildParams, targetSubjectDN), adjacencyList,
-                certPathList);
-            } catch (Exception e) {
+                                        new ReverseBuilder(buildParams),
+                                        adjacencyList, certPathList);
+            } catch (GeneralSecurityException | IOException e) {
                 // continue on error if more anchors to try
                 if (iter.hasNext())
                     continue;
@@ -331,7 +274,8 @@
      * Private build forward method.
      */
     private void buildForward(List<List<Vertex>> adjacencyList,
-        LinkedList<X509Certificate> certPathList, boolean searchAllCertStores)
+                              LinkedList<X509Certificate> certPathList,
+                              boolean searchAllCertStores)
         throws GeneralSecurityException, IOException
     {
         if (debug != null) {
@@ -340,20 +284,16 @@
 
         /* Initialize current state */
         ForwardState currentState = new ForwardState();
-        currentState.initState(buildParams.getCertPathCheckers());
+        currentState.initState(buildParams.certPathCheckers());
 
         /* Initialize adjacency list */
         adjacencyList.clear();
         adjacencyList.add(new LinkedList<Vertex>());
 
-        // init the crl checker
-        currentState.crlChecker
-            = new CrlRevocationChecker(null, buildParams, null, onlyEECert);
-
-        depthFirstSearchForward(targetSubjectDN, currentState,
-          new ForwardBuilder
-              (buildParams, targetSubjectDN, searchAllCertStores, onlyEECert),
-          adjacencyList, certPathList);
+        depthFirstSearchForward(buildParams.targetSubject(), currentState,
+                                new ForwardBuilder(buildParams,
+                                                   searchAllCertStores),
+                                adjacencyList, certPathList);
     }
 
     /*
@@ -371,27 +311,28 @@
      * @param dN the distinguished name being currently searched for certs
      * @param currentState the current PKIX validation state
      */
-    void depthFirstSearchForward(X500Principal dN, ForwardState currentState,
-        ForwardBuilder builder, List<List<Vertex>> adjList,
-        LinkedList<X509Certificate> certPathList)
+    private void depthFirstSearchForward(X500Principal dN,
+                                         ForwardState currentState,
+                                         ForwardBuilder builder,
+                                         List<List<Vertex>> adjList,
+                                         LinkedList<X509Certificate> cpList)
         throws GeneralSecurityException, IOException
     {
-        //XXX This method should probably catch & handle exceptions
-
         if (debug != null) {
             debug.println("SunCertPathBuilder.depthFirstSearchForward(" + dN
-                + ", " + currentState.toString() + ")");
+                          + ", " + currentState.toString() + ")");
         }
 
         /*
          * Find all the certificates issued to dN which
          * satisfy the PKIX certification path constraints.
          */
-        List<Vertex> vertices = addVertices
-           (builder.getMatchingCerts(currentState, orderedCertStores), adjList);
+        Collection<X509Certificate> certs =
+            builder.getMatchingCerts(currentState, buildParams.certStores());
+        List<Vertex> vertices = addVertices(certs, adjList);
         if (debug != null) {
             debug.println("SunCertPathBuilder.depthFirstSearchForward(): "
-                + "certs.size=" + vertices.size());
+                          + "certs.size=" + vertices.size());
         }
 
         /*
@@ -411,14 +352,14 @@
              * the next matching cert is tried.
              */
             ForwardState nextState = (ForwardState) currentState.clone();
-            X509Certificate cert = (X509Certificate) vertex.getCertificate();
+            X509Certificate cert = vertex.getCertificate();
 
             try {
-                builder.verifyCert(cert, nextState, certPathList);
+                builder.verifyCert(cert, nextState, cpList);
             } catch (GeneralSecurityException gse) {
                 if (debug != null) {
                     debug.println("SunCertPathBuilder.depthFirstSearchForward()"
-                        + ": validation failed: " + gse);
+                                  + ": validation failed: " + gse);
                     gse.printStackTrace();
                 }
                 vertex.setThrowable(gse);
@@ -436,51 +377,44 @@
              */
             if (builder.isPathCompleted(cert)) {
 
-                BasicChecker basicChecker = null;
                 if (debug != null)
                     debug.println("SunCertPathBuilder.depthFirstSearchForward()"
-                        + ": commencing final verification");
+                                  + ": commencing final verification");
 
-                ArrayList<X509Certificate> appendedCerts =
-                    new ArrayList<X509Certificate>(certPathList);
+                List<X509Certificate> appendedCerts = new ArrayList<>(cpList);
 
                 /*
                  * if the trust anchor selected is specified as a trusted
                  * public key rather than a trusted cert, then verify this
                  * cert (which is signed by the trusted public key), but
-                 * don't add it yet to the certPathList
+                 * don't add it yet to the cpList
                  */
                 if (builder.trustAnchor.getTrustedCert() == null) {
                     appendedCerts.add(0, cert);
                 }
 
-                HashSet<String> initExpPolSet = new HashSet<String>(1);
-                initExpPolSet.add(PolicyChecker.ANY_POLICY);
+                Set<String> initExpPolSet =
+                    Collections.singleton(PolicyChecker.ANY_POLICY);
 
                 PolicyNodeImpl rootNode = new PolicyNodeImpl(null,
                     PolicyChecker.ANY_POLICY, null, false, initExpPolSet, false);
 
+                List<PKIXCertPathChecker> checkers = new ArrayList<>();
                 PolicyChecker policyChecker
-                    = new PolicyChecker(buildParams.getInitialPolicies(),
-                                appendedCerts.size(),
-                                buildParams.isExplicitPolicyRequired(),
-                                buildParams.isPolicyMappingInhibited(),
-                                buildParams.isAnyPolicyInhibited(),
-                                buildParams.getPolicyQualifiersRejected(),
-                                rootNode);
+                    = new PolicyChecker(buildParams.initialPolicies(),
+                                        appendedCerts.size(),
+                                        buildParams.explicitPolicyRequired(),
+                                        buildParams.policyMappingInhibited(),
+                                        buildParams.anyPolicyInhibited(),
+                                        buildParams.policyQualifiersRejected(),
+                                        rootNode);
 
-                List<PKIXCertPathChecker> userCheckers = new
-                    ArrayList<PKIXCertPathChecker>
-                        (buildParams.getCertPathCheckers());
-                int mustCheck = 0;
-                userCheckers.add(mustCheck, policyChecker);
-                mustCheck++;
+                checkers.add(policyChecker);
 
                 // add the algorithm checker
-                userCheckers.add(mustCheck,
-                        new AlgorithmChecker(builder.trustAnchor));
-                mustCheck++;
+                checkers.add(new AlgorithmChecker(builder.trustAnchor));
 
+                BasicChecker basicChecker = null;
                 if (nextState.keyParamsNeeded()) {
                     PublicKey rootKey = cert.getPublicKey();
                     if (builder.trustAnchor.getTrustedCert() == null) {
@@ -495,24 +429,38 @@
                         (cert.getSubjectX500Principal(), rootKey, null);
 
                     // add the basic checker
-                    basicChecker = new BasicChecker(anchor,
-                                           builder.date,
-                                           buildParams.getSigProvider(),
-                                           true);
-                    userCheckers.add(mustCheck, basicChecker);
-                    mustCheck++;
+                    basicChecker = new BasicChecker(anchor, buildParams.date(),
+                                                    buildParams.sigProvider(),
+                                                    true);
+                    checkers.add(basicChecker);
+                }
+
+                buildParams.setCertPath(cf.generateCertPath(appendedCerts));
 
-                    // add the crl revocation checker
-                    if (buildParams.isRevocationEnabled()) {
-                        userCheckers.add(mustCheck, new CrlRevocationChecker
-                            (anchor, buildParams, null, onlyEECert));
-                        mustCheck++;
+                boolean revCheckerAdded = false;
+                List<PKIXCertPathChecker> ckrs = buildParams.certPathCheckers();
+                for (PKIXCertPathChecker ckr : ckrs) {
+                    if (ckr instanceof PKIXRevocationChecker) {
+                        revCheckerAdded = true;
+                        // if it's our own, initialize it
+                        if (ckr instanceof RevocationChecker)
+                            ((RevocationChecker)ckr).init(builder.trustAnchor,
+                                                          buildParams);
                     }
                 }
-                // Why we don't need BasicChecker and CrlRevocationChecker
+                // only add a RevocationChecker if revocation is enabled and
+                // a PKIXRevocationChecker has not already been added
+                if (buildParams.revocationEnabled() && !revCheckerAdded) {
+                    checkers.add(new RevocationChecker(builder.trustAnchor,
+                                                       buildParams));
+                }
+
+                checkers.addAll(ckrs);
+
+                // Why we don't need BasicChecker and RevocationChecker
                 // if nextState.keyParamsNeeded() is false?
 
-                for (int i=0; i<appendedCerts.size(); i++) {
+                for (int i = 0; i < appendedCerts.size(); i++) {
                     X509Certificate currCert = appendedCerts.get(i);
                     if (debug != null)
                         debug.println("current subject = "
@@ -523,18 +471,15 @@
                         unresCritExts = Collections.<String>emptySet();
                     }
 
-                    for (int j=0; j<userCheckers.size(); j++) {
-                        PKIXCertPathChecker currChecker = userCheckers.get(j);
-                        if (j < mustCheck ||
-                            !currChecker.isForwardCheckingSupported()) {
+                    for (PKIXCertPathChecker currChecker : checkers) {
+                        if (!currChecker.isForwardCheckingSupported()) {
                             if (i == 0) {
                                 currChecker.init(false);
 
                                 // The user specified
                                 // AlgorithmChecker may not be
                                 // able to set the trust anchor until now.
-                                if (j >= mustCheck &&
-                                    currChecker instanceof AlgorithmChecker) {
+                                if (currChecker instanceof AlgorithmChecker) {
                                     ((AlgorithmChecker)currChecker).
                                         trySetTrustAnchor(builder.trustAnchor);
                                 }
@@ -560,7 +505,7 @@
                      * are capable of processing.
                      */
                     for (PKIXCertPathChecker checker :
-                         buildParams.getCertPathCheckers())
+                         buildParams.certPathCheckers())
                     {
                         if (checker.isForwardCheckingSupported()) {
                             Set<String> suppExts =
@@ -572,24 +517,16 @@
                     }
 
                     if (!unresCritExts.isEmpty()) {
-                        unresCritExts.remove
-                            (PKIXExtensions.BasicConstraints_Id.toString());
-                        unresCritExts.remove
-                            (PKIXExtensions.NameConstraints_Id.toString());
-                        unresCritExts.remove
-                            (PKIXExtensions.CertificatePolicies_Id.toString());
-                        unresCritExts.remove
-                            (PKIXExtensions.PolicyMappings_Id.toString());
-                        unresCritExts.remove
-                            (PKIXExtensions.PolicyConstraints_Id.toString());
-                        unresCritExts.remove
-                            (PKIXExtensions.InhibitAnyPolicy_Id.toString());
-                        unresCritExts.remove(PKIXExtensions.
+                        unresCritExts.remove(BasicConstraints_Id.toString());
+                        unresCritExts.remove(NameConstraints_Id.toString());
+                        unresCritExts.remove(CertificatePolicies_Id.toString());
+                        unresCritExts.remove(PolicyMappings_Id.toString());
+                        unresCritExts.remove(PolicyConstraints_Id.toString());
+                        unresCritExts.remove(InhibitAnyPolicy_Id.toString());
+                        unresCritExts.remove(
                             SubjectAlternativeName_Id.toString());
-                        unresCritExts.remove
-                            (PKIXExtensions.KeyUsage_Id.toString());
-                        unresCritExts.remove
-                            (PKIXExtensions.ExtendedKeyUsage_Id.toString());
+                        unresCritExts.remove(KeyUsage_Id.toString());
+                        unresCritExts.remove(ExtendedKeyUsage_Id.toString());
 
                         if (!unresCritExts.isEmpty()) {
                             throw new CertPathValidatorException
@@ -606,10 +543,10 @@
                 /*
                  * if the user specified a trusted public key rather than
                  * trusted certs, then add this cert (which is signed by
-                 * the trusted public key) to the certPathList
+                 * the trusted public key) to the cpList
                  */
                 if (builder.trustAnchor.getTrustedCert() == null)
-                    builder.addCertToPath(cert, certPathList);
+                    builder.addCertToPath(cert, cpList);
                 // Save the trust anchor
                 this.trustAnchor = builder.trustAnchor;
 
@@ -620,10 +557,10 @@
                     finalPublicKey = basicChecker.getPublicKey();
                 } else {
                     Certificate finalCert;
-                    if (certPathList.size() == 0) {
+                    if (cpList.isEmpty()) {
                         finalCert = builder.trustAnchor.getTrustedCert();
                     } else {
-                        finalCert = certPathList.get(certPathList.size()-1);
+                        finalCert = cpList.getLast();
                     }
                     finalPublicKey = finalCert.getPublicKey();
                 }
@@ -631,7 +568,7 @@
                 policyTreeResult = policyChecker.getPolicyTree();
                 return;
             } else {
-                builder.addCertToPath(cert, certPathList);
+                builder.addCertToPath(cert, cpList);
             }
 
             /* Update the PKIX state */
@@ -645,8 +582,8 @@
             vertex.setIndex(adjList.size() - 1);
 
             /* recursively search for matching certs at next dN */
-            depthFirstSearchForward(cert.getIssuerX500Principal(), nextState, builder,
-                adjList, certPathList);
+            depthFirstSearchForward(cert.getIssuerX500Principal(), nextState,
+                                    builder, adjList, cpList);
 
             /*
              * If path has been completed, return ASAP!
@@ -662,8 +599,8 @@
                  */
                 if (debug != null)
                     debug.println("SunCertPathBuilder.depthFirstSearchForward()"
-                        + ": backtracking");
-                builder.removeFinalCertFromPath(certPathList);
+                                  + ": backtracking");
+                builder.removeFinalCertFromPath(cpList);
             }
         }
     }
@@ -683,9 +620,11 @@
      * @param dN the distinguished name being currently searched for certs
      * @param currentState the current PKIX validation state
      */
-    void depthFirstSearchReverse(X500Principal dN, ReverseState currentState,
-        ReverseBuilder builder, List<List<Vertex>> adjList,
-        LinkedList<X509Certificate> certPathList)
+    private void depthFirstSearchReverse(X500Principal dN,
+                                         ReverseState currentState,
+                                         ReverseBuilder builder,
+                                         List<List<Vertex>> adjList,
+                                         LinkedList<X509Certificate> cpList)
         throws GeneralSecurityException, IOException
     {
         if (debug != null)
@@ -696,8 +635,9 @@
          * Find all the certificates issued by dN which
          * satisfy the PKIX certification path constraints.
          */
-        List<Vertex> vertices = addVertices
-           (builder.getMatchingCerts(currentState, orderedCertStores), adjList);
+        Collection<X509Certificate> certs =
+            builder.getMatchingCerts(currentState, buildParams.certStores());
+        List<Vertex> vertices = addVertices(certs, adjList);
         if (debug != null)
             debug.println("SunCertPathBuilder.depthFirstSearchReverse(): "
                 + "certs.size=" + vertices.size());
@@ -717,9 +657,9 @@
              * the next matching cert is tried.
              */
             ReverseState nextState = (ReverseState) currentState.clone();
-            X509Certificate cert = (X509Certificate) vertex.getCertificate();
+            X509Certificate cert = vertex.getCertificate();
             try {
-                builder.verifyCert(cert, nextState, certPathList);
+                builder.verifyCert(cert, nextState, cpList);
             } catch (GeneralSecurityException gse) {
                 if (debug != null)
                     debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
@@ -733,7 +673,7 @@
              * self-signed cert) and update state
              */
             if (!currentState.isInitial())
-                builder.addCertToPath(cert, certPathList);
+                builder.addCertToPath(cert, cpList);
             // save trust anchor
             this.trustAnchor = currentState.trustAnchor;
 
@@ -782,7 +722,7 @@
 
             /* recursively search for matching certs at next dN */
             depthFirstSearchReverse(cert.getSubjectX500Principal(), nextState,
-                builder, adjList, certPathList);
+                                    builder, adjList, cpList);
 
             /*
              * If path has been completed, return ASAP!
@@ -800,7 +740,7 @@
                     debug.println("SunCertPathBuilder.depthFirstSearchReverse()"
                         + ": backtracking");
                 if (!currentState.isInitial())
-                    builder.removeFinalCertFromPath(certPathList);
+                    builder.removeFinalCertFromPath(cpList);
             }
         }
         if (debug != null)
@@ -812,13 +752,14 @@
      * Adds a collection of matching certificates to the
      * adjacency list.
      */
-    private List<Vertex> addVertices(Collection<X509Certificate> certs,
-        List<List<Vertex>> adjList) {
+    private static List<Vertex> addVertices(Collection<X509Certificate> certs,
+                                            List<List<Vertex>> adjList)
+    {
         List<Vertex> l = adjList.get(adjList.size() - 1);
 
         for (X509Certificate cert : certs) {
-           Vertex v = new Vertex(cert);
-           l.add(v);
+            Vertex v = new Vertex(cert);
+            l.add(v);
         }
 
         return l;
@@ -828,53 +769,13 @@
      * Returns true if trust anchor certificate matches specified
      * certificate constraints.
      */
-    private boolean anchorIsTarget(TrustAnchor anchor, X509CertSelector sel) {
+    private static boolean anchorIsTarget(TrustAnchor anchor,
+                                          CertSelector sel)
+    {
         X509Certificate anchorCert = anchor.getTrustedCert();
         if (anchorCert != null) {
             return sel.match(anchorCert);
         }
         return false;
     }
-
-    /**
-     * Comparator that orders CertStores so that local CertStores come before
-     * remote CertStores.
-     */
-    private static class CertStoreComparator implements Comparator<CertStore> {
-        public int compare(CertStore store1, CertStore store2) {
-            if (Builder.isLocalCertStore(store1)) {
-                return -1;
-            } else {
-                return 1;
-            }
-        }
-    }
-
-    /**
-     * Returns the target subject DN from the first X509Certificate that
-     * is fetched that matches the specified X509CertSelector.
-     */
-    private X500Principal getTargetSubjectDN(List<CertStore> stores,
-        X509CertSelector targetSel) {
-        for (CertStore store : stores) {
-            try {
-                Collection<? extends Certificate> targetCerts =
-                    (Collection<? extends Certificate>)
-                        store.getCertificates(targetSel);
-                if (!targetCerts.isEmpty()) {
-                    X509Certificate targetCert =
-                        (X509Certificate)targetCerts.iterator().next();
-                    return targetCert.getSubjectX500Principal();
-                }
-            } catch (CertStoreException e) {
-                // ignore but log it
-                if (debug != null) {
-                    debug.println("SunCertPathBuilder.getTargetSubjectDN: " +
-                        "non-fatal exception retrieving certs: " + e);
-                    e.printStackTrace();
-                }
-            }
-        }
-        return null;
-    }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderParameters.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/SunCertPathBuilderParameters.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2003, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -25,12 +25,11 @@
 
 package sun.security.provider.certpath;
 
-import java.util.Set;
-
 import java.security.InvalidAlgorithmParameterException;
 import java.security.KeyStore;
 import java.security.KeyStoreException;
 import java.security.cert.*;
+import java.util.Set;
 
 /**
  * This class specifies the set of parameters used as input for the Sun
@@ -120,8 +119,9 @@
      *
      * @return a formatted string describing the parameters.
      */
+    @Override
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("[\n");
         sb.append(super.toString());
         sb.append("  Build Forward Flag: " + String.valueOf(buildForward) + "\n");
--- a/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/URICertStore.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2006, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2006, 2012, 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
@@ -213,6 +213,7 @@
      *         match the specified selector
      * @throws CertStoreException if an exception occurs
      */
+    @Override
     @SuppressWarnings("unchecked")
     public synchronized Collection<X509Certificate> engineGetCertificates
         (CertSelector selector) throws CertStoreException {
@@ -322,6 +323,7 @@
      *         match the specified selector
      * @throws CertStoreException if an exception occurs
      */
+    @Override
     @SuppressWarnings("unchecked")
     public synchronized Collection<X509CRL> engineGetCRLs(CRLSelector selector)
         throws CertStoreException {
@@ -418,14 +420,14 @@
         URICertStoreParameters(URI uri) {
             this.uri = uri;
         }
-        public boolean equals(Object obj) {
+        @Override public boolean equals(Object obj) {
             if (!(obj instanceof URICertStoreParameters)) {
                 return false;
             }
             URICertStoreParameters params = (URICertStoreParameters) obj;
             return uri.equals(params.uri);
         }
-        public int hashCode() {
+        @Override public int hashCode() {
             if (hashCode == 0) {
                 int result = 17;
                 result = 37*result + uri.hashCode();
@@ -433,7 +435,7 @@
             }
             return hashCode;
         }
-        public Object clone() {
+        @Override public Object clone() {
             try {
                 return super.clone();
             } catch (CloneNotSupportedException e) {
--- a/jdk/src/share/classes/sun/security/provider/certpath/Vertex.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/Vertex.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -25,12 +25,11 @@
 
 package sun.security.provider.certpath;
 
-import sun.security.util.Debug;
-
-import java.security.cert.Certificate;
+import java.io.IOException;
 import java.security.cert.CertificateException;
 import java.security.cert.X509Certificate;
 
+import sun.security.util.Debug;
 import sun.security.x509.AuthorityKeyIdentifierExtension;
 import sun.security.x509.KeyIdentifier;
 import sun.security.x509.SubjectKeyIdentifierExtension;
@@ -50,17 +49,17 @@
 public class Vertex {
 
     private static final Debug debug = Debug.getInstance("certpath");
-    private Certificate cert;
-    private int         index;
-    private Throwable   throwable;
+    private X509Certificate cert;
+    private int index;
+    private Throwable throwable;
 
     /**
      * Constructor; creates vertex with index of -1
      * Use setIndex method to set another index.
      *
-     * @param cert Certificate associated with vertex
+     * @param cert X509Certificate associated with vertex
      */
-    Vertex(Certificate cert) {
+    Vertex(X509Certificate cert) {
         this.cert = cert;
         this.index = -1;
     }
@@ -68,9 +67,9 @@
     /**
      * return the certificate for this vertex
      *
-     * @returns Certificate
+     * @returns X509Certificate
      */
-    public Certificate getCertificate() {
+    public X509Certificate getCertificate() {
         return cert;
     }
 
@@ -121,6 +120,7 @@
      *
      * @returns String representation of vertex
      */
+    @Override
     public String toString() {
         return certToString() + throwableToString() + indexToString();
     }
@@ -132,70 +132,65 @@
      * @returns String representation of certificate info
      */
     public String certToString() {
-        String out = "";
-        if (cert == null || ! (cert instanceof X509Certificate))
-            return "Cert:       Not an X509Certificate\n";
+        StringBuilder sb = new StringBuilder();
 
         X509CertImpl x509Cert = null;
         try {
-            x509Cert = X509CertImpl.toImpl((X509Certificate)cert);
+            x509Cert = X509CertImpl.toImpl(cert);
         } catch (CertificateException ce) {
             if (debug != null) {
                 debug.println("Vertex.certToString() unexpected exception");
                 ce.printStackTrace();
             }
-            return out;
+            return sb.toString();
         }
 
-        out =       "Issuer:     " + x509Cert.getIssuerX500Principal() + "\n";
-        out = out + "Subject:    " + x509Cert.getSubjectX500Principal() + "\n";
-        out = out + "SerialNum:  " + (x509Cert.getSerialNumber()).toString(16) + "\n";
-        out = out + "Expires:    " + x509Cert.getNotAfter().toString() + "\n";
+        sb.append("Issuer:     ").append
+                 (x509Cert.getIssuerX500Principal()).append("\n");
+        sb.append("Subject:    ").append
+                 (x509Cert.getSubjectX500Principal()).append("\n");
+        sb.append("SerialNum:  ").append
+                 (x509Cert.getSerialNumber().toString(16)).append("\n");
+        sb.append("Expires:    ").append
+                 (x509Cert.getNotAfter().toString()).append("\n");
         boolean[] iUID = x509Cert.getIssuerUniqueID();
         if (iUID != null) {
-            out = out + "IssuerUID:  ";
-            for (int i=0; i < iUID.length; i++) {
-                out = out + (iUID[i]?1:0);
+            sb.append("IssuerUID:  ");
+            for (boolean b : iUID) {
+                sb.append(b ? 1 : 0);
             }
-            out = out + "\n";
+            sb.append("\n");
         }
         boolean[] sUID = x509Cert.getSubjectUniqueID();
         if (sUID != null) {
-            out = out + "SubjectUID: ";
-            for (int i=0; i< sUID.length; i++) {
-                out = out + (sUID[i]?1:0);
+            sb.append("SubjectUID: ");
+            for (boolean b : sUID) {
+                sb.append(b ? 1 : 0);
             }
-            out = out + "\n";
+            sb.append("\n");
         }
-        SubjectKeyIdentifierExtension sKeyID = null;
         try {
-            sKeyID = x509Cert.getSubjectKeyIdentifierExtension();
+            SubjectKeyIdentifierExtension sKeyID =
+                x509Cert.getSubjectKeyIdentifierExtension();
             if (sKeyID != null) {
                 KeyIdentifier keyID = sKeyID.get(
                         SubjectKeyIdentifierExtension.KEY_ID);
-                out = out + "SubjKeyID:  " + keyID.toString();
+                sb.append("SubjKeyID:  ").append(keyID.toString());
             }
-        } catch (Exception e) {
+            AuthorityKeyIdentifierExtension aKeyID =
+                x509Cert.getAuthorityKeyIdentifierExtension();
+            if (aKeyID != null) {
+                KeyIdentifier keyID = (KeyIdentifier)aKeyID.get(
+                        AuthorityKeyIdentifierExtension.KEY_ID);
+                sb.append("AuthKeyID:  ").append(keyID.toString());
+            }
+        } catch (IOException e) {
             if (debug != null) {
                 debug.println("Vertex.certToString() unexpected exception");
                 e.printStackTrace();
             }
         }
-        AuthorityKeyIdentifierExtension aKeyID = null;
-        try {
-            aKeyID = x509Cert.getAuthorityKeyIdentifierExtension();
-            if (aKeyID != null) {
-                KeyIdentifier keyID = (KeyIdentifier)aKeyID.get(
-                        AuthorityKeyIdentifierExtension.KEY_ID);
-                out = out + "AuthKeyID:  " + keyID.toString();
-            }
-        } catch (Exception e) {
-            if (debug != null) {
-                debug.println("Vertex.certToString() 2 unexpected exception");
-                e.printStackTrace();
-            }
-        }
-        return out;
+        return sb.toString();
     }
 
     /**
@@ -205,13 +200,13 @@
      * @returns String form of exception (or "none")
      */
     public String throwableToString() {
-        String out = "Exception:  ";
+        StringBuilder sb = new StringBuilder("Exception:  ");
         if (throwable != null)
-            out = out + throwable.toString();
+            sb.append(throwable.toString());
         else
-            out = out + "null";
-        out = out + "\n";
-        return out;
+            sb.append("null");
+        sb.append("\n");
+        return sb.toString();
     }
 
     /**
@@ -222,10 +217,10 @@
      * @returns String form of index as "Last cert?  [Yes/No]
      */
     public String moreToString() {
-        String out = "Last cert?  ";
-        out = out + ((index == -1)?"Yes":"No");
-        out = out + "\n";
-        return out;
+        StringBuilder sb = new StringBuilder("Last cert?  ");
+        sb.append((index == -1) ? "Yes" : "No");
+        sb.append("\n");
+        return sb.toString();
     }
 
     /**
@@ -235,7 +230,6 @@
      * @returns String form of index as "Index:     [numeric index]"
      */
     public String indexToString() {
-        String out = "Index:      " + index + "\n";
-        return out;
+        return "Index:      " + index + "\n";
     }
 }
--- a/jdk/src/share/classes/sun/security/provider/certpath/X509CertPath.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/X509CertPath.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -33,9 +33,10 @@
 import java.security.cert.Certificate;
 import java.security.cert.CertificateException;
 import java.security.cert.CertificateFactory;
+import java.security.cert.CertPath;
 import java.security.cert.X509Certificate;
 import java.util.*;
-import java.security.cert.CertPath;
+
 import sun.security.pkcs.ContentInfo;
 import sun.security.pkcs.PKCS7;
 import sun.security.pkcs.SignerInfo;
@@ -44,7 +45,6 @@
 import sun.security.util.DerOutputStream;
 import sun.security.util.DerInputStream;
 
-
 /**
  * A {@link java.security.cert.CertPath CertPath} (certification path)
  * consisting exclusively of
@@ -83,7 +83,7 @@
     private static final Collection<String> encodingList;
 
     static {
-        List<String> list = new ArrayList<String>(2);
+        List<String> list = new ArrayList<>(2);
         list.add(PKIPATH_ENCODING);
         list.add(PKCS7_ENCODING);
         encodingList = Collections.unmodifiableCollection(list);
@@ -272,6 +272,7 @@
      * @return the encoded bytes
      * @exception CertificateEncodingException if an encoding error occurs
      */
+    @Override
     public byte[] getEncoded() throws CertificateEncodingException {
         // @@@ Should cache the encoded form
         return encodePKIPATH();
@@ -342,6 +343,7 @@
      * @exception CertificateEncodingException if an encoding error occurs or
      *   the encoding requested is not supported
      */
+    @Override
     public byte[] getEncoded(String encoding)
             throws CertificateEncodingException {
         switch (encoding) {
@@ -376,6 +378,7 @@
      * @return an <code>Iterator</code> over the names of the supported
      *         encodings (as Strings)
      */
+    @Override
     public Iterator<String> getEncodings() {
         return getEncodingsStatic();
     }
@@ -387,6 +390,7 @@
      * @return an immutable <code>List</code> of <code>X509Certificate</code>s
      *         (may be empty, but not null)
      */
+    @Override
     public List<X509Certificate> getCertificates() {
         return certs;
     }
--- a/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/provider/certpath/X509CertificatePair.java	Wed May 30 17:19:46 2012 -0400
@@ -1,5 +1,5 @@
 /*
- * Copyright (c) 2000, 2011, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2000, 2012, 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
@@ -207,13 +207,14 @@
      *
      * @return A String describing the contents of the pair.
      */
+    @Override
     public String toString() {
-        StringBuffer sb = new StringBuffer();
+        StringBuilder sb = new StringBuilder();
         sb.append("X.509 Certificate Pair: [\n");
         if (forward != null)
-            sb.append("  Forward: " + forward + "\n");
+            sb.append("  Forward: ").append(forward).append("\n");
         if (reverse != null)
-            sb.append("  Reverse: " + reverse + "\n");
+            sb.append("  Reverse: ").append(reverse).append("\n");
         sb.append("]");
         return sb.toString();
     }
--- a/jdk/src/share/classes/sun/security/x509/X509CRLEntryImpl.java	Mon Jan 23 04:44:16 2012 -0800
+++ b/jdk/src/share/classes/sun/security/x509/X509CRLEntryImpl.java	Wed May 30 17:19:46 2012 -0400
@@ -31,6 +31,7 @@
 import java.security.cert.X509CRLEntry;
 import java.math.BigInteger;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Date;
 import java.util.Enumeration;
 import java.util.HashMap;
@@ -500,6 +501,9 @@
     }
 
     public Map<String, java.security.cert.Extension> getExtensions() {
+        if (extensions == null) {
+            return Collections.emptyMap();
+        }
         Collection<Extension> exts = extensions.getAllExtensions();
         HashMap<String, java.security.cert.Extension> map =
             new HashMap<String, java.security.cert.Extension>(exts.size());
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/jdk/test/java/security/cert/PKIXRevocationChecker/UnitTest.java	Wed May 30 17:19:46 2012 -0400
@@ -0,0 +1,179 @@
+/*
+ * Copyright (c) 2012, 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.
+ *
+ * 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.
+ */
+
+/**
+ * @test
+ * @bug 6854712
+ * @summary Basic unit test for PKIXRevocationChecker
+ */
+
+import java.io.ByteArrayInputStream;
+import java.io.InputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.net.URI;
+import java.security.cert.CertificateFactory;
+import java.security.cert.CertPathChecker;
+import java.security.cert.CertPathValidator;
+import java.security.cert.Extension;
+import java.security.cert.PKIXRevocationChecker;
+import java.security.cert.PKIXRevocationChecker.Option;
+import java.security.cert.X509Certificate;
+import java.util.ArrayList;
+import java.util.EnumSet;
+import java.util.List;
+import java.util.Map;
+import java.util.Set;
+
+public class UnitTest {
+
+    public static void main(String[] args) throws Exception {
+
+        CertPathValidator cpv = CertPathValidator.getInstance("PKIX");
+        CertPathChecker cpc = cpv.getRevocationChecker();
+        PKIXRevocationChecker prc = (PKIXRevocationChecker)cpc;
+
+        System.out.println("Testing that get methods return null or " +
+                           "empty lists/sets/maps");
+        requireNull(prc.getOCSPResponder(), "getOCSPResponder()");
+        requireNull(prc.getOCSPResponderCert(), "getOCSPResponderCert()");
+        requireEmpty(prc.getOCSPExtensions(), "getOCSPExtensions()");
+        requireEmpty(prc.getOCSPStapledResponses(),
+                     "getOCSPStapledResponses()");
+        requireEmpty(prc.getOptions(), "getOptions()");
+
+        System.out.println("Testing that get methods return same parameters " +
+                           "that are passed to set methods");
+        URI uri = new URI("http://localhost");
+        prc.setOCSPResponder(uri);
+        requireEquals(uri, prc.getOCSPResponder(), "getOCSPResponder()");
+
+        X509Certificate cert = getCert();
+        prc.setOCSPResponderCert(cert);
+        requireEquals(cert, prc.getOCSPResponderCert(),
+                      "getOCSPResponderCert()");
+
+        List<Extension> exts = new ArrayList<>();
+        for (String oid : cert.getNonCriticalExtensionOIDs()) {
+            System.out.println(oid);
+            exts.add(new ExtensionImpl(oid,
+                                       cert.getExtensionValue(oid), false));
+        }
+        prc.setOCSPExtensions(exts);
+        requireEquals(exts, prc.getOCSPExtensions(), "getOCSPExtensions()");
+
+        Set<Option> options = EnumSet.of(Option.ONLY_END_ENTITY);
+        prc.setOptions(options);
+        requireEquals(options, prc.getOptions(), "getOptions()");
+
+        System.out.println("Testing that parameters are re-initialized to " +
+                           "default values if null is passed to set methods");
+        prc.setOCSPResponder(null);
+        requireNull(prc.getOCSPResponder(), "getOCSPResponder()");
+        prc.setOCSPResponderCert(null);
+        requireNull(prc.getOCSPResponderCert(), "getOCSPResponderCert()");
+        prc.setOCSPExtensions(null);
+        requireEmpty(prc.getOCSPExtensions(), "getOCSPExtensions()");
+        prc.setOCSPStapledResponses(null);
+        requireEmpty(prc.getOCSPStapledResponses(),
+                     "getOCSPStapledResponses()");
+        prc.setOptions(null);
+        requireEmpty(prc.getOptions(), "getOptions()");
+    }
+
+    static void requireNull(Object o, String msg) throws Exception {
+        if (o != null) {
+            throw new Exception("FAILED: " + msg + " must return null");
+        }
+    }
+
+    static void requireEmpty(Map<?,?> m, String msg) throws Exception {
+        if (!m.isEmpty()) {
+            throw new Exception("FAILED: " + msg + " must return an empty map");
+        }
+    }
+
+    static void requireEmpty(List<?> l, String msg) throws Exception {
+        if (!l.isEmpty()) {
+            throw new Exception("FAILED: " + msg +" must return an empty list");
+        }
+    }
+
+    static void requireEmpty(Set<?> s, String msg) throws Exception {
+        if (!s.isEmpty()) {
+            throw new Exception("FAILED: " + msg + " must return an empty set");
+        }
+    }
+
+    static void requireEquals(Object a, Object b, String msg) throws Exception {
+        if (!a.equals(b)) {
+            throw new Exception("FAILED: " + msg + " does not return the " +
+                                "same object that was set");
+        }
+    }
+
+    static X509Certificate getCert() throws Exception {
+        String b64 =
+        "-----BEGIN CERTIFICATE-----\n" +
+        "MIIBLTCB2KADAgECAgEDMA0GCSqGSIb3DQEBBAUAMA0xCzAJBgNVBAMTAkNBMB4X\n" +
+        "DTAyMTEwNzExNTcwM1oXDTIyMTEwNzExNTcwM1owFTETMBEGA1UEAxMKRW5kIEVu\n" +
+        "dGl0eTBcMA0GCSqGSIb3DQEBAQUAA0sAMEgCQQDVBDfF+uBr5s5jzzDs1njKlZNt\n" +
+        "h8hHzEt3ASh67Peos+QrDzgpUyFXT6fdW2h7iPf0ifjM8eW2xa+3EnPjjU5jAgMB\n" +
+        "AAGjGzAZMBcGA1UdIAQQMA4wBgYEVR0gADAEBgIqADANBgkqhkiG9w0BAQQFAANB\n" +
+        "AFo//WOboCNOCcA1fvcWW9oc4MvV8ZPvFIAbyEbgyFd4id5lGDTRbRPvvNZRvdsN\n" +
+        "NM2gXYr+f87NHIXc9EF3pzw=\n" +
+        "-----END CERTIFICATE-----";
+
+        InputStream is = new ByteArrayInputStream(b64.getBytes("UTF-8"));
+        CertificateFactory cf = CertificateFactory.getInstance("X.509");
+        return (X509Certificate)cf.generateCertificate(is);
+    }
+
+    static class ExtensionImpl implements Extension {
+        private final String oid;
+        private final byte[] val;
+        private final boolean critical;
+
+        ExtensionImpl(String oid, byte[] val, boolean critical) {
+            this.oid = oid;
+            this.val = val;
+            this.critical = critical;
+        }
+
+        public void encode(OutputStream out) throws IOException {
+            throw new UnsupportedOperationException();
+        }
+
+        public String getId() {
+            return oid;
+        }
+
+        public byte[] getValue() {
+            return val.clone();
+        }
+
+        public boolean isCritical() {
+            return critical;
+        }
+    }
+}