package com.jobhive.sakimonkey;
import java.net.InetSocketAddress;
import java.net.Proxy;
import java.net.ProxySelector;
import java.net.URI;
import java.net.URISyntaxException;
import java.util.List;
import javax.net.ssl.HostnameVerifier;
import org.apache.http.HttpHost;
import org.apache.http.auth.AuthScope;
import org.apache.http.auth.UsernamePasswordCredentials;
import org.apache.http.client.CredentialsProvider;
import org.apache.http.client.config.RequestConfig;
import org.apache.http.client.config.RequestConfig.Builder;
import org.apache.http.conn.ssl.DefaultHostnameVerifier;
import org.apache.http.impl.client.BasicCredentialsProvider;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.jobhive.sakimonkey.data.request.ApiParam;
import com.jobhive.sakimonkey.exception.IORuntimeException;
import com.typesafe.config.Config;
/**
*
* @author Hussachai
*
*/
public abstract class AbstractMandrillClient {
protected final Logger log = LoggerFactory.getLogger(getClass());
protected MandrillContext context;
protected Config config;
public AbstractMandrillClient() {
this(null, null);
}
public AbstractMandrillClient(MandrillContext context) {
this.context = context;
this.config = context.getConfig();
init();
}
public AbstractMandrillClient(String apiKey, String configPath) {
this.context = new MandrillContext(apiKey, configPath);
this.config = this.context.getConfig();
init();
}
public MandrillContext getContext() {
return context;
}
abstract protected void init();
abstract public void shutdown();
protected String getApiKeyAsJson() {
/* Don't bother serializer to do this simple job */
return "{\"key\": \"" + context.getApiKey() + "\"}";
}
protected String getUserAgent(){
return context.getMetadata().getName() + "/"
+ context.getMetadata().getVersion();
}
protected String convertParamsToJson(Object params) {
if(params == null){
log.debug("JSON param of ApiParam : [apiKey]");
return getApiKeyAsJson();
}else if(params instanceof ApiParam){
((ApiParam)params).setKey(context.getApiKey());
}
String value = null;
try {
value = context.getObjectMapper().writeValueAsString(params);
log.debug("JSON param of {} : {}",
params.getClass().getSimpleName(), value);
} catch (JsonProcessingException e) {
throw new IORuntimeException(e);
}
return value;
}
protected HttpHost detectHttpProxy(){
if(config.getBoolean("httpClient.proxy.enabled")){
log.info("Proxy is set");
String host = config.getString("httpClient.proxy.host");
int port = config.getInt("httpClient.proxy.port");
log.info("Using proxy host='{}', port={}", host, port);
return new HttpHost(host, port);
}
List<Proxy> proxies = null;
try {
proxies = ProxySelector.getDefault().select(
new URI(MandrillContext.BASE_URL));
} catch (URISyntaxException e) {/*never happens*/}
if(proxies != null){
for(Proxy proxy: proxies){
InetSocketAddress addr = (InetSocketAddress) proxy.address();
if(addr != null){
log.info("System detects proxy( host='{}', port={} )",
addr.getHostName(), addr.getPort());
return new HttpHost(addr.getHostName(), addr.getPort());
}
}
}
return null;
}
/**
*
* @return default HostnameVerifier object
*/
protected HostnameVerifier createHostnameVerifier(){
return new DefaultHostnameVerifier();
}
protected CredentialsProvider createDefaultCredentialsProvider(String host, int port){
if(!config.hasPath("httpClient.proxy.username")){
return null;
}
log.info("Proxy authentication information is provided");
String username = config.getString("httpClient.proxy.username");
String password = config.getString("httpClient.proxy.password");
CredentialsProvider credsProvider = new BasicCredentialsProvider();
credsProvider.setCredentials(
new AuthScope(host, port),
new UsernamePasswordCredentials(username, password));
return credsProvider;
}
protected RequestConfig createDefaultRequestConfig(){
Builder configBuilder = RequestConfig.custom();
int socketTimeout = config.getInt("httpClient.request.socketTimeout");
int connTimeout = config.getInt("httpClient.request.connectTimeout");
int connReqTimeout = config.getInt("httpClient.request.connectionRequestTimeout");
log.info("Defeault request timeout: \n"
+ "\tsocketTimeout = {}\n"
+ "\tconnectionTimeout = {}\n"
+ "\tconnectionRequestTimeout = {}",
socketTimeout, connTimeout, connReqTimeout);
configBuilder.setSocketTimeout(socketTimeout);
configBuilder.setConnectTimeout(connTimeout);
configBuilder.setConnectionRequestTimeout(connReqTimeout);
return configBuilder.build();
}
protected ConnectionSettings createConnectionSettings(){
ConnectionSettings s = new ConnectionSettings();
s.shared = config.getBoolean("httpClient.connection.shared");
s.defaultMaxPerRoute = config.getInt("httpClient.connection.defaultMaxPerRoute");
s.maxTotal = config.getInt("httpClient.connection.maxTotal");
log.info("Default connection settings: \n"
+ "\tshared = {}\n"
+ "\tdefaultMaxPerRoute = {}\n"
+ "\tmaxTotal = {}",
s.shared, s.defaultMaxPerRoute, s.maxTotal);
if(s.shared){
log.info("!!! Connection Manager is set to shared !!!");
log.info("Client is responsible for managing the connection"
+ "and shutdown method has no effect on connection.");
}
return s;
}
protected class ConnectionSettings{
boolean shared;
int defaultMaxPerRoute;
int maxTotal;
}
}