org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean.java Source code

Java tutorial

Introduction

Here is the source code for org.springframework.amqp.rabbit.connection.RabbitConnectionFactoryBean.java

Source

/*
 * Copyright 2002-2019 the original author or authors.
 *
 * 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
 *
 *      https://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 org.springframework.amqp.rabbit.connection;

import java.io.IOException;
import java.net.URI;
import java.net.URISyntaxException;
import java.security.KeyManagementException;
import java.security.KeyStore;
import java.security.KeyStoreException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.security.UnrecoverableKeyException;
import java.security.cert.CertificateException;
import java.util.Arrays;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadFactory;

import javax.net.SocketFactory;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
import javax.net.ssl.SSLContext;
import javax.net.ssl.TrustManager;
import javax.net.ssl.TrustManagerFactory;

import org.springframework.amqp.rabbit.support.RabbitExceptionTranslator;
import org.springframework.beans.factory.config.AbstractFactoryBean;
import org.springframework.core.io.Resource;
import org.springframework.core.io.support.PathMatchingResourcePatternResolver;
import org.springframework.lang.Nullable;
import org.springframework.util.StringUtils;

import com.rabbitmq.client.ConnectionFactory;
import com.rabbitmq.client.ExceptionHandler;
import com.rabbitmq.client.MetricsCollector;
import com.rabbitmq.client.SaslConfig;
import com.rabbitmq.client.SocketConfigurator;
import com.rabbitmq.client.impl.nio.NioParams;

/**
 * Factory bean to create a RabbitMQ ConnectionFactory, delegating most setter methods and
 * optionally enabling SSL, with or without certificate validation. When
 * {@link #setSslPropertiesLocation(Resource) sslPropertiesLocation} is not null, the
 * default implementation loads a {@code PKCS12} keystore and a {@code JKS} truststore
 * using the supplied properties and intializes key and trust manager factories, using
 * algorithm {@code SunX509} by default. These are then used to initialize an
 * {@link SSLContext} using the {@link #setSslAlgorithm(String) sslAlgorithm} (default
 * TLSv1.1).
 * <p>
 * Override {@link #createSSLContext()} to create and/or perform further modification of
 * the context.
 * <p>
 * Override {@link #setUpSSL()} to take complete control over setting up SSL.
 *
 * @author Gary Russell
 * @author Heath Abelson
 * @author Arnaud Cogolu?gnes
 * @author Hareendran
 * @author Dominique Villard
 * @author Zachary DeLuca
 *
 * @since 1.4
 */
public class RabbitConnectionFactoryBean extends AbstractFactoryBean<ConnectionFactory> {

    private static final String SUN_X509 = "SunX509";

    private static final String KEY_STORE = "keyStore";

    private static final String TRUST_STORE = "trustStore";

    private static final String KEY_STORE_PASS_PHRASE = "keyStore.passPhrase";

    private static final String TRUST_STORE_PASS_PHRASE = "trustStore.passPhrase";

    private static final String KEY_STORE_TYPE = "keyStore.type";

    private static final String TRUST_STORE_TYPE = "trustStore.type";

    private static final String TLS_V1_1 = "TLSv1.1";

    private static final String KEY_STORE_DEFAULT_TYPE = "PKCS12";

    private static final String TRUST_STORE_DEFAULT_TYPE = "JKS";

    protected final ConnectionFactory connectionFactory = new ConnectionFactory(); // NOSONAR

    private final Properties sslProperties = new Properties();

    private final PathMatchingResourcePatternResolver resolver = new PathMatchingResourcePatternResolver();

    private boolean useSSL;

    private Resource sslPropertiesLocation;

    private String keyStore;

    private String trustStore;

    private Resource keyStoreResource;

    private Resource trustStoreResource;

    private String keyStorePassphrase;

    private String trustStorePassphrase;

    private String keyStoreType;

    private String trustStoreType;

    private String sslAlgorithm = TLS_V1_1;

    private boolean sslAlgorithmSet;

    private SecureRandom secureRandom;

    private boolean skipServerCertificateValidation;

    private boolean enableHostnameVerification = true;

    private String keyStoreAlgorithm = SUN_X509;

    private String trustStoreAlgorithm = SUN_X509;

    public RabbitConnectionFactoryBean() {
        this.connectionFactory.setAutomaticRecoveryEnabled(false);
    }

    /**
     * Whether or not Server Side certificate has to be validated or not.
     * @return true if Server Side certificate has to be skipped
     * @since 1.6.6
     */
    public boolean isSkipServerCertificateValidation() {
        return this.skipServerCertificateValidation;
    }

    /**
     * Whether or not Server Side certificate has to be validated or not.
     * This would be used if useSSL is set to true and should only be used on dev or Qa regions
     * skipServerCertificateValidation should <b> never be set to true in production</b>
     * @param skipServerCertificateValidation Flag to override Server side certificate checks;
     * if set to {@code true} {@link com.rabbitmq.client.TrustEverythingTrustManager} would be used.
     * @since 1.6.6
     * @see com.rabbitmq.client.TrustEverythingTrustManager
     */
    public void setSkipServerCertificateValidation(boolean skipServerCertificateValidation) {
        this.skipServerCertificateValidation = skipServerCertificateValidation;
    }

    /**
     * Whether or not the factory should be configured to use SSL.
     * @param useSSL true to use SSL.
     */
    public void setUseSSL(boolean useSSL) {
        this.useSSL = useSSL;
    }

    /**
     * @return true to use ssl.
     * @since 1.4.4.
     */
    protected boolean isUseSSL() {
        return this.useSSL;
    }

    /**
     * Set the algorithm to use; default TLSv1.1.
     * @param sslAlgorithm the algorithm.
     */
    public void setSslAlgorithm(String sslAlgorithm) {
        this.sslAlgorithm = sslAlgorithm;
        this.sslAlgorithmSet = true;
    }

    /**
     * @return the ssl algorithm.
     * @since 1.4.4
     */
    protected String getSslAlgorithm() {
        return this.sslAlgorithm;
    }

    /**
     * When {@link #setUseSSL(boolean)} is true, the SSL properties to use (optional).
     * Resource referencing a properties file with the following properties:
     * <ul>
     * <li>keyStore=file:/secret/keycert.p12</li>
     * <li>trustStore=file:/secret/trustStore</li>
     * <li>keyStore.passPhrase=secret</li>
     * <li>trustStore.passPhrase=secret</li>
     * </ul>
     * <p>
     * If this is provided, its properties (if present) will override the explicitly
     * set property in this bean.
     * @param sslPropertiesLocation the Resource to the ssl properties
     */
    public void setSslPropertiesLocation(Resource sslPropertiesLocation) {
        this.sslPropertiesLocation = sslPropertiesLocation;
    }

    /**
     * @return the properties location.
     * @since 1.4.4
     */
    protected Resource getSslPropertiesLocation() {
        return this.sslPropertiesLocation;
    }

    /**
     * @return the key store resource.
     * @since 1.5
     */
    protected String getKeyStore() {
        return this.keyStore == null ? this.sslProperties.getProperty(KEY_STORE) : this.keyStore;
    }

    /**
     * Set the key store resource (e.g. file:/foo/keystore) - overrides
     * the property in {@link #setSslPropertiesLocation(Resource)}.
     * Ignored if {@link #setTrustStoreResource(Resource)} is called with a
     * resource.
     * @param keyStore the keystore resource.
     * @since 1.5
     */
    public void setKeyStore(String keyStore) {
        this.keyStore = keyStore;
    }

    protected Resource getKeyStoreResource() {
        return this.keyStoreResource;
    }

    /**
     * Set a Resource pointing to the key store.
     * @param keyStoreResource the resource.
     * @since 1.6.4
     */
    public void setKeyStoreResource(Resource keyStoreResource) {
        this.keyStoreResource = keyStoreResource;
    }

    /**
     * @return the trust store resource.
     * @since 1.5
     */
    protected String getTrustStore() {
        return this.trustStore == null ? this.sslProperties.getProperty(TRUST_STORE) : this.trustStore;
    }

    /**
     * Set the key store resource (e.g. file:/foo/truststore) - overrides
     * the property in {@link #setSslPropertiesLocation(Resource)}.
     * Ignored if {@link #setTrustStoreResource(Resource)} is called with a
     * resource.
     * @param trustStore the truststore resource.
     * @since 1.5
     */
    public void setTrustStore(String trustStore) {
        this.trustStore = trustStore;
    }

    protected Resource getTrustStoreResource() {
        return this.trustStoreResource;
    }

    /**
     * Set a Resource pointing to the trust store.
     * @param trustStoreResource the resource.
     * @since 1.6.4
     */
    public void setTrustStoreResource(Resource trustStoreResource) {
        this.trustStoreResource = trustStoreResource;
    }

    /**
     * @return the key store pass phrase.
     * @since 1.5
     */
    protected String getKeyStorePassphrase() {
        return this.keyStorePassphrase == null ? this.sslProperties.getProperty(KEY_STORE_PASS_PHRASE)
                : this.keyStorePassphrase;
    }

    /**
     * Set the key store pass phrase - overrides
     * the property in {@link #setSslPropertiesLocation(Resource)}.
     * @param keyStorePassphrase the key store pass phrase.
     * @since 1.5
     */
    public void setKeyStorePassphrase(String keyStorePassphrase) {
        this.keyStorePassphrase = keyStorePassphrase;
    }

    /**
     * @return the trust store pass phrase.
     * @since 1.5
     */
    protected String getTrustStorePassphrase() {
        return this.trustStorePassphrase == null ? this.sslProperties.getProperty(TRUST_STORE_PASS_PHRASE)
                : this.trustStorePassphrase;
    }

    /**
     * Set the trust store pass phrase - overrides
     * the property in {@link #setSslPropertiesLocation(Resource)}.
     * @param trustStorePassphrase the trust store pass phrase.
     * @since 1.5
     */
    public void setTrustStorePassphrase(String trustStorePassphrase) {
        this.trustStorePassphrase = trustStorePassphrase;
    }

    /**
     * Get the key store type - this defaults to PKCS12 if not overridden by
     * {@link #setSslPropertiesLocation(Resource)} or {@link #setKeyStoreType}.
     * @return the key store type.
     * @since 1.6.2
     */
    protected String getKeyStoreType() {
        if (this.keyStoreType == null && this.sslProperties.getProperty(KEY_STORE_TYPE) == null) {
            return KEY_STORE_DEFAULT_TYPE;
        } else if (this.keyStoreType != null) {
            return this.keyStoreType;
        } else {
            return this.sslProperties.getProperty(KEY_STORE_TYPE);
        }
    }

    /**
     * Set the key store type - overrides
     * the property in {@link #setSslPropertiesLocation(Resource)}.
     * @param keyStoreType the key store type.
     * @since 1.6.2
     * @see java.security.KeyStore#getInstance(String)
     */
    public void setKeyStoreType(String keyStoreType) {
        this.keyStoreType = keyStoreType;
    }

    /**
     * Get the trust store type - this defaults to JKS if not overridden by
     * {@link #setSslPropertiesLocation(Resource)} or {@link #setTrustStoreType}.
     * @return the trust store type.
     * @since 1.6.2
     */
    protected String getTrustStoreType() {
        if (this.trustStoreType == null && this.sslProperties.getProperty(TRUST_STORE_TYPE) == null) {
            return TRUST_STORE_DEFAULT_TYPE;
        } else if (this.trustStoreType != null) {
            return this.trustStoreType;
        } else {
            return this.sslProperties.getProperty(TRUST_STORE_TYPE);
        }
    }

    /**
     * Set the trust store type - overrides
     * the property in {@link #setSslPropertiesLocation(Resource)}.
     * @param trustStoreType the trust store type.
     * @since 1.6.2
     * @see java.security.KeyStore#getInstance(String)
     */
    public void setTrustStoreType(String trustStoreType) {
        this.trustStoreType = trustStoreType;
    }

    protected SecureRandom getSecureRandom() {
        return this.secureRandom;
    }

    /**
     * Set the secure random to use when initializing the {@link SSLContext}.
     * Defaults to null, in which case the default implementation is used.
     * @param secureRandom the secure random.
     * @since 1.6.4
     * @see SSLContext#init(KeyManager[], TrustManager[], SecureRandom)
     */
    public void setSecureRandom(SecureRandom secureRandom) {
        this.secureRandom = secureRandom;
    }

    /**
     * @param host the host.
     * @see com.rabbitmq.client.ConnectionFactory#setHost(java.lang.String)
     */
    public void setHost(String host) {
        this.connectionFactory.setHost(host);
    }

    /**
     * @param port the port.
     * @see com.rabbitmq.client.ConnectionFactory#setPort(int)
     */
    public void setPort(int port) {
        this.connectionFactory.setPort(port);
    }

    /**
     * @param username the user name.
     * @see com.rabbitmq.client.ConnectionFactory#setUsername(java.lang.String)
     */
    public void setUsername(String username) {
        this.connectionFactory.setUsername(username);
    }

    /**
     * @param password the password.
     * @see com.rabbitmq.client.ConnectionFactory#setPassword(java.lang.String)
     */
    public void setPassword(String password) {
        this.connectionFactory.setPassword(password);
    }

    /**
     * @param virtualHost the virtual host.
     * @see com.rabbitmq.client.ConnectionFactory#setVirtualHost(java.lang.String)
     */
    public void setVirtualHost(String virtualHost) {
        this.connectionFactory.setVirtualHost(virtualHost);
    }

    /**
     * @param uri the uri.
     * @see com.rabbitmq.client.ConnectionFactory#setUri(java.net.URI)
     */
    public void setUri(URI uri) {
        try {
            this.connectionFactory.setUri(uri);
        } catch (URISyntaxException | NoSuchAlgorithmException | KeyManagementException e) {
            throw new IllegalArgumentException("Unable to set uri", e);
        }
    }

    /**
     * @param uriString the uri.
     * @see com.rabbitmq.client.ConnectionFactory#setUri(java.lang.String)
     */
    public void setUri(String uriString) {
        try {
            this.connectionFactory.setUri(uriString);
        } catch (URISyntaxException | NoSuchAlgorithmException | KeyManagementException e) {
            throw new IllegalArgumentException("Unable to set uri", e);
        }
    }

    /**
     * @param requestedChannelMax the max requested channels.
     * @see com.rabbitmq.client.ConnectionFactory#setRequestedChannelMax(int)
     */
    public void setRequestedChannelMax(int requestedChannelMax) {
        this.connectionFactory.setRequestedChannelMax(requestedChannelMax);
    }

    /**
     * @param requestedFrameMax the requested max frames.
     * @see com.rabbitmq.client.ConnectionFactory#setRequestedFrameMax(int)
     */
    public void setRequestedFrameMax(int requestedFrameMax) {
        this.connectionFactory.setRequestedFrameMax(requestedFrameMax);
    }

    /**
     * @param connectionTimeout the connection timeout.
     * @see com.rabbitmq.client.ConnectionFactory#setConnectionTimeout(int)
     */
    public void setConnectionTimeout(int connectionTimeout) {
        this.connectionFactory.setConnectionTimeout(connectionTimeout);
    }

    /**
     * @param requestedHeartbeat the requested heartbeat.
     * @see com.rabbitmq.client.ConnectionFactory#setRequestedHeartbeat(int)
     */
    public void setRequestedHeartbeat(int requestedHeartbeat) {
        this.connectionFactory.setRequestedHeartbeat(requestedHeartbeat);
    }

    /**
     * Add custom client properties.
     * @param clientProperties the client properties.
     * @see com.rabbitmq.client.ConnectionFactory#setClientProperties(java.util.Map)
     */
    public void setClientProperties(Map<String, Object> clientProperties) {
        this.connectionFactory.getClientProperties().putAll(clientProperties);
    }

    /**
     * @param saslConfig the sasl config.
     * @see com.rabbitmq.client.ConnectionFactory#setSaslConfig(com.rabbitmq.client.SaslConfig)
     */
    public void setSaslConfig(SaslConfig saslConfig) {
        this.connectionFactory.setSaslConfig(saslConfig);
    }

    /**
     * @param factory the socket factory.
     * @see com.rabbitmq.client.ConnectionFactory#setSocketFactory(javax.net.SocketFactory)
     */
    public void setSocketFactory(SocketFactory factory) {
        this.connectionFactory.setSocketFactory(factory);
    }

    /**
     * @param socketConfigurator the socket configurator.
     * @see com.rabbitmq.client.ConnectionFactory#setSocketConfigurator(com.rabbitmq.client.SocketConfigurator)
     */
    public void setSocketConfigurator(SocketConfigurator socketConfigurator) {
        this.connectionFactory.setSocketConfigurator(socketConfigurator);
    }

    /**
     * @param executor the executor service
     * @see com.rabbitmq.client.ConnectionFactory#setSharedExecutor(java.util.concurrent.ExecutorService)
     */
    public void setSharedExecutor(ExecutorService executor) {
        this.connectionFactory.setSharedExecutor(executor);
    }

    /**
     * @param threadFactory the thread factory.
     * @see com.rabbitmq.client.ConnectionFactory#setThreadFactory(java.util.concurrent.ThreadFactory)
     */
    public void setThreadFactory(ThreadFactory threadFactory) {
        this.connectionFactory.setThreadFactory(threadFactory);
    }

    /**
     * @param exceptionHandler the exception handler.
     * @see com.rabbitmq.client.ConnectionFactory#setExceptionHandler(com.rabbitmq.client.ExceptionHandler)
     */
    public void setExceptionHandler(ExceptionHandler exceptionHandler) {
        this.connectionFactory.setExceptionHandler(exceptionHandler);
    }

    /**
     * Whether or not the factory should be configured to use Java NIO.
     * @param useNio true to use Java NIO, false to use blocking IO
     * @see com.rabbitmq.client.ConnectionFactory#useNio()
     */
    public void setUseNio(boolean useNio) {
        if (useNio) {
            this.connectionFactory.useNio();
        } else {
            this.connectionFactory.useBlockingIo();
        }
    }

    /**
     * @param nioParams the NIO parameters
     * @see com.rabbitmq.client.ConnectionFactory#setNioParams(com.rabbitmq.client.impl.nio.NioParams)
     */
    public void setNioParams(NioParams nioParams) {
        this.connectionFactory.setNioParams(nioParams);
    }

    /**
     * @param metricsCollector the metrics collector instance
     * @see com.rabbitmq.client.ConnectionFactory#setMetricsCollector(MetricsCollector)
     */
    public void setMetricsCollector(MetricsCollector metricsCollector) {
        this.connectionFactory.setMetricsCollector(metricsCollector);
    }

    /**
     * Set to true to enable amqp-client automatic recovery. Note: Spring AMQP
     * implements its own connection recovery and this is generally not needed.
     * @param automaticRecoveryEnabled true to enable.
     * @since 1.7.1
     */
    public void setAutomaticRecoveryEnabled(boolean automaticRecoveryEnabled) {
        this.connectionFactory.setAutomaticRecoveryEnabled(automaticRecoveryEnabled);
    }

    /**
     * Set to true to enable amqp-client topology recovery. Note: if there is a
     * Rabbit admin in the application context, Spring AMQP
     * implements its own recovery and this is generally not needed.
     * @param topologyRecoveryEnabled true to enable.
     * @since 1.7.1
     */
    public void setTopologyRecoveryEnabled(boolean topologyRecoveryEnabled) {
        this.connectionFactory.setTopologyRecoveryEnabled(topologyRecoveryEnabled);
    }

    /**
     * @param channelRpcTimeout continuation timeout for RPC calls in channels
     * @since 2.0
     * @see com.rabbitmq.client.ConnectionFactory#setChannelRpcTimeout(int)
     */
    public void setChannelRpcTimeout(int channelRpcTimeout) {
        this.connectionFactory.setChannelRpcTimeout(channelRpcTimeout);
    }

    /**
     * Enable server hostname verification for TLS connections.
     * <p>
     * This enables hostname verification regardless of the IO mode used (blocking or
     * non-blocking IO).
     * <p>
     * This can be called typically after setting the {@link SSLContext} with one of the
     * <code>useSslProtocol</code> methods. Requires amqp-client 5.4.0 or later.
     * @param enable false to disable.
     * @since 2.0.6
     * @see com.rabbitmq.client.ConnectionFactory#enableHostnameVerification()
     */
    public void setEnableHostnameVerification(boolean enable) {
        this.enableHostnameVerification = enable;
    }

    protected String getKeyStoreAlgorithm() {
        return this.keyStoreAlgorithm;
    }

    /**
     * Set the algorithm used when creating the key store, default {@code SunX509}.
     * @param keyStoreAlgorithm the algorithm.
     * @since 2.1.6
     */
    public void setKeyStoreAlgorithm(String keyStoreAlgorithm) {
        this.keyStoreAlgorithm = keyStoreAlgorithm;
    }

    protected String getTrustStoreAlgorithm() {
        return this.trustStoreAlgorithm;
    }

    /**
     * Set the algorithm used when creating the trust store, default {@code SunX509}.
     * @param trustStoreAlgorithm the algorithm.
     * @since 2.1.6
     */
    public void setTrustStoreAlgorithm(String trustStoreAlgorithm) {
        this.trustStoreAlgorithm = trustStoreAlgorithm;
    }

    /**
     * Access the connection factory to set any other properties not supported by
     * this factory bean.
     * @return the connection factory.
     * @since 1.7.14
     */
    public ConnectionFactory getRabbitConnectionFactory() {
        return this.connectionFactory;
    }

    @Override
    public void afterPropertiesSet() {
        try {
            super.afterPropertiesSet();
        } catch (Exception e) {
            throw RabbitExceptionTranslator.convertRabbitAccessException(e);
        }
    }

    @Override
    public Class<?> getObjectType() {
        return ConnectionFactory.class;
    }

    @Override
    protected ConnectionFactory createInstance() {
        if (this.useSSL) {
            setUpSSL();
        }
        return this.connectionFactory;
    }

    /**
     * Override this method to take complete control over the SSL setup.
     * @since 1.4.4
     */
    protected void setUpSSL() {
        try {
            if (this.sslPropertiesLocation == null && this.keyStore == null && this.trustStore == null // NOSONAR boolean complexity
                    && this.keyStoreResource == null && this.trustStoreResource == null) {
                setupBasicSSL();
            } else {
                if (this.sslPropertiesLocation != null) {
                    this.sslProperties.load(this.sslPropertiesLocation.getInputStream());
                }
                KeyManager[] keyManagers = configureKeyManagers();
                TrustManager[] trustManagers = configureTrustManagers();

                if (this.logger.isDebugEnabled()) {
                    this.logger.debug("Initializing SSLContext with KM: " + Arrays.toString(keyManagers) + ", TM: "
                            + Arrays.toString(trustManagers) + ", random: " + this.secureRandom);
                }
                SSLContext context = createSSLContext();
                context.init(keyManagers, trustManagers, this.secureRandom);
                this.connectionFactory.useSslProtocol(context);
                if (this.enableHostnameVerification) {
                    this.connectionFactory.enableHostnameVerification();
                }
            }
        } catch (Exception e) {
            throw RabbitExceptionTranslator.convertRabbitAccessException(e);
        }
    }

    private void setupBasicSSL() throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
        if (this.skipServerCertificateValidation) {
            if (this.sslAlgorithmSet) {
                this.connectionFactory.useSslProtocol(this.sslAlgorithm);
            } else {
                this.connectionFactory.useSslProtocol();
            }
        } else {
            useDefaultTrustStoreMechanism();
        }
    }

    @Nullable
    protected KeyManager[] configureKeyManagers() throws KeyStoreException, IOException, NoSuchAlgorithmException,
            CertificateException, UnrecoverableKeyException {
        String keyStoreName = getKeyStore();
        String keyStorePassword = getKeyStorePassphrase();
        String storeType = getKeyStoreType();
        char[] keyPassphrase = null;
        if (keyStorePassword != null) {
            keyPassphrase = keyStorePassword.toCharArray();
        }
        KeyManager[] keyManagers = null;
        if (StringUtils.hasText(keyStoreName) || this.keyStoreResource != null) {
            Resource resource = this.keyStoreResource != null ? this.keyStoreResource
                    : this.resolver.getResource(keyStoreName);
            KeyStore ks = KeyStore.getInstance(storeType);
            ks.load(resource.getInputStream(), keyPassphrase);
            KeyManagerFactory kmf = KeyManagerFactory.getInstance(this.keyStoreAlgorithm);
            kmf.init(ks, keyPassphrase);
            keyManagers = kmf.getKeyManagers();
        }
        return keyManagers;
    }

    @Nullable
    protected TrustManager[] configureTrustManagers()
            throws KeyStoreException, IOException, NoSuchAlgorithmException, CertificateException {
        String trustStoreName = getTrustStore();
        String trustStorePassword = getTrustStorePassphrase();
        String storeType = getTrustStoreType();
        char[] trustPassphrase = null;
        if (trustStorePassword != null) {
            trustPassphrase = trustStorePassword.toCharArray();
        }
        TrustManager[] trustManagers = null;
        if (StringUtils.hasText(trustStoreName) || this.trustStoreResource != null) {
            Resource resource = this.trustStoreResource != null ? this.trustStoreResource
                    : this.resolver.getResource(trustStoreName);
            KeyStore tks = KeyStore.getInstance(storeType);
            tks.load(resource.getInputStream(), trustPassphrase);
            TrustManagerFactory tmf = TrustManagerFactory.getInstance(this.trustStoreAlgorithm);
            tmf.init(tks);
            trustManagers = tmf.getTrustManagers();
        }
        return trustManagers;
    }

    /**
     * Override this method to create and/or configure the {@link SSLContext} used
     * by the {@link ConnectionFactory}.
     * @return The {@link SSLContext}.
     * @throws NoSuchAlgorithmException if the algorithm is not available.
     * @since 1.4.4
     */
    protected SSLContext createSSLContext() throws NoSuchAlgorithmException {
        return SSLContext.getInstance(this.sslAlgorithm);
    }

    private void useDefaultTrustStoreMechanism()
            throws NoSuchAlgorithmException, KeyManagementException, KeyStoreException {
        SSLContext sslContext = SSLContext.getInstance(this.sslAlgorithm);
        TrustManagerFactory trustManagerFactory = TrustManagerFactory
                .getInstance(TrustManagerFactory.getDefaultAlgorithm());
        trustManagerFactory.init((KeyStore) null);
        sslContext.init(null, trustManagerFactory.getTrustManagers(), null);
        this.connectionFactory.useSslProtocol(sslContext);
        if (this.enableHostnameVerification) {
            this.connectionFactory.enableHostnameVerification();
        }
    }

}