package com.drfirst.pdmp.service.util;
import org.apache.commons.lang3.BooleanUtils;
import org.apache.commons.lang3.math.NumberUtils;
import org.apache.http.client.config.CookieSpecs;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.config.Registry;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.impl.client.CloseableHttpClient;
import org.apache.http.impl.client.HttpClients;
import org.apache.http.impl.conn.PoolingHttpClientConnectionManager;
import javax.annotation.PreDestroy;
import java.util.HashMap;
import java.util.Map;
import java.util.Properties;
import java.util.concurrent.TimeUnit;
import static org.apache.commons.lang3.StringUtils.isNotEmpty;
/**
* State HttpClient factory maintain all connection manager by state and registry by service provider
* User: Carlos
* Date: 2018/7/4
*/
public class StateHttpClientFactory {
private RequestConfig requestConfig;
private Map
<String, PoolingHttpClientConnectionManager
> stateHttpPool
= new HashMap
<>();
private Registry<ConnectionSocketFactory> socketFactoryRegistry;
public StateHttpClientFactory
(Properties properties, Registry
<ConnectionSocketFactory
> socketFactoryRegistry
) {
this.properties = properties;
this.socketFactoryRegistry = socketFactoryRegistry;
}
private synchronized PoolingHttpClientConnectionManager setup
(String statusCode
) {
PoolingHttpClientConnectionManager cm = stateHttpPool.get(statusCode);
if (cm != null) {
return cm;
}
HttpProp prop = new HttpProp(statusCode, properties);
requestConfig = RequestConfig.custom()
.setSocketTimeout(prop.getSoTimeout())
.setConnectTimeout(prop.getConnectTimeout())
.setConnectionRequestTimeout(prop.getConnectionRequestTimeout())
.setCookieSpec(CookieSpecs.IGNORE_COOKIES)
.build();
if (socketFactoryRegistry == null) {
cm = new PoolingHttpClientConnectionManager(prop.getPoolingMsTimeToLive(), TimeUnit.MILLISECONDS);
} else {
cm = new PoolingHttpClientConnectionManager(socketFactoryRegistry, null, null, null, prop.getPoolingMsTimeToLive(), TimeUnit.MILLISECONDS);
}
cm.setDefaultMaxPerRoute(prop.getPoolingDefaultMaxPerRoute());
cm.setMaxTotal(prop.getPoolingMaxTotal());
cm.setDefaultSocketConfig(SocketConfig.custom()
.setTcpNoDelay(prop.isTcpNoDelay())
.setSoLinger(prop.getLinger())
.setSoTimeout(prop.getSoTimeout())
.setSndBufSize(prop.getSocketBufferSize())
.setRcvBufSize(prop.getSocketBufferSize())
.build());
stateHttpPool.put(statusCode, cm);
return cm;
}
public CloseableHttpClient getHttpClient
(String statusCode
) {
PoolingHttpClientConnectionManager cm = setup(statusCode);
return HttpClients.custom()
.setDefaultRequestConfig(requestConfig)
.setConnectionManager(cm)
.build();
}
public PoolingHttpClientConnectionManager getConnectionManager
(String statusCode
) {
return stateHttpPool.get(statusCode);
}
@PreDestroy
public void shutdown(){
for (PoolingHttpClientConnectionManager cm : stateHttpPool.values()) {
cm.close();
}
}
return properties;
}
public void setProperties
(Properties properties
) {
this.properties = properties;
}
class HttpProp {
private final static String SO_TIMEOUT
= "http.soTimeout";
private final static String CONN_TIMEOUT
= "http.connectTimeout";
private final static String CONN_REQ_TIMEOUT
= "http.connectionRequestTimeout";
private final static String TCP_NO_DELAY
= "http.tcpNoDelay";
private final static String LINGER
= "http.linger";
private final static String SOCKET_BUFFER_SIZE
= "http.socketBufferSize";
private final static String POOLING_TTL
= "http.pooling.msTimeToLive";
private final static String POOLING_MAX_ROUTE
= "http.pooling.defaultMaxPerRoute";
private final static String POOLING_TOTAL
= "http.pooling.maxTotal";
int soTimeout, connectTimeout, connectionRequestTimeout, linger, socketBufferSize, poolingDefaultMaxPerRoute, poolingMaxTotal;
boolean tcpNoDelay;
long poolingMsTimeToLive;
soTimeout = load(state, p, SO_TIMEOUT, 60000);
connectTimeout = load(state, p, CONN_TIMEOUT, 60000);
connectionRequestTimeout = load(state, p, CONN_REQ_TIMEOUT, 60000);
tcpNoDelay = load(state, p, TCP_NO_DELAY, "true");
linger = load(state, p, LINGER, 0);
socketBufferSize = load(state, p, SOCKET_BUFFER_SIZE, 32768);
poolingMsTimeToLive = load(state, p, POOLING_TTL, 60000L);
poolingDefaultMaxPerRoute = load(state, p, POOLING_MAX_ROUTE, 40);
poolingMaxTotal = load(state, p, POOLING_TOTAL, 200);
}
int defaultVal = NumberUtils.toInt(p.getProperty(key), defaultValue);
if (isNotEmpty(state) && p.containsKey(state + "." + key)) {
return NumberUtils.toInt(p.getProperty(state + "." + key), defaultVal);
}
return defaultVal;
}
Boolean defaultVal
= BooleanUtils.
toBoolean(p.
getProperty(key, defaultValue
));
if (isNotEmpty(state) && p.containsKey(state + "." + key)) {
return BooleanUtils.toBoolean(p.getProperty(state + "." + key, defaultVal.toString()));
}
return defaultVal;
}
long defaultVal = NumberUtils.toLong(p.getProperty(key), defaultValue);
if (isNotEmpty(state) && p.containsKey(state + "." + key)) {
return NumberUtils.toLong(p.getProperty(state + "." + key), defaultVal);
}
return defaultVal;
}
int getSoTimeout() {
return soTimeout;
}
int getConnectTimeout() {
return connectTimeout;
}
int getConnectionRequestTimeout() {
return connectionRequestTimeout;
}
int getLinger() {
return linger;
}
int getSocketBufferSize() {
return socketBufferSize;
}
int getPoolingDefaultMaxPerRoute() {
return poolingDefaultMaxPerRoute;
}
int getPoolingMaxTotal() {
return poolingMaxTotal;
}
boolean isTcpNoDelay() {
return tcpNoDelay;
}
long getPoolingMsTimeToLive() {
return poolingMsTimeToLive;
}
}
}
@Bean(name = "logicoyHttpClientFactory")
public StateHttpClientFactory logicoyHttpClient
() throws Exception {
SSLContext sslContext = SSLContexts.custom().build();
SSLConnectionSocketFactory sslConnectionSocketFactory = new SSLConnectionSocketFactory(sslContext,
null,
new NoopHostnameVerifier());
Registry<ConnectionSocketFactory> socketFactoryRegistry = RegistryBuilder
.<ConnectionSocketFactory>create().register("https", sslConnectionSocketFactory)
.build();
Properties properties
= loadProperties
("${instance.properties}/state-httpclient.properties");
return new StateHttpClientFactory(properties,socketFactoryRegistry);
}