/*
 *  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.tomcat.util.net;

import java.io.File;
import java.util.ArrayList;
import java.util.Collection;
import java.util.List;

import org.junit.Assert;
import org.junit.Assume;
import org.junit.Ignore;
import org.junit.Test;
import org.junit.runner.RunWith;
import org.junit.runners.Parameterized;
import org.junit.runners.Parameterized.Parameter;

import org.apache.catalina.Context;
import org.apache.catalina.connector.Connector;
import org.apache.catalina.core.AprLifecycleListener;
import org.apache.catalina.core.StandardServer;
import org.apache.catalina.startup.TesterServlet;
import org.apache.catalina.startup.Tomcat;
import org.apache.catalina.startup.TomcatBaseTest;
import org.apache.tomcat.util.buf.ByteChunk;

/*
 * Tests compatibility of JSSE and OpenSSL settings.
 */
@RunWith(Parameterized.class)
public class TestSSLHostConfigCompat extends TomcatBaseTest {

    @Parameterized.Parameters(name = "{0}")
    public static Collection<Object[]> parameters() {
        List<Object[]> parameterSets = new ArrayList<>();

        parameterSets.add(new Object[] {"NIO-JSSE", "org.apache.coyote.http11.Http11NioProtocol",
                "org.apache.tomcat.util.net.jsse.JSSEImplementation"});

        parameterSets.add(new Object[] {"NIO-OpenSSL", "org.apache.coyote.http11.Http11NioProtocol",
                "org.apache.tomcat.util.net.openssl.OpenSSLImplementation"});

        parameterSets.add(new Object[] { "APR/Native", "org.apache.coyote.http11.Http11AprProtocol",
                "org.apache.tomcat.util.net.openssl.OpenSSLImplementation"});

        return parameterSets;
    }

    @Parameter(0)
    public String connectorName;

    @Parameter(1)
    public String protocolName;

    @Parameter(2)
    public String sslImplementationName;

    private SSLHostConfig sslHostConfig = new SSLHostConfig();

    @Test
    public void testHostPEM() throws Exception {
        sslHostConfig.setCertificateFile(getPath(TesterSupport.LOCALHOST_CERT_PEM));
        sslHostConfig.setCertificateKeyFile(getPath(TesterSupport.LOCALHOST_KEY_PEM));
    }


    @Test
    @Ignore // Currently the APR/native connector cannot be configured using a Keystore
    public void testHostKeystore() throws Exception {
        sslHostConfig.setCertificateKeystoreFile(getPath(TesterSupport.LOCALHOST_JKS));
    }


    @Override
    protected String getProtocol() {
        return protocolName;
    }


    @Override
    public void setUp() throws Exception {
        super.setUp();

        AprLifecycleListener listener = new AprLifecycleListener();
        Assume.assumeTrue(AprLifecycleListener.isAprAvailable());

        TesterSupport.configureClientSsl();


        Tomcat tomcat = getTomcatInstance();
        Connector connector = tomcat.getConnector();

        connector.setPort(0);
        connector.setScheme("https");
        connector.setSecure(true);
        connector.setProperty("SSLEnabled", "true");
        connector.addSslHostConfig(sslHostConfig);

        StandardServer server = (StandardServer) tomcat.getServer();
        server.addLifecycleListener(listener);

        // Simple webapp
        Context ctxt = tomcat.addContext("", null);
        Tomcat.addServlet(ctxt, "TesterServlet", new TesterServlet());
        ctxt.addServletMappingDecoded("/*", "TesterServlet");
    }


    @Override
    public void tearDown() throws Exception {
        Tomcat tomcat = getTomcatInstance();
        tomcat.start();

        // Check a request can be made
        ByteChunk res = getUrl("https://localhost:" + getPort() + "/");
        try {
            Assert.assertEquals("OK", res.toString());
        } finally {
            super.tearDown();
        }
    }


    private static String getPath(String relativePath) {
        File f = new File(relativePath);
        return f.getAbsolutePath();
    }
}

@@ -2876,24 +2876,42 @@
 _KEY_PEM));%0A
+        doTest();%0A
     %7D%0A%0A%0A    
@@ -3142,24 +3142,327 @@
 HOST_JKS));%0A
+        doTest();%0A    %7D%0A%0A%0A    private void doTest() throws Exception %7B%0A        Tomcat tomcat = getTomcatInstance();%0A        tomcat.start();%0A%0A        // Check a request can be made%0A        ByteChunk res = getUrl(%22https://localhost:%22 + getPort() + %22/%22);%0A        Assert.assertEquals(%22OK%22, res.toString());%0A
     %7D%0A%0A%0A    
@@ -4453,386 +4453,8 @@
 %7D%0A%0A%0A
-    @Override%0A    public void tearDown() throws Exception %7B%0A        Tomcat tomcat = getTomcatInstance();%0A        tomcat.start();%0A%0A        // Check a request can be made%0A        ByteChunk res = getUrl(%22https://localhost:%22 + getPort() + %22/%22);%0A        try %7B%0A            Assert.assertEquals(%22OK%22, res.toString());%0A        %7D finally %7B%0A            super.tearDown();%0A        %7D%0A    %7D%0A%0A%0A
     

Refactor so tests are correctly skipped when Tomcat Native is not available