com.adaptris.core.http.jetty.HttpsConnection.java Source code

Java tutorial

Introduction

Here is the source code for com.adaptris.core.http.jetty.HttpsConnection.java

Source

/*
 * Copyright 2015 Adaptris Ltd.
 * 
 * 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.adaptris.core.http.jetty;

import static org.apache.commons.lang.StringUtils.isEmpty;

import java.util.ArrayList;
import java.util.List;
import java.util.StringTokenizer;

import javax.validation.Valid;
import javax.validation.constraints.NotNull;

import org.eclipse.jetty.server.Connector;
import org.eclipse.jetty.server.ssl.SslSocketConnector;
import org.eclipse.jetty.util.ssl.SslContextFactory;

import com.adaptris.annotation.AdapterComponent;
import com.adaptris.annotation.AdvancedConfig;
import com.adaptris.annotation.AutoPopulated;
import com.adaptris.annotation.ComponentProfile;
import com.adaptris.annotation.DisplayOrder;
import com.adaptris.security.exc.PasswordException;
import com.adaptris.security.password.Password;
import com.adaptris.util.KeyValuePair;
import com.adaptris.util.KeyValuePairSet;
import com.thoughtworks.xstream.annotations.XStreamAlias;

/**
 * Concrete implementation of JettyConnection that allows HTTPs traffic.
 * 
 * <p>
 * By default all fields are left as null. This will cause Jetty to use its internal defaults. Consult the Jetty Documentation for
 * information on the behaviour and configuration required.
 * </p>
 * <p>
 * The key from the <code>ssl-properties</code> element should match the name of the underlying {@link SslContextFactory} setter.
 * 
 * <pre>
 * {@code 
 *   <ssl-properties>
 *     <key-value-pair>
 *        <key>WantClientAuth</key>
 *        <value>true</value>
 *     </key-value-pair>
 *   </ssl-properties>
 * }
 * </pre>
 * will invoke {@link SslContextFactory#setWantClientAuth(boolean)}, setting the WantClientAuth property to true. Note that no
 * validation of the various properties is performed and will be passed as-is to the {@link SslContextFactory} with an attempt to
 * transform into the correct type. Invalid combinations may result in undefined behaviour.
 * </p>
 * 
 * @config jetty-https-connection
 * 
 * @author lchan
 * @see JettyConnection
 */
@XStreamAlias("jetty-https-connection")
@AdapterComponent
@ComponentProfile(summary = "Connection that creates its own jetty engine instance and listens on the specified port", tag = "connections,https,jetty")
@DisplayOrder(order = { "port", "httpProperties, sslProperties" })
public class HttpsConnection extends HttpConnection {
    /**
     * Properties for {@link SslContextFactory}.
     * 
     * 
     */
    public enum SslProperty {

        /**
         * 
         * @see SslContextFactory#setKeyStorePath(String)
         */
        KeyStorePath {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setKeyStorePath(value);
            }
        },
        /**
         * Set the keystore password (may be encoded using {@link com.adaptris.security.password.Password}.
         * <p>
         * Note that the password may also be obfuscated using the internal jetty utility
         * {@link org.eclipse.jetty.util.security.Password} using one of the reversible schemes.
         * </p>
         * 
         * @see SslContextFactory#setKeyStorePassword(String)
         */
        KeyStorePassword {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) throws PasswordException {
                sslContextFactory.setKeyStorePassword(Password.decode(value));
            }
        },
        /**
         * 
         * @see SslContextFactory#setKeyStoreType(String)
         */
        KeyStoreType {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setKeyStoreType(value);
            }
        },
        /**
         * @see SslContextFactory#setKeyStoreProvider(String)
         */
        KeyStoreProvider {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setKeyStoreProvider(value);
            }
        },
        /**
         * 
         * @see SslContextFactory#setTrustStore(String)
         */
        TrustStore {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setTrustStore(value);
            }
        },
        /**
         * Set the truststore password (may be encoded using {@link com.adaptris.security.password.Password} .
         * <p>
         * Note that the password may also be obfuscated using the internal jetty utility
         * {@link org.eclipse.jetty.util.security.Password} using one of the reversible schemes.
         * </p>
         * 
         * @see SslContextFactory#setTrustStorePassword(String)
         */
        TrustStorePassword {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) throws PasswordException {
                sslContextFactory.setTrustStorePassword(Password.decode(value));
            }
        },
        /**
         * 
         * @see SslContextFactory#setTrustStoreType(String)
         */
        TrustStoreType {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setTrustStoreType(value);
            }
        },
        /**
         * @see SslContextFactory#setTrustStoreProvider(String)
         */
        TrustStoreProvider {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setTrustStoreProvider(value);
            }
        },
        /**
         * Set the key manager password (may be encoded using {@link com.adaptris.security.password.Password} .
         * <p>
         * Note that the password may also be obfuscated using the internal jetty utility
         * {@link org.eclipse.jetty.util.security.Password} using one of the reversible schemes.
         * </p>
         * 
         * @see SslContextFactory#setKeyManagerPassword(String)
         */
        KeyManagerPassword {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) throws PasswordException {
                sslContextFactory.setKeyManagerPassword(Password.decode(value));
            }
        },

        /**
         * A comma separated list of cipher suites to exclude.
         * 
         * @see SslContextFactory#setExcludeCipherSuites(String...)
         */
        ExcludeCipherSuites {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setExcludeCipherSuites(asArray(value));
            }
        },
        /**
         * A comma separated list of cipher suites to include.
         * 
         * @see SslContextFactory#setIncludeCipherSuites(String...)
         */
        IncludeCipherSuites {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setIncludeCipherSuites(asArray(value));
            }
        },
        /**
         * A comma separated list of protocols to exclude
         * 
         * @see SslContextFactory#setExcludeProtocols(String...)
         */
        ExcludeProtocols {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setExcludeProtocols(asArray(value));
            }
        },
        /**
         * A comma separated list of protocols to include
         * 
         * @see SslContextFactory#setIncludeProtocols(String...)
         */
        IncludeProtocols {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setIncludeProtocols(asArray(value));
            }
        },
        /**
         * 
         * @see SslContextFactory#setSecureRandomAlgorithm(String)
         */
        SecureRandomAlgorithm {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setSecureRandomAlgorithm(value);
            }
        },
        /**
         * @see SslContextFactory#setSessionCachingEnabled(boolean)
         */
        SessionCachingEnabled {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setSessionCachingEnabled(Boolean.valueOf(value).booleanValue());
            }
        },
        /**
         * @see SslContextFactory#setMaxCertPathLength(int)
         */
        MaxCertPathLength {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setMaxCertPathLength(Integer.parseInt(value));
            }
        },
        /**
         * @see SslContextFactory#setNeedClientAuth(boolean)
         */
        NeedClientAuth {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setNeedClientAuth(Boolean.valueOf(value).booleanValue());
            }
        },
        /**
         * @see SslContextFactory#setOcspResponderURL(String)
         */
        OcspResponderURL {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setOcspResponderURL(value);
            }
        },
        /**
         * @see SslContextFactory#setSslSessionTimeout(int)
         */
        SslSessionTimeout {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setSslSessionTimeout(Integer.parseInt(value));
            }
        },
        /**
         * @see SslContextFactory#setTrustAll(boolean)
         */
        TrustAll {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setTrustAll(Boolean.valueOf(value).booleanValue());
            }
        },
        /**
         * @see SslContextFactory#setTrustManagerFactoryAlgorithm(String)
         */
        TrustManagerFactoryAlgorithm {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setTrustManagerFactoryAlgorithm(value);
            }
        },
        /**
         * @see SslContextFactory#setValidateCerts(boolean)
         */
        ValidateCerts {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setValidateCerts(Boolean.valueOf(value).booleanValue());
            }
        },
        /**
         * @see SslContextFactory#setValidatePeerCerts(boolean)
         */
        ValidatePeerCerts {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setValidatePeerCerts(Boolean.valueOf(value).booleanValue());
            }
        },
        /**
         * 
         * @see SslContextFactory#setWantClientAuth(boolean)
         */
        WantClientAuth {
            @Override
            void applyProperty(SslContextFactory sslContextFactory, String value) {
                sslContextFactory.setWantClientAuth(Boolean.valueOf(value).booleanValue());
            }
        };

        abstract void applyProperty(SslContextFactory sslContextFactory, String value) throws Exception;

    }

    @NotNull
    @Valid
    @AutoPopulated
    @AdvancedConfig
    private KeyValuePairSet sslProperties;

    /**
     * Default Constructor.
     * <p>
     * Defaults are :
     * <ul>
     * <li>port = 8443</li>
     * </ul>
     * </p>
     * <p>
     * Other fields are null, which causes Jetty to use its internal defaults.
     * </p>
     */
    public HttpsConnection() {
        super();
        setPort(8443);
        setSslProperties(new KeyValuePairSet());
    }

    private static String[] asArray(String s) {
        if (s == null) {
            return new String[0];
        }
        StringTokenizer st = new StringTokenizer(s, ",");
        List<String> l = new ArrayList<String>();
        while (st.hasMoreTokens()) {
            String tok = st.nextToken().trim();
            if (!isEmpty(tok))
                l.add(tok);
        }
        return l.toArray(new String[0]);
    }

    @Override
    Connector createConnector() throws Exception {
        SslSocketConnector connector = (SslSocketConnector) configure(new SslSocketConnector());

        SslContextFactory sslContextFactory = connector.getSslContextFactory();
        for (KeyValuePair kvp : getSslProperties().getKeyValuePairs()) {
            boolean matched = false;
            for (SslProperty sp : SslProperty.values()) {
                if (kvp.getKey().equalsIgnoreCase(sp.toString())) {
                    sp.applyProperty(sslContextFactory, kvp.getValue());
                    matched = true;
                    break;
                }
            }
            if (!matched) {
                log.trace("Ignoring unsupported Property " + kvp.getKey());
            }
        }
        return connector;
    }

    public KeyValuePairSet getSslProperties() {
        return sslProperties;
    }

    /**
     * Set the SSL properties.
     * 
     * @param kvps the SSL properties
     * @see SslProperty
     */
    public void setSslProperties(KeyValuePairSet kvps) {
        this.sslProperties = kvps;
    }
}