/* * 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.xades; import java.util.ArrayList; import java.util.List; import javax.xml.crypto.dsig.XMLSignature; import org.w3c.dom.Document; import org.w3c.dom.Element; import org.w3c.dom.Node; import org.w3c.dom.NodeList; import eu.europa.ec.markt.dss.DSSUtils; import eu.europa.ec.markt.dss.DSSXMLUtils; import eu.europa.ec.markt.dss.exception.DSSException; import eu.europa.ec.markt.dss.exception.DSSNullException; import eu.europa.ec.markt.dss.signature.DSSDocument; import eu.europa.ec.markt.dss.signature.InMemoryDocument; import eu.europa.ec.markt.dss.validation102853.AdvancedSignature; import eu.europa.ec.markt.dss.validation102853.SignedDocumentValidator; import eu.europa.ec.markt.dss.validation102853.scope.SignatureScopeFinder; import eu.europa.ec.markt.dss.validation102853.scope.SignatureScopeFinderFactory; /** * Validator of XML Signed document * * @version $Revision: 889 $ - $Date: 2011-05-31 17:29:35 +0200 (Tue, 31 May 2011) $ */ public class XMLDocumentValidator extends SignedDocumentValidator { /** * This variable contains the list of {@code XPathQueryHolder} adapted to the specific signature schema. */ protected List<XPathQueryHolder> xPathQueryHolders; protected Document rootElement; /** * The default constructor for XMLDocumentValidator. The created instance is initialised with default {@code XPathQueryHolder} and {@code XAdES111XPathQueryHolder}. * * @param dssDocument The instance of {@code DSSDocument} to validate * @throws DSSException */ public XMLDocumentValidator(final DSSDocument dssDocument) throws DSSException { xadesSignatureScopeFinder = SignatureScopeFinderFactory.geInstance(XAdESSignature.class); this.document = dssDocument; this.rootElement = DSSXMLUtils.buildDOM(dssDocument); xPathQueryHolders = new ArrayList<XPathQueryHolder>(); final XAdES111XPathQueryHolder xades111xPathQueryHolder = new XAdES111XPathQueryHolder(); xPathQueryHolders.add(xades111xPathQueryHolder); final XPathQueryHolder xades122XPathQueryHolder = new XAdES122XPathQueryHolder(); xPathQueryHolders.add(xades122XPathQueryHolder); final XPathQueryHolder xPathQueryHolder = new XPathQueryHolder(); xPathQueryHolders.add(xPathQueryHolder); } @Override public List<AdvancedSignature> getSignatures() { if (signatures != null) { return signatures; } signatures = new ArrayList<AdvancedSignature>(); final NodeList signatureNodeList = DSSXMLUtils.getNodeList(rootElement, "//ds:Signature[not(parent::xades:CounterSignature)]"); //final NodeList signatureNodeList = rootElement.getElementsByTagNameNS(XMLSignature.XMLNS, XPathQueryHolder.XMLE_SIGNATURE); for (int ii = 0; ii < signatureNodeList.getLength(); ii++) { final Element signatureEl = (Element) signatureNodeList.item(ii); final XAdESSignature xadesSignature = new XAdESSignature(signatureEl, xPathQueryHolders, validationCertPool); xadesSignature.setDetachedContents(detachedContents); xadesSignature.setProvidedSigningCertificateToken(providedSigningCertificateToken); signatures.add(xadesSignature); } return signatures; } /** * Retrieves a signature based on its Id * * @param signatureId the given Id * @return the corresponding {@code XAdESSignature} * @throws DSSException in case no Id is provided, or in case no signature was found for the given Id */ public AdvancedSignature getSignatureById(final String signatureId) throws DSSException { if (DSSUtils.isBlank(signatureId)) { throw new DSSNullException(String.class, "signatureId"); } final List<AdvancedSignature> advancedSignatures = getSignatures(); for (final AdvancedSignature advancedSignature : advancedSignatures) { final String advancedSignatureId = advancedSignature.getId(); if (signatureId.equals(advancedSignatureId)) { return advancedSignature; } } throw new DSSException("The signature with the given id was not found!"); } @Override public DSSDocument removeSignature(final String signatureId) throws DSSException { if (DSSUtils.isBlank(signatureId)) { throw new DSSNullException(String.class, "signatureId"); } // TODO (31/07/2014): Checks on signature packaging to be added final NodeList signatureNodeList = rootElement.getElementsByTagNameNS(XMLSignature.XMLNS, XPathQueryHolder.XMLE_SIGNATURE); for (int ii = 0; ii < signatureNodeList.getLength(); ii++) { final Element signatureEl = (Element) signatureNodeList.item(ii); final String idIdentifier = DSSXMLUtils.getIDIdentifier(signatureEl); if (signatureId.equals(idIdentifier)) { signatureEl.getParentNode().removeChild(signatureEl); // TODO (31/07/2014): Save the modified document final Node documentElement = rootElement.getDocumentElement(); final byte[] documentBytes = DSSXMLUtils.serializeNode(documentElement); final InMemoryDocument inMemoryDocument = new InMemoryDocument(documentBytes); return inMemoryDocument; } } throw new DSSException("The signature with the given id was not found!"); } /** * This getter returns the {@code XPathQueryHolder} * * @return */ public List<XPathQueryHolder> getXPathQueryHolder() { return xPathQueryHolders; } /** * This adds a {@code XPathQueryHolder}. This is useful when the signature follows a particular schema. * * @param xPathQueryHolder */ public void addXPathQueryHolder(final XPathQueryHolder xPathQueryHolder) { xPathQueryHolders.add(xPathQueryHolder); } /** * Removes all of the elements from the list of query holders. The list will be empty after this call returns. */ public void clearQueryHolders() { xPathQueryHolders.clear(); } @Override protected SignatureScopeFinder getSignatureScopeFinder() { return xadesSignatureScopeFinder; } /** * @return */ public Document getRootElement() { return rootElement; } }