/*
* DSS - Digital Signature Services
*
* Copyright (C) 2013 European Commission, Directorate-General Internal Market and Services (DG MARKT), B-1049 Bruxelles/Brussel
*
* Developed by: 2013 ARHS Developments S.A. (rue Nicolas Bové 2B, L-1253 Luxembourg) http://www.arhs-developments.com
*
* This file is part of the "DSS - Digital Signature Services" project.
*
* "DSS - Digital Signature Services" is free software: you can redistribute it and/or modify it under the terms of
* the GNU Lesser General Public License as published by the Free Software Foundation, either version 2.1 of the
* License, or (at your option) any later version.
*
* DSS 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 Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public License along with
* "DSS - Digital Signature Services". If not, see <http://www.gnu.org/licenses/>.
*/
package eu.europa.ec.markt.dss.validation102853.crl;
import java.security.cert.X509CRL;
import java.util.Collections;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.europa.ec.markt.dss.exception.DSSNullException;
import eu.europa.ec.markt.dss.validation102853.CertificateToken;
/**
* This class if a basic skeleton that is able to retrieve needed CRL data from the contained list. The child need to retrieve
* the list of wrapped CRLs.
*
* @version $Revision$ - $Date$
*/
public abstract class OfflineCRLSource extends CommonCRLSource {
private static final Logger LOG = LoggerFactory.getLogger(OfflineCRLSource.class);
/**
* List of contained {@code X509CRL}s. One CRL list contains many CRLToken(s).
*/
protected List<X509CRL> x509CRLList;
protected HashMap<CertificateToken, CRLToken> validCRLTokenList = new HashMap<CertificateToken, CRLToken>();
/**
* This {@code HashMap} contains the {@code CRLValidity} object for each {@code X509CRL}. It is used for performance reasons.
*/
protected Map<X509CRL, CRLValidity> crlValidityMap = new HashMap<X509CRL, CRLValidity>();
@Override
final public CRLToken findCrl(final CertificateToken certificateToken) {
if (certificateToken == null) {
throw new DSSNullException(CertificateToken.class, "certificateToken");
}
final CRLToken validCRLToken = validCRLTokenList.get(certificateToken);
if (validCRLToken != null) {
return validCRLToken;
}
final CertificateToken issuerToken = certificateToken.getIssuerToken();
if (issuerToken == null) {
throw new DSSNullException(CertificateToken.class, "issuerToken");
}
final CRLValidity bestCRLValidity = getBestCrlValidity(certificateToken, issuerToken);
if (bestCRLValidity == null) {
return null;
}
final CRLToken crlToken = new CRLToken(certificateToken, bestCRLValidity);
validCRLTokenList.put(certificateToken, crlToken);
return crlToken;
}
/**
* This method returns the best {@code CRLValidity} containing the most recent {@code X509CRL}.
*
* @param certificateToken {@code CertificateToken} for with the CRL is issued
* @param issuerToken {@code CertificateToken} representing the signing certificate of the CRL
* @return {@code CRLValidity}
*/
private CRLValidity getBestCrlValidity(final CertificateToken certificateToken, final CertificateToken issuerToken) {
CRLValidity bestCRLValidity = null;
Date bestX509UpdateDate = null;
final List<String> dpUrlList = getCrlUrl(certificateToken, null);
for (final X509CRL x509CRL : x509CRLList) {
final CRLValidity crlValidity = getCrlValidity(x509CRL, issuerToken, dpUrlList);
if (crlValidity == null) {
continue;
}
if (issuerToken.equals(crlValidity.issuerToken) && crlValidity.isValid()) {
final Date thisUpdate = x509CRL.getThisUpdate();
if (!certificateToken.hasExpiredCertOnCRLExtension()) {
if (thisUpdate.before(certificateToken.getNotBefore()) || thisUpdate.after(certificateToken.getNotAfter())) {
LOG.warn("The CRL was not issued during the validity period of the certificate! Certificate: " + certificateToken.getDSSIdAsString());
continue;
}
}
if (bestX509UpdateDate == null || thisUpdate.after(bestX509UpdateDate)) {
bestCRLValidity = crlValidity;
bestX509UpdateDate = thisUpdate;
}
}
}
return bestCRLValidity;
}
/**
* This method returns {@code CRLValidity} object based on the given {@code X509CRL}. The check of the validity of the CRL is performed.
*
* @param x509CRL {@code X509CRL} the validity to be checked
* @param issuerToken {@code CertificateToken} issuer of the CRL
* @param dpUrlStringList {@code List} of {@code String} representation of the DP's url
* @return returns updated {@code CRLValidity} object
*/
private synchronized CRLValidity getCrlValidity(final X509CRL x509CRL, final CertificateToken issuerToken, final List<String> dpUrlStringList) {
CRLValidity crlValidity = crlValidityMap.get(x509CRL);
if (crlValidity == null) {
crlValidity = isValidCRL(x509CRL, issuerToken, dpUrlStringList);
if (crlValidity.isValid()) {
crlValidityMap.put(x509CRL, crlValidity);
}
}
return crlValidity;
}
/**
* @return unmodifiable {@code List} of {@code X509CRL}s
*/
public List<X509CRL> getContainedX509CRLs() {
final List<X509CRL> x509CRLs = Collections.unmodifiableList(x509CRLList);
return x509CRLs;
}
}