blob: b9e2c9c5536d8df4a295d7e7fef7d2eace0d2cf8 [file] [log] [blame]
/*
* Licensed to the Apache Software Foundation (ASF) under one
* or more contributor license agreements. See the NOTICE file
* distributed with this work for additional information
* regarding copyright ownership. The ASF licenses this file
* to you 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 org.apache.chemistry.opencmis.client.bindings.spi.http;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import javax.net.ssl.HostnameVerifier;
import javax.net.ssl.SSLSocket;
import javax.net.ssl.SSLSocketFactory;
import org.apache.chemistry.opencmis.client.bindings.impl.CmisBindingsHelper;
import org.apache.chemistry.opencmis.client.bindings.spi.BindingSession;
import org.apache.chemistry.opencmis.commons.impl.UrlBuilder;
import org.apache.chemistry.opencmis.commons.spi.AuthenticationProvider;
import org.apache.http.client.params.ClientPNames;
import org.apache.http.client.params.CookiePolicy;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.HttpInetSocketAddress;
import org.apache.http.conn.scheme.PlainSocketFactory;
import org.apache.http.conn.scheme.Scheme;
import org.apache.http.conn.scheme.SchemeLayeredSocketFactory;
import org.apache.http.conn.scheme.SchemeRegistry;
import org.apache.http.conn.ssl.BrowserCompatHostnameVerifier;
import org.apache.http.conn.ssl.X509HostnameVerifier;
import org.apache.http.impl.client.DefaultHttpClient;
import org.apache.http.impl.conn.PoolingClientConnectionManager;
import org.apache.http.impl.conn.ProxySelectorRoutePlanner;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParams;
/**
* A {@link HttpInvoker} that uses The Apache HTTP client.
*/
public class ApacheClientHttpInvoker extends AbstractApacheClientHttpInvoker {
protected DefaultHttpClient createHttpClient(UrlBuilder url, BindingSession session) {
// set params
HttpParams params = createDefaultHttpParams(session);
params.setParameter(ClientPNames.COOKIE_POLICY, CookiePolicy.IGNORE_COOKIES);
// set up scheme registry and connection manager
SchemeRegistry registry = new SchemeRegistry();
registry.register(new Scheme("http", 80, PlainSocketFactory.getSocketFactory()));
registry.register(new Scheme("https", 443, getSSLSocketFactory(url, session)));
// set up connection manager
PoolingClientConnectionManager connManager = new PoolingClientConnectionManager(registry);
// set max connection a
String keepAliveStr = System.getProperty("http.keepAlive", "true");
if ("true".equalsIgnoreCase(keepAliveStr)) {
String maxConnStr = System.getProperty("http.maxConnections", "5");
int maxConn = 5;
try {
maxConn = Integer.parseInt(maxConnStr);
} catch (NumberFormatException nfe) {
// ignore
}
connManager.setDefaultMaxPerRoute(maxConn);
connManager.setMaxTotal(4 * maxConn);
}
// set up proxy
ProxySelectorRoutePlanner routePlanner = new ProxySelectorRoutePlanner(registry, null);
// set up client
DefaultHttpClient httpclient = new DefaultHttpClient(connManager, params);
httpclient.setRoutePlanner(routePlanner);
return httpclient;
}
/**
* Builds a SSL Socket Factory for the Apache HTTP Client.
*/
private SchemeLayeredSocketFactory getSSLSocketFactory(final UrlBuilder url, final BindingSession session) {
// get authentication provider
AuthenticationProvider authProvider = CmisBindingsHelper.getAuthenticationProvider(session);
// check SSL Socket Factory
final SSLSocketFactory sf = authProvider.getSSLSocketFactory();
if (sf == null) {
// no custom factory -> return default factory
return org.apache.http.conn.ssl.SSLSocketFactory.getSocketFactory();
}
// check hostame verifier and use default if not set
final HostnameVerifier hv = (authProvider.getHostnameVerifier() == null ? new BrowserCompatHostnameVerifier()
: authProvider.getHostnameVerifier());
if (hv instanceof X509HostnameVerifier) {
return new org.apache.http.conn.ssl.SSLSocketFactory(sf, (X509HostnameVerifier) hv);
}
// build new socket factory
return new SchemeLayeredSocketFactory() {
public boolean isSecure(Socket sock) {
return true;
}
public Socket createSocket(HttpParams params) throws IOException {
return sf.createSocket();
}
public Socket connectSocket(final Socket socket, final InetSocketAddress remoteAddress,
final InetSocketAddress localAddress, final HttpParams params) throws IOException {
Socket sock = (socket != null ? socket : createSocket(params));
if (localAddress != null) {
sock.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params));
sock.bind(localAddress);
}
int connTimeout = HttpConnectionParams.getConnectionTimeout(params);
int soTimeout = HttpConnectionParams.getSoTimeout(params);
try {
sock.setSoTimeout(soTimeout);
sock.connect(remoteAddress, connTimeout);
} catch (SocketTimeoutException ex) {
closeSocket(sock);
throw new ConnectTimeoutException("Connect to " + remoteAddress + " timed out!");
}
String host;
if (remoteAddress instanceof HttpInetSocketAddress) {
host = ((HttpInetSocketAddress) remoteAddress).getHttpHost().getHostName();
} else {
host = remoteAddress.getHostName();
}
SSLSocket sslSocket;
if (sock instanceof SSLSocket) {
sslSocket = (SSLSocket) sock;
} else {
int port = remoteAddress.getPort();
sslSocket = (SSLSocket) sf.createSocket(sock, host, port, true);
}
verify(hv, host, sslSocket);
return sslSocket;
}
public Socket createLayeredSocket(final Socket socket, final String host, final int port,
final HttpParams params) throws IOException {
SSLSocket sslSocket = (SSLSocket) sf.createSocket(socket, host, port, true);
verify(hv, host, sslSocket);
return sslSocket;
}
};
}
}