/**
   * Checks if an attribute certificate is revoked.
   *
   * @param attrCert Attribute certificate to check if it is revoked.
   * @param paramsPKIX PKIX parameters.
   * @param issuerCert The issuer certificate of the attribute certificate <code>attrCert</code>.
   * @param validDate The date when the certificate revocation status should be checked.
   * @param certPathCerts The certificates of the certification path to be checked.
   * @throws CertPathValidatorException if the certificate is revoked or the status cannot be
   *     checked or some error occurs.
   */
  protected static void checkCRLs(
      X509AttributeCertificate attrCert,
      ExtendedPKIXParameters paramsPKIX,
      X509Certificate issuerCert,
      Date validDate,
      List certPathCerts)
      throws CertPathValidatorException {
    if (paramsPKIX.isRevocationEnabled()) {
      // check if revocation is available
      if (attrCert.getExtensionValue(NO_REV_AVAIL) == null) {
        CRLDistPoint crldp = null;
        try {
          crldp =
              CRLDistPoint.getInstance(
                  CertPathValidatorUtilities.getExtensionValue(attrCert, CRL_DISTRIBUTION_POINTS));
        } catch (AnnotatedException e) {
          throw new CertPathValidatorException(
              "CRL distribution point extension could not be read.", e);
        }
        try {
          CertPathValidatorUtilities.addAdditionalStoresFromCRLDistributionPoint(crldp, paramsPKIX);
        } catch (AnnotatedException e) {
          throw new CertPathValidatorException(
              "No additional CRL locations could be decoded from CRL distribution point extension.",
              e);
        }
        CertStatus certStatus = new CertStatus();
        ReasonsMask reasonsMask = new ReasonsMask();

        AnnotatedException lastException = null;
        boolean validCrlFound = false;
        // for each distribution point
        if (crldp != null) {
          DistributionPoint dps[] = null;
          try {
            dps = crldp.getDistributionPoints();
          } catch (Exception e) {
            throw new ExtCertPathValidatorException("Distribution points could not be read.", e);
          }
          try {
            for (int i = 0;
                i < dps.length
                    && certStatus.getCertStatus() == CertStatus.UNREVOKED
                    && !reasonsMask.isAllReasons();
                i++) {
              ExtendedPKIXParameters paramsPKIXClone = (ExtendedPKIXParameters) paramsPKIX.clone();
              checkCRL(
                  dps[i],
                  attrCert,
                  paramsPKIXClone,
                  validDate,
                  issuerCert,
                  certStatus,
                  reasonsMask,
                  certPathCerts);
              validCrlFound = true;
            }
          } catch (AnnotatedException e) {
            lastException = new AnnotatedException("No valid CRL for distribution point found.", e);
          }
        }

        /*
         * If the revocation status has not been determined, repeat the
         * process above with any available CRLs not specified in a
         * distribution point but issued by the certificate issuer.
         */

        if (certStatus.getCertStatus() == CertStatus.UNREVOKED && !reasonsMask.isAllReasons()) {
          try {
            /*
             * assume a DP with both the reasons and the cRLIssuer
             * fields omitted and a distribution point name of the
             * certificate issuer.
             */
            DERObject issuer = null;
            try {

              issuer =
                  new ASN1InputStream(
                          ((X500Principal) attrCert.getIssuer().getPrincipals()[0]).getEncoded())
                      .readObject();
            } catch (Exception e) {
              throw new AnnotatedException(
                  "Issuer from certificate for CRL could not be reencoded.", e);
            }
            DistributionPoint dp =
                new DistributionPoint(
                    new DistributionPointName(
                        0, new GeneralNames(new GeneralName(GeneralName.directoryName, issuer))),
                    null,
                    null);
            ExtendedPKIXParameters paramsPKIXClone = (ExtendedPKIXParameters) paramsPKIX.clone();
            checkCRL(
                dp,
                attrCert,
                paramsPKIXClone,
                validDate,
                issuerCert,
                certStatus,
                reasonsMask,
                certPathCerts);
            validCrlFound = true;
          } catch (AnnotatedException e) {
            lastException = new AnnotatedException("No valid CRL for distribution point found.", e);
          }
        }

        if (!validCrlFound) {
          throw new ExtCertPathValidatorException("No valid CRL found.", lastException);
        }
        if (certStatus.getCertStatus() != CertStatus.UNREVOKED) {
          String message =
              "Attribute certificate revocation after " + certStatus.getRevocationDate();
          message += ", reason: " + RFC3280CertPathUtilities.crlReasons[certStatus.getCertStatus()];
          throw new CertPathValidatorException(message);
        }
        if (!reasonsMask.isAllReasons() && certStatus.getCertStatus() == CertStatus.UNREVOKED) {
          certStatus.setCertStatus(CertStatus.UNDETERMINED);
        }
        if (certStatus.getCertStatus() == CertStatus.UNDETERMINED) {
          throw new CertPathValidatorException(
              "Attribute certificate status could not be determined.");
        }

      } else {
        if (attrCert.getExtensionValue(CRL_DISTRIBUTION_POINTS) != null
            || attrCert.getExtensionValue(AUTHORITY_INFO_ACCESS) != null) {
          throw new CertPathValidatorException(
              "No rev avail extension is set, but also an AC revocation pointer.");
        }
      }
    }
  }