/******************************************************************************* * Copyright (c) 2006-2010 eBay Inc. All Rights Reserved. * 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 *******************************************************************************/ package org.ebayopensource.turmeric.runtime.sif.impl.transport.http; import java.util.Map; import org.ebayopensource.turmeric.runtime.common.exceptions.ServiceException; import org.ebayopensource.turmeric.runtime.common.impl.utils.ReflectionUtils; import org.ebayopensource.turmeric.runtime.common.pipeline.TransportOptions; import org.ebayopensource.turmeric.runtime.common.types.SOAConstants; import com.ebay.kernel.bean.configuration.BaseConfigBean; import com.ebay.kernel.bean.configuration.BeanConfigCategoryInfo; import com.ebay.kernel.bean.configuration.BeanPropertyInfo; import com.ebay.kernel.bean.configuration.ConfigCategoryCreateException; import com.ebay.kernel.initialization.InitializationException; import com.ebay.kernel.service.invocation.HttpConfig; import com.ebay.kernel.service.invocation.SocketConfig; import com.ebay.kernel.service.invocation.SslConfig; import com.ebay.kernel.service.invocation.SvcChannelStatus; import com.ebay.kernel.service.invocation.SvcInvocationConfig; import com.ebay.kernel.service.invocation.client.http.nio.NioHttpConfig; import com.ebay.kernel.service.invocation.client.http.nio.NioSvcInvocationConfig; public class HTTPClientTransportConfig extends BaseConfigBean { // Static labels for file config properties; // these match the config bean names public static final String USE_HTTPS = "USE_HTTPS"; public static final String VERIFY_TRUST_FOR_HTTPS = "VERIFY_TRUST_FOR_HTTPS"; public static final String PROXY_HOST = "PROXY_HOST"; public static final String PROXY_PASSWORD = "PROXY_PASSWORD"; public static final String PROXY_PORT = "PROXY_PORT"; public static final String PROXY_USER = "PROXY_USER"; public static final String NON_PROXY_HOSTS = "NON_PROXY_HOSTS"; public static final String PROXY_ENABLED = "PROXY_ENABLED"; // Only used by Async Transport public static final String KEEP_ALIVE = "KEEP_ALIVE"; public static final String CONSECUTIVE_FAILURE_THRESHOLD = "CONSECUTIVE_FAILURE_THRESHOLD"; // defaults - first class SOA config options. public static final boolean DEFAULT_KEEP_ALIVE = false; public static final int DEFAULT_CONSECUTIVE_FAILURE_THRESHOLD = Integer.MAX_VALUE; // ConnectionConfig NUM_RETRY for SocketConnector.getSocket(). public static final int DEFAULT_MAX_CONNECT_RETRY = 1; protected static final String DEFAULT_SSL_CONFIG_FACTORY = "org.ebayopensource.turmeric.runtime.sif.impl.transport.http.FileSystemSslConfigFactory"; // Applies to socket connect *only*. // CONNECT_TIMEOUT (msec) public static final int DEFAULT_HTTP_CONNECTION_TIMEOUT = 36000; // ConnectionConfig: // SO_TIMEOUT (msec) public static final int DEFAULT_SOCKET_RECV_TIMEOUT = 50000; // SocketConfig: // defaults - options set via name-value 'other-options' transport config // properties public static final int DEFAULT_INVOCATION_TIMEOUT = 0; // LimitedDurationInvocationConfig: // MAX_INVOCATION_DURATION : Used by Sync only private static final boolean DEFAULT_USE_HTTPS = false; // this bean private static final boolean DEFAULT_VERIFY_TRUST_FOR_HTTPS = true; // this // bean private static final boolean DEFAULT_CLIENT_STREAMING = false; private static final String CONFIG_ID_PREFIX = SOAConstants.CONFIG_BEAN_PREFIX_CLIENT + "http."; public static final String SSL_CONFIG_FACTORY = "SSL_CONFIG_FACTORY"; public static final String SSL_TRUSTSTORE_CHANNELNAME = "SSL_TRUSTSTORE_CHANNELNAME"; public static final String SSL_KEYPAIR_CHANNELNAME = "SSL_KEYPAIR_CHANNELNAME"; // Member fields for this bean - can't be final private boolean useHttps; private boolean verifyTrustForHttps; private long maxInvocationDuration; // Contained beans private SvcInvocationConfig svcIvcConfig; private NioSvcInvocationConfig nioSvcIvcConfig; private SslConfig sslConfig; // member variables - final private final String configName; private final String configId; private final TransportOptions transportOptions; protected static final BeanPropertyInfo PROP_USE_HTTPS = createBeanPropertyInfo( "useHttps", USE_HTTPS, true); protected static final BeanPropertyInfo PROP_VERIFY_TRUST_FOR_HTTPS = createBeanPropertyInfo( "verifyTrustForHttps", VERIFY_TRUST_FOR_HTTPS, true); protected static final BeanPropertyInfo MAX_INVOCATION_DURATION = createBeanPropertyInfo( "maxInvocationDuration", "MAX_INVOCATION_DURATION", true); /** * Constructor that requires full set of parameters to be specified */ public HTTPClientTransportConfig(String configName, TransportOptions options) { this.configName = configName; this.configId = CONFIG_ID_PREFIX + configName; this.transportOptions = options; BeanConfigCategoryInfo categoryInfo; try { categoryInfo = BeanConfigCategoryInfo.createBeanConfigCategoryInfo( configId, null, SOAConstants.CONFIG_BEAN_GROUP, false, true, null, "SOA HttpClient Configuration", true); // Parameters in order // categoryId, alias, group, isPersistent, opsManagable, persistFileUri, description, returnExistingOne } catch (ConfigCategoryCreateException e) { throw new InitializationException(e); } this.useHttps = isSecure(); this.verifyTrustForHttps = verifyTrust(); createServiceConfigs(categoryInfo); init(categoryInfo, true); } private boolean isSecure() { boolean isSecure = DEFAULT_USE_HTTPS; Boolean b = getBoolean(transportOptions.getProperties(), USE_HTTPS); if (b != null) { isSecure = b.booleanValue(); } return isSecure; } private boolean verifyTrust() { boolean verifyTrust = DEFAULT_VERIFY_TRUST_FOR_HTTPS; Boolean b = getBoolean(transportOptions.getProperties(), VERIFY_TRUST_FOR_HTTPS); if (b != null) { verifyTrust = b.booleanValue(); } return verifyTrust; } private void createServiceConfigs(BeanConfigCategoryInfo categoryInfo ) { int httpConnectionTimeout = getHttpConnTimeout(); int socketRecvTimeout = getSocketRecvTimeout(); Map<String, String> propertyMap = transportOptions.getProperties(); // Main config bean for HTTPClient String svcHost = null; String svcPort = null; boolean ignoreConfigedSvcHost = false; boolean asyncInvocation = false; svcIvcConfig = new SvcInvocationConfig(categoryInfo, configName, SvcChannelStatus.MARK_UP, svcHost, svcPort, ignoreConfigedSvcHost, asyncInvocation); nioSvcIvcConfig = new NioSvcInvocationConfig(categoryInfo, configName, SvcChannelStatus.MARK_UP); boolean clientStreaming = isStreaming(); if (clientStreaming) { nioSvcIvcConfig.setUseResponseStreaming(clientStreaming); } int maxAvailableThreads = 1; int maxActiveThreads = 1; boolean useConnPool = false; svcIvcConfig.createConnectionConfig(maxAvailableThreads, maxActiveThreads, httpConnectionTimeout, getMaxConnectRetry(), false, false, useConnPool); nioSvcIvcConfig.createConnectionConfig(httpConnectionTimeout, getMaxConnectRetry()); if (useHttps) { Integer soLinger = null; Integer soRcvBuf = null; Integer soSndBuf = null; Boolean tcpNoDelay = Boolean.TRUE; Boolean soKeepAlive = null; SocketConfig socketConfig = svcIvcConfig.createSocketConfig( Integer.valueOf(socketRecvTimeout), soLinger, soRcvBuf, soSndBuf, tcpNoDelay, soKeepAlive); SocketConfig nioSocketConfig = nioSvcIvcConfig.createRequestConfig( Integer.valueOf(socketRecvTimeout), soLinger, soRcvBuf, soSndBuf, tcpNoDelay, soKeepAlive); try { sslConfig = createSSLConfig(socketConfig); } catch (SslConfigCreationException e) { throwInitializationException(e); } socketConfig.setSslConfig(sslConfig); nioSocketConfig.setSslConfig(sslConfig); } // HTTP Config boolean followHttpRedirect = true; boolean enableKeepAlive = false; boolean enableProxy = false; HttpConfig httpConfig = svcIvcConfig.createHttpConfig(followHttpRedirect, enableKeepAlive, enableProxy); NioHttpConfig nioHttpConfig = nioSvcIvcConfig.createHttpConfig(followHttpRedirect, enableKeepAlive, enableProxy); nioHttpConfig.setKeepAliveEnabled(doIKeepAlive()); String proxyHost = propertyMap.get(PROXY_HOST); if (proxyHost != null) { String nonProxyHosts = propertyMap.get(NON_PROXY_HOSTS); String proxyPassword = propertyMap.get(PROXY_PASSWORD); String proxyPort = propertyMap.get(PROXY_PORT); String proxyUser = propertyMap.get(PROXY_USER); Boolean proxyEnabled = getBoolean(propertyMap, PROXY_ENABLED); httpConfig.createProxyConfig(proxyHost, nonProxyHosts, proxyPort, proxyUser, proxyPassword); nioHttpConfig.createProxyConfig(proxyHost, nonProxyHosts, proxyPort, proxyUser, proxyPassword); if (proxyEnabled != null && proxyEnabled.booleanValue()) { httpConfig.setProxyEnabled(true); nioHttpConfig.setProxyEnabled(true); } } // limit the invocation duration if invocation timeout is specified // Default is false. boolean enableInvocationTimeout = false; int invocationTimeout = getInvocationTimeout(); if (invocationTimeout > 0) { enableInvocationTimeout = true; } svcIvcConfig.createLimitedDurationInvocationConfig(enableInvocationTimeout, invocationTimeout); nioSvcIvcConfig.setConsecutiveFailureThreshold(getConsecutiveFailureThreashold()); } private int getConsecutiveFailureThreashold() { Integer consecutiveFailureThreshold = getInteger(transportOptions.getProperties(), CONSECUTIVE_FAILURE_THRESHOLD); consecutiveFailureThreshold = consecutiveFailureThreshold == null ? Integer .valueOf(DEFAULT_CONSECUTIVE_FAILURE_THRESHOLD) : consecutiveFailureThreshold; return consecutiveFailureThreshold.intValue(); } private boolean doIKeepAlive() { Boolean keepAlive = getBoolean(transportOptions.getProperties(), KEEP_ALIVE); keepAlive = keepAlive == null ? Boolean.valueOf(DEFAULT_KEEP_ALIVE) : keepAlive; return keepAlive.booleanValue(); } private int getInvocationTimeout() { int invocationTimeout = DEFAULT_INVOCATION_TIMEOUT; Integer i = transportOptions.getInvocationTimeout(); if (i != null) { invocationTimeout = i.intValue(); } return invocationTimeout; } private boolean isStreaming() { Boolean clientStreaming = transportOptions.isClientStreaming(); if (clientStreaming == null) return DEFAULT_CLIENT_STREAMING; return clientStreaming; } private int getSocketRecvTimeout() { int socketRecvTimeout = DEFAULT_SOCKET_RECV_TIMEOUT; Integer i = transportOptions.getReceiveTimeout(); if (i != null) { socketRecvTimeout = i.intValue(); } return socketRecvTimeout; } private int getHttpConnTimeout() { int httpConnectionTimeout = DEFAULT_HTTP_CONNECTION_TIMEOUT; Integer i = transportOptions.getConnectTimeout(); if (i != null) { httpConnectionTimeout = i.intValue(); } return httpConnectionTimeout; } private int getMaxConnectRetry() { int maxConnectRetry = DEFAULT_MAX_CONNECT_RETRY; Integer i = transportOptions.getNumConnectRetries(); if (i != null) { maxConnectRetry = i.intValue(); } return maxConnectRetry; } private void throwInitializationException(SslConfigCreationException cause) { throw new InitializationException("Trouble creating SSL Config", cause); } public long getMaxInvocationDuration() { return maxInvocationDuration; } public SvcInvocationConfig getSvcInvocationConfig() { return svcIvcConfig; } public NioSvcInvocationConfig getNioSvcInvocationConfig() { return nioSvcIvcConfig; } public boolean isVerifyTrustForHttps() { return verifyTrustForHttps; } private Boolean getBoolean(Map<String, String> propertyMap, String name) { String s = propertyMap.get(name); if (s == null) { return null; } return Boolean.valueOf(Boolean.parseBoolean(s)); } private Integer getInteger(Map<String, String> propertyMap, String name) { String s = propertyMap.get(name); if (s == null) { return null; } return Integer.valueOf(Integer.parseInt(s)); } @SuppressWarnings("unchecked") private SslConfig createSSLConfig(SocketConfig sc) throws SslConfigCreationException { Map<String, String> properties = transportOptions.getProperties(); AbstractSslConfigFactory<? extends SslConfig> sslConfigFactory = null; String sslFactoryName = properties.get(SSL_CONFIG_FACTORY); if (sslFactoryName == null) { sslFactoryName = DEFAULT_SSL_CONFIG_FACTORY; } ClassLoader cl = Thread.currentThread().getContextClassLoader(); try { sslConfigFactory = ReflectionUtils.createInstance(sslFactoryName, AbstractSslConfigFactory.class, cl); } catch (ServiceException e) { throw new SslConfigCreationException("Instantiation of " + sslFactoryName + " failed", e); } return sslConfigFactory.createSslConfig(sc.getBeanConfigCategoryInfo(), properties); } private static final long serialVersionUID = 1L; }