/**
* DSS - Digital Signature Services
* Copyright (C) 2015 European Commission, provided under the CEF programme
*
* This file is part of the "DSS - Digital Signature Services" project.
*
* This library 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.
*
* This library 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 this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
*/
package eu.europa.esig.dss.validation.executor;
import java.util.Date;
import java.util.HashSet;
import java.util.List;
import java.util.Set;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import eu.europa.esig.dss.DSSException;
import eu.europa.esig.dss.jaxb.detailedreport.DetailedReport;
import eu.europa.esig.dss.jaxb.detailedreport.XmlBasicBuildingBlocks;
import eu.europa.esig.dss.jaxb.detailedreport.XmlConclusion;
import eu.europa.esig.dss.jaxb.detailedreport.XmlConstraint;
import eu.europa.esig.dss.jaxb.detailedreport.XmlConstraintsConclusion;
import eu.europa.esig.dss.jaxb.detailedreport.XmlName;
import eu.europa.esig.dss.jaxb.detailedreport.XmlQMatrixBlock;
import eu.europa.esig.dss.jaxb.detailedreport.XmlSignatureAnalysis;
import eu.europa.esig.dss.jaxb.detailedreport.XmlSubXCV;
import eu.europa.esig.dss.jaxb.detailedreport.XmlTLAnalysis;
import eu.europa.esig.dss.jaxb.detailedreport.XmlValidationProcessTimestamps;
import eu.europa.esig.dss.jaxb.detailedreport.XmlXCV;
import eu.europa.esig.dss.jaxb.simplereport.SimpleReport;
import eu.europa.esig.dss.jaxb.simplereport.XmlPolicy;
import eu.europa.esig.dss.jaxb.simplereport.XmlSignature;
import eu.europa.esig.dss.jaxb.simplereport.XmlSignatureLevel;
import eu.europa.esig.dss.jaxb.simplereport.XmlSignatureScope;
import eu.europa.esig.dss.utils.Utils;
import eu.europa.esig.dss.validation.AttributeValue;
import eu.europa.esig.dss.validation.SignatureQualification;
import eu.europa.esig.dss.validation.policy.ValidationPolicy;
import eu.europa.esig.dss.validation.policy.rules.Indication;
import eu.europa.esig.dss.validation.policy.rules.SubIndication;
import eu.europa.esig.dss.validation.reports.wrapper.CertificateWrapper;
import eu.europa.esig.dss.validation.reports.wrapper.DiagnosticData;
import eu.europa.esig.dss.validation.reports.wrapper.SignatureWrapper;
/**
* This class builds a SimpleReport XmlDom from the diagnostic data and detailed validation report.
*/
public class SimpleReportBuilder {
private static final Logger logger = LoggerFactory.getLogger(SimpleReportBuilder.class);
private final Date currentTime;
private final ValidationPolicy policy;
private final DiagnosticData diagnosticData;
private final ValidationLevel validationLevel;
private final DetailedReport detailedReport;
private int totalSignatureCount = 0;
private int validSignatureCount = 0;
public SimpleReportBuilder(Date currentTime, ValidationPolicy policy, DiagnosticData diagnosticData, ValidationLevel validationLevel,
DetailedReport detailedReport) {
this.currentTime = currentTime;
this.policy = policy;
this.diagnosticData = diagnosticData;
this.validationLevel = validationLevel;
this.detailedReport = detailedReport;
}
/**
* This method generates the validation simpleReport.
*
* @param params
* validation process parameters
* @return the object representing {@code SimpleReport}
*/
public eu.europa.esig.dss.jaxb.simplereport.SimpleReport build() {
SimpleReport simpleReport = new SimpleReport();
addPolicyNode(simpleReport);
addValidationTime(simpleReport);
addDocumentName(simpleReport);
boolean containerInfoPresent = diagnosticData.isContainerInfoPresent();
if (containerInfoPresent) {
addContainerType(simpleReport);
}
addSignatures(simpleReport, containerInfoPresent);
addStatistics(simpleReport);
return simpleReport;
}
private void addPolicyNode(SimpleReport report) {
XmlPolicy xmlpolicy = new XmlPolicy();
xmlpolicy.setPolicyName(policy.getPolicyName());
xmlpolicy.setPolicyDescription(policy.getPolicyDescription());
report.setPolicy(xmlpolicy);
}
private void addValidationTime(SimpleReport report) {
report.setValidationTime(currentTime);
}
private void addDocumentName(SimpleReport report) {
report.setDocumentName(diagnosticData.getDocumentName());
}
private void addContainerType(SimpleReport simpleReport) {
simpleReport.setContainerType(diagnosticData.getContainerType());
}
private void addSignatures(SimpleReport simpleReport, boolean container) throws DSSException {
validSignatureCount = 0;
totalSignatureCount = 0;
List<SignatureWrapper> signatures = diagnosticData.getSignatures();
for (SignatureWrapper signature : signatures) {
addSignature(simpleReport, signature, container);
}
}
private void addStatistics(SimpleReport simpleReport) {
simpleReport.setValidSignaturesCount(validSignatureCount);
simpleReport.setSignaturesCount(totalSignatureCount);
}
/**
* @param simpleReport
* @param signature
* the diagnosticSignature element in the diagnostic data
* @param container
* true if the current file is a container
*/
private void addSignature(SimpleReport simpleReport, SignatureWrapper signature, boolean container) {
totalSignatureCount++;
String signatureId = signature.getId();
XmlSignature xmlSignature = new XmlSignature();
xmlSignature.setId(signatureId);
addCounterSignature(signature, xmlSignature);
addSignatureScope(signature, xmlSignature);
addSigningTime(signature, xmlSignature);
addSignatureFormat(signature, xmlSignature);
xmlSignature.setSignedBy(getSignedBy(signature));
if (container) {
xmlSignature.setFilename(signature.getSignatureFilename());
}
XmlConstraintsConclusion constraintsConclusion = null;
switch (validationLevel) {
case BASIC_SIGNATURES:
case TIMESTAMPS:
constraintsConclusion = getBasicSignatureValidationConclusion(signatureId);
break;
case LONG_TERM_DATA:
constraintsConclusion = getLongTermDataValidationConclusion(signatureId);
break;
case ARCHIVAL_DATA:
constraintsConclusion = getArchivalValidationConclusion(signatureId);
break;
default:
logger.error("Unsupported validation level : " + validationLevel);
break;
}
XmlConclusion conclusion = constraintsConclusion.getConclusion();
Indication indication = conclusion.getIndication();
SubIndication subIndication = conclusion.getSubIndication();
Set<String> errorList = new HashSet<String>();
Set<String> warnList = new HashSet<String>();
Set<String> infoList = new HashSet<String>();
XmlQMatrixBlock qmatrixBlock = detailedReport.getQMatrixBlock();
if (qmatrixBlock != null) {
List<XmlTLAnalysis> tlAnalysis = qmatrixBlock.getTLAnalysis();
for (XmlTLAnalysis xmlTLAnalysis : tlAnalysis) {
collectErrors(errorList, xmlTLAnalysis);
collectWarnings(warnList, xmlTLAnalysis);
collectInfos(infoList, xmlTLAnalysis);
}
List<XmlSignatureAnalysis> signatureAnalysis = qmatrixBlock.getSignatureAnalysis();
for (XmlSignatureAnalysis analysis : signatureAnalysis) {
if (Utils.areStringsEqual(analysis.getId(), signatureId)) {
collectErrors(errorList, analysis);
collectWarnings(warnList, analysis);
collectInfos(infoList, analysis);
}
}
}
List<XmlName> errors = conclusion.getErrors();
if (Utils.isCollectionNotEmpty(errors)) {
for (XmlName error : errors) {
errorList.add(error.getValue());
}
}
// TODO refactor
warnList.addAll(getWarnings(signatureId));
infoList.addAll(getInfos(signatureId));
xmlSignature.getErrors().addAll(errorList);
xmlSignature.getWarnings().addAll(warnList);
xmlSignature.getInfos().addAll(infoList);
if (Indication.PASSED.equals(indication)) {
validSignatureCount++;
xmlSignature.setIndication(Indication.TOTAL_PASSED);
} else if (Indication.FAILED.equals(indication)) {
xmlSignature.setIndication(Indication.TOTAL_FAILED);
} else {
xmlSignature.setIndication(indication); // INDERTERMINATE
}
xmlSignature.setSubIndication(subIndication);
addSignatureProfile(signature, xmlSignature);
simpleReport.getSignature().add(xmlSignature);
}
private Set<String> getWarnings(String signatureId) {
Set<String> warns = new HashSet<String>();
List<eu.europa.esig.dss.jaxb.detailedreport.XmlSignature> signatures = detailedReport.getSignatures();
for (eu.europa.esig.dss.jaxb.detailedreport.XmlSignature xmlSignature : signatures) {
if (Utils.areStringsEqual(signatureId, xmlSignature.getId())) {
collectWarnings(warns, xmlSignature.getValidationProcessBasicSignatures());
List<XmlValidationProcessTimestamps> validationProcessTimestamps = xmlSignature.getValidationProcessTimestamps();
if (Utils.isCollectionNotEmpty(validationProcessTimestamps)) {
for (XmlValidationProcessTimestamps xmlValidationProcessTimestamps : validationProcessTimestamps) {
collectWarnings(warns, xmlValidationProcessTimestamps);
}
}
collectWarnings(warns, xmlSignature.getValidationProcessLongTermData());
collectWarnings(warns, xmlSignature.getValidationProcessArchivalData());
}
}
return warns;
}
private void collectWarnings(Set<String> result, XmlConstraintsConclusion constraintConclusion) {
if (constraintConclusion != null) {
if (Utils.isCollectionNotEmpty(constraintConclusion.getConstraint())) {
for (XmlConstraint constraint : constraintConclusion.getConstraint()) {
if (Utils.isStringNotEmpty(constraint.getId())) {
List<XmlBasicBuildingBlocks> basicBuildingBlocks = detailedReport.getBasicBuildingBlocks();
if (Utils.isCollectionNotEmpty(basicBuildingBlocks)) {
for (XmlBasicBuildingBlocks xmlBasicBuildingBlocks : basicBuildingBlocks) {
if (Utils.areStringsEqual(xmlBasicBuildingBlocks.getId(), constraint.getId())) {
collectWarnings(result, xmlBasicBuildingBlocks);
}
}
}
}
XmlName warning = constraint.getWarning();
if (warning != null) {
result.add(warning.getValue());
}
}
}
}
}
private void collectErrors(Set<String> result, XmlConstraintsConclusion constraintConclusion) {
if (constraintConclusion != null && Utils.isCollectionNotEmpty(constraintConclusion.getConstraint())) {
for (XmlConstraint constraint : constraintConclusion.getConstraint()) {
XmlName error = constraint.getError();
if (error != null) {
result.add(error.getValue());
}
}
}
}
private void collectWarnings(Set<String> result, XmlBasicBuildingBlocks bbb) {
if (bbb != null) {
collectWarnings(result, bbb.getFC());
collectWarnings(result, bbb.getISC());
collectWarnings(result, bbb.getCV());
collectWarnings(result, bbb.getSAV());
XmlXCV xcv = bbb.getXCV();
if (xcv != null) {
collectWarnings(result, xcv);
List<XmlSubXCV> subXCV = xcv.getSubXCV();
if (Utils.isCollectionNotEmpty(subXCV)) {
for (XmlSubXCV xmlSubXCV : subXCV) {
collectWarnings(result, xmlSubXCV);
}
}
}
collectWarnings(result, bbb.getVCI());
}
}
private Set<String> getInfos(String signatureId) {
Set<String> infos = new HashSet<String>();
List<eu.europa.esig.dss.jaxb.detailedreport.XmlSignature> signatures = detailedReport.getSignatures();
for (eu.europa.esig.dss.jaxb.detailedreport.XmlSignature xmlSignature : signatures) {
if (Utils.areStringsEqual(signatureId, xmlSignature.getId())) {
collectInfos(infos, xmlSignature.getValidationProcessBasicSignatures());
List<XmlValidationProcessTimestamps> validationProcessTimestamps = xmlSignature.getValidationProcessTimestamps();
if (Utils.isCollectionNotEmpty(validationProcessTimestamps)) {
for (XmlValidationProcessTimestamps xmlValidationProcessTimestamps : validationProcessTimestamps) {
collectInfos(infos, xmlValidationProcessTimestamps);
}
}
collectInfos(infos, xmlSignature.getValidationProcessLongTermData());
collectInfos(infos, xmlSignature.getValidationProcessArchivalData());
}
}
return infos;
}
private void collectInfos(Set<String> result, XmlConstraintsConclusion constraintConclusion) {
if (constraintConclusion != null) {
if (Utils.isCollectionNotEmpty(constraintConclusion.getConstraint())) {
for (XmlConstraint constraint : constraintConclusion.getConstraint()) {
if (Utils.isStringNotEmpty(constraint.getId())) {
List<XmlBasicBuildingBlocks> basicBuildingBlocks = detailedReport.getBasicBuildingBlocks();
if (Utils.isCollectionNotEmpty(basicBuildingBlocks)) {
for (XmlBasicBuildingBlocks xmlBasicBuildingBlocks : basicBuildingBlocks) {
if (Utils.areStringsEqual(xmlBasicBuildingBlocks.getId(), constraint.getId())) {
collectInfos(result, xmlBasicBuildingBlocks);
}
}
}
}
XmlName info = constraint.getInfo();
if (info != null) {
result.add(info.getValue());
}
}
}
}
}
private void collectInfos(Set<String> result, XmlBasicBuildingBlocks bbb) {
if (bbb != null) {
collectInfos(result, bbb.getFC());
collectInfos(result, bbb.getISC());
collectInfos(result, bbb.getCV());
collectInfos(result, bbb.getSAV());
XmlXCV xcv = bbb.getXCV();
if (xcv != null) {
collectInfos(result, xcv);
List<XmlSubXCV> subXCV = xcv.getSubXCV();
if (Utils.isCollectionNotEmpty(subXCV)) {
for (XmlSubXCV xmlSubXCV : subXCV) {
collectInfos(result, xmlSubXCV);
}
}
}
collectInfos(result, bbb.getVCI());
}
}
private XmlConstraintsConclusion getBasicSignatureValidationConclusion(String signatureId) {
List<eu.europa.esig.dss.jaxb.detailedreport.XmlSignature> signatures = detailedReport.getSignatures();
for (eu.europa.esig.dss.jaxb.detailedreport.XmlSignature xmlSignature : signatures) {
if (Utils.areStringsEqual(signatureId, xmlSignature.getId())) {
return xmlSignature.getValidationProcessBasicSignatures();
}
}
return null;
}
private XmlConstraintsConclusion getLongTermDataValidationConclusion(String signatureId) {
List<eu.europa.esig.dss.jaxb.detailedreport.XmlSignature> signatures = detailedReport.getSignatures();
for (eu.europa.esig.dss.jaxb.detailedreport.XmlSignature xmlSignature : signatures) {
if (Utils.areStringsEqual(signatureId, xmlSignature.getId())) {
return xmlSignature.getValidationProcessLongTermData();
}
}
return null;
}
private XmlConstraintsConclusion getArchivalValidationConclusion(String signatureId) {
List<eu.europa.esig.dss.jaxb.detailedreport.XmlSignature> signatures = detailedReport.getSignatures();
for (eu.europa.esig.dss.jaxb.detailedreport.XmlSignature xmlSignature : signatures) {
if (Utils.areStringsEqual(signatureId, xmlSignature.getId())) {
return xmlSignature.getValidationProcessArchivalData();
}
}
return null;
}
private void addCounterSignature(SignatureWrapper signature, XmlSignature xmlSignature) {
if (AttributeValue.COUNTERSIGNATURE.equals(signature.getType())) {
xmlSignature.setType(AttributeValue.COUNTERSIGNATURE);
xmlSignature.setParentId(signature.getParentId());
}
}
private void addSignatureScope(final SignatureWrapper signature, final XmlSignature xmlSignature) {
List<eu.europa.esig.dss.jaxb.diagnostic.XmlSignatureScope> signatureScopes = signature.getSignatureScopes();
if (Utils.isCollectionNotEmpty(signatureScopes)) {
for (eu.europa.esig.dss.jaxb.diagnostic.XmlSignatureScope scopeType : signatureScopes) {
XmlSignatureScope scope = new XmlSignatureScope();
scope.setName(scopeType.getName());
scope.setScope(scopeType.getScope());
scope.setValue(scopeType.getValue());
xmlSignature.getSignatureScope().add(scope);
}
}
}
private void addSigningTime(final SignatureWrapper signature, final XmlSignature xmlSignature) {
xmlSignature.setSigningTime(signature.getDateTime());
}
private void addSignatureFormat(final SignatureWrapper signature, final XmlSignature xmlSignature) {
xmlSignature.setSignatureFormat(signature.getSignatureFormat());
}
private String getSignedBy(final SignatureWrapper signature) {
CertificateWrapper signingCert = diagnosticData.getUsedCertificateById(signature.getSigningCertificateId());
if (signingCert != null) {
if (Utils.isStringNotEmpty(signingCert.getCommonName())) {
return signingCert.getCommonName();
}
if (Utils.isStringNotEmpty(signingCert.getGivenName())) {
return signingCert.getGivenName();
}
if (Utils.isStringNotEmpty(signingCert.getSurname())) {
return signingCert.getSurname();
}
if (Utils.isStringNotEmpty(signingCert.getPseudo())) {
return signingCert.getPseudo();
}
}
return "?";
}
private void addSignatureProfile(SignatureWrapper signature, final XmlSignature xmlSignature) {
XmlQMatrixBlock qmatrixBlock = detailedReport.getQMatrixBlock();
if (qmatrixBlock != null) {
SignatureQualification qualification = null;
List<XmlSignatureAnalysis> signatureAnalysis = qmatrixBlock.getSignatureAnalysis();
for (XmlSignatureAnalysis xmlSignatureAnalysis : signatureAnalysis) {
if (Utils.areStringsEqual(xmlSignatureAnalysis.getId(), signature.getId())) {
qualification = xmlSignatureAnalysis.getSignatureQualification();
}
}
if (qualification != null) {
XmlSignatureLevel sigLevel = new XmlSignatureLevel();
sigLevel.setValue(qualification);
sigLevel.setDescription(qualification.getLabel());
xmlSignature.setSignatureLevel(sigLevel);
}
}
}
}