/**
 * 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.stax.test;

import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList;
import java.util.Enumeration;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Properties;
import java.util.logging.Level;
import java.util.logging.LogManager;
import java.util.logging.Logger;

import javax.security.auth.callback.CallbackHandler;
import javax.xml.namespace.NamespaceContext;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;
import javax.xml.stream.XMLInputFactory;
import javax.xml.stream.XMLStreamException;
import javax.xml.stream.XMLStreamReader;
import javax.xml.stream.XMLStreamWriter;
import javax.xml.transform.TransformerException;
import javax.xml.transform.TransformerFactory;
import javax.xml.xpath.XPath;
import javax.xml.xpath.XPathExpression;
import javax.xml.xpath.XPathExpressionException;
import javax.xml.xpath.XPathFactory;

import org.apache.wss4j.common.bsp.BSPRule;
import org.apache.wss4j.common.crypto.Crypto;
import org.apache.wss4j.common.crypto.CryptoFactory;
import org.apache.wss4j.common.ext.WSSecurityException;
import org.apache.wss4j.common.util.SOAPUtil;
import org.apache.wss4j.common.util.XMLUtils;
import org.apache.wss4j.dom.WSConstants;

import org.apache.wss4j.dom.engine.WSSConfig;
import org.apache.wss4j.dom.engine.WSSecurityEngine;
import org.apache.wss4j.dom.engine.WSSecurityEngineResult;
import org.apache.wss4j.dom.handler.HandlerAction;
import org.apache.wss4j.dom.handler.RequestData;
import org.apache.wss4j.dom.handler.WSHandler;
import org.apache.wss4j.dom.handler.WSHandlerConstants;
import org.apache.wss4j.dom.handler.WSHandlerResult;
import org.apache.wss4j.dom.util.WSSecurityUtil;
import org.apache.wss4j.stax.ext.WSSConstants;
import org.apache.wss4j.stax.ext.WSSSecurityProperties;
import org.apache.wss4j.stax.setup.ConfigurationConverter;
import org.apache.wss4j.stax.setup.InboundWSSec;
import org.apache.wss4j.stax.setup.OutboundWSSec;
import org.apache.wss4j.stax.setup.WSSec;
import org.apache.wss4j.stax.test.utils.StAX2DOM;
import org.apache.wss4j.stax.test.utils.XmlReaderToWriter;
import org.apache.xml.security.exceptions.XMLSecurityException;
import org.apache.xml.security.stax.securityEvent.SecurityEvent;
import org.apache.xml.security.stax.securityEvent.SecurityEventConstants;
import org.apache.xml.security.stax.securityEvent.SecurityEventListener;

import org.w3c.dom.Document;
import org.w3c.dom.Element;

import static org.junit.jupiter.api.Assertions.assertNotEquals;
import static org.junit.jupiter.api.Assertions.assertNotNull;
import static org.junit.jupiter.api.Assertions.fail;

public abstract class AbstractTestBase {

    //javax.xml.transform.Transformer transformer = TransformerFactory.newInstance().newTransformer();
    //transformer.transform(new StreamSource(new ByteArrayInputStream(baos.toByteArray())), new StreamResult(System.out));

    protected static final XMLInputFactory xmlInputFactory = XMLInputFactory.newInstance();
    protected static final TransformerFactory TRANSFORMER_FACTORY = TransformerFactory.newInstance();
    protected DocumentBuilderFactory documentBuilderFactory;

    protected static final String SECURED_DOCUMENT = "securedDocument";

    static {
        LogManager.getLogManager().addLogger(Logger.getLogger("org.jcp.xml.dsig.internal.dom"));
        LogManager.getLogManager().getLogger("org.jcp.xml.dsig.internal.dom").setLevel(Level.FINE);
        WSSConfig.init();
    }

    public AbstractTestBase() {
        documentBuilderFactory = DocumentBuilderFactory.newInstance();
        documentBuilderFactory.setNamespaceAware(true);
        documentBuilderFactory.setIgnoringComments(false);
        documentBuilderFactory.setCoalescing(false);
        documentBuilderFactory.setIgnoringElementContentWhitespace(false);
        xmlInputFactory.setProperty(XMLInputFactory.IS_COALESCING, false);
        xmlInputFactory.setProperty(XMLInputFactory.SUPPORT_DTD, false);
        //xmlInputFactory.setProperty(WstxInputProperties.P_MIN_TEXT_SEGMENT, new Integer(5 * 8192));
    }

    public Document doInboundSecurity(WSSSecurityProperties securityProperties, InputStream inputStream)
            throws XMLStreamException, ParserConfigurationException, XMLSecurityException {
        return doInboundSecurity(securityProperties, xmlInputFactory.createXMLStreamReader(inputStream), null);
    }

    public Document doInboundSecurity(WSSSecurityProperties securityProperties, InputStream inputStream,
                                      SecurityEventListener securityEventListener)
            throws XMLStreamException, ParserConfigurationException, XMLSecurityException {
        return doInboundSecurity(securityProperties, xmlInputFactory.createXMLStreamReader(inputStream), securityEventListener);
    }

    public Document doInboundSecurity(WSSSecurityProperties securityProperties, InputStream inputStream,
                                      List<SecurityEvent> securityEventList, SecurityEventListener securityEventListener)
            throws XMLStreamException, ParserConfigurationException, XMLSecurityException {
        return doInboundSecurity(securityProperties, xmlInputFactory.createXMLStreamReader(inputStream), securityEventList, securityEventListener);
    }

    public Document doInboundSecurity(WSSSecurityProperties securityProperties, XMLStreamReader xmlStreamReader)
            throws XMLStreamException, ParserConfigurationException, XMLSecurityException {
        return doInboundSecurity(securityProperties, xmlStreamReader, null);
    }

    public Document doInboundSecurity(WSSSecurityProperties securityProperties, XMLStreamReader xmlStreamReader,
                                      SecurityEventListener securityEventListener)
            throws XMLStreamException, ParserConfigurationException, XMLSecurityException {
        return doInboundSecurity(securityProperties, xmlStreamReader, new ArrayList<SecurityEvent>(), securityEventListener);
    }

    public Document doInboundSecurity(WSSSecurityProperties securityProperties, XMLStreamReader xmlStreamReader,
                                      List<SecurityEvent> securityEventList, SecurityEventListener securityEventListener)
            throws XMLStreamException, ParserConfigurationException, XMLSecurityException {
        InboundWSSec wsSecIn = WSSec.getInboundWSSec(securityProperties, false, true);
        XMLStreamReader outXmlStreamReader = wsSecIn.processInMessage(xmlStreamReader, securityEventList, securityEventListener);
        return StAX2DOM.readDoc(documentBuilderFactory.newDocumentBuilder(), outXmlStreamReader);
    }

    protected ByteArrayOutputStream doOutboundSecurity(WSSSecurityProperties securityProperties, InputStream sourceDocument)
            throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
        XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
        XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
        XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
        xmlStreamWriter.close();
        return baos;
    }

    protected ByteArrayOutputStream doOutboundSecurity(Map<String, Object> config, InputStream sourceDocument)
        throws Exception {
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        WSSSecurityProperties securityProperties = ConfigurationConverter.convert(config);
        OutboundWSSec wsSecOut = WSSec.getOutboundWSSec(securityProperties);
        XMLStreamWriter xmlStreamWriter = wsSecOut.processOutMessage(baos, StandardCharsets.UTF_8.name(), new ArrayList<SecurityEvent>());
        XMLStreamReader xmlStreamReader = xmlInputFactory.createXMLStreamReader(sourceDocument);
        XmlReaderToWriter.writeAll(xmlStreamReader, xmlStreamWriter);
        xmlStreamWriter.close();
        return baos;
    }

    protected Document doOutboundSecurityWithWSS4J(InputStream sourceDocument, String action, Properties properties)
            throws WSSecurityException, TransformerException, IOException {
        Map<String, Object> context = doOutboundSecurityWithWSS4J_1(sourceDocument, action, properties);
        return (Document) context.get(SECURED_DOCUMENT);
    }

    protected Map<String, Object> doOutboundSecurityWithWSS4J_1(
            InputStream sourceDocument, String action, final Properties properties
    ) throws WSSecurityException, TransformerException, IOException {
        CustomWSS4JHandler wss4JHandler = new CustomWSS4JHandler();
        final Map<String, Object> messageContext = getMessageContext(sourceDocument);
        messageContext.put(WSHandlerConstants.ACTION, action);
        messageContext.put(WSHandlerConstants.USER, "transmitter");

        Properties sigProperties = new Properties();
        sigProperties.setProperty("org.apache.wss4j.crypto.provider", "org.apache.wss4j.common.crypto.Merlin");
        sigProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.file", "transmitter.jks");
        sigProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.password", "default");
        //sigProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.alias", "transmitter");
        wss4JHandler.setPassword(messageContext, "default");
        messageContext.put(WSHandlerConstants.SIG_PROP_REF_ID, "" + sigProperties.hashCode());
        messageContext.put("" + sigProperties.hashCode(), sigProperties);

        Properties encProperties = new Properties();
        encProperties.setProperty("org.apache.wss4j.crypto.provider", "org.apache.wss4j.common.crypto.Merlin");
        encProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.file", "transmitter.jks");
        encProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.password", "default");
        //sigProperties.setProperty("org.apache.wss4j.crypto.merlin.keystore.alias", "transmitter");
        wss4JHandler.setPassword(messageContext, "default");
        messageContext.put(WSHandlerConstants.ENCRYPTION_USER, "receiver");
        messageContext.put(WSHandlerConstants.ENC_PROP_REF_ID, "" + encProperties.hashCode());
        messageContext.put("" + encProperties.hashCode(), encProperties);

        Enumeration<?> enumeration = properties.propertyNames();
        while (enumeration.hasMoreElements()) {
            String s = (String) enumeration.nextElement();
            messageContext.put(s, properties.get(s));
        }

        RequestData requestData = new RequestData();
        requestData.setMsgContext(messageContext);
        if (messageContext.get(WSHandlerConstants.PW_CALLBACK_REF) == null) {
            requestData.setCallbackHandler(new WSS4JCallbackHandlerImpl());
        }
        requestData.setWssConfig(WSSConfig.getNewInstance());

        wss4JHandler.doSender(messageContext, requestData, true);

        return messageContext;
    }

    protected Document doInboundSecurityWithWSS4J(Document document, String action) throws Exception {
        Map<String, Object> messageContext = doInboundSecurityWithWSS4J_1(document, action);
        return (Document) messageContext.get(SECURED_DOCUMENT);
    }

    protected Map<String, Object> doInboundSecurityWithWSS4J_1(Document document, String action) throws Exception {
        return doInboundSecurityWithWSS4J_1(document, action, new Properties(), false);
    }

    protected Map<String, Object> doInboundSecurityWithWSS4J_1(
            Document document, String action, Properties properties, boolean client
    ) throws Exception {
        CustomWSS4JHandler wss4JHandler = new CustomWSS4JHandler();
        Map<String, Object> messageContext = getMessageContext(document);
        messageContext.put(WSHandlerConstants.ACTION, action);
        if (client) {
            messageContext.put(WSHandlerConstants.USER, "transmitter");
        } else {
            messageContext.put(WSHandlerConstants.USER, "receiver");
        }

        if (properties.get(WSHandlerConstants.PW_CALLBACK_REF) != null) {
            messageContext.put(WSHandlerConstants.PW_CALLBACK_REF, properties.get(WSHandlerConstants.PW_CALLBACK_REF));
        } else {
            messageContext.put(WSHandlerConstants.PW_CALLBACK_REF, new WSS4JCallbackHandlerImpl());
        }

        messageContext.put(WSHandlerConstants.VALIDATE_SAML_SUBJECT_CONFIRMATION, "false");
        Enumeration<?> enumeration = properties.propertyNames();
        while (enumeration.hasMoreElements()) {
            String s = (String) enumeration.nextElement();
            messageContext.put(s, properties.get(s));
        }

        RequestData requestData = new RequestData();
        requestData.setMsgContext(messageContext);
        if (client) {
            final Crypto crypto = CryptoFactory.getInstance("transmitter-crypto.properties");
            requestData.setDecCrypto(crypto);
            requestData.setSigVerCrypto(crypto);
        } else {
            final Crypto crypto = CryptoFactory.getInstance("receiver-crypto.properties");
            requestData.setDecCrypto(crypto);
            requestData.setSigVerCrypto(crypto);
        }

        if (properties.get(WSHandlerConstants.ALLOW_USERNAMETOKEN_NOPASSWORD) != null) {
            messageContext.put(WSHandlerConstants.ALLOW_USERNAMETOKEN_NOPASSWORD,
                               properties.get(WSHandlerConstants.ALLOW_USERNAMETOKEN_NOPASSWORD));
        } else if (WSHandlerConstants.USERNAME_TOKEN_SIGNATURE.equals(action)) {
            messageContext.put(WSHandlerConstants.ALLOW_USERNAMETOKEN_NOPASSWORD, "true");
        }

        // Disable PrefixList checking as the stax code doesn't support this yet
        //todo
        List<BSPRule> ignoredRules = new ArrayList<>();
        ignoredRules.add(BSPRule.R5404);
        ignoredRules.add(BSPRule.R5406);
        ignoredRules.add(BSPRule.R5407);
        ignoredRules.add(BSPRule.R5417);
        ignoredRules.add(BSPRule.R3063);
        ignoredRules.add(BSPRule.R5620);
        ignoredRules.add(BSPRule.R5621);
        //ignoredRules.add(BSPRule.R5215);
        requestData.setIgnoredBSPRules(ignoredRules);

        wss4JHandler.doReceiver(messageContext, requestData, false);

        return messageContext;
    }

    protected Map<String, Object> getMessageContext(InputStream inputStream) {
        Map<String, Object> context = new HashMap<>();
        try {
            context.put(SECURED_DOCUMENT, SOAPUtil.toSOAPPart(inputStream));
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return context;
    }

    private Map<String, Object> getMessageContext(Document document) {
        Map<String, Object> context = new HashMap<>();
        context.put(SECURED_DOCUMENT, document);
        return context;
    }

    protected XPathExpression getXPath(String expression) throws XPathExpressionException {
        XPathFactory xPathFactory = XPathFactory.newInstance();
        XPath xPath = xPathFactory.newXPath();
        xPath.setNamespaceContext(
                new NamespaceContext() {
                    @Override
                    public String getNamespaceURI(String prefix) {
                        if (WSSConstants.PREFIX_DSIG.equals(prefix)) {
                            return WSSConstants.NS_DSIG;
                        } else if (WSSConstants.PREFIX_SOAPENV.equals(prefix)) {
                            return WSSConstants.NS_SOAP11;
                        } else if (WSSConstants.PREFIX_WSSE.equals(prefix)) {
                            return WSSConstants.NS_WSSE10;
                        } else if (WSSConstants.PREFIX_WSU.equals(prefix)) {
                            return WSSConstants.NS_WSU10;
                        } else if (WSSConstants.PREFIX_XENC.equals(prefix)) {
                            return WSSConstants.NS_XMLENC;
                        } else if (WSSConstants.PREFIX_XENC11.equals(prefix)) {
                            return WSSConstants.NS_XMLENC11;
                        } else {
                            return null;
                        }
                    }

                    @Override
                    public String getPrefix(String namespaceURI) {
                        if (WSSConstants.NS_DSIG.equals(namespaceURI)) {
                            return WSSConstants.PREFIX_DSIG;
                        } else if (WSSConstants.NS_SOAP11.equals(namespaceURI)) {
                            return WSSConstants.PREFIX_SOAPENV;
                        } else if (WSSConstants.NS_WSSE10.equals(namespaceURI)) {
                            return WSSConstants.PREFIX_WSSE;
                        } else if (WSSConstants.NS_WSU10.equals(namespaceURI)) {
                            return WSSConstants.PREFIX_WSU;
                        } else if (WSSConstants.NS_XMLENC.equals(namespaceURI)) {
                            return WSSConstants.PREFIX_XENC;
                        } else if (WSSConstants.NS_XMLENC11.equals(namespaceURI)) {
                            return WSSConstants.PREFIX_XENC11;
                        } else {
                            return null;
                        }
                    }

                    @Override
                    public Iterator<String> getPrefixes(String namespaceURI) {
                        return null;
                    }
                }
        );
        return xPath.compile(expression);
    }

    class CustomWSS4JHandler extends WSHandler {

        private final org.slf4j.Logger LOG =
            org.slf4j.LoggerFactory.getLogger(CustomWSS4JHandler.class.getName());
        private final boolean doDebug = LOG.isDebugEnabled();

        /**
         * Handles incoming web service requests and outgoing responses
         *
         * @throws TransformerException
         * @throws IOException
         */
        public boolean doSender(Map<String, Object> mc, RequestData reqData, boolean isRequest)
                throws WSSecurityException, TransformerException, IOException {

            /*
             * Get the action first.
             */
            String action = (String) mc.get(WSHandlerConstants.ACTION);
            if (action == null) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
                                              new Object[] {"WSS4JHandler: No action defined"});
            }
            List<HandlerAction> actions = WSSecurityUtil.decodeHandlerAction(action, null);
            if (actions.isEmpty()) {
                return true;
            }

            /*
            * For every action we need a username, so get this now. The username
            * defined in the deployment descriptor takes precedence.
            */
            reqData.setUsername((String) getOption(WSHandlerConstants.USER));
            if (reqData.getUsername() == null || reqData.getUsername().isEmpty()) {
                reqData.setUsername((String) mc.get(WSHandlerConstants.USER));
            }

            /*
            * Now we perform some set-up for UsernameToken and Signature
            * functions. No need to do it for encryption only. Check if username
            * is available and then get a password.
            */
            boolean usernameRequired = false;
            for (HandlerAction handlerAction : actions) {
                if (handlerAction.getAction() == WSConstants.SIGN
                    || handlerAction.getAction() == WSConstants.UT
                    || handlerAction.getAction() == WSConstants.UT_SIGN) {
                    usernameRequired = true;
                    break;
                }
            }
            if (usernameRequired && (reqData.getUsername() == null || reqData.getUsername().isEmpty())) {
                /*
                 * We need a username - if none throw a WSSecurityException. For encryption
                 * there is a specific parameter to get a username.
                 */
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
                                              new Object[] {"WSS4JHandler: Empty username for specified action"}
                );
            }
            if (doDebug) {
                LOG.debug("Actor: " + reqData.getActor());
            }
            /*
            * Now get the SOAP part from the request message and convert it into a
            * Document.
            *
            * Now we can perform our security operations on this request.
            */
            Document doc = (Document) mc.get(SECURED_DOCUMENT);
            if (doc == null) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
                                              new Object[] {"WSS4JHandler: cannot get SOAP envlope from message"}
                );
            }
            if (doDebug) {
                LOG.debug("WSS4JHandler: orginal SOAP request: ");
                LOG.debug(XMLUtils.prettyDocumentToString(doc));
            }
            doSenderAction(doc, reqData, actions, isRequest);

            mc.put(SECURED_DOCUMENT, doc);

            return true;
        }

        @SuppressWarnings("unchecked")
        public boolean doReceiver(Map<String, Object> mc, RequestData reqData, boolean isRequest)
                throws WSSecurityException {
            String action = (String) mc.get(WSHandlerConstants.ACTION);
            if (action == null) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
                                              new Object[] {"WSS4JHandler: No action defined"});
            }
            List<Integer> actions = WSSecurityUtil.decodeAction(action);

            String actor = (String) mc.get(WSHandlerConstants.ACTOR);

            Document doc = (Document) mc.get(SECURED_DOCUMENT);

            /*
             * Check if it's a fault. Don't process faults.
             */
            org.apache.wss4j.dom.SOAPConstants soapConstants =
                    WSSecurityUtil.getSOAPConstants(doc.getDocumentElement());
            if (XMLUtils.findElement(
                doc.getDocumentElement(), "Fault", soapConstants.getEnvelopeURI()) != null
            ) {
                return false;
            }

            /*
             * To check a UsernameToken or to decrypt an encrypted message we need
             * a password.
             */
            CallbackHandler cbHandler = getPasswordCallbackHandler(reqData);
            reqData.setCallbackHandler(cbHandler);

            /*
             * Get and check the Signature specific parameters first because they
             * may be used for encryption too.
             */
            WSSConfig wssConfig = WSSConfig.getNewInstance();
            reqData.setWssConfig(wssConfig);
            reqData.setActor(actor);
            doReceiverAction(actions, reqData);

            Element elem = WSSecurityUtil.getSecurityHeader(doc, actor);

            WSSecurityEngine secEngine = new WSSecurityEngine();
            secEngine.setWssConfig(wssConfig);
            WSHandlerResult wsResult = null;
            try {
                wsResult = secEngine.processSecurityHeader(elem, reqData);
            } catch (WSSecurityException ex) {
                if (doDebug) {
                    LOG.debug(ex.getMessage(), ex);
                }
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, ex, "empty",
                                              new Object[] {"WSS4JHandler: security processing failed"}
                );
            }
            if (wsResult.getResults() == null || wsResult.getResults().isEmpty()) {
                // no security header found
                if (actions.isEmpty()) {
                    return true;
                } else {
                    throw new WSSecurityException(WSSecurityException.ErrorCode.INVALID_SECURITY, "empty",
                                                  new Object[] {"WSS4JHandler: Request does not contain required Security header"}
                    );
                }
            }
            if (reqData.isEnableSignatureConfirmation() && !isRequest) {
                checkSignatureConfirmation(reqData, wsResult);
            }

            if (doDebug) {
                LOG.debug("Processed received SOAP request");
            }

            /*
             * now check the security actions: do they match, in right order?
             */
            if (!checkReceiverResults(wsResult.getResults(), actions)) {
                throw new WSSecurityException(WSSecurityException.ErrorCode.FAILURE, "empty",
                                              new Object[] {"WSS4JHandler: security processing failed (actions mismatch)"}
                );
            }

            /*
             * All ok up to this point. Now construct and setup the
             * security result structure. The service may fetch this
             * and check it.
             */
            List<WSHandlerResult> results = null;
            if ((results = (List<WSHandlerResult>) mc.get(WSHandlerConstants.RECV_RESULTS)) == null) {
                results = new ArrayList<>();
                mc.put(WSHandlerConstants.RECV_RESULTS, results);
            }
            results.add(0, wsResult);
            if (doDebug) {
                LOG.debug("WSS4JHandler: exit invoke()");
            }

            return true;
        }

        @Override
        protected boolean checkReceiverResults(
            List<WSSecurityEngineResult> wsResult, List<Integer> actions
        ) {
            List<WSSecurityEngineResult> wsSecurityEngineResults = new ArrayList<>();
            for (WSSecurityEngineResult result : wsResult) {
                boolean found = false;
                for (WSSecurityEngineResult res : wsSecurityEngineResults) {
                    if (result.get(WSSecurityEngineResult.TAG_ACTION).equals(res.get(WSSecurityEngineResult.TAG_ACTION))) {
                        found = true;
                        break;
                    }
                }
                if (!found) {
                    wsSecurityEngineResults.add(result);
                }
            }
            int size = actions.size();
            int ai = 0;
            for (WSSecurityEngineResult result : wsSecurityEngineResults) {
                final Integer act = (Integer) result.get(WSSecurityEngineResult.TAG_ACTION);
                if (act != null) {
                    if (act.intValue() == WSConstants.SC || act.intValue() == WSConstants.BST
                        || act.intValue() == WSConstants.DKT || act.intValue() == WSConstants.SCT
                        || act.intValue() == WSConstants.UT_NOPASSWORD) {
                        continue;
                    }

                    if (ai >= size || actions.get(ai++).intValue() != act) {
                        return false;
                    }
                }
            }
            /*
        if (ai != size) {
            return false;
        }
             */
            return true;
        }

        @Override
        public Object getOption(String key) {
            return null;
        }

        @SuppressWarnings("unchecked")
        @Override
        public Object getProperty(Object msgContext, String key) {
            return ((Map<String, Object>) msgContext).get(key);
        }

        @SuppressWarnings("unchecked")
        @Override
        public void setProperty(Object msgContext, String key, Object value) {
            ((Map<String, Object>) msgContext).put(key, value);
        }

        @SuppressWarnings("unchecked")
        @Override
        public String getPassword(Object msgContext) {
            return (String) ((Map<String, Object>) msgContext).get("password");
        }

        @SuppressWarnings("unchecked")
        @Override
        public void setPassword(Object msgContext, String password) {
            ((Map<String, Object>) msgContext).put("password", password);
        }
    }

    protected class TestSecurityEventListener implements SecurityEventListener {
        private SecurityEventConstants.Event[] expectedEvents;
        private List<SecurityEvent> receivedSecurityEvents = new ArrayList<>();

        public TestSecurityEventListener(SecurityEventConstants.Event[] expectedEvents) {
            this.expectedEvents = expectedEvents;
        }

        public List<SecurityEvent> getReceivedSecurityEvents() {
            return receivedSecurityEvents;
        }

        @SuppressWarnings("unchecked")
        public <T> T getSecurityEvent(SecurityEventConstants.Event securityEvent) {
            for (SecurityEvent event : receivedSecurityEvents) {
                if (event.getSecurityEventType() == securityEvent) {
                    return (T) event;
                }
            }
            return null;
        }

        @SuppressWarnings("unchecked")
        public <T> List<T> getSecurityEvents(SecurityEventConstants.Event securityEvent) {
            List<T> foundEvents = new ArrayList<>();
            for (SecurityEvent event : receivedSecurityEvents) {
                if (event.getSecurityEventType() == securityEvent) {
                    foundEvents.add((T) event);
                }
            }
            return foundEvents;
        }

        @Override
        public void registerSecurityEvent(SecurityEvent securityEvent) throws WSSecurityException {
            assertNotNull(securityEvent.getCorrelationID());
            assertNotEquals("", securityEvent.getCorrelationID());
            receivedSecurityEvents.add(securityEvent);
        }

        public void compare() {
            if (expectedEvents.length != receivedSecurityEvents.size()) {
                printEvents();
                fail("event count mismatch");
            }
            boolean asserted = true;
            for (int i = 0; i < expectedEvents.length; i++) {
                if (!expectedEvents[i].equals(receivedSecurityEvents.get(i).getSecurityEventType())) {
                    asserted = false;
                    break;
                }
            }
            if (!asserted) {
                printEvents();
                fail("event mismatch");
            }
        }

        private void printEvents() {
            System.out.println("expected events:");
            for (int i = 0; i < expectedEvents.length; i++) {
                SecurityEventConstants.Event expectedEvent = expectedEvents[i];
                System.out.println("WSSecurityEventConstants." + expectedEvent + ",");
            }
            System.out.println("received events:");
            for (int i = 0; i < receivedSecurityEvents.size(); i++) {
                SecurityEvent securityEvent = receivedSecurityEvents.get(i);
                System.out.println("WSSecurityEventConstants." + securityEvent.getSecurityEventType() + ",");
            }
        }
    }

    public static Double getJavaSpecificationVersion() {
        String jsv = System.getProperty("java.specification.version");
        if (jsv != null) {
            return Double.parseDouble(jsv);
        }
        return 0.0d;
    }
}