/*
 *
 * 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.qpid.systests.jms_1_1.extensions.tls;

import static java.nio.charset.StandardCharsets.UTF_8;
import static org.hamcrest.CoreMatchers.anyOf;
import static org.hamcrest.CoreMatchers.equalTo;
import static org.hamcrest.CoreMatchers.is;
import static org.hamcrest.CoreMatchers.not;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.fail;
import static org.junit.Assume.assumeThat;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.io.InputStream;
import java.io.UnsupportedEncodingException;
import java.net.InetSocketAddress;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.security.Key;
import java.security.cert.Certificate;
import java.util.Base64;
import java.util.Collections;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

import javax.jms.Connection;
import javax.jms.JMSException;
import javax.jms.Session;

import org.junit.AfterClass;
import org.junit.BeforeClass;
import org.junit.Test;

import org.apache.qpid.server.model.Port;
import org.apache.qpid.server.model.Protocol;
import org.apache.qpid.server.security.FileKeyStore;
import org.apache.qpid.server.security.FileTrustStore;
import org.apache.qpid.systests.AmqpManagementFacade;
import org.apache.qpid.systests.ConnectionBuilder;
import org.apache.qpid.systests.JmsTestBase;
import org.apache.qpid.test.utils.TestSSLConstants;
import org.apache.qpid.test.utils.TestSSLUtils;
import org.apache.qpid.tests.utils.BrokerAdmin;

public class TlsTest extends JmsTestBase
{
    @BeforeClass
    public static void setUp()
    {
        System.setProperty("javax.net.debug", "ssl");

        // workaround for QPID-8069
        if (getProtocol() != Protocol.AMQP_1_0 && getProtocol() != Protocol.AMQP_0_10)
        {
            System.setProperty("amqj.MaximumStateWait", "4000");
        }

        // legacy client keystore/truststore types can only be configured with JVM settings
        if (getProtocol() != Protocol.AMQP_1_0)
        {
            System.setProperty("javax.net.ssl.trustStoreType", TestSSLConstants.JAVA_KEYSTORE_TYPE);
            System.setProperty("javax.net.ssl.keyStoreType", TestSSLConstants.JAVA_KEYSTORE_TYPE);
        }
    }

    @AfterClass
    public static void tearDown()
    {
        System.clearProperty("javax.net.debug");
        if (getProtocol() != Protocol.AMQP_1_0)
        {
            System.clearProperty("amqj.MaximumStateWait");
        }

        if (getProtocol() != Protocol.AMQP_1_0)
        {
            System.clearProperty("javax.net.ssl.trustStoreType");
            System.clearProperty("javax.net.ssl.keyStoreType");
        }
    }

    @Test
    public void testCreateSSLConnectionUsingConnectionURLParams() throws Exception
    {
        //Start the broker (NEEDing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), true, false, false);

        InetSocketAddress brokerAddress = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.AMQP);
        Connection connection = getConnectionBuilder().setPort(port)
                                                      .setHost(brokerAddress.getHostName())
                                                      .setTls(true)
                                                      .setKeyStoreLocation(TestSSLConstants.CLIENT_KEYSTORE)
                                                      .setKeyStorePassword(TestSSLConstants.PASSWORD)
                                                      .setTrustStoreLocation(TestSSLConstants.CLIENT_TRUSTSTORE)
                                                      .setTrustStorePassword(TestSSLConstants.PASSWORD)
                                                      .build();
        try
        {
            assertConnection(connection);
        }
        finally
        {
            connection.close();
        }
    }

    @Test
    public void testCreateSSLConnectionWithCertificateTrust() throws Exception
    {
        assumeThat("Qpid JMS Client does not support trusting of a certificate",
                   getProtocol(),
                   is(not(equalTo(Protocol.AMQP_1_0))));

        int port = configureTlsPort(getTestPortName(), false, false, false);
        File trustCertFile = extractCertFileFromTestTrustStore();

        InetSocketAddress brokerAddress = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.AMQP);
        Connection connection = getConnectionBuilder().setPort(port)
                                                      .setHost(brokerAddress.getHostName())
                                                      .setTls(true)
                                                      .setOptions(Collections.singletonMap("trusted_certs_path",
                                                                                           encodePathOption(trustCertFile.getCanonicalPath())))
                                                      .build();
        try
        {
            assertConnection(connection);
        }
        finally
        {
            connection.close();
        }
    }

    @Test
    public void testSSLConnectionToPlainPortRejected() throws Exception
    {
        assumeThat("QPID-8069", getProtocol(), is(anyOf(equalTo(Protocol.AMQP_1_0), equalTo(Protocol.AMQP_0_10))));

        setSslStoreSystemProperties();
        try
        {
            InetSocketAddress brokerAddress = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.AMQP);
            getConnectionBuilder().setPort(brokerAddress.getPort())
                                  .setHost(brokerAddress.getHostName())
                                  .setTls(true)
                                  .build();

            fail("Exception not thrown");
        }
        catch (JMSException e)
        {
            // PASS
        }
        finally
        {
            clearSslStoreSystemProperties();
        }
    }

    @Test
    public void testHostVerificationIsOnByDefault() throws Exception
    {
        assumeThat("QPID-8069", getProtocol(), is(anyOf(equalTo(Protocol.AMQP_1_0), equalTo(Protocol.AMQP_0_10))));

        //Start the broker (NEEDing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), true, false, false);

        try
        {
            getConnectionBuilder().setPort(port)
                                  .setHost("127.0.0.1")
                                  .setTls(true)
                                  .setKeyStoreLocation(TestSSLConstants.CLIENT_KEYSTORE)
                                  .setKeyStorePassword(TestSSLConstants.PASSWORD)
                                  .setTrustStoreLocation(TestSSLConstants.CLIENT_TRUSTSTORE)
                                  .setTrustStorePassword(TestSSLConstants.PASSWORD)
                                  .build();
            fail("Exception not thrown");
        }
        catch (JMSException e)
        {
            // PASS
        }

        Connection connection = getConnectionBuilder().setPort(port)
                                                      .setHost("127.0.0.1")
                                                      .setTls(true)
                                                      .setKeyStoreLocation(TestSSLConstants.CLIENT_KEYSTORE)
                                                      .setKeyStorePassword(TestSSLConstants.PASSWORD)
                                                      .setTrustStoreLocation(TestSSLConstants.CLIENT_TRUSTSTORE)
                                                      .setTrustStorePassword(TestSSLConstants.PASSWORD)
                                                      .setVerifyHostName(false)
                                                      .build();
        try
        {
            assertConnection(connection);
        }
        finally
        {
            connection.close();
        }
    }

    @Test
    public void testCreateSslConnectionUsingJVMSettings() throws Exception
    {
        //Start the broker (NEEDing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), true, false, false);
        setSslStoreSystemProperties();
        try
        {
            Connection connection = getConnectionBuilder().setPort(port)
                                                          .setTls(true)
                                                          .build();
            try
            {
                assertConnection(connection);
            }
            finally
            {
                connection.close();
            }
        }
        finally
        {
            clearSslStoreSystemProperties();
        }
    }

    @Test
    public void testMultipleCertsInSingleStore() throws Exception
    {
        //Start the broker (NEEDing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), true, false, false);
        setSslStoreSystemProperties();
        try
        {
            Connection connection = getConnectionBuilder().setClientId(getTestName())
                                                          .setPort(port)
                                                          .setTls(true)
                                                          .setKeyAlias(TestSSLConstants.CERT_ALIAS_APP1)
                                                          .build();
            try
            {
                assertConnection(connection);
            }
            finally
            {
                connection.close();
            }

            Connection connection2 = getConnectionBuilder().setPort(port)
                                                           .setTls(true)
                                                           .setKeyAlias(TestSSLConstants.CERT_ALIAS_APP2)
                                                           .build();
            try
            {
                assertConnection(connection2);
            }
            finally
            {
                connection2.close();
            }
        }
        finally
        {
            clearSslStoreSystemProperties();
        }
    }

    @Test
    public void testVerifyHostNameWithIncorrectHostname() throws Exception
    {
        assumeThat("QPID-8069", getProtocol(), is(anyOf(equalTo(Protocol.AMQP_1_0), equalTo(Protocol.AMQP_0_10))));

        //Start the broker (WANTing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), false, true, false);

        setSslStoreSystemProperties();
        try
        {
            getConnectionBuilder().setPort(port)
                                  .setHost("127.0.0.1")
                                  .setTls(true)
                                  .setVerifyHostName(true)
                                  .build();
            fail("Exception not thrown");
        }
        catch (JMSException e)
        {
            // PASS
        }
        finally
        {
            clearSslStoreSystemProperties();
        }
    }

    @Test
    public void testVerifyLocalHost() throws Exception
    {
        //Start the broker (WANTing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), false, true, false);

        setSslStoreSystemProperties();
        try
        {
            Connection connection = getConnectionBuilder().setPort(port)
                                                          .setHost("localhost")
                                                          .setTls(true)
                                                          .build();
            try
            {
                assertConnection(connection);
            }
            finally
            {
                connection.close();
            }
        }
        finally
        {
            clearSslStoreSystemProperties();
        }
    }

    @Test
    public void testCreateSSLConnectionUsingConnectionURLParamsTrustStoreOnly() throws Exception
    {
        //Start the broker (WANTing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), false, true, false);

        InetSocketAddress brokerAddress = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.AMQP);
        Connection connection = getConnectionBuilder().setPort(port)
                                                      .setHost(brokerAddress.getHostName())
                                                      .setTls(true)
                                                      .setTrustStoreLocation(TestSSLConstants.CLIENT_TRUSTSTORE)
                                                      .setTrustStorePassword(TestSSLConstants.PASSWORD)
                                                      .build();
        try
        {
            assertConnection(connection);
        }
        finally
        {
            connection.close();
        }
    }

    @Test
    public void testClientCertificateMissingWhilstNeeding() throws Exception
    {
        assumeThat("QPID-8069", getProtocol(), is(anyOf(equalTo(Protocol.AMQP_1_0), equalTo(Protocol.AMQP_0_10))));

        //Start the broker (NEEDing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), true, false, false);

        try
        {
            getConnectionBuilder().setPort(port)
                                  .setHost(getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.AMQP).getHostName())
                                  .setTls(true)
                                  .setTrustStoreLocation(TestSSLConstants.CLIENT_TRUSTSTORE)
                                  .setTrustStorePassword(TestSSLConstants.PASSWORD)
                                  .build();
            fail("Connection was established successfully");
        }
        catch (JMSException e)
        {
            // PASS
        }
    }

    @Test
    public void testClientCertificateMissingWhilstWanting() throws Exception
    {
        //Start the broker (WANTing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), false, true, false);

        InetSocketAddress brokerAddress = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.AMQP);
        Connection connection = getConnectionBuilder().setPort(port)
                                                      .setHost(brokerAddress.getHostName())
                                                      .setTls(true)
                                                      .setTrustStoreLocation(TestSSLConstants.CLIENT_TRUSTSTORE)
                                                      .setTrustStorePassword(TestSSLConstants.PASSWORD)
                                                      .build();
        try
        {
            assertConnection(connection);
        }
        finally
        {
            connection.close();
        }
    }

    @Test
    public void testClientCertMissingWhilstWantingAndNeeding() throws Exception
    {
        assumeThat("QPID-8069", getProtocol(), is(anyOf(equalTo(Protocol.AMQP_1_0), equalTo(Protocol.AMQP_0_10))));
        //Start the broker (NEEDing and WANTing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), true, true, false);

        try
        {
            getConnectionBuilder().setPort(port)
                                  .setHost(getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.AMQP).getHostName())
                                  .setTls(true)
                                  .setTrustStoreLocation(TestSSLConstants.CLIENT_TRUSTSTORE)
                                  .setTrustStorePassword(TestSSLConstants.PASSWORD)
                                  .build();
            fail("Connection was established successfully");
        }
        catch (JMSException e)
        {
            // PASS
        }
    }

    @Test
    public void testCreateSSLandTCPonSamePort() throws Exception
    {

        //Start the broker (WANTing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), false, true, true);

        InetSocketAddress brokerAddress = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.AMQP);
        Connection connection = getConnectionBuilder().setPort(port)
                                                      .setHost(brokerAddress.getHostName())
                                                      .setTls(true)
                                                      .setKeyStoreLocation(TestSSLConstants.CLIENT_KEYSTORE)
                                                      .setKeyStorePassword(TestSSLConstants.PASSWORD)
                                                      .setTrustStoreLocation(TestSSLConstants.CLIENT_TRUSTSTORE)
                                                      .setTrustStorePassword(TestSSLConstants.PASSWORD)
                                                      .build();
        try
        {
            assertConnection(connection);
        }
        finally
        {
            connection.close();
        }

        Connection connection2 = getConnectionBuilder().setPort(port)
                                                       .setHost(brokerAddress.getHostName())
                                                       .build();
        try
        {
            assertConnection(connection2);
        }
        finally
        {
            connection2.close();
        }
    }

    @Test
    public void testCreateSSLWithCertFileAndPrivateKey() throws Exception
    {
        assumeThat("Qpid JMS Client does not support trusting of a certificate",
                   getProtocol(),
                   is(not(equalTo(Protocol.AMQP_1_0))));

        assumeThat("QPID-8255: certificate can only be loaded using jks keystore ",
                   java.security.KeyStore.getDefaultType(),
                   is(equalTo("jks")));

        //Start the broker (NEEDing client certificate authentication)
        int port = configureTlsPort(getTestPortName(), true, false, false);

        clearSslStoreSystemProperties();
        File[] certAndKeyFiles = extractResourcesFromTestKeyStore();
        final Map<String, String> options = new HashMap<>();
        options.put("client_cert_path", encodePathOption(certAndKeyFiles[1].getCanonicalPath()));
        options.put("client_cert_priv_key_path", encodePathOption(certAndKeyFiles[0].getCanonicalPath()));
        InetSocketAddress brokerAddress = getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.AMQP);
        Connection connection = getConnectionBuilder().setPort(port)
                                                      .setHost(brokerAddress.getHostName())
                                                      .setTls(true)
                                                      .setTrustStoreLocation(TestSSLConstants.CLIENT_TRUSTSTORE)
                                                      .setTrustStorePassword(TestSSLConstants.PASSWORD)
                                                      .setVerifyHostName(false)
                                                      .setOptions(options)
                                                      .build();
        try
        {
            assertConnection(connection);
        }
        finally
        {
            connection.close();
        }
    }


    private int configureTlsPort(final String portName,
                                 final boolean needClientAuth,
                                 final boolean wantClientAuth,
                                 final boolean samePort) throws Exception
    {

        return createTlsPort(portName,
                             needClientAuth,
                             wantClientAuth,
                             samePort,
                             getConnectionBuilder(),
                             new AmqpManagementFacade(getProtocol()),
                             getBrokerAdmin().getBrokerAddress(BrokerAdmin.PortType.AMQP).getPort());
    }

    public static int createTlsPort(final String portName,
                                    final boolean needClientAuth,
                                    final boolean wantClientAuth,
                                    final boolean plainAndSsl,
                                    final ConnectionBuilder connectionBuilder,
                                    final AmqpManagementFacade managementFacade,
                                    final int brokerPort) throws Exception
    {
        Connection connection = connectionBuilder.setVirtualHost("$management").build();
        try
        {
            connection.start();
            String keyStoreName = portName + "KeyStore";
            String trustStoreName = portName + "TrustStore";
            String authenticationProvider = null;

            Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            try
            {
                List<Map<String, Object>> ports =
                        managementFacade.managementQueryObjects(session, "org.apache.qpid.AmqpPort");
                for (Map<String, Object> port : ports)
                {
                    String name = String.valueOf(port.get(Port.NAME));

                    Session s = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
                    try
                    {
                        Map<String, Object> attributes = managementFacade.readEntityUsingAmqpManagement(s,
                                                                                                        "org.apache.qpid.AmqpPort",
                                                                                                        name,
                                                                                                        false);
                        if (attributes.get("boundPort").equals(brokerPort))
                        {
                            authenticationProvider = String.valueOf(attributes.get(Port.AUTHENTICATION_PROVIDER));
                            break;
                        }
                    }
                    finally
                    {
                        s.close();
                    }
                }
            }
            finally
            {
                session.close();
            }

            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            try
            {
                final Map<String, Object> keyStoreAttributes = new HashMap<>();
                keyStoreAttributes.put("storeUrl", TestSSLConstants.BROKER_KEYSTORE);
                keyStoreAttributes.put("password", TestSSLConstants.PASSWORD);
                keyStoreAttributes.put("keyStoreType", TestSSLConstants.JAVA_KEYSTORE_TYPE);
                managementFacade.createEntityAndAssertResponse(keyStoreName,
                                                               FileKeyStore.class.getName(),
                                                               keyStoreAttributes,
                                                               session);
            }
            finally
            {
                session.close();
            }

            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            try
            {
                final Map<String, Object> trustStoreAttributes = new HashMap<>();
                trustStoreAttributes.put("storeUrl", TestSSLConstants.BROKER_TRUSTSTORE);
                trustStoreAttributes.put("password", TestSSLConstants.PASSWORD);
                trustStoreAttributes.put("trustStoreType", TestSSLConstants.JAVA_KEYSTORE_TYPE);
                managementFacade.createEntityAndAssertResponse(trustStoreName,
                                                               FileTrustStore.class.getName(),
                                                               trustStoreAttributes,
                                                               session);
            }
            finally
            {
                session.close();
            }

            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            try
            {
                Map<String, Object> sslPortAttributes = new HashMap<>();
                sslPortAttributes.put(Port.TRANSPORTS, plainAndSsl ? "[\"SSL\",\"TCP\"]" : "[\"SSL\"]");
                sslPortAttributes.put(Port.PORT, 0);
                sslPortAttributes.put(Port.AUTHENTICATION_PROVIDER, authenticationProvider);
                sslPortAttributes.put(Port.NEED_CLIENT_AUTH, needClientAuth);
                sslPortAttributes.put(Port.WANT_CLIENT_AUTH, wantClientAuth);
                sslPortAttributes.put(Port.NAME, portName);
                sslPortAttributes.put(Port.KEY_STORE, keyStoreName);
                sslPortAttributes.put(Port.TRUST_STORES, "[\"" + trustStoreName + "\"]");

                managementFacade.createEntityAndAssertResponse(portName,
                                                               "org.apache.qpid.AmqpPort",
                                                               sslPortAttributes,
                                                               session);
            }
            finally
            {
                session.close();
            }

            session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
            try
            {
                Map<String, Object> portEffectiveAttributes =
                        managementFacade.readEntityUsingAmqpManagement(session,
                                                                       "org.apache.qpid.AmqpPort",
                                                                       portName,
                                                                       false);
                if (portEffectiveAttributes.containsKey("boundPort"))
                {
                    return (int) portEffectiveAttributes.get("boundPort");
                }
                throw new RuntimeException("Bound port is not found");
            }
            finally
            {
                session.close();
            }
        }
        finally
        {
            connection.close();
        }
    }

    private void setSslStoreSystemProperties()
    {
        System.setProperty("javax.net.ssl.keyStore", TestSSLConstants.CLIENT_KEYSTORE);
        System.setProperty("javax.net.ssl.keyStorePassword", TestSSLConstants.PASSWORD);
        System.setProperty("javax.net.ssl.trustStore", TestSSLConstants.CLIENT_TRUSTSTORE);
        System.setProperty("javax.net.ssl.trustStorePassword", TestSSLConstants.PASSWORD);
    }

    private void clearSslStoreSystemProperties()
    {
        System.clearProperty("javax.net.ssl.keyStore");
        System.clearProperty("javax.net.ssl.keyStorePassword");
        System.clearProperty("javax.net.ssl.trustStore");
        System.clearProperty("javax.net.ssl.trustStorePassword");
    }

    private File[] extractResourcesFromTestKeyStore() throws Exception
    {
        java.security.KeyStore ks = java.security.KeyStore.getInstance(TestSSLConstants.JAVA_KEYSTORE_TYPE);
        try (InputStream is = new FileInputStream(TestSSLConstants.CLIENT_KEYSTORE))
        {
            ks.load(is, TestSSLConstants.PASSWORD.toCharArray());
        }

        File privateKeyFile = Files.createTempFile(getTestName(), ".private-key.der").toFile();
        try (FileOutputStream kos = new FileOutputStream(privateKeyFile))
        {
            Key pvt = ks.getKey(TestSSLConstants.CERT_ALIAS_APP1, TestSSLConstants.PASSWORD.toCharArray());
            kos.write(TestSSLUtils.privateKeyToPEM(pvt).getBytes(UTF_8));
        }

        File certificateFile = Files.createTempFile(getTestName(), ".certificate.der").toFile();
        try (FileOutputStream cos = new FileOutputStream(certificateFile))
        {
            Certificate[] chain = ks.getCertificateChain(TestSSLConstants.CERT_ALIAS_APP1);
            for (Certificate pub : chain)
            {
                cos.write(TestSSLUtils.certificateToPEM(pub).getBytes(UTF_8));
            }
            cos.flush();
        }

        return new File[]{privateKeyFile, certificateFile};
    }

    private File extractCertFileFromTestTrustStore() throws Exception
    {
        java.security.KeyStore ks = java.security.KeyStore.getInstance(TestSSLConstants.JAVA_KEYSTORE_TYPE);
        try (InputStream is = new FileInputStream(TestSSLConstants.CLIENT_TRUSTSTORE))
        {
            ks.load(is, TestSSLConstants.PASSWORD.toCharArray());
        }

        File certificateFile = Files.createTempFile(getTestName(), ".crt").toFile();

        try (FileOutputStream cos = new FileOutputStream(certificateFile))
        {

            for (String alias : Collections.list(ks.aliases()))
            {
                Certificate pub = ks.getCertificate(alias);
                cos.write("-----BEGIN CERTIFICATE-----\n".getBytes());
                String base64encoded = Base64.getEncoder().encodeToString(pub.getEncoded());
                while (base64encoded.length() > 76)
                {
                    cos.write(base64encoded.substring(0, 76).getBytes());
                    cos.write("\n".getBytes());
                    base64encoded = base64encoded.substring(76);
                }
                cos.write(base64encoded.getBytes());

                cos.write("\n-----END CERTIFICATE-----\n".getBytes());
            }
            cos.flush();
        }

        return certificateFile;
    }

    private String getTestPortName()
    {
        return getTestName() + "TlsPort";
    }

    private void assertConnection(final Connection connection) throws JMSException
    {
        assertNotNull("connection should be successful", connection);
        Session session = connection.createSession(false, Session.AUTO_ACKNOWLEDGE);
        assertNotNull("create session should be successful", session);
    }

    private String encodePathOption(final String canonicalPath)
    {
        try
        {
            return URLEncoder.encode(canonicalPath, StandardCharsets.UTF_8.name()).replace("+", "%20");
        }
        catch (UnsupportedEncodingException e)
        {
            throw new RuntimeException(e);
        }
    }
}
