/*
 * Licensed to the Apache Software Foundation (ASF) under one or more
 * contributor license agreements.  See the NOTICE file distributed with
 * this work for additional information regarding copyright ownership.
 * The ASF licenses this file to You under the Apache License, Version 2.0
 * (the "License"); you may not use this file except in compliance with
 * the License.  You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
package org.apache.camel.component.xmlsecurity.processor;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.security.GeneralSecurityException;
import java.security.InvalidAlgorithmParameterException;
import java.security.InvalidKeyException;
import java.security.NoSuchAlgorithmException;
import java.security.NoSuchProviderException;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;

import javax.xml.crypto.AlgorithmMethod;
import javax.xml.crypto.KeySelector;
import javax.xml.crypto.dom.DOMStructure;
import javax.xml.crypto.dsig.CanonicalizationMethod;
import javax.xml.crypto.dsig.DigestMethod;
import javax.xml.crypto.dsig.Reference;
import javax.xml.crypto.dsig.SignatureMethod;
import javax.xml.crypto.dsig.SignedInfo;
import javax.xml.crypto.dsig.Transform;
import javax.xml.crypto.dsig.XMLObject;
import javax.xml.crypto.dsig.XMLSignature;
import javax.xml.crypto.dsig.XMLSignatureException;
import javax.xml.crypto.dsig.XMLSignatureFactory;
import javax.xml.crypto.dsig.dom.DOMSignContext;
import javax.xml.crypto.dsig.keyinfo.KeyInfo;
import javax.xml.crypto.dsig.spec.C14NMethodParameterSpec;
import javax.xml.crypto.dsig.spec.TransformParameterSpec;
import javax.xml.crypto.dsig.spec.XPathFilterParameterSpec;
import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.validation.Schema;
import javax.xml.xpath.XPathConstants;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;

import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;

import org.xml.sax.ErrorHandler;
import org.xml.sax.SAXException;

import org.apache.camel.Exchange;
import org.apache.camel.Message;
import org.apache.camel.component.xmlsecurity.api.KeyAccessor;
import org.apache.camel.component.xmlsecurity.api.SignatureType;
import org.apache.camel.component.xmlsecurity.api.XmlSignatureConstants;
import org.apache.camel.component.xmlsecurity.api.XmlSignatureException;
import org.apache.camel.component.xmlsecurity.api.XmlSignatureFormatException;
import org.apache.camel.component.xmlsecurity.api.XmlSignatureHelper;
import org.apache.camel.component.xmlsecurity.api.XmlSignatureInvalidKeyException;
import org.apache.camel.component.xmlsecurity.api.XmlSignatureNoKeyException;
import org.apache.camel.component.xmlsecurity.api.XmlSignatureProperties;
import org.apache.camel.support.processor.validation.DefaultValidationErrorHandler;
import org.apache.camel.support.processor.validation.ValidatorErrorHandler;
import org.apache.camel.util.IOHelper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

/**
 * Creates from the message body a XML signature element which is returned in
 * the message body of the output message. Enveloped, enveloping XML, and
 * detached signatures are supported.
 * <p>
 * In the enveloped XML signature case, the method
 * {@link XmlSignerConfiguration#getParentLocalName()} must not return
 * <code>null</code>. In this case the parent element must be contained in the
 * XML document provided by the message body and the signature element is added
 * as last child element of the parent element. If a KeyInfo instance is
 * provided by the {@link KeyAccessor} and
 * {@link XmlSignerConfiguration#getAddKeyInfoReference()} is <code>true</code>,
 * then also a reference to the KeyInfo element is added. The generated XML
 * signature has the following structure:
 * 
 * <pre>
 * {@code
 * <[parent element]>
 *     ...
 *      <Signature Id="[signature_id]">
 *          <SignedInfo>
 *                <Reference URI=""> 
 *                      <Transform Algorithm="http://www.w3.org/2000/09/xmldsig#enveloped-signature"/>
 *                      (<Transform>)*
 *                      <DigestMethod>
 *                      <DigestValue>
 *                </Reference>
 *                (<Reference URI="#[keyinfo_Id]">
 *                      <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
 *                      <DigestMethod>
 *                      <DigestValue>
 *                </Reference>)?
 *                <!-- further references possible, see XmlSignerConfiguration#setProperties(XmlSignatureProperties) -->
 *         </SignedInfo>
 *         <SignatureValue>
 *         (<KeyInfo Id="[keyinfo_id]">)?
 *         <!-- Object elements possible, see XmlSignerConfiguration#setProperties(XmlSignatureProperties) -->
 *     </Signature>
 * </[parent element]>
 * }
 * </pre>
 * <p>
 * In the enveloping XML signature case, the generated XML signature has the
 * following structure:
 * 
 * <pre>
 *  {@code
 *  <Signature Id="[signature_id]">
 *     <SignedInfo>
 *            <Reference URI="#[object_id]" type="[optional_type_value]"> 
 *                  (<Transform>)*
 *                  <DigestMethod>
 *                  <DigestValue>
 *            </Reference>
 *            (<Reference URI="#[keyinfo_id]">
 *                  <Transform Algorithm="http://www.w3.org/TR/2001/REC-xml-c14n-20010315"/>
 *                  <DigestMethod>
 *                  <DigestValue>
 *            </Reference>)?
 *             <!-- further references possible, see XmlSignerConfiguration#setProperties(XmlSignatureProperties) -->
 *     </SignedInfo>
 *     <SignatureValue>
 *     (<KeyInfo Id="[keyinfo_id]">)?
 *     <Object Id="[object_id]"/>
 *     <!-- further Object elements possible, see XmlSignerConfiguration#setProperties(XmlSignatureProperties) -->
 * </Signature>   
 *  }
 * </pre>
 * 
 * In the enveloping XML signature case, also message bodies containing plain
 * text are supported. This must be indicated via the header
 * {@link XmlSignatureConstants#HEADER_MESSAGE_IS_PLAIN_TEXT} or via the
 * configuration {@link XmlSignerConfiguration#getPlainText()}.
 * 
 * <p>
 * Detached signatures where the signature element is a sibling element to the
 * signed element are supported. Those elements can be signed which have ID
 * attributes. The elements to be signed must be specified via xpath expressions
 * (see {@link XmlSignerConfiguration#setXpathsToIdAttributes(List)}) and the
 * XML schema must be provided via the schema resource URI (see method
 * {@link XmlSignerConfiguration#setSchemaResourceUri(String)}. Elements with
 * deeper hierarchy level are signed first. This procedure can result in nested
 * signatures.
 * 
 * <p>
 * In all cases, the digest algorithm is either read from the configuration
 * method {@link XmlSignerConfiguration#getDigestAlgorithm()} or calculated from
 * the signature algorithm (
 * {@link XmlSignerConfiguration#getSignatureAlgorithm()}. The optional
 * transforms are read from {@link XmlSignerConfiguration#getTransformMethods()}
 * .
 * <p>
 * In all cases, you can add additional references and objects which contain
 * properties for the XML signature, see
 * {@link XmlSignerConfiguration#setProperties(XmlSignatureProperties)}.
 */

public class XmlSignerProcessor extends XmlSignatureProcessor {

    private static final Logger LOG = LoggerFactory.getLogger(XmlSignerProcessor.class);

    private static final String SHA512 = "sha512";
    private static final String SHA384 = "sha384";
    private static final String SHA256 = "sha256";
    private static final String SHA224 = "sha224";
    private static final String SHA1 = "sha1";
    private static final String RIPEMD160 = "ripemd160";

    private static final String HTTP_WWW_W3_ORG_2001_04_XMLDSIG_MORE_SHA224 = 
        "http://www.w3.org/2001/04/xmldsig-more#sha224"; // see RFC 4051
    
    private static final String HTTP_WWW_W3_ORG_2001_04_XMLDSIG_MORE_SHA384 = 
        "http://www.w3.org/2001/04/xmldsig-more#sha384"; // see RFC 4051

    private final XmlSignerConfiguration config;
    
    public XmlSignerProcessor(XmlSignerConfiguration config) {
        this.config = config;
    }

    @Override
    public XmlSignerConfiguration getConfiguration() {
        return config;
    }

    @Override
    public void process(Exchange exchange) throws Exception { //NOPMD

        try {
            LOG.debug("XML signature generation started using algorithm {} and canonicalization method {}", getConfiguration()
                    .getSignatureAlgorithm(), getConfiguration().getCanonicalizationMethod().getAlgorithm());

            // lets setup the out message before we invoke the signing
            // so that it can mutate it if necessary
            Message out = exchange.getOut();
            out.copyFrom(exchange.getIn());

            Document outputDoc = sign(out);

            ByteArrayOutputStream outStream = new ByteArrayOutputStream();
            XmlSignatureHelper.transformNonTextNodeToOutputStream(outputDoc, outStream, omitXmlDeclaration(out), getConfiguration().getOutputXmlEncoding());
            byte[] data = outStream.toByteArray();
            out.setBody(data);
            setOutputEncodingToMessageHeader(out);
            clearMessageHeaders(out);
            LOG.debug("XML signature generation finished");
        } catch (Exception e) {
            // remove OUT message, as an exception occurred
            exchange.setOut(null);
            throw e;
        }
    }

    protected Document sign(final Message out) throws Exception { //NOPMD

        try {
            XMLSignatureFactory fac;
            // Try to install the Santuario Provider - fall back to the JDK provider if this does
            // not work
            try {
                fac = XMLSignatureFactory.getInstance("DOM", "ApacheXMLDSig");
            } catch (NoSuchProviderException ex) {
                fac = XMLSignatureFactory.getInstance("DOM");
            }

            final Node node = getMessageBodyNode(out);

            if (getConfiguration().getKeyAccessor() == null) {
                throw new XmlSignatureNoKeyException(
                    "Key accessor is missing for XML signature generation. Specify a key accessor in the configuration.");
            }
            
            final KeySelector keySelector = getConfiguration().getKeyAccessor().getKeySelector(out);
            if (keySelector == null) {
                throw new XmlSignatureNoKeyException(
                        "Key selector is missing for XML signature generation. Specify a key selector in the configuration.");
            }

            SignatureType signatureType = determineSignatureType(out);

            final List<String> contentReferenceUris = getContentReferenceUris(out, signatureType, node);

            Node lastParent = null;
            // per content reference URI a signature is built; for enveloped and enveloping there is only one content reference URI;
            // only in the detached case there can be several
            for (final String contentReferenceUri : contentReferenceUris) {

                // the method KeyAccessor.getKeyInfo must be called after the method KeyAccessor.getKeySelector, this is part of the interface contract!
                // and this method must be called within the loop over the content reference URIs, because for each signature the key info ID must be different
                final KeyInfo keyInfo = getConfiguration().getKeyAccessor().getKeyInfo(out, node, fac.getKeyInfoFactory());

                String signatureId = getConfiguration().getSignatureId();
                if (signatureId == null) {
                    signatureId = "_" + UUID.randomUUID().toString();
                } else if (signatureId.isEmpty()) {
                    // indicator that no signature Id attribute shall be generated
                    signatureId = null;
                }

                // parent only relevant for enveloped or detached signature
                Node parent = getParentOfSignature(out, node, contentReferenceUri, signatureType);

                if (parent == null) {
                    // for enveloping signature, create new document 
                    parent = XmlSignatureHelper.newDocumentBuilder(Boolean.TRUE).newDocument();
                }
                lastParent = parent;

                XmlSignatureProperties.Input input = new InputBuilder().contentDigestAlgorithm(getDigestAlgorithmUri()).keyInfo(keyInfo)
                        .message(out).messageBodyNode(node).parent(parent).signatureAlgorithm(getConfiguration().getSignatureAlgorithm())
                        .signatureFactory(fac).signatureId(signatureId).contentReferenceUri(contentReferenceUri)
                        .signatureType(signatureType)
                        .prefixForXmlSignatureNamespace(getConfiguration().getPrefixForXmlSignatureNamespace()).build();

                XmlSignatureProperties.Output properties = getSignatureProperties(input);

                
                // the signature properties can overwrite the signature Id
                if (properties != null && properties.getSignatureId() != null && !properties.getSignatureId().isEmpty()) {
                    signatureId = properties.getSignatureId();
                }

                List<? extends XMLObject> objects = getObjects(input, properties);
                List<? extends Reference> refs = getReferences(input, properties, getKeyInfoId(keyInfo));

                SignedInfo si = createSignedInfo(fac, refs);

                DOMSignContext dsc = createAndConfigureSignContext(parent, keySelector);

                XMLSignature signature = fac.newXMLSignature(si, keyInfo, objects, signatureId, null);
                // generate the signature
                signature.sign(dsc);
            }

            return XmlSignatureHelper.getDocument(lastParent);

        } catch (XMLSignatureException se) {
            if (se.getCause() instanceof InvalidKeyException) {
                throw new XmlSignatureInvalidKeyException(se.getMessage(), se);
            } else {
                throw new XmlSignatureException(se);
            }
        } catch (GeneralSecurityException e) {
            // like NoSuchAlgorithmException, InvalidAlgorithmParameterException, NoSuchProviderException
            throw new XmlSignatureException(e);
        }

    }

    private SignatureType determineSignatureType(Message message) throws XmlSignatureException {
        if (getConfiguration().getParentLocalName() != null && getConfiguration().getParentXpath() != null) {
            throw new XmlSignatureException(
                    "The configuration of the XML signer component is wrong. The parent local name "
                            + getConfiguration().getParentLocalName()
                            + " and the parent XPath " + getConfiguration().getParentXpath().getXPath() + " are specified. You must not specify both parameters.");

        }

        boolean isEnveloped = getConfiguration().getParentLocalName() != null || getConfiguration().getParentXpath() != null;

        boolean isDetached = getXpathToIdAttributes(message).size() > 0;

        if (isEnveloped && isDetached) {
            if (getConfiguration().getParentLocalName() != null) {
                throw new XmlSignatureException(
                    "The configuration of the XML signer component is wrong. The parent local name "
                            + getConfiguration().getParentLocalName()
                            + " for an enveloped signature and the XPATHs to ID attributes for a detached signature are specified. You must not specify both parameters.");
            } else {
                throw new XmlSignatureException(
                        "The configuration of the XML signer component is wrong. The parent XPath "
                                + getConfiguration().getParentXpath().getXPath()
                                + " for an enveloped signature and the XPATHs to ID attributes for a detached signature are specified. You must not specify both parameters.");

            }
        }

        SignatureType result;
        if (isEnveloped) {
            result = SignatureType.enveloped;
        } else if (isDetached) {
            if (getSchemaResourceUri(message) == null) {
                throw new XmlSignatureException(
                        "The configruation of the XML Signature component is wrong: No XML schema specified in the detached case");
            }
            result = SignatureType.detached;
        } else {
            result = SignatureType.enveloping;
        }

        LOG.debug("Signature type: {}", result);
        return result;

    }

    protected List<XPathFilterParameterSpec> getXpathToIdAttributes(Message message) {

        @SuppressWarnings("unchecked")
        List<XPathFilterParameterSpec> result = (List<XPathFilterParameterSpec>) message
                .getHeader(XmlSignatureConstants.HEADER_XPATHS_TO_ID_ATTRIBUTES);
        if (result == null) {
            result = getConfiguration().getXpathsToIdAttributes();
        }
        return result;
    }

    protected XmlSignatureProperties.Output getSignatureProperties(XmlSignatureProperties.Input input) throws Exception { //NOPMD
        XmlSignatureProperties propGetter = getConfiguration().getProperties();
        XmlSignatureProperties.Output propsOutput = null;
        if (propGetter != null) {
            propsOutput = propGetter.get(input);
        }
        return propsOutput;
    }

    private DOMSignContext createAndConfigureSignContext(Node parent, KeySelector keySelector) {
        DOMSignContext dsc = new DOMSignContext(keySelector, parent);
        // set namespace prefix for "http://www.w3.org/2000/09/xmldsig#" according to best practice described in http://www.w3.org/TR/xmldsig-bestpractices/#signing-xml-without-namespaces
        if (getConfiguration().getPrefixForXmlSignatureNamespace() != null
                && !getConfiguration().getPrefixForXmlSignatureNamespace().isEmpty()) {
            dsc.putNamespacePrefix("http://www.w3.org/2000/09/xmldsig#", getConfiguration().getPrefixForXmlSignatureNamespace());
        }
        dsc.putNamespacePrefix("http://www.w3.org/2001/10/xml-exc-c14n#", "ec");
        setCryptoContextProperties(dsc);
        setUriDereferencerAndBaseUri(dsc);
        return dsc;
    }

    protected Boolean omitXmlDeclaration(Message message) {
        Boolean omitXmlDeclaration = message.getHeader(XmlSignatureConstants.HEADER_OMIT_XML_DECLARATION, Boolean.class);
        if (omitXmlDeclaration == null) {
            omitXmlDeclaration = getConfiguration().getOmitXmlDeclaration();
        }
        if (omitXmlDeclaration == null) {
            omitXmlDeclaration = Boolean.FALSE;
        }
        LOG.debug("Omit XML declaration: {}", omitXmlDeclaration);
        return omitXmlDeclaration;
    }

    protected SignedInfo createSignedInfo(XMLSignatureFactory fac, List<? extends Reference> refs) throws Exception { //NOPMD
        return fac.newSignedInfo(fac.newCanonicalizationMethod(getConfiguration().getCanonicalizationMethod().getAlgorithm(),
                (C14NMethodParameterSpec) getConfiguration().getCanonicalizationMethod().getParameterSpec()),
                getSignatureMethod(getConfiguration().getSignatureAlgorithm(), fac), refs);
    }

    private SignatureMethod getSignatureMethod(String signatureAlgorithm, XMLSignatureFactory fac) throws NoSuchAlgorithmException,
            InvalidAlgorithmParameterException {
        return fac.newSignatureMethod(signatureAlgorithm, null);
    }

    protected Node getMessageBodyNode(Message message) throws Exception { //NOPMD
        InputStream is = message.getMandatoryBody(InputStream.class);

        Boolean isPlainText = isPlainText(message);

        Node node;
        if (isPlainText != null && isPlainText) {
            node = getTextNode(message, is);
        } else {
            ValidatorErrorHandler errorHandler = new DefaultValidationErrorHandler();
            Schema schema = getSchemaForSigner(message, errorHandler);
            Document doc = parseInput(is, getConfiguration().getDisallowDoctypeDecl(), schema, errorHandler);
            errorHandler.handleErrors(message.getExchange(), schema, null); // throws ValidationException
            node = doc.getDocumentElement();
            LOG.debug("Root element of document to be signed: {}", node);
        }
        return node;
    }

    protected Schema getSchemaForSigner(Message message, ValidatorErrorHandler errorHandler) throws XmlSignatureException, SAXException,
            IOException {
        Schema schema;
        String schemaResourceUri = getSchemaResourceUri(message);
        if (schemaResourceUri == null) {
            schema = null;
        } else {
            schema = getSchema(message);
        }
        return schema;
    }

    protected Boolean isPlainText(Message message) {
        Boolean isPlainText = message.getHeader(XmlSignatureConstants.HEADER_MESSAGE_IS_PLAIN_TEXT, Boolean.class);
        if (isPlainText == null) {
            isPlainText = getConfiguration().getPlainText();
        }
        LOG.debug("Is plain text: {}", isPlainText);
        return isPlainText;
    }

    protected Element getParentOfSignature(Message inMessage, Node messageBodyNode, String contentReferenceURI, SignatureType sigType)
        throws Exception { //NOPMD
        if (SignatureType.enveloping == sigType) {
            // enveloping case
            return null;
        }
        if (messageBodyNode.getParentNode() == null || messageBodyNode.getParentNode().getNodeType() != Node.DOCUMENT_NODE) {
            throw new XmlSignatureFormatException(
                    "Incomming message has wrong format: It is not an XML document. Cannot create an enveloped or detached XML signature.");
        }
        Document doc = (Document) messageBodyNode.getParentNode();
        if (SignatureType.detached == sigType) {
            return getParentForDetachedCase(doc, inMessage, contentReferenceURI);
        } else {
            // enveloped case
            return getParentForEnvelopedCase(doc, inMessage);
        }

    }
    
    protected Element getParentForEnvelopedCase(Document doc, Message inMessage) throws Exception { //NOPMD
        if (getConfiguration().getParentXpath() != null) {
            XPathFilterParameterSpec xp = getConfiguration().getParentXpath();
            XPathExpression exp;
            try {
                exp = XmlSignatureHelper.getXPathExpression(xp);
            } catch (XPathExpressionException e) {
                throw new XmlSignatureException("The parent XPath " + getConfiguration().getParentXpath().getXPath() + " is wrongly configured: The XPath " + xp.getXPath() + " is invalid.", e);
            }
            NodeList list = (NodeList) exp.evaluate(doc.getDocumentElement(), XPathConstants.NODESET);
            if (list == null || list.getLength() == 0) {
                throw new XmlSignatureException("The parent XPath " + xp.getXPath() + " returned no result. Check the configuration of the XML signer component.");
            }
            int length = list.getLength();
            for (int i = 0; i < length; i++) {
                Node node = list.item(i);
                if (node.getNodeType() == Node.ELEMENT_NODE) {
                    // return the first element
                    return (Element)node;
                }
            }
            throw new XmlSignatureException("The parent XPath " + xp.getXPath() + " returned no element. Check the configuration of the XML signer component.");
        } else {
            // parent local name is not null!
            NodeList parents = doc.getElementsByTagNameNS(getConfiguration().getParentNamespace(), getConfiguration().getParentLocalName());
            if (parents == null || parents.getLength() == 0) {
                throw new XmlSignatureFormatException(
                        String.format(
                                "Incoming message has wrong format: The parent element with the local name %s and the namespace %s was not found in the message to build an enveloped XML signature.",
                                getConfiguration().getParentLocalName(), getConfiguration().getParentNamespace()));
            }
            // return the first element
            return (Element) parents.item(0);
        }
    }

    private Element getParentForDetachedCase(Document doc, Message inMessage, String referenceUri) throws XmlSignatureException {
        String elementId = referenceUri;
        if (elementId.startsWith("#")) {
            elementId = elementId.substring(1);
        }
        Element el = doc.getElementById(elementId);
        if (el == null) {
            // should not happen because has been checked before
            throw new IllegalStateException("No element found for element ID " + elementId);
        }
        LOG.debug("Sibling element of the detached XML Signature with reference URI {}: {}  {}",
                new Object[] {referenceUri, el.getLocalName(), el.getNamespaceURI() });
        Element result = getParentElement(el);
        if (result != null) {
            return result;
        } else {
            throw new XmlSignatureException(
                    "Either the configuration of the XML Signature component is wrong or the incoming document has an invalid structure: The element "
                            + el.getLocalName() + "{" + el.getNamespaceURI() + "} which is referenced by the reference URI " + referenceUri
                            + " has no parent element. The element must have a parent element in the configured detached case.");
        }
    }

    private Element getParentElement(Node node) {
        int counter = 0;
        while (node != null && counter < 10000) {
            // counter is for avoiding security attacks
            Node parent = node.getParentNode();
            if (parent != null && parent.getNodeType() == Node.ELEMENT_NODE) {
                return (Element) parent;
            }
            node = parent;
            counter++;
        }
        return null;
    }

    protected List<? extends Reference> getReferences(XmlSignatureProperties.Input input, XmlSignatureProperties.Output properties,
            String keyInfoId) throws Exception { //NOPMD

        String referenceId = properties == null ? null : properties.getContentReferenceId();
        // Create Reference with URI="#<objectId>" for enveloping signature, URI="" for enveloped signature, and URI = <value from configuration> for detached signature and the transforms
        Reference ref = createReference(input.getSignatureFactory(), input.getContentReferenceUri(),
                getContentReferenceType(input.getMessage()), input.getSignatureType(), referenceId, input.getMessage());
        Reference keyInfoRef = createKeyInfoReference(input.getSignatureFactory(), keyInfoId, input.getContentDigestAlgorithm());

        int propsRefsSize = properties == null || properties.getReferences() == null || properties.getReferences().isEmpty() ? 0
                : properties.getReferences().size();
        int size = keyInfoRef == null ? propsRefsSize + 1 : propsRefsSize + 2;
        List<Reference> referenceList = new ArrayList<>(size);
        referenceList.add(ref);
        if (keyInfoRef != null) {
            referenceList.add(keyInfoRef);
        }
        if (properties != null && properties.getReferences() != null && !properties.getReferences().isEmpty()) {
            referenceList.addAll(properties.getReferences());
        }
        return referenceList;
    }

    protected List<? extends XMLObject> getObjects(XmlSignatureProperties.Input input, XmlSignatureProperties.Output properties)
        throws Exception { //NOPMD

        if (SignatureType.enveloped == input.getSignatureType() || SignatureType.detached == input.getSignatureType()) {
            if (properties == null || properties.getObjects() == null) {
                return Collections.emptyList();
            }
            return properties.getObjects();
        }

        // enveloping signature --> add additional object
        final String objectId = getConfiguration().getContentObjectId();
        LOG.debug("Object Content Id {}", objectId);

        XMLObject obj = createXMLObject(input.getSignatureFactory(), input.getMessageBodyNode(), objectId);
        if (properties == null || properties.getObjects() == null || properties.getObjects().isEmpty()) {
            return Collections.singletonList(obj);
        }
        List<XMLObject> result = new ArrayList<>(properties.getObjects().size() + 1);
        result.add(obj);
        result.addAll(properties.getObjects());
        return result;
    }

    private Node getTextNode(Message inMessage, InputStream is) throws IOException, ParserConfigurationException, XmlSignatureException {
        LOG.debug("Message body to be signed is plain text");
        String encoding = getMessageEncoding(inMessage);
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        IOHelper.copyAndCloseInput(is, bos);
        try {
            String text = new String(bos.toByteArray(), encoding);
            return XmlSignatureHelper.newDocumentBuilder(true).newDocument().createTextNode(text);
        } catch (UnsupportedEncodingException e) {
            throw new XmlSignatureException(String.format("The message encoding %s is not supported.", encoding), e);
        }
    }

    protected String getMessageEncoding(Message inMessage) {
        String encoding = inMessage.getHeader(XmlSignatureConstants.HEADER_PLAIN_TEXT_ENCODING, String.class);
        if (encoding == null) {
            encoding = getConfiguration().getPlainTextEncoding();
        }
        LOG.debug("Messge encoding: {}", encoding);
        return encoding;
    }

    protected Document parseInput(InputStream is, Boolean disallowDoctypeDecl, Schema schema, ErrorHandler errorHandler)
        throws ParserConfigurationException, IOException, XmlSignatureFormatException {
        try {
            DocumentBuilder db = XmlSignatureHelper.newDocumentBuilder(disallowDoctypeDecl, schema);
            db.setErrorHandler(errorHandler);
            return db.parse(is);
        } catch (SAXException e) {
            throw new XmlSignatureFormatException(
                    "XML signature generation not possible. Sent message is not an XML document. Check the sent message.", e);
        } finally {
            IOHelper.close(is, "input stream");
        }
    }

    protected Reference createReference(XMLSignatureFactory fac, String uri, String type, SignatureType sigType, String id, Message message)
        throws InvalidAlgorithmParameterException, XmlSignatureException {
        try {
            List<Transform> transforms = getTransforms(fac, sigType, message);
            Reference ref = fac.newReference(uri, fac.newDigestMethod(getDigestAlgorithmUri(), null), transforms, type, id);
            return ref;
        } catch (NoSuchAlgorithmException e) {
            throw new XmlSignatureException("Wrong algorithm specified in the configuration.", e);
        }
    }

    protected String getContentReferenceType(Message message) {
        String type = message.getHeader(XmlSignatureConstants.HEADER_CONTENT_REFERENCE_TYPE, String.class);
        if (type == null) {
            type = getConfiguration().getContentReferenceType();
        }
        LOG.debug("Content reference type: {}", type);
        return type;
    }

    protected List<String> getContentReferenceUris(Message message, SignatureType signatureType, Node messageBodyNode)
        throws XmlSignatureException, XPathExpressionException {

        List<String> result;
        if (SignatureType.enveloping == signatureType) {
            String uri = "#" + getConfiguration().getContentObjectId();
            result = Collections.singletonList(uri);
        } else if (SignatureType.enveloped == signatureType) {
            // only for enveloped the parameter content reference URI is used
            String uri = message.getHeader(XmlSignatureConstants.HEADER_CONTENT_REFERENCE_URI, String.class);
            if (uri == null) {
                uri = getConfiguration().getContentReferenceUri();
            }
            if (uri == null) {
                uri = "";
            }
            result = Collections.singletonList(uri);
        } else if (SignatureType.detached == signatureType) {
            result = getContentReferenceUrisForDetachedCase(message, messageBodyNode);
        } else {
            // should not occur
            throw new IllegalStateException("Signature type " + signatureType + " not supported");
        }

        LOG.debug("Content reference URI(s): {}", result);
        return result;
    }

    private List<String> getContentReferenceUrisForDetachedCase(Message message, Node messageBodyNode) throws XmlSignatureException,
            XPathExpressionException {
        List<XPathFilterParameterSpec> xpathsToIdAttributes = getXpathToIdAttributes(message);
        if (xpathsToIdAttributes.isEmpty()) {
            // should not happen, has already been checked earlier
            throw new IllegalStateException("List of XPATHs to ID attributes is empty in detached signature case");
        }
        List<ComparableNode> result = new ArrayList<>(xpathsToIdAttributes.size());
        for (XPathFilterParameterSpec xp : xpathsToIdAttributes) {
            XPathExpression exp;
            try {
                exp = XmlSignatureHelper.getXPathExpression(xp);
            } catch (XPathExpressionException e) {
                throw new XmlSignatureException("The configured xpath expression " + xp.getXPath() + " is invalid.", e);
            }
            NodeList list = (NodeList) exp.evaluate(messageBodyNode, XPathConstants.NODESET);
            if (list == null) {
                //assume optional element, XSD validation has been done before
                LOG.warn("No ID attribute found for xpath expression {}. Therfore this xpath expression will be ignored.", xp.getXPath());
                continue;
            }
            int length = list.getLength();
            for (int i = 0; i < length; i++) {
                Node node = list.item(i);
                if (node.getNodeType() == Node.ATTRIBUTE_NODE) {
                    Attr attr = (Attr) node;
                    String value = attr.getValue();
                    // check that attribute is ID attribute
                    Element element = messageBodyNode.getOwnerDocument().getElementById(value);
                    if (element == null) {
                        throw new XmlSignatureException(
                                "Wrong configured xpath expression for ID attributes: The evaluation of the xpath expression "
                                        + xp.getXPath() + " resulted in an attribute which is not of type ID. The attribute value is "
                                        + value + ".");
                    }
                    result.add(new ComparableNode(element, "#" + value));
                    LOG.debug("ID attribute with value {} found for xpath {}", value, xp.getXPath());
                } else {
                    throw new XmlSignatureException(
                            "Wrong configured xpath expression for ID attributes: The evaluation of the xpath expression " + xp.getXPath()
                                    + " returned a node which was not of type Attribute.");
                }
            }
        }
        if (result.size() == 0) {
            throw new XmlSignatureException(
                    "No element to sign found in the detached case. No node found for the configured xpath expressions "
                            + toString(xpathsToIdAttributes)
                            + ". Either the configuration of the XML signature component is wrong or the incoming message has not the correct structure.");
        }
        // sort so that elements with deeper hierarchy level are treated first
        Collections.sort(result);
        return ComparableNode.getReferenceUris(result);
    }

    private String toString(List<XPathFilterParameterSpec> xpathsToIdAttributes) {
        StringBuilder result = new StringBuilder();
        int counter = 0;
        for (XPathFilterParameterSpec xp : xpathsToIdAttributes) {
            counter++;
            result.append(xp.getXPath());
            if (counter < xpathsToIdAttributes.size()) {
                result.append(", ");
            }
        }
        return result.toString();
    }

    protected XMLObject createXMLObject(XMLSignatureFactory fac, Node node, String id) {
        return fac.newXMLObject(Collections.singletonList(new DOMStructure(node)), id, null, null);
    }

    private List<Transform> getTransforms(XMLSignatureFactory fac, SignatureType sigType, Message message) throws NoSuchAlgorithmException,
            InvalidAlgorithmParameterException {
        String transformMethodsHeaderValue = message.getHeader(XmlSignatureConstants.HEADER_TRANSFORM_METHODS, String.class);
        if (transformMethodsHeaderValue == null) {
            List<AlgorithmMethod> configuredTrafos = getConfiguration().getTransformMethods();
            if (SignatureType.enveloped == sigType) {
                // add enveloped transform if necessary
                if (configuredTrafos.size() > 0) {
                    if (!containsEnvelopedTransform(configuredTrafos)) {
                        configuredTrafos = new ArrayList<>(configuredTrafos.size() + 1);
                        configuredTrafos.add(XmlSignatureHelper.getEnvelopedTransform());
                        configuredTrafos.addAll(getConfiguration().getTransformMethods());
                    }
                } else {
                    // add enveloped and C14N trafo
                    configuredTrafos = new ArrayList<>(2);
                    configuredTrafos.add(XmlSignatureHelper.getEnvelopedTransform());
                    configuredTrafos.add(XmlSignatureHelper.getCanonicalizationMethod(CanonicalizationMethod.INCLUSIVE));
                }
            }

            List<Transform> transforms = new ArrayList<>(configuredTrafos.size());
            for (AlgorithmMethod trafo : configuredTrafos) {
                Transform transform = fac.newTransform(trafo.getAlgorithm(), (TransformParameterSpec) trafo.getParameterSpec());
                transforms.add(transform);
                LOG.debug("Transform method: {}", trafo.getAlgorithm());
            }
            return transforms;
        } else {
            LOG.debug("Header {} with value '{}' found", XmlSignatureConstants.HEADER_TRANSFORM_METHODS, transformMethodsHeaderValue);
            String[] transformAlgorithms = transformMethodsHeaderValue.split(",");
            List<Transform> transforms = new ArrayList<>(transformAlgorithms.length);
            for (String transformAlgorithm : transformAlgorithms) {
                transformAlgorithm = transformAlgorithm.trim();
                Transform transform = fac.newTransform(transformAlgorithm, (TransformParameterSpec) null);
                transforms.add(transform);
                LOG.debug("Transform method: {}", transformAlgorithm);
            }
            return transforms;
        }
    }

    private boolean containsEnvelopedTransform(List<AlgorithmMethod> configuredTrafos) {
        for (AlgorithmMethod m : configuredTrafos) {
            if (Transform.ENVELOPED.equals(m.getAlgorithm())) {
                return true;
            }
        }
        return false;
    }

    protected String getDigestAlgorithmUri() throws XmlSignatureException {

        String result = getConfiguration().getDigestAlgorithm();
        if (result == null) {
            String signatureAlgorithm = getConfiguration().getSignatureAlgorithm();
            if (signatureAlgorithm != null) {
                if (signatureAlgorithm.contains(SHA1)) {
                    result = DigestMethod.SHA1;
                } else if (signatureAlgorithm.contains(SHA224)) {
                    result = HTTP_WWW_W3_ORG_2001_04_XMLDSIG_MORE_SHA224;
                } else if (signatureAlgorithm.contains(SHA256)) {
                    result = DigestMethod.SHA256;
                } else if (signatureAlgorithm.contains(SHA384)) {
                    result = HTTP_WWW_W3_ORG_2001_04_XMLDSIG_MORE_SHA384;
                } else if (signatureAlgorithm.contains(SHA512)) {
                    result = DigestMethod.SHA512;
                } else if (signatureAlgorithm.contains(RIPEMD160)) {
                    return DigestMethod.RIPEMD160;
                }
            }
        }
        if (result != null) {
            LOG.debug("Digest algorithm: {}", result);
            return result;
        }
        throw new XmlSignatureException(
                "Digest algorithm missing for XML signature generation. Specify the digest algorithm in the configuration.");
    }

    protected Reference createKeyInfoReference(XMLSignatureFactory fac, String keyInfoId, String digestAlgorithm) throws Exception { //NOPMD

        if (keyInfoId == null) {
            return null;
        }
        if (getConfiguration().getAddKeyInfoReference() == null) {
            return null;
        }

        if (!getConfiguration().getAddKeyInfoReference()) {
            return null;
        }

        LOG.debug("Creating reference to key info element with Id: {}", keyInfoId);
        List<Transform> transforms = new ArrayList<>(1);
        Transform transform = fac.newTransform(CanonicalizationMethod.INCLUSIVE, (TransformParameterSpec) null);
        transforms.add(transform);
        return fac.newReference("#" + keyInfoId, fac.newDigestMethod(digestAlgorithm, null), transforms, null, null);
    }

    private String getKeyInfoId(KeyInfo keyInfo) throws Exception { //NOPMD
        if (keyInfo == null) {
            return null;
        }
        return keyInfo.getId();
    }
    
    protected void setOutputEncodingToMessageHeader(Message message) {
        if (getConfiguration().getOutputXmlEncoding() != null) {
            message.setHeader(Exchange.CHARSET_NAME, getConfiguration().getOutputXmlEncoding());
        }
    }


    private static class InputBuilder {

        private XMLSignatureFactory signatureFactory;

        private String signatureAlgorithm;

        private Node parent;

        private Node messageBodyNode;

        private Message message;

        private KeyInfo keyInfo;

        private String contentDigestAlgorithm;

        private String signatureId;

        private String contentReferenceUri;

        private SignatureType signatureType;

        private String prefixForXmlSignatureNamespace;

        public InputBuilder signatureFactory(XMLSignatureFactory signatureFactory) {
            this.signatureFactory = signatureFactory;
            return this;
        }

        public InputBuilder signatureAlgorithm(String signatureAlgorithm) {
            this.signatureAlgorithm = signatureAlgorithm;
            return this;
        }

        public InputBuilder parent(Node parent) {
            this.parent = parent;
            return this;
        }

        public InputBuilder messageBodyNode(Node messageBodyNode) {
            this.messageBodyNode = messageBodyNode;
            return this;
        }

        public InputBuilder message(Message message) {
            this.message = message;
            return this;
        }

        public InputBuilder keyInfo(KeyInfo keyInfo) {
            this.keyInfo = keyInfo;
            return this;
        }

        public InputBuilder contentDigestAlgorithm(String contentDigestAlgorithm) {
            this.contentDigestAlgorithm = contentDigestAlgorithm;
            return this;
        }

        public InputBuilder signatureId(String signatureId) {
            this.signatureId = signatureId;
            return this;
        }

        public InputBuilder contentReferenceUri(String contentReferenceUri) {
            this.contentReferenceUri = contentReferenceUri;
            return this;
        }

        public InputBuilder signatureType(SignatureType signatureType) {
            this.signatureType = signatureType;
            return this;
        }

        public InputBuilder prefixForXmlSignatureNamespace(String prefixForXmlSignatureNamespace) {
            this.prefixForXmlSignatureNamespace = prefixForXmlSignatureNamespace;
            return this;
        }

        public XmlSignatureProperties.Input build() {
            return new XmlSignatureProperties.Input() {

                @Override
                public XMLSignatureFactory getSignatureFactory() {
                    return signatureFactory;
                }

                @Override
                public String getSignatureAlgorithm() {
                    return signatureAlgorithm;
                }

                @Override
                public Node getParent() {
                    return parent;
                }

                @Override
                public Node getMessageBodyNode() {
                    return messageBodyNode;
                }

                @Override
                public Message getMessage() {
                    return message;
                }

                @Override
                public KeyInfo getKeyInfo() {
                    return keyInfo;
                }

                @Override
                public String getContentDigestAlgorithm() {
                    return contentDigestAlgorithm;
                }

                @Override
                public String getSignatureId() {
                    return signatureId;
                }

                @Override
                public String getContentReferenceUri() {
                    return contentReferenceUri;
                }

                @Override
                public SignatureType getSignatureType() {
                    return signatureType;
                }

                @Override
                public String getPrefixForXmlSignatureNamespace() {
                    return prefixForXmlSignatureNamespace;
                }

            };
        }

    }

    /** Compares nodes by their hierarchy level. */
    static class ComparableNode implements Comparable<ComparableNode> {

        private final String referenceUri;
        private final int level;

        ComparableNode(Element node, String referenceUri) {
            this.referenceUri = referenceUri;
            level = calculateLevel(node);
        }

        private int calculateLevel(Element node) {
            int counter = 0;
            for (Node n = node; n != null; n = n.getParentNode()) {
                if (Node.ELEMENT_NODE == n.getNodeType()) {
                    counter++;
                    if (counter > 10000) {
                        // prevent security attack
                        throw new IllegalStateException("Hierachy level is limited to 10000");
                    }
                }
            }
            return counter;
        }

        @Override
        public int compareTo(ComparableNode o) {
            return o.level - level;
        }

        String getReferenceUri() {
            return referenceUri;
        }

        static List<String> getReferenceUris(List<ComparableNode> input) {
            List<String> result = new ArrayList<>(input.size());
            for (ComparableNode cn : input) {
                result.add(cn.getReferenceUri());
            }
            return result;
        }

    }

}
