package com.bluecatcode.common.security;

import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.security.*;

import static java.lang.String.format;

/**
 * Key store related utility methods
 */
public class KeyStores {

    public static KeyStore loadKeyStore(String keyStorePath, String keyStorePassword) {
        return loadKeyStore(KeyStore.getDefaultType(), keyStorePath, keyStorePassword);
    }

    public static KeyStore loadKeyStore(String type, String path, String password) {
        InputStream resourceAsStream = null;
        try {
            resourceAsStream = new FileInputStream(path);
            KeyStore keyStore = KeyStore.getInstance(type);
            keyStore.load(resourceAsStream, password.toCharArray());
            return keyStore;
        } catch (GeneralSecurityException | IOException e) {
            throw new IllegalStateException(format("Cannot load the key store: '%s'", path), e);
        } finally {
            if (resourceAsStream != null) {
                try {
                    resourceAsStream.close();
                } catch (IOException e) {
                    // safe to ignore
                }
            }
        }
    }

    public static KeyManager[] loadKeyManagers(String keyStorePath, String keyStorePassword) {
        KeyStore keyStore = KeyStores.loadKeyStore("JKS", keyStorePath, keyStorePassword);
        String keyAlgorithm = KeyManagerFactory.getDefaultAlgorithm();
        KeyManagerFactory keyFactory;
        try {
            keyFactory = KeyManagerFactory.getInstance(keyAlgorithm);
            keyFactory.init(keyStore, keyStorePassword.toCharArray());
        } catch (UnrecoverableKeyException ex) {
            throw new IllegalArgumentException(ex);
        } catch (NoSuchAlgorithmException | KeyStoreException ex) {
            throw new IllegalStateException(ex);
        }
        return keyFactory.getKeyManagers();
    }

    public static TrustManager[] loadTrustManagers(String trustStorePath, String trustStorePassword) {
        KeyStore trustStore = KeyStores.loadKeyStore("JKS", trustStorePath, trustStorePassword);
        String trustAlgorithm = TrustManagerFactory.getDefaultAlgorithm();
        TrustManagerFactory trustFactory;
        try {
            trustFactory = TrustManagerFactory.getInstance(trustAlgorithm);
            trustFactory.init(trustStore);
        } catch (NoSuchAlgorithmException | KeyStoreException ex) {
            throw new IllegalStateException(ex);
        }
        return trustFactory.getTrustManagers();
    }

    public static KeyStore emptyKeyStore() {
        try {
            return KeyStore.getInstance(KeyStore.getDefaultType());
        } catch (KeyStoreException e) {
            throw new IllegalStateException(e);
        }
    }

    private KeyStores() {
        throw new UnsupportedOperationException();
    }
}

@@ -1458,32 +1458,246 @@
 torePassword) %7B%0A
+        return loadKeyManagers(KeyStore.getDefaultType(), keyStorePath, keyStorePassword);%0A    %7D%0A%0A    public static KeyManager%5B%5D loadKeyManagers(String keyStoreType, String keyStorePath, String keyStorePassword) %7B%0A
         KeyStore
@@ -1731,21 +1731,28 @@
 eyStore(
-%22JKS%22
+keyStoreType
 , keySto
@@ -1841,32 +1841,227 @@
 ultAlgorithm();%0A
+        return loadKeyManagers(keyAlgorithm, keyStore, keyStorePassword);%0A    %7D%0A%0A    public static KeyManager%5B%5D loadKeyManagers(String keyAlgorithm, KeyStore keyStore, String keyStorePassword) %7B%0A
         KeyManag
@@ -2570,24 +2570,246 @@
 gers(String 
+keyStorePath, String keyStorePassword) %7B%0A        return loadTrustManagers(KeyStore.getDefaultType(), keyStorePath, keyStorePassword);%0A    %7D%0A%0A    public static TrustManager%5B%5D loadTrustManagers(String trustStoreType, String 
 trustStorePa
@@ -2898,13 +2898,22 @@
 ore(
-%22JKS%22
+trustStoreType
 , tr
@@ -3014,32 +3014,198 @@
 ultAlgorithm();%0A
+        return loadTrustManagers(trustAlgorithm, trustStore);%0A    %7D%0A%0A    public static TrustManager%5B%5D loadTrustManagers(String trustAlgorithm, KeyStore trustStore) %7B%0A
         TrustMan

Update key stores