
eu.europa.esig.dss.asic.cades.merge.ASiCEWithCAdESContainerMerger Maven / Gradle / Ivy
/**
* 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.asic.cades.merge;
import eu.europa.esig.dss.asic.cades.validation.ASiCWithCAdESUtils;
import eu.europa.esig.dss.asic.common.ASiCContent;
import eu.europa.esig.dss.asic.common.ASiCUtils;
import eu.europa.esig.dss.asic.common.ZipUtils;
import eu.europa.esig.dss.asic.common.validation.ASiCManifestParser;
import eu.europa.esig.dss.enumerations.ASiCContainerType;
import eu.europa.esig.dss.exception.IllegalInputException;
import eu.europa.esig.dss.model.DSSDocument;
import eu.europa.esig.dss.spi.DSSUtils;
import eu.europa.esig.dss.utils.Utils;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Iterator;
import java.util.List;
/**
* This class is used to merge ASiC-E with CAdES containers.
*
*/
public class ASiCEWithCAdESContainerMerger extends AbstractASiCWithCAdESContainerMerger {
/**
* Empty constructor
*/
ASiCEWithCAdESContainerMerger() {
// empty
}
/**
* This constructor is used to create an ASiC-E With CAdES container merger from provided container documents
*
* @param containers {@link DSSDocument}s representing containers to be merged
*/
public ASiCEWithCAdESContainerMerger(DSSDocument... containers) {
super(containers);
}
/**
* This constructor is used to create an ASiC-E With CAdES from to given {@code ASiCContent}s
*
* @param asicContents {@link ASiCContent}s to be merged
*/
public ASiCEWithCAdESContainerMerger(ASiCContent... asicContents) {
super(asicContents);
}
@Override
protected boolean isSupported(DSSDocument container) {
return super.isSupported(container) && (!ASiCUtils.isASiCSContainer(container) || doesNotContainSignatures(container));
}
private boolean doesNotContainSignatures(DSSDocument container) {
List entryNames = ZipUtils.getInstance().extractEntryNames(container);
return !ASiCUtils.filesContainSignatures(entryNames);
}
@Override
protected boolean isSupported(ASiCContent asicContent) {
return super.isSupported(asicContent) && (!ASiCUtils.isASiCSContainer(asicContent) || doesNotContainSignatures(asicContent));
}
private boolean doesNotContainSignatures(ASiCContent asicContent) {
return Utils.isCollectionEmpty(asicContent.getSignatureDocuments());
}
@Override
protected ASiCContainerType getTargetASiCContainerType() {
return ASiCContainerType.ASiC_E;
}
@Override
protected void ensureContainerContentAllowMerge() {
// no checks available
}
@Override
protected void ensureSignaturesAllowMerge() {
if (Arrays.stream(asicContents).filter(asicContent -> Utils.isCollectionNotEmpty(asicContent.getSignatureDocuments()) ||
Utils.isCollectionNotEmpty(asicContent.getTimestampDocuments())).count() <= 1) {
// no signatures nor timestamps in all containers except maximum one. Can merge.
return;
}
ensureSignatureDocumentsValid();
ensureManifestDocumentsValid();
}
private void ensureSignatureDocumentsValid() {
List mergedSignatureNames = new ArrayList<>();
List asicContentsToProcess = new ArrayList<>(Arrays.asList(asicContents));
Iterator iterator = asicContentsToProcess.iterator();
while (iterator.hasNext()) {
ASiCContent asicContent = iterator.next();
iterator.remove(); // remove entry to avoid recursive comparison
List signatureDocumentList = new ArrayList<>(asicContent.getSignatureDocuments());
for (DSSDocument signatureDocument : signatureDocumentList) {
if (mergedSignatureNames.contains(signatureDocument.getName())) {
continue;
}
List signaturesToMerge = getSignatureDocumentsToBeMerged(asicContent, signatureDocument, asicContentsToProcess);
if (Utils.isCollectionNotEmpty(signaturesToMerge)) {
signaturesToMerge.add(signatureDocument);
mergedSignatureNames.add(signatureDocument.getName());
DSSDocument signaturesCms = mergeCmsSignatures(signaturesToMerge);
updateMergedSignatureInContainers(signaturesCms);
}
}
}
}
private List getSignatureDocumentsToBeMerged(ASiCContent currentASiCContent,
DSSDocument currentSignatureDocument,
List asicContentList) {
if (currentSignatureDocument.getName() == null) {
throw new IllegalInputException("Name shall be provided for a document!");
}
DSSDocument manifest = ASiCManifestParser.getLinkedManifest(
currentASiCContent.getAllManifestDocuments(), currentSignatureDocument.getName());
if (manifest == null) {
throw new UnsupportedOperationException(String.format("Unable to merge ASiC-E with CAdES containers. " +
"A signature with filename '%s' does not have a corresponding manifest file!", currentSignatureDocument.getName()));
}
List result = new ArrayList<>();
for (ASiCContent asicContentToCompare : asicContentList) {
DSSDocument signatureToCompare = DSSUtils.getDocumentWithName(
asicContentToCompare.getSignatureDocuments(), currentSignatureDocument.getName());
if (signatureToCompare != null) {
DSSDocument manifestToCompare = ASiCManifestParser.getLinkedManifest(
asicContentToCompare.getAllManifestDocuments(), signatureToCompare.getName());
if (manifestToCompare == null) {
throw new UnsupportedOperationException(String.format("Unable to merge ASiC-E with CAdES containers. " +
"A signature with filename '%s' does not have a corresponding manifest file!", signatureToCompare.getName()));
} else if (ASiCWithCAdESUtils.isCoveredByManifest(currentASiCContent.getAllManifestDocuments(), currentSignatureDocument.getName()) ||
ASiCWithCAdESUtils.isCoveredByManifest(asicContentToCompare.getAllManifestDocuments(), signatureToCompare.getName())) {
throw new UnsupportedOperationException(String.format("Unable to merge ASiC-E with CAdES containers. " +
"A signature with name '%s' in a container is covered by a manifest!", currentSignatureDocument.getName()));
} else if (manifest.getName().equals(manifestToCompare.getName()) &&
manifest.getDigest(DEFAULT_DIGEST_ALGORITHM).equals(manifestToCompare.getDigest(DEFAULT_DIGEST_ALGORITHM))) {
result.add(signatureToCompare);
} else {
throw new UnsupportedOperationException(String.format("Unable to merge ASiC-E with CAdES containers. " +
"Signatures with filename '%s' sign different manifests!", currentSignatureDocument.getName()));
}
}
}
return result;
}
private void updateMergedSignatureInContainers(DSSDocument mergedCmsSignature) {
for (ASiCContent asicContent : asicContents) {
if (DSSUtils.getDocumentNames(asicContent.getSignatureDocuments()).contains(mergedCmsSignature.getName())) {
ASiCUtils.addOrReplaceDocument(asicContent.getSignatureDocuments(), mergedCmsSignature);
}
}
}
private void ensureManifestDocumentsValid() {
ASiCContent mergedASiCContent = createEmptyContainer();
for (ASiCContent asicContent : asicContents) {
mergedASiCContent.getManifestDocuments().addAll(asicContent.getManifestDocuments());
mergedASiCContent.getArchiveManifestDocuments().addAll(asicContent.getArchiveManifestDocuments());
}
List asicContentsToProcess = new ArrayList<>(Arrays.asList(asicContents));
Iterator iterator = asicContentsToProcess.iterator();
while (iterator.hasNext()) {
ASiCContent asicContent = iterator.next();
iterator.remove();
for (DSSDocument manifest : asicContent.getManifestDocuments()) {
for (ASiCContent currentASiCContent : asicContentsToProcess) {
for (DSSDocument currentManifest : currentASiCContent.getManifestDocuments()) {
if (manifest.getName() != null && manifest.getName().equals(currentManifest.getName())) {
if (manifest.getDigest(DEFAULT_DIGEST_ALGORITHM).equals(currentManifest.getDigest(DEFAULT_DIGEST_ALGORITHM))) {
// continue
} else if (ASiCWithCAdESUtils.isCoveredByManifest(asicContent.getAllManifestDocuments(), manifest.getName()) ||
ASiCWithCAdESUtils.isCoveredByManifest(currentASiCContent.getAllManifestDocuments(), currentManifest.getName())) {
throw new UnsupportedOperationException(String.format("Unable to merge ASiC-E with CAdES containers. " +
"A manifest with name '%s' in a container is covered by another manifest!", currentManifest.getName()));
} else {
String newManifestName = asicFilenameFactory.getManifestFilename(mergedASiCContent);
currentManifest.setName(newManifestName);
}
}
}
}
}
for (DSSDocument manifest : asicContent.getArchiveManifestDocuments()) {
for (ASiCContent currentASiCContent : asicContentsToProcess) {
for (DSSDocument currentManifest : currentASiCContent.getArchiveManifestDocuments()) {
if (manifest.getName() != null && manifest.getName().equals(currentManifest.getName())) {
if (manifest.getDigest(DEFAULT_DIGEST_ALGORITHM).equals(currentManifest.getDigest(DEFAULT_DIGEST_ALGORITHM))) {
// continue
} else if (ASiCWithCAdESUtils.isCoveredByManifest(asicContent.getAllManifestDocuments(), manifest.getName()) ||
ASiCWithCAdESUtils.isCoveredByManifest(currentASiCContent.getAllManifestDocuments(), currentManifest.getName())) {
throw new UnsupportedOperationException(String.format("Unable to merge ASiC-E with CAdES containers. " +
"A manifest with name '%s' in a container is covered by another manifest!", currentManifest.getName()));
} else {
String newManifestName = asicFilenameFactory.getArchiveManifestFilename(mergedASiCContent);
currentManifest.setName(newManifestName);
}
}
}
}
}
}
}
}
© 2015 - 2025 Weber Informatics LLC | Privacy Policy