com.redblackit.web.client.X509HttpClientFactoryBean.java Source code

Java tutorial

Introduction

Here is the source code for com.redblackit.web.client.X509HttpClientFactoryBean.java

Source

/*
 * Copyright 2002-2011 the original author or authors, or Red-Black IT Ltd, as appropriate.
 *
 * 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.redblackit.web.client;

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

import org.apache.http.client.HttpClient;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.CoreConnectionPNames;
import org.apache.http.params.HttpParams;
import org.apache.log4j.Logger;
import org.springframework.beans.factory.FactoryBean;
import org.springframework.beans.factory.InitializingBean;
import org.springframework.util.ResourceUtils;

/**
 * Factory creating an HttpClient for use with x.509, using configured key and
 * trust store information.
 * 
 * @author djnorth
 */
public class X509HttpClientFactoryBean implements FactoryBean<HttpClient>, InitializingBean {

    /**
     * Default read timeout, used if no HttpParams are provided.
     */
    private static final int DEFAULT_READ_TIMEOUT_MILLISECONDS = (60 * 1000);

    /**
     * Logger
     */
    private Logger logger = Logger.getLogger("web.client");

    /**
     * KeyStore
     */
    private String keyStore = System.getProperty("javax.net.ssl.keyStore");

    /**
     * KeyStore type
     */
    private String keyStoreType = "jks";

    /**
     * KeyStore password
     */
    private String keyStorePassword = System.getProperty("javax.net.ssl.keyStorePassword", "changeit");

    /**
     * TrustStore for client
     */
    private String trustStore = System.getProperty("javax.net.ssl.trustStore");

    /**
     * TrustStore type
     */
    private String trustStoreType = "jks";

    /**
     * TrustStore password
     */
    private String trustStorePassword = System.getProperty("javax.net.ssl.trustStorePassword", "changeit");

    /**
     * https port
     */
    private int httpsPort = 8443;

    /**
     * Optional HttpParams
     */
    private HttpParams httpParams = null;

    /**
     * HttpClient object
     */
    private HttpClient httpClient = null;

    /**
     * Set keyStore filename (default system property javax.net.ssl.keyStore)
     * 
     * @param keyStore
     *            the keyStore to set
     */
    public void setKeyStore(String keyStore) {
        this.keyStore = keyStore;
    }

    /**
     * @return the keyStore
     */
    public String getKeyStore() {
        return keyStore;
    }

    /**
     * Set the keyStore type (default "jks")
     * 
     * @param keyStoreType
     *            the keyStoreType to set
     */
    public void setKeyStoreType(String keyStoreType) {
        this.keyStoreType = keyStoreType;
    }

    /**
     * @return the keyStoreType
     */
    public String getKeyStoreType() {
        return keyStoreType;
    }

    /**
     * Set keyStorePassword (default system property
     * javax.net.ssl.keyStorePassword, or changeit) N.B. This must equal the
     * (private) key password
     * 
     * @param keyStorePassword
     *            the keyStorePassword to set
     */
    public void setKeyStorePassword(String keyStorePassword) {
        this.keyStorePassword = keyStorePassword;
    }

    /**
     * @return the keyStorePassword
     */
    public String getKeyStorePassword() {
        return keyStorePassword;
    }

    /**
     * Set trustStore filename (default system property
     * javax.net.ssl.trustStore)
     * 
     * @param trustStore
     *            the trustStore to set
     */
    public void setTrustStore(String trustStore) {
        this.trustStore = trustStore;
    }

    /**
     * @return the trustStore
     */
    public String getTrustStore() {
        return trustStore;
    }

    /**
     * Set the trustStore type (default "jks")
     * 
     * @param trustStoreType
     *            the trustStoreType to set
     */
    public void setTrustStoreType(String trustStoreType) {
        this.trustStoreType = trustStoreType;
    }

    /**
     * @return the trustStoreType
     */
    public String getTrustStoreType() {
        return trustStoreType;
    }

    /**
     * Set trustStorePassword (default system property
     * javax.net.ssl.trustStorePassword, or changeit)
     * 
     * @param trustStorePassword
     *            the trustStorePassword to set
     */
    public void setTrustStorePassword(String trustStorePassword) {
        this.trustStorePassword = trustStorePassword;
    }

    /**
     * @return the trustStorePassword
     */
    public String getTrustStorePassword() {
        return trustStorePassword;
    }

    /**
     * Set the https port (default 8443)
     * 
     * @param httpsPort
     *            the httpsPort to set
     */
    public void setHttpsPort(int httpsPort) {
        this.httpsPort = httpsPort;
    }

    /**
     * @return the hppsPort
     */
    public int getHttpsPort() {
        return httpsPort;
    }

    /**
     * Set HttpParams to use. Default is a BasicHttpParams instance with a read
     * timeout value set to DEFAULT_READ_TIMEOUT_MILLISECONDS.
     * 
     * @param httpParams
     *            the httpParams to set
     */
    public void setHttpParams(HttpParams httpParams) {
        this.httpParams = httpParams;
    }

    /**
     * @return the httpParams
     */
    public HttpParams getHttpParams() {
        return httpParams;
    }

    /**
     * Ensure we have keystores and passwords defined.
     * 
     * @see org.springframework.beans.factory.InitializingBean#afterPropertiesSet()
     */
    @Override
    public void afterPropertiesSet() throws Exception {
        if (getKeyStore() == null || getKeyStore().length() == 0 || getKeyStoreType() == null
                || getKeyStoreType().length() == 0 || getKeyStorePassword() == null
                || getKeyStorePassword().length() == 0 || getTrustStore() == null || getTrustStore().length() == 0
                || getTrustStoreType() == null || getTrustStoreType().length() == 0
                || getTrustStorePassword() == null || getTrustStorePassword().length() == 0) {
            throw new IllegalArgumentException("Missing key/trust store info:" + this);
        }

        if (logger.isDebugEnabled()) {
            logger.debug("afterPropertiesSet:E:this=" + this);
        }

        try {

            final KeyStore keystore = KeyStore.getInstance(getKeyStoreType());
            InputStream keystoreInput = new FileInputStream(ResourceUtils.getFile(getKeyStore()));
            keystore.load(keystoreInput, getKeyStorePassword().toCharArray());

            KeyStore truststore = KeyStore.getInstance(getTrustStoreType());
            InputStream truststoreInput = new FileInputStream(ResourceUtils.getFile(getTrustStore()));
            truststore.load(truststoreInput, getTrustStorePassword().toCharArray());

            final SchemeRegistry schemeRegistry = new SchemeRegistry();
            schemeRegistry.register(new Scheme("https", getHttpsPort(),
                    new SSLSocketFactory(keystore, getKeyStorePassword(), truststore)));

            if (httpParams == null) {
                httpParams = new BasicHttpParams();
                httpParams.setIntParameter(CoreConnectionPNames.SO_TIMEOUT, DEFAULT_READ_TIMEOUT_MILLISECONDS);
            }

            httpClient = new DefaultHttpClient(new ThreadSafeClientConnManager(schemeRegistry), httpParams);

            if (logger.isDebugEnabled()) {
                logger.debug("afterPropertiesSet:R:this=" + this);
            }

        } catch (Throwable t) {
            throw new RuntimeException(this.toString(), t);
        }

    }

    /**
     * Return the httpClient created from the properties set
     * 
     * @see org.springframework.beans.factory.FactoryBean#getObject()
     */
    @Override
    public HttpClient getObject() {
        return httpClient;
    }

    /**
     * Return the interface type. This should be sufficient information to
     * support @Autowire
     * 
     * @see org.springframework.beans.factory.FactoryBean#getObjectType()
     */
    @Override
    public Class<?> getObjectType() {
        return HttpClient.class;
    }

    /**
     * We do cache our client
     * 
     * @see org.springframework.beans.factory.FactoryBean#isSingleton()
     */
    @Override
    public boolean isSingleton() {
        return true;
    }

    /**
     * toString
     */
    public String toString() {
        StringBuffer tos = new StringBuffer(super.toString());
        tos.append(":keyStore=").append(keyStore);
        tos.append(":keyStoreType=").append(keyStoreType);
        tos.append(":keyStorePassword=").append(keyStorePassword);
        tos.append(":trustStore=").append(trustStore);
        tos.append(":trustStoreType=").append(trustStoreType);
        tos.append(":trustStorePassword=").append(trustStorePassword);
        tos.append(":httpsPort=").append(httpsPort);
        tos.append(":httpClient=").append(httpClient);
        tos.append(":httpParams=").append(httpParams);

        return tos.toString();
    }

}