All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.ibm.cp4waiops.connectors.sdk.HConnectionClient Maven / Gradle / Ivy

The newest version!
package com.ibm.cp4waiops.connectors.sdk;

import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.net.Authenticator;
import java.net.InetSocketAddress;
import java.net.MalformedURLException;
import java.net.PasswordAuthentication;
import java.net.ProxySelector;
import java.net.Socket;
import java.net.URL;
import java.net.http.HttpClient;
import java.net.http.HttpClient.Builder;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.cert.CertificateException;
import java.security.cert.X509Certificate;
import java.time.Duration;

import javax.net.ssl.SSLContext;
import javax.net.ssl.SSLEngine;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;
import javax.net.ssl.X509ExtendedTrustManager;

import java.util.logging.Level;
import java.util.logging.Logger;

public class HConnectionClient {

    static final Logger logger = Logger.getLogger(HConnectionClient.class.getName());

    private SSLContext sslContext;
    private HttpClient httpClient;
    private Builder builder;
    private HttpClient.Version protocol;
    private String proxyUser = null, proxyPassword = null;
    private String proxyHost = null, proxyPort = null;
    public static final int CONNECT_TIMEOUT = 120;
    private int connectTimeout = CONNECT_TIMEOUT;
    private boolean tls = false;
    private boolean enableProxy = false;
    private boolean enableProxyAuth = false;
    private String tlsProtocol = null;

    public HConnectionClient() {

        if (Constant.DEFAULT_PROTOCOL != null) {
            protocol = Constant.DEFAULT_PROTOCOL;
        } else {
            protocol = HttpClient.Version.HTTP_1_1;
        }

        try {
            this.sslContext = setSSLContext();
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException
                | IOException e) {
            logger.log(Level.SEVERE, "Error occured during setting up sslContext {}", e);
            throw new HConnectionClientException("Error occured during setting up sslContext");
        }
    }

    public HConnectionClient(int connectTimeout, HttpClient.Version protocol, String proxyHost, String proxyPort,
            Boolean enableProxy, String truststorePass) {

        if (connectTimeout > 0)
            this.connectTimeout = connectTimeout;

        if (protocol != null) {
            this.protocol = protocol;
        } else {
            protocol = HttpClient.Version.HTTP_1_1;
        }

        if (enableProxy) {
            if (proxyHost != null && !proxyHost.isEmpty()) {
                this.proxyHost = proxyHost;
            }

            if (proxyPort != null && !proxyPort.isEmpty()) {
                this.proxyPort = proxyPort;
            }
        }

        this.enableProxy = enableProxy;

        try {
            this.sslContext = setSSLContext(tls, truststorePass);
        } catch (KeyManagementException | NoSuchAlgorithmException | KeyStoreException | CertificateException
                | IOException e) {
            logger.log(Level.SEVERE, "Error occured during setting up sslContext {}", e);
            throw new HConnectionClientException("Error occured during setting up sslContext");
        }
    }

    public HConnectionClient(int connectTimeout) {

        if (connectTimeout > 0) {
            this.connectTimeout = connectTimeout;
        } else {
            this.connectTimeout = CONNECT_TIMEOUT;
        }

    }

    class HttpAuthenticator extends Authenticator {
        String username;
        String password;
        String proxyHost;

        protected HttpAuthenticator(String proxyHost, String proxyUsername, String proxyPassword) {
            this.username = proxyUsername;
            this.password = proxyPassword;
            this.proxyHost = proxyHost;
        }

        @Override
        protected PasswordAuthentication getPasswordAuthentication() {
            if (getRequestorType().equals(RequestorType.PROXY)) {
                return getPasswordAuthentication(getRequestingHost());
            } else {
                return null;
            }
        }

        protected PasswordAuthentication getPasswordAuthentication(String proxyHost) {
            if (proxyHost.equals(this.proxyHost)) {
                return new PasswordAuthentication(this.username, this.password.toCharArray());
            }
            return null;
        }
    }

    public void setProtocol(HttpClient.Version protocol) {
        this.protocol = protocol;
    }

    public HttpClient.Version getProtocol() {
        return protocol;
    }

    public void setConnectTimeout(int connectTimeout) {
        if (connectTimeout >= 0)
            this.connectTimeout = connectTimeout;
    }

    public int getConnectTimeout() {
        return connectTimeout;
    }

    public void setProxyHost(String proxyHost) {
        this.proxyHost = proxyHost;
    }

    public String getProxyHost() {
        return proxyHost;
    }

    public void setProxyPort(String proxyPort) {
        this.proxyPort = proxyPort;
    }

    public String getProxyPort() {
        return proxyPort;
    }

    public void setProxyUsername(String proxyUser) {
        this.proxyUser = proxyUser;
    }

    public String getProxyUsername() {
        return proxyUser;
    }

    public void setProxyPassword(String proxyPassword) {
        this.proxyPassword = proxyPassword;
    }

    public String getProxyPassword() {
        return proxyPassword;
    }

    public SSLContext getSSLContext() {
        return sslContext;
    }

    public void setTLS(Boolean tls, String truststorePass) throws KeyManagementException, NoSuchAlgorithmException,
            KeyStoreException, FileNotFoundException, CertificateException, IOException {

        logger.info("Setting sslContext for HTTP Client");

        this.sslContext = setSSLContext(tls, truststorePass);

        this.tls = tls;
    }

    public Boolean getTLS() {
        return tls;
    }

    public void setProxy(Boolean enableProxy) {
        this.enableProxy = enableProxy;
    }

    public Boolean getProxy() {
        return enableProxy;
    }

    public void setProxyAuthentication(Boolean enableProxyAuth) {
        this.enableProxyAuth = enableProxyAuth;
    }

    public Boolean getProxyAuthentication() {
        return enableProxyAuth;
    }

    public void setTLSProtocol(String tlsProtocol) {
        this.tlsProtocol = tlsProtocol;
    }

    public String getTLSProtocol() {
        return tlsProtocol;
    }

    public SSLContext setSSLContext(Boolean tls, String truststorePass) throws NoSuchAlgorithmException,
            KeyStoreException, FileNotFoundException, IOException, CertificateException, KeyManagementException {

        if (tlsProtocol != null) {
            sslContext = SSLContext.getInstance(tlsProtocol);
        } else {
            sslContext = SSLContext.getInstance("TLS");
        }

        if (tls) {

            logger.info("TLS is enabled");

            if (truststorePass == null || truststorePass.isEmpty()) {
                logger.log(Level.SEVERE, "Failed to read certificate : truststore password cannot be empty/null");
                throw new HConnectionClientException(
                        "Failed to import certificate : truststore password cannot be empty/null");
            }

            // Load the truststore
            KeyStore truststore = KeyStore.getInstance(KeyStore.getDefaultType());

            try (FileInputStream truststoreFile = new FileInputStream(Constant.TRUSTSTORE_PATH)) {
                truststore.load(truststoreFile, truststorePass.toCharArray());
            }

            // Create an SSLContext with the truststore

            TrustManagerFactory trustManagerFactory = TrustManagerFactory
                    .getInstance(TrustManagerFactory.getDefaultAlgorithm());

            trustManagerFactory.init(truststore);

            sslContext.init(null, trustManagerFactory.getTrustManagers(), new java.security.SecureRandom());

        } else {

            logger.info("TLS is disabled");

            sslContext.init(null, new TrustManager[] { new X509ExtendedTrustManager() {
                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
                    //
                }

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
                    //
                }

                @Override
                public X509Certificate[] getAcceptedIssuers() {
                    return new X509Certificate[0];
                }

                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {
                    //
                }

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {
                    //
                }

                @Override
                public void checkClientTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {
                    //
                }

                @Override
                public void checkServerTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {
                    //
                }
            } }, null);

        }

        return sslContext;
    }

    public SSLContext setSSLContext() throws NoSuchAlgorithmException, KeyStoreException, FileNotFoundException,
            IOException, CertificateException, KeyManagementException {

        if (tlsProtocol != null) {
            sslContext = SSLContext.getInstance(tlsProtocol);
        } else {
            sslContext = SSLContext.getInstance("TLS");
        }

        // Only needed during initialisation as default TLS is disabled
        logger.info("TLS is disabled");

        sslContext.init(null, new TrustManager[] { new X509ExtendedTrustManager() {
            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s) {
                //
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s) {
                //
            }

            @Override
            public X509Certificate[] getAcceptedIssuers() {
                return new X509Certificate[0];
            }

            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {
                //
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s, Socket socket) {
                //
            }

            @Override
            public void checkClientTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {
                //
            }

            @Override
            public void checkServerTrusted(X509Certificate[] x509Certificates, String s, SSLEngine sslEngine) {
                //
            }
        } }, null);

        return sslContext;
    }

    public Builder setProxy(Builder builder, String proxy_url, String proxy_port, String proxy_username,
            String proxy_password) throws MalformedURLException {

        if (proxy_url != null && !proxy_url.isEmpty() && proxy_port != null && !proxy_port.isEmpty()) {
            logger.info("Connector is using proxy - " + proxy_url + ":" + proxy_port);

            if (!proxy_url.startsWith("http://") && !proxy_url.startsWith("https://")) {
                proxy_url = "http://" + proxy_url;
            }

            URL getURL = new URL(proxy_url);
            // Now just get the host without the protocol http or https
            String host = getURL.getHost();

            builder.proxy(ProxySelector.of(new InetSocketAddress(host, Integer.valueOf(proxy_port))));

            if (proxy_username != null && !proxy_username.isEmpty() && proxy_password != null
                    && !proxy_password.isEmpty()) {
                // THIS CODE BLOCK IS NOT REACHABLE IN RUNTIME BECAUSE THE
                // UI DOES NOT EXPOSE THE USERNAME AND PASSWORD PARAMETERS FOR PROXY.
                // CODE IS LEFT HERE FOR FUTURE WORK TO IMPLEMENT FULL PROXY SUPPORT.
                // For proxy auth
                System.setProperty("jdk.http.auth.tunneling.disabledSchemes", "");

                // Use our custom authenticator
                Authenticator authenticator = new HttpAuthenticator(host, proxy_username, proxy_password);

                // Add proxy auth
                builder.authenticator(authenticator);
            } else {
                logger.log(Level.SEVERE,
                        "Proxy  authentication is enabled but some information are missing or null - proxyUrl & proxyPort");
                throw new HConnectionClientException(
                        "Setting proxy error. Missing or null - proxyUsername & proxyPassword");
            }

        } else {
            logger.log(Level.SEVERE,
                    "Proxy is enabled but some information are missing or null - proxyUrl & proxyPort");
            throw new HConnectionClientException("Setting proxy error. Missing or null - proxyUrl & proxyPort");
        }

        return builder;
    }

    public Builder setProxy(Builder builder, String proxy_url, String proxy_port) throws MalformedURLException {

        if (proxy_url != null && !proxy_url.isEmpty() && proxy_port != null && !proxy_port.isEmpty()) {
            logger.info("Connector is using proxy - " + proxy_url + ":" + proxy_port);

            if (!proxy_url.startsWith("http://") && !proxy_url.startsWith("https://")) {
                proxy_url = "http://" + proxy_url;
            }

            URL getURL = new URL(proxy_url);

            String host = getURL.getHost();

            builder.proxy(ProxySelector.of(new InetSocketAddress(host, Integer.valueOf(proxy_port))));

        } else {
            logger.log(Level.SEVERE,
                    "Proxy is enabled but some information are missing or null - proxyUrl & proxyPort");
            throw new HConnectionClientException("Setting proxy error");
        }

        return builder;
    }

    public HttpClient setClient() throws MalformedURLException {

        logger.info("Setting up HTTP Client");

        Builder build = HttpClient.newBuilder().version(protocol).connectTimeout(Duration.ofSeconds(connectTimeout))
                .sslContext(sslContext);

        if (enableProxy) {

            if (enableProxyAuth) {
                logger.info("Proxy with Authentication");
                this.builder = setProxy(build, proxyHost, proxyPort, proxyUser, proxyPassword);
            } else {
                logger.info("Proxy without Authentication");
                this.builder = setProxy(build, proxyHost, proxyPort);
            }

        } else {
            this.builder = build;
        }

        this.httpClient = builder.build();

        return httpClient;
    }

}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy