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

import java.io.FileInputStream;
import java.io.InputStream;
import java.security.KeyStore;
import java.util.List;

import javax.net.ssl.KeyManager;
import javax.net.ssl.SSLSessionContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import org.apache.tomcat.util.net.SSLContext;
import org.apache.tomcat.util.net.SSLHostConfig;
import org.apache.tomcat.util.net.SSLHostConfigCertificate;
import org.apache.tomcat.util.net.SSLUtil;

public class OpenSSLUtil implements SSLUtil {

    private final SSLHostConfig sslHostConfig;
    private final SSLHostConfigCertificate certificate;

    private String[] enabledProtocols = null;
    private String[] enabledCiphers = null;

    public OpenSSLUtil(SSLHostConfig sslHostConfig, SSLHostConfigCertificate certificate) {
        this.sslHostConfig = sslHostConfig;
        this.certificate = certificate;
    }

    @Override
    public SSLContext createSSLContext(List<String> negotiableProtocols) throws Exception {
        return new OpenSSLContext(sslHostConfig, certificate, negotiableProtocols);
    }

    @Override
    public KeyManager[] getKeyManagers() throws Exception {
        KeyManager[] managers = {
                new OpenSSLKeyManager(SSLHostConfig.adjustRelativePath(certificate.getCertificateFile()),
                        SSLHostConfig.adjustRelativePath(certificate.getCertificateKeyFile()))
                };
        return managers;
    }

    /* In fact we can use the JSSE one for the moment */
    @Override
    public TrustManager[] getTrustManagers() throws Exception {
        String storefile = System.getProperty("java.home") + "/lib/security/cacerts";
        String password = "changeit";
        String type = "jks";
        String provider = null;
        if (sslHostConfig.getTruststoreFile() != null) {
            storefile = sslHostConfig.getTruststoreFile();
        }
        if (sslHostConfig.getTruststorePassword() != null) {
            password = sslHostConfig.getTruststorePassword();
        }
        if (sslHostConfig.getTruststoreType() != null) {
            type = sslHostConfig.getTruststoreType();
        }
        if (sslHostConfig.getTruststoreProvider() != null) {
            provider = sslHostConfig.getTruststoreProvider();
        }

        TrustManagerFactory factory;
        if (provider == null)
            factory = TrustManagerFactory.getInstance(TrustManagerFactory.getDefaultAlgorithm());
        else
            factory = TrustManagerFactory.getInstance(provider);

        KeyStore keystore = KeyStore.getInstance(type);
        InputStream stream = new FileInputStream(storefile);
        keystore.load(stream, password.toCharArray());
        factory.init(keystore);
        TrustManager[] managers = factory.getTrustManagers();
        return managers;
    }


    @Override
    public void configureSessionContext(SSLSessionContext sslSessionContext) {
        // do nothing. configuration is done in the init phase
    }

    @Override
    public String[] getEnableableCiphers(SSLContext context) {
        if (enabledCiphers == null) {
            List<String> enabledCiphersList = ((OpenSSLContext) context).getCiphers();
            enabledCiphers = enabledCiphersList.toArray(new String[enabledCiphersList.size()]);
        }
        return enabledCiphers;
    }

    @Override
    public String[] getEnableableProtocols(SSLContext context) {
        if (enabledProtocols == null) {
            enabledProtocols = new OpenSSLProtocols(((OpenSSLContext) context).getEnabledProtocol()).getProtocols();
        }
        return enabledProtocols;
    }

}

@@ -856,31 +856,27 @@
 java.io.
-FileInputStream
+IOException
 ;%0Aimport
@@ -1103,16 +1103,69 @@
 ctory;%0A%0A
+import org.apache.tomcat.util.file.ConfigFileLoader;%0A
 import o
@@ -2640,24 +2640,25 @@
  String 
-provider
+algorithm
  = null;
@@ -3077,24 +3077,25 @@
 uststore
-Provider
+Algorithm
 () != nu
@@ -3112,20 +3112,18 @@
     
-    provider
+%09algorithm
  = s
@@ -3152,16 +3152,17 @@
 tore
-Provider
+Algorithm
 ();%0A
@@ -3221,24 +3221,25 @@
     if (
-provider
+algorithm
  == null
@@ -3409,16 +3409,17 @@
 nce(
-provider
+algorithm
 );%0A%0A
@@ -3508,15 +3508,65 @@
  = n
-ew File
+ull;%0A        try %7B%0A        %09stream = ConfigFileLoader.get
 Inpu
@@ -3593,16 +3593,17 @@
         
+%09
 keystore
@@ -3637,24 +3637,317 @@
 arArray());%0A
+        %7D catch (Exception ex) %7B%0A        %09throw ex;%0A        %7D finally %7B%0A            if (stream != null) %7B%0A                try %7B%0A                    stream.close();%0A                %7D catch (IOException ioe) %7B%0A                    // Do nothing%0A                %7D%0A            %7D%0A        %7D%0A        %0A
         fact

Arrange provider to algorithm. make sure the file is closed.