blob: b3d3c9339d234dfc713feeb6db1cabe45670a49a [file] [log] [blame]
/*
* Copyright 2009 Guenther Niess
*
* 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.kenai.jbosh;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
import org.apache.http.HttpHost;
import org.apache.http.HttpVersion;
import org.apache.http.client.HttpClient;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.conn.params.ConnManagerParams;
import org.apache.http.conn.params.ConnRoutePNames;
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.tsccm.ThreadSafeClientConnManager;
import org.apache.http.params.BasicHttpParams;
import org.apache.http.params.HttpParams;
import org.apache.http.params.HttpProtocolParams;
/**
* Implementation of the {@code HTTPSender} interface which uses the
* Apache HttpClient API to send messages to the connection manager.
*/
final class ApacheHTTPSender implements HTTPSender {
/**
* Lock used for internal synchronization.
*/
private final Lock lock = new ReentrantLock();
/**
* Session configuration.
*/
private BOSHClientConfig cfg;
/**
* HttpClient instance to use to communicate.
*/
private HttpClient httpClient;
///////////////////////////////////////////////////////////////////////////
// Constructors:
/**
* Prevent construction apart from our package.
*/
ApacheHTTPSender() {
// Load Apache HTTP client class
HttpClient.class.getName();
}
///////////////////////////////////////////////////////////////////////////
// HTTPSender interface methods:
/**
* {@inheritDoc}
*/
public void init(final BOSHClientConfig session) {
lock.lock();
try {
cfg = session;
httpClient = initHttpClient(session);
} finally {
lock.unlock();
}
}
/**
* {@inheritDoc}
*/
public void destroy() {
lock.lock();
try {
if (httpClient != null) {
httpClient.getConnectionManager().shutdown();
}
} finally {
cfg = null;
httpClient = null;
lock.unlock();
}
}
/**
* {@inheritDoc}
*/
public HTTPResponse send(
final CMSessionParams params,
final AbstractBody body) {
HttpClient mClient;
BOSHClientConfig mCfg;
lock.lock();
try {
if (httpClient == null) {
httpClient = initHttpClient(cfg);
}
mClient = httpClient;
mCfg = cfg;
} finally {
lock.unlock();
}
return new ApacheHTTPResponse(mClient, mCfg, params, body);
}
///////////////////////////////////////////////////////////////////////////
// Package-private methods:
private synchronized HttpClient initHttpClient(final BOSHClientConfig config) {
// Create and initialize HTTP parameters
HttpParams params = new BasicHttpParams();
ConnManagerParams.setMaxTotalConnections(params, 100);
HttpProtocolParams.setVersion(params, HttpVersion.HTTP_1_1);
HttpProtocolParams.setUseExpectContinue(params, false);
if (config != null &&
config.getProxyHost() != null &&
config.getProxyPort() != 0) {
HttpHost proxy = new HttpHost(
config.getProxyHost(),
config.getProxyPort());
params.setParameter(ConnRoutePNames.DEFAULT_PROXY, proxy);
}
// Create and initialize scheme registry
SchemeRegistry schemeRegistry = new SchemeRegistry();
schemeRegistry.register(
new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
SSLSocketFactory sslFactory = SSLSocketFactory.getSocketFactory();
sslFactory.setHostnameVerifier(SSLSocketFactory.ALLOW_ALL_HOSTNAME_VERIFIER);
schemeRegistry.register(
new Scheme("https", sslFactory, 443));
// Create an HttpClient with the ThreadSafeClientConnManager.
// This connection manager must be used if more than one thread will
// be using the HttpClient.
ClientConnectionManager cm = new ThreadSafeClientConnManager(params, schemeRegistry);
return new DefaultHttpClient(cm, params);
}
}