package net.kittyandbear;
//2012-11-13 johnpfeiffer requires maven: org.apache.httpcomponents - httpclient and httpmime 4.2.2 , commons-logging-1.1.1
/*
* performance note: "While HttpClient instances are thread safe and can be shared between multiple threads of execution, it is highly recommended that each thread maintains its own dedicated instance of HttpContext."
* http://hc.apache.org/httpcomponents-client-ga/tutorial/html/connmgmt.html#d5e639
*
* Example Usage:
*
* HttpClientFactory myHttpClientFactory = HttpClientFactory.getInstance();
* myHttpClientFactory.setMaxConnectionsOverall(200);
* myHttpClientFactory.setMaxConnectionsPerRoute(100);
* httpclient = HttpClientFactory.getStaticHttpClient();
*/
//TODO: research whether an enum singleton pattern would be better
import org.apache.http.client.HttpClient;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.SSLSocketFactory;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
public class HttpClientFactory
{
private PoolingClientConnectionManager cm;
private Scheme http;
private Scheme https;
private int maxConnectionsPerRoute = 100;
private int maxConnectionsOverall = 100;
private static HttpClient httpclient = null;
// Eager initialization to improve response time when httpclient is first used
private static final HttpClientFactory INSTANCE = new HttpClientFactory();
private HttpClientFactory()
{
// Prepare the connection configurations (http and https capabilities, pool manager, maxconnections, etc.)
SchemeRegistry schemeRegistry = new SchemeRegistry();
https = new Scheme("https", 443, SSLSocketFactory.getSocketFactory());
schemeRegistry.register(https);
http = new Scheme("http", 80, PlainSocketFactory.getSocketFactory());
schemeRegistry.register(http);
cm = new PoolingClientConnectionManager(schemeRegistry);
cm.setDefaultMaxPerRoute(maxConnectionsPerRoute); // Override PoolingClientConnectionManager default of 2 concurrent connections per Route
cm.setMaxTotal(maxConnectionsOverall); // Override PoolingClientConnectionManager default of 20 connections total
httpclient = new DefaultHttpClient(cm);
}
// Allows dependency injection, especially for EasyMock
void setPoolingClientConnectionManager( PoolingClientConnectionManager cm )
{
this.cm = cm;
}
public static HttpClientFactory getInstance()
{
return INSTANCE;
}
public static HttpClient getStaticHttpClient()
{
return httpclient;
}
public int getMaxConnectionsPerRoute()
{
return cm.getDefaultMaxPerRoute();
}
public int getMaxConnectionsOverall()
{
return cm.getMaxTotal();
}
// Ensure modifications to the factory's connection pool configuration are thread safe
public synchronized void setMaxConnectionsPerRoute(int maxConnectionsPerRoute) throws IllegalArgumentException
{
if (maxConnectionsPerRoute < 1)
{
throw new IllegalArgumentException("ERROR: maxConnectionsPerRoute must be larger than 0");
}
this.maxConnectionsPerRoute = maxConnectionsPerRoute;
cm.setDefaultMaxPerRoute(maxConnectionsPerRoute);
httpclient = new DefaultHttpClient(cm);
}
// Ensure modifications to the factory's connection pool configuration are thread safe
public synchronized void setMaxConnectionsOverall(int maxConnectionsOverall) throws IllegalArgumentException
{
if (maxConnectionsOverall < 1)
{
throw new IllegalArgumentException("ERROR: maxConnectionsOverall must be larger than 0");
}
this.maxConnectionsOverall = maxConnectionsOverall;
cm.setMaxTotal(maxConnectionsOverall);
httpclient = new DefaultHttpClient(cm);
}
} // end class