// 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 com.cloud.consoleproxy;

import java.io.ByteArrayInputStream;
import java.io.FileInputStream;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.security.KeyStore;

import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLParameters;
import javax.net.ssl.SSLServerSocket;
import javax.net.ssl.SSLServerSocketFactory;
import javax.net.ssl.TrustManagerFactory;

import org.apache.log4j.Logger;

import com.sun.net.httpserver.HttpServer;
import com.sun.net.httpserver.HttpsConfigurator;
import com.sun.net.httpserver.HttpsParameters;
import com.sun.net.httpserver.HttpsServer;

public class ConsoleProxySecureServerFactoryImpl implements ConsoleProxyServerFactory  {
    private static final Logger s_logger = Logger.getLogger(ConsoleProxySecureServerFactoryImpl.class);
    
    private SSLContext sslContext = null;
    
    public ConsoleProxySecureServerFactoryImpl() {
    }
    
    @Override
    public void init(byte[] ksBits, String ksPassword) {
        s_logger.info("Start initializing SSL");

        if(ksBits == null) {
            try {
                s_logger.info("Initializing SSL from built-in default certificate");
                
                char[] passphrase = "vmops.com".toCharArray();
                KeyStore ks = KeyStore.getInstance("JKS");
                
                ks.load(new FileInputStream("certs/realhostip.keystore"), passphrase);
                // ks.load(ConsoleProxy.class.getResourceAsStream("/realhostip.keystore"), passphrase);
                
                s_logger.info("SSL certificate loaded");
                
                KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
                kmf.init(ks, passphrase);
                s_logger.info("Key manager factory is initialized");

                TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
                tmf.init(ks);
                s_logger.info("Trust manager factory is initialized");

                sslContext = SSLContext.getInstance("TLS");
                sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
                s_logger.info("SSL context is initialized");
            } catch (Exception ioe) {
                s_logger.error(ioe.toString(), ioe);
            }
            
        } else {
            char[] passphrase = ksPassword != null ? ksPassword.toCharArray() : null;
            try {
                s_logger.info("Initializing SSL from passed-in certificate");
                
                KeyStore ks = KeyStore.getInstance("JKS");
                ks.load(new ByteArrayInputStream(ksBits), passphrase);
                
                KeyManagerFactory kmf = KeyManagerFactory.getInstance("SunX509");
                kmf.init(ks, passphrase);
                s_logger.info("Key manager factory is initialized");
        
                TrustManagerFactory tmf = TrustManagerFactory.getInstance("SunX509");
                tmf.init(ks);
                s_logger.info("Trust manager factory is initialized");
        
                sslContext = SSLContext.getInstance("TLS");
                sslContext.init(kmf.getKeyManagers(), tmf.getTrustManagers(), null);
                s_logger.info("SSL context is initialized");
            } catch(Exception e) {
                s_logger.error("Unable to init factory due to exception ", e);
            }
        }
        
    }
    
    public HttpServer createHttpServerInstance(int port) throws IOException {
        try {
            HttpsServer server = HttpsServer.create(new InetSocketAddress(port), 5);
            server.setHttpsConfigurator (new HttpsConfigurator(sslContext) {
                @Override
                public void configure (HttpsParameters params) {

                // get the remote address if needed
                InetSocketAddress remote = params.getClientAddress();
                SSLContext c = getSSLContext();

                // get the default parameters
                SSLParameters sslparams = c.getDefaultSSLParameters();

                params.setSSLParameters(sslparams);
                // statement above could throw IAE if any params invalid.
                // eg. if app has a UI and parameters supplied by a user.
                }
            });
            
            s_logger.info("create HTTPS server instance on port: " + port);
            return server;
        } catch (Exception ioe) {
            s_logger.error(ioe.toString(), ioe);
        }
        return null;
    }
    
    public SSLServerSocket createSSLServerSocket(int port) throws IOException {
        try {
            SSLServerSocket srvSock = null;
            SSLServerSocketFactory ssf = sslContext.getServerSocketFactory();
            srvSock = (SSLServerSocket) ssf.createServerSocket(port);
            
            s_logger.info("create SSL server socket on port: " + port);
            return srvSock;
        } catch (Exception ioe) {
            s_logger.error(ioe.toString(), ioe);
        }
        return null;
    }
}
