com.github.technosf.posterer.modules.commons.transport.CommonsRequestModelImpl.java Source code

Java tutorial

Introduction

Here is the source code for com.github.technosf.posterer.modules.commons.transport.CommonsRequestModelImpl.java

Source

/*
 * Copyright 2014 technosf [https://github.com/technosf]
 * 
 * Licensed 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.github.technosf.posterer.modules.commons.transport;

import java.io.FileNotFoundException;
import java.io.IOException;
import java.security.KeyManagementException;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.function.BooleanSupplier;

import org.apache.http.HttpHost;
import org.apache.http.impl.client.HttpClientBuilder;
import org.apache.http.impl.client.HttpClients;
import org.eclipse.jdt.annotation.Nullable;

import com.github.technosf.posterer.models.Proxy;
import com.github.technosf.posterer.models.Request;
import com.github.technosf.posterer.models.RequestModel;
import com.github.technosf.posterer.models.impl.KeyStoreBean;
import com.github.technosf.posterer.models.impl.base.AbstractRequestModel;
import com.github.technosf.posterer.modules.commons.transport.ssl.AuditingSSLSocketFactory;
import com.github.technosf.posterer.utils.Auditor;
import com.github.technosf.posterer.utils.ssl.PromiscuousHostnameVerifier;

/**
 * Apache Commons implementation of {@RequestModel}
 * <p>
 * Create an Apache Commons HTTP call configuration and embeds it into
 * an Apache Commons HTTP implementation of a ResponseModelTask that
 * is ready to be fired off.
 * 
 * @author technosf
 * @since 0.0.1
 * @version 0.0.1
 */
public class CommonsRequestModelImpl extends AbstractRequestModel<CommonsResponseModelTaskImpl>
        implements RequestModel {

    /**
     * Bean to hold call configuration
     */
    private class CallConfigBean {
        final HttpClientBuilder builder;
        final BooleanSupplier neededClientAuth;

        CallConfigBean(HttpClientBuilder builder, @Nullable BooleanSupplier neededClientAuth) {
            this.builder = builder;
            if (neededClientAuth == null) {
                this.neededClientAuth = new BooleanSupplier() {

                    @Override
                    public boolean getAsBoolean() {
                        return false;
                    }
                };
            } else {
                this.neededClientAuth = neededClientAuth;
            }
        }
    }

    /* ------------------------------------------------ */

    private static final String CONST_ERR_SSL_KEY = "SSL :: Key exception";
    private static final String CONST_ERR_SSL_ALGO = "SSL :: Algo exception";
    private static final String CONST_ERR_SSL_STORE = "SSL :: Key Store exception";
    private static final String CONST_ERR_SSL_FILE = "SSL :: File exception";
    private static final String CONST_ERR_SSL_CERT = "SSL :: Certificate exception";
    private static final String CONST_ERR_SSL_IO = "SSL :: IO exception";

    /* ------------------------------------------------ */

    /**
     * {@inheritDoc}
     *
     * @see com.github.technosf.posterer.models.impl.base.AbstractRequestModel#createRequest(int,
     *      int, com.github.technosf.posterer.models.Request)
     */
    @Override
    protected CommonsResponseModelTaskImpl createRequest(final int requestId, final Auditor auditor,
            final int timeout, final Request request) {
        CallConfigBean callconfig = createCallConfig(auditor, request.getSecurity());
        return new CommonsResponseModelTaskImpl(requestId, auditor, callconfig.builder, timeout, request,
                callconfig.neededClientAuth);
    }

    /**
     * {@inheritDoc}
     *
     * @see com.github.technosf.posterer.models.impl.base.AbstractRequestModel#createRequest(int,
     *      com.github.technosf.posterer.utils.Auditor, int,
     *      com.github.technosf.posterer.models.Request,
     *      com.github.technosf.posterer.models.Proxy,
     *      com.github.technosf.posterer.models.impl.KeyStoreBean,
     *      java.lang.String)
     */
    @Override
    protected CommonsResponseModelTaskImpl createRequest(int requestId, final Auditor auditor, int timeout,
            final Request request, final Proxy proxy) {
        CallConfigBean callconfig = createCallConfig(auditor, request.getSecurity(), proxy);

        return new CommonsResponseModelTaskImpl(requestId, auditor, callconfig.builder, timeout, request,
                callconfig.neededClientAuth);
    }

    /**
     * {@inheritDoc}
     *
     * @see com.github.technosf.posterer.models.impl.base.AbstractRequestModel#createRequest(int,
     *      com.github.technosf.posterer.utils.Auditor, int,
     *      com.github.technosf.posterer.models.Request,
     *      com.github.technosf.posterer.models.Proxy,
     *      com.github.technosf.posterer.models.impl.KeyStoreBean,
     *      java.lang.String)
     */
    @Override
    protected CommonsResponseModelTaskImpl createRequest(int requestId, final Auditor auditor, int timeout,
            final Request request, final KeyStoreBean keyStoreBean, final String alias) {
        CallConfigBean callconfig = createCallConfig(auditor, request.getSecurity(), keyStoreBean, alias);

        return new CommonsResponseModelTaskImpl(requestId, auditor, callconfig.builder, timeout, request,
                callconfig.neededClientAuth);
    }

    /**
     * {@inheritDoc}
     *
     * @see com.github.technosf.posterer.models.impl.base.AbstractRequestModel#createRequest(int,
     *      com.github.technosf.posterer.utils.Auditor, int,
     *      com.github.technosf.posterer.models.Request,
     *      com.github.technosf.posterer.models.Proxy,
     *      com.github.technosf.posterer.models.impl.KeyStoreBean,
     *      java.lang.String)
     */
    @Override
    protected CommonsResponseModelTaskImpl createRequest(int requestId, final Auditor auditor, int timeout,
            final Request request, final Proxy proxy, final KeyStoreBean keyStoreBean, final String alias) {
        CallConfigBean callconfig = createCallConfig(auditor, request.getSecurity(), proxy, keyStoreBean, alias);

        return new CommonsResponseModelTaskImpl(requestId, auditor, callconfig.builder, timeout, request,
                callconfig.neededClientAuth);
    }

    /**
     * Creates a call config for the given ssl impl
     * 
     * @param ssl
     * @return the call config
     */
    @SuppressWarnings("null")
    private CallConfigBean createCallConfig(Auditor auditor, final String ssl) {
        BooleanSupplier neededClientAuth = null;
        HttpClientBuilder builder = HttpClients.custom();

        if (!ssl.isEmpty())
        /*
         * Use custom builder
         */
        {
            /*
             * Configure builder
             */
            neededClientAuth = buildInSSL(auditor, builder, ssl);
        }
        return new CallConfigBean(builder, neededClientAuth);
    }

    /**
     * Creates a call config for the given ssl impl and proxy
     * 
     * @param auditor
     * @param string
     * @return the call config
     */
    @SuppressWarnings("null")
    private CallConfigBean createCallConfig(final Auditor auditor, final String ssl, final Proxy proxy) {
        BooleanSupplier neededClientAuth = null;
        HttpClientBuilder builder = HttpClients.custom();

        if (!ssl.isEmpty() || !proxy.toString().isEmpty())
        /*
         * Use custom builder 
         */
        {
            /*
             * Configure builder
             */
            neededClientAuth = buildInSSL(auditor, builder, ssl);
            buildInProxy(auditor, builder, proxy);
        } // custom builder

        return new CallConfigBean(builder, neededClientAuth);
    }

    /**
     * Creates a call config for the given ssl impl and proxy
     * 
     * @param auditor
     * @param string
     * @return the call config
     */
    @SuppressWarnings("null")
    private CallConfigBean createCallConfig(final Auditor auditor, final String ssl,
            final KeyStoreBean keyStoreBean, final String alias) {
        BooleanSupplier neededClientAuth = null;
        HttpClientBuilder builder = HttpClients.custom();

        if (!ssl.isEmpty())
        /*
         * Use custom builder 
         */
        {
            /*
             * Configure builder
             */
            neededClientAuth = buildInSSL(auditor, builder, ssl, keyStoreBean, alias);
        } // custom builder

        return new CallConfigBean(builder, neededClientAuth);
    }

    /**
     * Creates a call config for the given ssl impl and proxy
     * 
     * @param auditor
     * @param string
     * @return the call config
     */
    @SuppressWarnings("null")
    private CallConfigBean createCallConfig(final Auditor auditor, final String ssl, final Proxy proxy,
            final KeyStoreBean keyStoreBean, final String alias) {
        BooleanSupplier neededClientAuth = null;
        HttpClientBuilder builder = HttpClients.custom();

        if (!ssl.isEmpty() || !proxy.toString().isEmpty())
        /*
         * Use custom builder 
         */
        {
            /*
             * Configure builder
             */
            neededClientAuth = buildInSSL(auditor, builder, ssl, keyStoreBean, alias);
            buildInProxy(auditor, builder, proxy);
        } // custom builder

        return new CallConfigBean(builder, neededClientAuth);
    }

    /**
     * Configures builder for the given proxy
     * 
     * @param builder
     *            the builder to configure
     * @param proxy
     *            the proxy info
     */
    private void buildInProxy(Auditor auditor, HttpClientBuilder builder, final Proxy proxy) {
        HttpHost httpproxy = new HttpHost(proxy.getProxyHost(), Integer.parseInt(proxy.getProxyPort()));

        if (!proxy.getProxyUser().isEmpty())
        /* 
         * Add proxy auth
         */
        {
            // TODO Implement proxy auth
            //ProxyAuthenticationStrategy auth = new ProxyAuthenticationStrategy();
        }
        builder.setProxy(httpproxy);
    }

    /**
     * Configures builder for the given SSL/TLS version
     * 
     * @param builder
     *            the builder to configure
     * @param ssl
     *            the ssl info
     */
    private @Nullable BooleanSupplier buildInSSL(Auditor auditor, HttpClientBuilder builder, final String ssl,
            final KeyStoreBean keyStoreBean, final String alias) {

        builder.setSSLHostnameVerifier(new PromiscuousHostnameVerifier(auditor));
        try {
            AuditingSSLSocketFactory auditingSSLSocketFactory = new AuditingSSLSocketFactory(auditor, ssl,
                    keyStoreBean, alias);
            builder.setSSLSocketFactory(auditingSSLSocketFactory);
            return auditingSSLSocketFactory.getNeededClientAuthSupplier();
        } catch (KeyManagementException | UnrecoverableKeyException e) {
            auditor.append(true, CONST_ERR_SSL_KEY).append(false, "\t%1$s", e.getMessage());
        } catch (NoSuchAlgorithmException e) {
            auditor.append(true, CONST_ERR_SSL_ALGO).append(false, "\t%1$s", e.getMessage());
        } catch (KeyStoreException e) {
            auditor.append(true, CONST_ERR_SSL_STORE).append(false, "\t%1$s", e.getMessage());
        } catch (FileNotFoundException e) {
            auditor.append(true, CONST_ERR_SSL_FILE).append(false, "\t%1$s", e.getMessage());
        } catch (CertificateException e) {
            auditor.append(true, CONST_ERR_SSL_CERT).append(false, "\t%1$s", e.getMessage());
        } catch (IOException e) {
            auditor.append(true, CONST_ERR_SSL_IO).append(false, "\t%1$s", e.getMessage());
        }
        return null;
    }

    /**
     * Configures builder for the given SSL/TLS version
     * 
     * @param builder
     *            the builder to configure
     * @param ssl
     *            the ssl info
     */
    private @Nullable BooleanSupplier buildInSSL(Auditor auditor, HttpClientBuilder builder, final String ssl) {
        builder.setSSLHostnameVerifier(new PromiscuousHostnameVerifier(auditor));
        try {
            AuditingSSLSocketFactory auditingSSLSocketFactory = new AuditingSSLSocketFactory(auditor, ssl);
            builder.setSSLSocketFactory(auditingSSLSocketFactory);
            return auditingSSLSocketFactory.getNeededClientAuthSupplier();
        } catch (KeyManagementException | UnrecoverableKeyException e) {
            auditor.append(true, CONST_ERR_SSL_KEY).append(false, "\t%1$s", e.getMessage());
        } catch (NoSuchAlgorithmException e) {
            auditor.append(true, CONST_ERR_SSL_ALGO).append(false, "\t%1$s", e.getMessage());
        } catch (KeyStoreException e) {
            auditor.append(true, CONST_ERR_SSL_STORE).append(false, "\t%1$s", e.getMessage());
        } catch (FileNotFoundException e) {
            auditor.append(true, CONST_ERR_SSL_FILE).append(false, "\t%1$s", e.getMessage());
        } catch (CertificateException e) {
            auditor.append(true, CONST_ERR_SSL_CERT).append(false, "\t%1$s", e.getMessage());
        } catch (IOException e) {
            auditor.append(true, CONST_ERR_SSL_IO).append(false, "\t%1$s", e.getMessage());
        }

        return null;
    }

}