/**
 * 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.wss4j.dom.util;

import org.apache.wss4j.dom.SOAP11Constants;
import org.apache.wss4j.dom.SOAP12Constants;
import org.apache.wss4j.dom.SOAPConstants;
import org.apache.wss4j.dom.WSConstants;
import org.apache.wss4j.dom.callback.CallbackLookup;
import org.apache.wss4j.dom.engine.WSSConfig;
import org.apache.wss4j.common.WSEncryptionPart;
import org.apache.wss4j.common.ext.Attachment;
import org.apache.wss4j.common.ext.AttachmentResultCallback;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.util.AttachmentUtils;
import org.apache.wss4j.common.util.XMLUtils;
import org.apache.wss4j.dom.handler.HandlerAction;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.apache.xml.security.stax.ext.XMLSecurityConstants;
import org.w3c.dom.Attr;
import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.Text;

//import com.sun.xml.internal.messaging.saaj.soap.SOAPDocumentImpl;

import java.io.ByteArrayInputStream;
import java.io.UnsupportedEncodingException;
import java.lang.reflect.AccessibleObject;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.AccessController;
import java.security.PrivilegedAction;
import java.security.PrivilegedActionException;
import java.security.PrivilegedExceptionAction;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

import javax.security.auth.callback.Callback;
import javax.security.auth.callback.CallbackHandler;


/**
 * WS-Security Utility methods. <p/>
 */
public final class WSSecurityUtil {

    private static boolean isSAAJ14 = false;

    private static final org.slf4j.Logger LOG =
        org.slf4j.LoggerFactory.getLogger(WSSecurityUtil.class);

    private static final ClassValue<Method> GET_DOM_ELEMENTS_METHODS = new ClassValue<Method>() {
        @Override
        protected Method computeValue(Class<?> type) {
            try {
                return getMethod(type, "getDomElement");
            } catch (NoSuchMethodException e) {
                //best effort to try, do nothing if NoSuchMethodException
                return null;
            }
        }
    };

    private static final ClassValue<Method> GET_ENVELOPE_METHODS = new ClassValue<Method>() {
        @Override
        protected Method computeValue(Class<?> type) {
            try {
                return getMethod(type, "getEnvelope");
            } catch (NoSuchMethodException e) {
                //best effort to try, do nothing if NoSuchMethodException
                return null;
            }
        }
    };

    static {
        try {
            Method[] methods = WSSecurityUtil.class.getClassLoader().
                loadClass("com.sun.xml.messaging.saaj.soap.SOAPDocumentImpl").getMethods();
            for (Method method : methods) {
                if (method.getName().equals("register")) {
                    //this is the 1.4+ SAAJ impl
                    isSAAJ14 = true;
                    break;
                }
            }
        } catch (ClassNotFoundException cnfe) {
            LOG.debug("Can't load class com.sun.xml.messaging.saaj.soap.SOAPDocumentImpl", cnfe);

            try {
                Method[] methods = WSSecurityUtil.class.getClassLoader().
                    loadClass("com.sun.xml.internal.messaging.saaj.soap.SOAPDocumentImpl").getMethods();
                for (Method method : methods) {
                    if (method.getName().equals("register")) {
                        //this is the SAAJ impl in JDK9
                        isSAAJ14 = true;
                        break;
                    }
                }
            } catch (ClassNotFoundException cnfe1) {
                LOG.debug("can't load class com.sun.xml.internal.messaging.saaj.soap.SOAPDocumentImpl", cnfe1);
            }
        }
    }

    private WSSecurityUtil() {
        // Complete
    }

    private static Method getMethod(final Class<?> clazz, final String name,
                                   final Class<?>... parameterTypes) throws NoSuchMethodException {
        try {
            return AccessController.doPrivileged(new PrivilegedExceptionAction<Method>() {
                public Method run() throws Exception {
                    return clazz.getMethod(name, parameterTypes);
                }
            });
        } catch (PrivilegedActionException pae) {
            Exception e = pae.getException();
            if (e instanceof NoSuchMethodException) {
                throw (NoSuchMethodException)e;
            }
            throw new SecurityException(e);
        }
    }

    private static <T extends AccessibleObject> T setAccessible(final T o) {
        return AccessController.doPrivileged(new PrivilegedAction<T>() {
            public T run() {
                o.setAccessible(true);
                return o;
            }
        });
    }

    public static Element getSOAPHeader(Document doc) {
        String soapNamespace = WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement());
        return
            XMLUtils.getDirectChildElement(
                doc.getDocumentElement(), WSConstants.ELEM_HEADER, soapNamespace
            );
    }

    /**
     * Returns the first WS-Security header element for a given actor. Only one
     * WS-Security header is allowed for an actor.
     *
     * @param doc
     * @param actor
     * @return the <code>wsse:Security</code> element or <code>null</code>
     *         if not such element found
     */
    public static Element getSecurityHeader(Document doc, String actor) throws WSSecurityException {
        Element soapHeaderElement = getSOAPHeader(doc);
        if (soapHeaderElement == null) { // no SOAP header at all
            return null;
        }

        String soapNamespace = WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement());
        return getSecurityHeader(soapHeaderElement, actor, WSConstants.URI_SOAP12_ENV.equals(soapNamespace));
    }

    /**
     * Returns the first WS-Security header element for a given actor. Only one
     * WS-Security header is allowed for an actor.
     */
    public static Element getSecurityHeader(Element soapHeader, String actor, boolean soap12)
        throws WSSecurityException {

        String actorLocal = WSConstants.ATTR_ACTOR;
        String soapNamespace = WSConstants.URI_SOAP11_ENV;
        if (soap12) {
            actorLocal = WSConstants.ATTR_ROLE;
            soapNamespace = WSConstants.URI_SOAP12_ENV;
        }

        //
        // Iterate through the security headers
        //
        Element foundSecurityHeader = null;
        for (
            Node currentChild = soapHeader.getFirstChild();
            currentChild != null;
            currentChild = currentChild.getNextSibling()
        ) {
            if (Node.ELEMENT_NODE == currentChild.getNodeType()
                && WSConstants.WSSE_LN.equals(currentChild.getLocalName())
                && (WSConstants.WSSE_NS.equals(currentChild.getNamespaceURI())
                    || WSConstants.OLD_WSSE_NS.equals(currentChild.getNamespaceURI()))) {

                Element elem = (Element)currentChild;
                Attr attr = elem.getAttributeNodeNS(soapNamespace, actorLocal);
                String hActor = (attr != null) ? attr.getValue() : null;

                if (WSSecurityUtil.isActorEqual(actor, hActor)) {
                    if (foundSecurityHeader != null) {
                        LOG.debug(
                            "Two or more security headers have the same actor name: {}", actor
                        );
                        throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
                    }
                    foundSecurityHeader = elem;
                }
            }
        }
        return foundSecurityHeader;
    }


    /**
     * Compares two actor strings and returns true if these are equal. Takes
     * care of the null length strings and uses ignore case.
     *
     * @param actor
     * @param hActor
     * @return true is the actor arguments are equal
     */
    public static boolean isActorEqual(String actor, String hActor) {
        if ((hActor == null || hActor.length() == 0)
            && (actor == null || actor.length() == 0)) {
            return true;
        }

        if (hActor != null && actor != null && hActor.equalsIgnoreCase(actor)) {
            return true;
        }

        return false;
    }

    /**
     * Gets all direct children with specified localname and namespace. <p/>
     *
     * @param fNode the node where to start the search
     * @param localName local name of the children to get
     * @param namespace the namespace of the children to get
     * @return the list of nodes or <code>null</code> if not such nodes are found
     */
    public static List<Element> getDirectChildElements(
        Node fNode,
        String localName,
        String namespace
    ) {
        List<Element> children = new ArrayList<>();
        for (
            Node currentChild = fNode.getFirstChild();
            currentChild != null;
            currentChild = currentChild.getNextSibling()
        ) {
            if (Node.ELEMENT_NODE == currentChild.getNodeType()
                && localName.equals(currentChild.getLocalName())
                && namespace.equals(currentChild.getNamespaceURI())) {
                children.add((Element)currentChild);
            }
        }
        return children;
    }


    /**
     * return the first soap "Body" element. <p/>
     *
     * @param doc
     * @return the body element or <code>null</code> if document does not
     *         contain a SOAP body
     */
    public static Element findBodyElement(Document doc) {
        Element docElement = doc.getDocumentElement();
        String ns = docElement.getNamespaceURI();
        return XMLUtils.getDirectChildElement(docElement, WSConstants.ELEM_BODY, ns);
    }


    /**
     * Find the DOM Element in the SOAP Envelope that is referenced by the
     * WSEncryptionPart argument. The "Id" is used before the Element localname/namespace.
     *
     * @param part The WSEncryptionPart object corresponding to the DOM Element(s) we want
     * @param callbackLookup The CallbackLookup object used to find Elements
     * @param doc The owning document
     * @return the DOM Element in the SOAP Envelope that is found
     */
    public static List<Element> findElements(
        WSEncryptionPart part, CallbackLookup callbackLookup, Document doc
    ) throws WSSecurityException {
        // See if the DOM Element is stored in the WSEncryptionPart first
        if (part.getElement() != null) {
            return Collections.singletonList(part.getElement());
        }

        // Next try to find the Element via its wsu:Id
        String id = part.getId();
        if (id != null) {
            Element foundElement = callbackLookup.getElement(id, null, false);
            return Collections.singletonList(foundElement);
        }
        // Otherwise just lookup all elements with the localname/namespace
        return callbackLookup.getElements(part.getName(), part.getNamespace());
    }



    /**
     * Get the default encryption part - the SOAP Body of type "Content".
     */
    public static WSEncryptionPart getDefaultEncryptionPart(Document doc) {
        String soapNamespace =
            WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement());
        return new WSEncryptionPart(WSConstants.ELEM_BODY, soapNamespace, "Content");
    }

    /**
     * create a new element in the same namespace <p/>
     *
     * @param parent for the new element
     * @param localName of the new element
     * @return the new element
     */
    private static Element createElementInSameNamespace(Node parent, String localName) {
        String qName = localName;
        String prefix = parent.getPrefix();
        if (prefix != null && prefix.length() > 0) {
            qName = prefix + ":" + localName;
        }

        String nsUri = parent.getNamespaceURI();
        return parent.getOwnerDocument().createElementNS(nsUri, qName);
    }




    /**
     * prepend a child element <p/>
     *
     * @param parent element of this child element
     * @param child the element to append
     * @return the child element
     */
    public static Element prependChildElement(
        Element parent,
        Element child
    ) {
        Node firstChild = parent.getFirstChild();
        Element domChild = null;
        try {
            domChild = (Element)getDomElement(child);
        } catch (WSSecurityException e) {
            LOG.debug("Error when try to get Dom Element from the child", e);
        }
        if (firstChild == null) {
            return (Element)parent.appendChild(domChild);
        } else {
            return (Element)parent.insertBefore(domChild, firstChild);
        }
    }


    /**
     * find the first ws-security header block <p/>
     *
     * @param doc the DOM document (SOAP request)
     * @param envelope the SOAP envelope
     * @param doCreate if true create a new WSS header block if none exists
     * @return the WSS header or null if none found and doCreate is false
     */
    public static Element findWsseSecurityHeaderBlock(
        Document doc,
        Element envelope,
        boolean doCreate
    ) throws WSSecurityException {
        return findWsseSecurityHeaderBlock(doc, envelope, null, doCreate);
    }

    /**
     * find a WS-Security header block for a given actor <p/>
     *
     * @param doc the DOM document (SOAP request)
     * @param envelope the SOAP envelope
     * @param actor the actor (role) name of the WSS header
     * @param doCreate if true create a new WSS header block if none exists
     * @return the WSS header or null if none found and doCreate is false
     */
    public static Element findWsseSecurityHeaderBlock(
        Document doc,
        Element envelope,
        String actor,
        boolean doCreate
    ) throws WSSecurityException {
        String soapNamespace = WSSecurityUtil.getSOAPNamespace(doc.getDocumentElement());
        Element header =
            XMLUtils.getDirectChildElement(
                doc.getDocumentElement(),
                WSConstants.ELEM_HEADER,
                soapNamespace
            );
        if (header == null) { // no SOAP header at all
            if (doCreate) {
                if (isSAAJ14) {
                    try {
                        Node node = null;
                        Method method = GET_ENVELOPE_METHODS.get(doc.getClass());
                        if (method != null) {
                            try {
                                node = (Node)setAccessible(method).invoke(doc);
                            } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                                throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
                            }
                        }
                        if (node != null) {
                            header = createElementInSameNamespace(node, WSConstants.ELEM_HEADER);
                        } else {
                            header = createElementInSameNamespace(doc.getDocumentElement(), WSConstants.ELEM_HEADER);
                        }
                        header = (Element)doc.importNode(header, true);
                        header = (Element)getDomElement(header);
                        header = prependChildElement(envelope, header);

                    } catch (Exception e) {
                        throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
                    }

                } else {
                    header = createElementInSameNamespace(envelope, WSConstants.ELEM_HEADER);
                    header = prependChildElement(envelope, header);
                }
            } else {
                return null;
            }
        }

        String actorLocal = WSConstants.ATTR_ACTOR;
        if (WSConstants.URI_SOAP12_ENV.equals(soapNamespace)) {
            actorLocal = WSConstants.ATTR_ROLE;
        }

        //
        // Iterate through the security headers
        //
        Element foundSecurityHeader = null;
        for (
            Node currentChild = header.getFirstChild();
            currentChild != null;
            currentChild = currentChild.getNextSibling()
        ) {
            if (Node.ELEMENT_NODE == currentChild.getNodeType()
                && WSConstants.WSSE_LN.equals(currentChild.getLocalName())
                && WSConstants.WSSE_NS.equals(currentChild.getNamespaceURI())) {

                Element elem = (Element)currentChild;
                Attr attr = elem.getAttributeNodeNS(soapNamespace, actorLocal);
                String hActor = (attr != null) ? attr.getValue() : null;

                if (WSSecurityUtil.isActorEqual(actor, hActor)) {
                    if (foundSecurityHeader != null) {
                        LOG.debug(
                            "Two or more security headers have the same actor name: {}", actor
                        );
                        throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
                    }
                    foundSecurityHeader = elem;
                }
            }
        }
        if (foundSecurityHeader != null) {
            return foundSecurityHeader;
        } else if (doCreate) {
            foundSecurityHeader = doc.createElementNS(WSConstants.WSSE_NS, "wsse:Security");
            foundSecurityHeader.setAttributeNS(WSConstants.XMLNS_NS, "xmlns:wsse", WSConstants.WSSE_NS);
            foundSecurityHeader = (Element)doc.importNode(foundSecurityHeader, true);
            foundSecurityHeader = (Element)getDomElement(foundSecurityHeader);

            return prependChildElement(header, foundSecurityHeader);
        }
        return null;
    }

    /**
     * create a base64 test node <p/>
     *
     * @param doc the DOM document (SOAP request)
     * @param data to encode
     * @return a Text node containing the base64 encoded data
     */
    public static Text createBase64EncodedTextNode(Document doc, byte[] data) {
        return doc.createTextNode(org.apache.xml.security.utils.XMLUtils.encodeToString(data));
    }

    public static SOAPConstants getSOAPConstants(Element startElement) {
        Document doc = startElement.getOwnerDocument();
        String ns = doc.getDocumentElement().getNamespaceURI();
        if (WSConstants.URI_SOAP12_ENV.equals(ns)) {
            return new SOAP12Constants();
        }
        return new SOAP11Constants();
    }

    public static String getSOAPNamespace(Element startElement) {
        return getSOAPConstants(startElement).getEnvelopeURI();
    }

    public static List<Integer> decodeAction(String action) throws WSSecurityException {
        String actionToParse = action;
        if (actionToParse == null) {
            return Collections.emptyList();
        }
        actionToParse = actionToParse.trim();
        if ("".equals(actionToParse)) {
            return Collections.emptyList();
        }

        List<Integer> actions = new ArrayList<>();
        String[] single = actionToParse.split("\\s");
        for (int i = 0; i < single.length; i++) {
            if (single[i].equals(WSHandlerConstants.NO_SECURITY)) {
                return Collections.emptyList();
            } else if (single[i].equals(WSHandlerConstants.USERNAME_TOKEN)) {
                actions.add(WSConstants.UT);
            } else if (single[i].equals(WSHandlerConstants.USERNAME_TOKEN_NO_PASSWORD)) {
                actions.add(WSConstants.UT_NOPASSWORD);
            } else if (single[i].equals(WSHandlerConstants.SIGNATURE)) {
                actions.add(WSConstants.SIGN);
            } else if (single[i].equals(WSHandlerConstants.SIGNATURE_DERIVED)) {
                actions.add(WSConstants.DKT_SIGN);
            } else if (single[i].equals(WSHandlerConstants.ENCRYPT)) {
                actions.add(WSConstants.ENCR);
            } else if (single[i].equals(WSHandlerConstants.ENCRYPT_DERIVED)) {
                actions.add(WSConstants.DKT_ENCR);
            } else if (single[i].equals(WSHandlerConstants.SAML_TOKEN_UNSIGNED)) {
                actions.add(WSConstants.ST_UNSIGNED);
            } else if (single[i].equals(WSHandlerConstants.SAML_TOKEN_SIGNED)) {
                actions.add(WSConstants.ST_SIGNED);
            } else if (single[i].equals(WSHandlerConstants.TIMESTAMP)) {
                actions.add(WSConstants.TS);
            } else if (single[i].equals(WSHandlerConstants.USERNAME_TOKEN_SIGNATURE)) {
                actions.add(WSConstants.UT_SIGN);
            } else if (single[i].equals(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION)) {
                actions.add(WSConstants.SC);
            } else if (single[i].equals(WSHandlerConstants.CUSTOM_TOKEN)) {
                actions.add(WSConstants.CUSTOM_TOKEN);
            } else {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
                                              new Object[] {"Unknown action defined: " + single[i]}
                );
            }
        }
        return actions;
    }


    /**
     * Decode an action String. This method should only be called on the outbound side.
     * @param action The initial String of actions to perform
     * @param wssConfig This object holds the list of custom actions to be performed.
     * @return The list of HandlerAction Objects
     * @throws WSSecurityException
     */
    public static List<HandlerAction> decodeHandlerAction(
        String action,
        WSSConfig wssConfig
    ) throws WSSecurityException {
        if (action == null) {
            return Collections.emptyList();
        }

        List<HandlerAction> actions = new ArrayList<>();
        String[] single = action.split(" ");
        for (int i = 0; i < single.length; i++) {
            if (single[i].equals(WSHandlerConstants.NO_SECURITY)) {
                return actions;
            } else if (single[i].equals(WSHandlerConstants.USERNAME_TOKEN)) {
                actions.add(new HandlerAction(WSConstants.UT));
            } else if (single[i].equals(WSHandlerConstants.USERNAME_TOKEN_NO_PASSWORD)) {
                actions.add(new HandlerAction(WSConstants.UT_NOPASSWORD));
            } else if (single[i].equals(WSHandlerConstants.SIGNATURE)) {
                actions.add(new HandlerAction(WSConstants.SIGN));
            } else if (single[i].equals(WSHandlerConstants.SIGNATURE_DERIVED)) {
                actions.add(new HandlerAction(WSConstants.DKT_SIGN));
            } else if (single[i].equals(WSHandlerConstants.ENCRYPT)) {
                actions.add(new HandlerAction(WSConstants.ENCR));
            } else if (single[i].equals(WSHandlerConstants.ENCRYPT_DERIVED)) {
                actions.add(new HandlerAction(WSConstants.DKT_ENCR));
            } else if (single[i].equals(WSHandlerConstants.SAML_TOKEN_UNSIGNED)) {
                actions.add(new HandlerAction(WSConstants.ST_UNSIGNED));
            } else if (single[i].equals(WSHandlerConstants.SAML_TOKEN_SIGNED)) {
                actions.add(new HandlerAction(WSConstants.ST_SIGNED));
            } else if (single[i].equals(WSHandlerConstants.TIMESTAMP)) {
                actions.add(new HandlerAction(WSConstants.TS));
            } else if (single[i].equals(WSHandlerConstants.USERNAME_TOKEN_SIGNATURE)) {
                actions.add(new HandlerAction(WSConstants.UT_SIGN));
            } else if (single[i].equals(WSHandlerConstants.ENABLE_SIGNATURE_CONFIRMATION)) {
                actions.add(new HandlerAction(WSConstants.SC));
            } else if (single[i].equals(WSHandlerConstants.CUSTOM_TOKEN)) {
                actions.add(new HandlerAction(WSConstants.CUSTOM_TOKEN));
            } else {
                try {
                    int parsedAction = Integer.parseInt(single[i]);
                    if (wssConfig == null || wssConfig.getAction(parsedAction) == null) {
                        throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
                                                      new Object[] {"Unknown action defined: " + single[i]}
                        );
                    }
                    actions.add(new HandlerAction(parsedAction));
                } catch (NumberFormatException ex) {
                    throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
                                                  new Object[] {"Unknown action defined: " + single[i]}
                    );
                }
            }
        }
        return actions;
    }

    /**
     * Generate a nonce of the given length using the SHA1PRNG algorithm. The SecureRandom
     * instance that backs this method is cached for efficiency.
     *
     * @return a nonce of the given length
     * @throws WSSecurityException
     */
    public static byte[] generateNonce(int length) throws WSSecurityException {
        try {
            return XMLSecurityConstants.generateBytes(length);
        } catch (Exception ex) {
            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, ex,
                    "empty", new Object[] {"Error in generating nonce of length " + length}
            );
        }
    }

    public static void inlineAttachments(List<Element> includeElements,
                                         CallbackHandler attachmentCallbackHandler,
                                         boolean removeAttachments) throws WSSecurityException {
        for (Element includeElement : includeElements) {
            String xopURI = includeElement.getAttributeNS(null, "href");
            if (xopURI != null) {
                // Retrieve the attachment bytes
                byte[] attachmentBytes =
                    WSSecurityUtil.getBytesFromAttachment(xopURI, attachmentCallbackHandler, removeAttachments);
                String encodedBytes = org.apache.xml.security.utils.XMLUtils.encodeToString(attachmentBytes);

                Node encodedChild =
                    includeElement.getOwnerDocument().createTextNode(encodedBytes);
                includeElement.getParentNode().replaceChild(encodedChild, includeElement);
            }
        }
    }

    /**
     * Register the javax.xml.soap.Node with new Cloned Dom Node with java9
     * @param doc The SOAPDocumentImpl
     * @param clonedElement The cloned Element
     * @return new clonedElement which already associated with the SAAJ Node
     * @throws WSSecurityException
     */
    public static Element cloneElement(Document doc, Element clonedElement) throws WSSecurityException {
        clonedElement = (Element)clonedElement.cloneNode(true);
        if (isSAAJ14) {
            // here we need register the javax.xml.soap.Node with new instance
            clonedElement = (Element)doc.importNode(clonedElement, true);
            clonedElement = (Element)getDomElement(clonedElement);
        }
        return clonedElement;
    }

    /**
     * Try to get the DOM Node from the SAAJ Node with JAVA9
     * @param node The original node we need check
     * @return The DOM node
     * @throws WSSecurityException
     */
    private static Node getDomElement(Node node) throws WSSecurityException {
        if (node != null && isSAAJ14) {

            Method method = GET_DOM_ELEMENTS_METHODS.get(node.getClass());
            if (method != null) {
                try {
                    return (Node)setAccessible(method).invoke(node);
                } catch (IllegalAccessException | IllegalArgumentException | InvocationTargetException e) {
                    throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY);
                }
            }
        }
        return node;
    }

    public static byte[] getBytesFromAttachment(
        String xopUri, RequestData data
    ) throws WSSecurityException {
        return getBytesFromAttachment(xopUri, data.getAttachmentCallbackHandler());
    }

    public static byte[] getBytesFromAttachment(
        String xopUri, CallbackHandler attachmentCallbackHandler
    ) throws WSSecurityException {
        return getBytesFromAttachment(xopUri, attachmentCallbackHandler, true);
    }

    public static byte[] getBytesFromAttachment(
        String xopUri, CallbackHandler attachmentCallbackHandler, boolean removeAttachments
    ) throws WSSecurityException {
        return AttachmentUtils.getBytesFromAttachment(xopUri, attachmentCallbackHandler, removeAttachments);
    }

    public static String getAttachmentId(String xopUri) throws WSSecurityException {
        return AttachmentUtils.getAttachmentId(xopUri);
    }

    public static void storeBytesInAttachment(
        Element parentElement,
        Document doc,
        String attachmentId,
        byte[] bytes,
        CallbackHandler attachmentCallbackHandler
    ) throws WSSecurityException {
        parentElement.setAttributeNS(XMLUtils.XMLNS_NS, "xmlns:xop", WSConstants.XOP_NS);
        Element xopInclude =
            doc.createElementNS(WSConstants.XOP_NS, "xop:Include");
        try {
            xopInclude.setAttributeNS(null, "href", "cid:" + URLEncoder.encode(attachmentId, StandardCharsets.UTF_8.name()));
        } catch (UnsupportedEncodingException e) {
            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
        }
        parentElement.appendChild(xopInclude);

        Attachment resultAttachment = new Attachment();
        resultAttachment.setId(attachmentId);
        resultAttachment.setMimeType("application/ciphervalue");
        resultAttachment.setSourceStream(new ByteArrayInputStream(bytes));

        AttachmentResultCallback attachmentResultCallback = new AttachmentResultCallback();
        attachmentResultCallback.setAttachmentId(attachmentId);
        attachmentResultCallback.setAttachment(resultAttachment);
        try {
            attachmentCallbackHandler.handle(new Callback[]{attachmentResultCallback});
        } catch (Exception e) {
            throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, e);
        }

    }


}
