Configuration API changes: deprecated SchemeSocketFactory and SchemeLayeredSocketFactory in favor of ConnectionSocketFactory and LayeredConnectionSocketFactory interfaces (new API no longer relies on HttpParams)

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1414674 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2012-11-28 13:35:46 +00:00
parent 697556b9b0
commit 4dc5821acb
9 changed files with 400 additions and 109 deletions

View File

@ -28,7 +28,9 @@
package org.apache.http.conn;
import java.io.InterruptedIOException;
import java.net.InetSocketAddress;
import org.apache.http.HttpHost;
import org.apache.http.annotation.Immutable;
/**
@ -59,4 +61,18 @@ public class ConnectTimeoutException extends InterruptedIOException {
super(message);
}
/**
* Creates a ConnectTimeoutException with the specified detail message.
*
* @param message The exception detail message
*
* @since 4.3
*/
public ConnectTimeoutException(final HttpHost host, final InetSocketAddress remoteAddress) {
super("Connect to " +
(host != null ? host.toHostString() : " remote host") +
(remoteAddress != null ? " (" + remoteAddress.getAddress() + ")" : "")
+ " timed out");
}
}

View File

@ -35,8 +35,11 @@ import org.apache.http.HttpHost;
* Extended {@link InetSocketAddress} implementation that also provides access to the original
* {@link HttpHost} used to resolve the address.
*
* @since 4.2
* @since 4.2 no longer used.
*
* @deprecated (4.3)
*/
@Deprecated
public class HttpInetSocketAddress extends InetSocketAddress {
private static final long serialVersionUID = -6650701828361907957L;

View File

@ -43,18 +43,13 @@ import org.apache.http.params.HttpParams;
/**
* The default class for creating plain (unencrypted) sockets.
* <p>
* The following parameters can be used to customize the behavior of this
* class:
* <ul>
* <li>{@link org.apache.http.params.CoreConnectionPNames#CONNECTION_TIMEOUT}</li>
* <li>{@link org.apache.http.params.CoreConnectionPNames#SO_REUSEADDR}</li>
* </ul>
*
* @since 4.0
*
* @deprecated (4.3) use {@link org.apache.http.conn.socket.PlainSocketFactory}
*/
@SuppressWarnings("deprecation")
@Immutable
@Deprecated
public class PlainSocketFactory implements SocketFactory, SchemeSocketFactory {
private final HostNameResolver nameResolver;

View File

@ -37,7 +37,10 @@ import org.apache.http.params.HttpParams;
* Extended {@link SchemeSocketFactory} interface for layered sockets such as SSL/TLS.
*
* @since 4.2
*
* @deprecated (4.3) use {@link LayeredConnectionSocketFactory}
*/
@Deprecated
public interface SchemeLayeredSocketFactory extends SchemeSocketFactory {
/**

View File

@ -35,6 +35,7 @@ import java.net.UnknownHostException;
import org.apache.http.HttpHost;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.HttpInetSocketAddress;
import org.apache.http.conn.socket.ConnectionSocketFactory;
import org.apache.http.params.HttpParams;
/**
@ -42,7 +43,10 @@ import org.apache.http.params.HttpParams;
* for establishing a socket connection.
*
* @since 4.1
*
* @deprecated (4.3) use {@link ConnectionSocketFactory}
*/
@Deprecated
public interface SchemeSocketFactory {
/**

View File

@ -0,0 +1,87 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.conn.socket;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import org.apache.http.HttpHost;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.protocol.HttpContext;
/**
* A factory for creating and connecting sockets.
*
* @since 4.3
*/
public interface ConnectionSocketFactory {
/**
* Creates new, unconnected socket. The socket should subsequently be passed to
* {@link #connectSocket(Socket, SocketConfig, HttpHost, InetSocketAddress, InetSocketAddress,
* HttpContext))}.
*
* @return a new socket
*
* @throws IOException if an I/O error occurs while creating the socket
*/
Socket createSocket(HttpContext context) throws IOException;
/**
* Connects a socket to the target host with the given resolved remote address.
*
* @param connectTimeout connect timeout.
* @param sock the socket to connect, as obtained from {@link #createSocket(HttpContext)}.
* <code>null</code> indicates that a new socket should be created and connected.
* @param config Socket configuration. If <code>null</cpde> {@link SocketConfig#DEFAULT}
* will be used.
* @param host target host as specified by the caller (end user).
* @param remoteAddress the resolved remote address to connect to.
* @param localAddress the local address to bind the socket to, or <code>null</code> for any.
* @param context the actual HTTP context.
*
* @return the connected socket. The returned object may be different
* from the <code>sock</code> argument if this factory supports
* a layered protocol.
*
* @throws IOException if an I/O error occurs
* @throws ConnectTimeoutException if the socket cannot be connected
* within the time limit defined in the <code>params</code>
*/
Socket connectSocket(
int connectTimeout,
Socket sock,
SocketConfig config,
HttpHost host,
InetSocketAddress remoteAddress,
InetSocketAddress localAddress,
HttpContext context) throws IOException, ConnectTimeoutException;
}

View File

@ -0,0 +1,63 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.conn.socket;
import java.io.IOException;
import java.net.Socket;
import java.net.UnknownHostException;
import org.apache.http.protocol.HttpContext;
/**
* Extended {@link ConnectionSocketFactory} interface for layered sockets such as SSL/TLS.
*
* @since 4.3
*/
public interface LayeredConnectionSocketFactory extends ConnectionSocketFactory {
/**
* Returns a socket connected to the given host that is layered over an
* existing socket. Used primarily for creating secure sockets through
* proxies.
*
* @param socket the existing socket
* @param target the name of the target host.
* @param port the port to connect to on the target host.
* @param context the actual HTTP context.
*
* @return Socket a new socket
*
* @throws IOException if an I/O error occurs while creating the socket
*/
Socket createLayeredSocket(
Socket socket,
String target,
int port,
HttpContext context) throws IOException, UnknownHostException;
}

View File

@ -0,0 +1,91 @@
/*
* ====================================================================
* 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.
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the Apache Software Foundation. For more
* information on the Apache Software Foundation, please see
* <http://www.apache.org/>.
*
*/
package org.apache.http.conn.socket;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import org.apache.http.HttpHost;
import org.apache.http.annotation.Immutable;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.protocol.HttpContext;
/**
* The default class for creating plain (unencrypted) sockets.
*
* @since 4.3
*/
@Immutable
public class PlainSocketFactory implements ConnectionSocketFactory {
public static final PlainSocketFactory INSTANCE = new PlainSocketFactory();
public static PlainSocketFactory getSocketFactory() {
return INSTANCE;
}
public PlainSocketFactory() {
super();
}
public Socket createSocket(final HttpContext context) throws IOException {
return new Socket();
}
public Socket connectSocket(
final int connectTimeout,
final Socket socket,
final SocketConfig config,
final HttpHost host,
final InetSocketAddress remoteAddress,
final InetSocketAddress localAddress,
final HttpContext context) throws IOException, ConnectTimeoutException {
Socket sock = socket != null ? socket : createSocket(context);
SocketConfig sconf = config != null ? config : SocketConfig.DEFAULT;
if (localAddress != null) {
sock.setReuseAddress(sconf.isSoReuseAddress());
sock.bind(localAddress);
}
try {
sock.setSoTimeout(sconf.getSoTimeout());
sock.connect(remoteAddress, connectTimeout);
} catch (SocketTimeoutException ex) {
throw new ConnectTimeoutException(host, remoteAddress);
}
sock.setTcpNoDelay(sconf.isTcpNoDelay());
int linger = sconf.getSoLinger();
if (linger >= 0) {
sock.setSoLinger(linger > 0, linger);
}
return sock;
}
}

View File

@ -30,14 +30,19 @@ package org.apache.http.conn.ssl;
import org.apache.http.HttpHost;
import org.apache.http.annotation.ThreadSafe;
import org.apache.http.config.SocketConfig;
import org.apache.http.conn.ConnectTimeoutException;
import org.apache.http.conn.HttpInetSocketAddress;
import org.apache.http.conn.scheme.HostNameResolver;
import org.apache.http.conn.scheme.LayeredSchemeSocketFactory;
import org.apache.http.conn.scheme.LayeredSocketFactory;
import org.apache.http.conn.scheme.SchemeLayeredSocketFactory;
import org.apache.http.conn.socket.LayeredConnectionSocketFactory;
import org.apache.http.conn.socket.PlainSocketFactory;
import org.apache.http.params.HttpConnectionParams;
import org.apache.http.params.HttpParamConfig;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
import javax.net.ssl.KeyManager;
import javax.net.ssl.KeyManagerFactory;
@ -53,7 +58,6 @@ import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.Socket;
import java.net.SocketTimeoutException;
import java.net.UnknownHostException;
import java.security.KeyManagementException;
import java.security.KeyStore;
@ -84,14 +88,6 @@ import java.security.cert.CertificateException;
* {@link TrustStrategy}. This interface is primarily intended for allowing self-signed
* certificates to be accepted as trusted without having to add them to the trust-store file.
* <p>
* The following parameters can be used to customize the behavior of this
* class:
* <ul>
* <li>{@link org.apache.http.params.CoreConnectionPNames#CONNECTION_TIMEOUT}</li>
* <li>{@link org.apache.http.params.CoreConnectionPNames#SO_TIMEOUT}</li>
* <li>{@link org.apache.http.params.CoreConnectionPNames#SO_REUSEADDR}</li>
* </ul>
* <p>
* SSLSocketFactory will enable client authentication when supplied with
* a {@link KeyStore key-store} file containing a private key/public certificate
* pair. The client secure socket will use the private key to authenticate
@ -147,7 +143,7 @@ import java.security.cert.CertificateException;
*/
@SuppressWarnings("deprecation")
@ThreadSafe
public class SSLSocketFactory implements SchemeLayeredSocketFactory,
public class SSLSocketFactory implements LayeredConnectionSocketFactory, SchemeLayeredSocketFactory,
LayeredSchemeSocketFactory, LayeredSocketFactory {
public static final String TLS = "TLS";
@ -242,7 +238,7 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory,
sslcontext.init(keymanagers, trustmanagers, random);
return sslcontext;
}
private static SSLContext createSystemSSLContext(
String algorithm,
final SecureRandom random) throws IOException, NoSuchAlgorithmException, NoSuchProviderException,
@ -370,7 +366,8 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory,
}
/**
* @deprecated Use {@link #SSLSocketFactory(String, KeyStore, String, KeyStore, SecureRandom, X509HostnameVerifier)}
* @deprecated (4.1) Use {@link #SSLSocketFactory(String, KeyStore, String, KeyStore,
* SecureRandom, X509HostnameVerifier)}
*/
@Deprecated
public SSLSocketFactory(
@ -464,7 +461,7 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory,
}
/**
* @deprecated Use {@link #SSLSocketFactory(SSLContext)}
* @deprecated (4.1) Use {@link #SSLSocketFactory(SSLContext)}
*/
@Deprecated
public SSLSocketFactory(
@ -493,7 +490,7 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory,
* @since 4.2
*/
public SSLSocketFactory(
final javax.net.ssl.SSLSocketFactory socketfactory,
final javax.net.ssl.SSLSocketFactory socketfactory,
final X509HostnameVerifier hostnameVerifier) {
if (socketfactory == null) {
throw new IllegalArgumentException("SSL socket factory may not be null");
@ -507,23 +504,29 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory,
* @param params Optional parameters. Parameters passed to this method will have no effect.
* This method will create a unconnected instance of {@link Socket} class.
* @since 4.1
*
* @deprecated (4.3) use {@link #createSocket(HttpContext)}
*/
@Deprecated
public Socket createSocket(final HttpParams params) throws IOException {
SSLSocket sock = (SSLSocket) this.socketfactory.createSocket();
prepareSocket(sock);
return sock;
return createSocket((HttpContext) null);
}
/**
* @deprecated (4.1) use {@link #createSocket(HttpParams)}
*/
@Deprecated
public Socket createSocket() throws IOException {
SSLSocket sock = (SSLSocket) this.socketfactory.createSocket();
prepareSocket(sock);
return sock;
return createSocket((HttpContext) null);
}
/**
* @since 4.1
*
* @deprecated (4.3) use {@link #connectSocket(Socket, SocketConfig, HttpHost,
* InetSocketAddress, InetSocketAddress, HttpContext)}
*/
@Deprecated
public Socket connectSocket(
final Socket socket,
final InetSocketAddress remoteAddress,
@ -535,52 +538,17 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory,
if (params == null) {
throw new IllegalArgumentException("HTTP parameters may not be null");
}
Socket sock = socket != null ? socket : this.socketfactory.createSocket();
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) {
throw new ConnectTimeoutException("Connect to " + remoteAddress + " timed out");
}
String hostname;
HttpHost host;
if (remoteAddress instanceof HttpInetSocketAddress) {
hostname = ((HttpInetSocketAddress) remoteAddress).getHttpHost().getHostName();
host = ((HttpInetSocketAddress) remoteAddress).getHttpHost();
} else {
hostname = remoteAddress.getHostName();
host = new HttpHost(remoteAddress.getHostName(), remoteAddress.getPort(), "https");
}
SSLSocket sslsock;
// Setup SSL layering if necessary
if (sock instanceof SSLSocket) {
sslsock = (SSLSocket) sock;
} else {
int port = remoteAddress.getPort();
sslsock = (SSLSocket) this.socketfactory.createSocket(sock, hostname, port, true);
prepareSocket(sslsock);
}
if (this.hostnameVerifier != null) {
try {
this.hostnameVerifier.verify(hostname, sslsock);
// verifyHostName() didn't blowup - good!
} catch (IOException iox) {
// close the socket before re-throwing the exception
try { sslsock.close(); } catch (Exception x) { /*ignore*/ }
throw iox;
}
}
return sslsock;
int connectTimeout = HttpConnectionParams.getConnectionTimeout(params);
SocketConfig config = HttpParamConfig.getSocketConfig(params);
return connectSocket(connectTimeout, socket, config, host, remoteAddress, localAddress, null);
}
/**
* Checks whether a socket connection is secure.
* This factory creates TLS/SSL socket connections
@ -594,7 +562,10 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory,
* @return <code>true</code>
*
* @throws IllegalArgumentException if the argument is invalid
*
* @deprecated (4.3) no longer used.
*/
@Deprecated
public boolean isSecure(final Socket sock) throws IllegalArgumentException {
if (sock == null) {
throw new IllegalArgumentException("Socket may not be null");
@ -612,48 +583,33 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory,
/**
* @since 4.2
*
* @deprecated (4.3) use {@link #createLayeredSocket(Socket, String, int, HttpContext)}
*/
@Deprecated
public Socket createLayeredSocket(
final Socket socket,
final String host,
final int port,
final HttpParams params) throws IOException, UnknownHostException {
SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(
socket,
host,
port,
true);
prepareSocket(sslSocket);
if (this.hostnameVerifier != null) {
this.hostnameVerifier.verify(host, sslSocket);
}
// verifyHostName() didn't blowup - good!
return sslSocket;
return createLayeredSocket(socket, host, port, (HttpContext) null);
}
/**
* @deprecated use {@link #createLayeredSocket(Socket, String, int, HttpParams)}
* @deprecated (4.1) use {@link #createLayeredSocket(Socket, String, int, HttpParams)}
*/
@Deprecated
public Socket createLayeredSocket(
public Socket createLayeredSocket(
final Socket socket,
final String host,
final int port,
final boolean autoClose) throws IOException, UnknownHostException {
SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(
socket,
host,
port,
autoClose
);
prepareSocket(sslSocket);
if (this.hostnameVerifier != null) {
this.hostnameVerifier.verify(host, sslSocket);
}
// verifyHostName() didn't blowup - good!
return sslSocket;
return createLayeredSocket(socket, host, port, (HttpContext) null);
}
/**
* @deprecated (4.1) use constructor.
*/
@Deprecated
public void setHostnameVerifier(X509HostnameVerifier hostnameVerifier) {
if ( hostnameVerifier == null ) {
@ -667,34 +623,36 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory,
}
/**
* @deprecated Use {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress, HttpParams)}
* @deprecated (4.1) Use {@link #connectSocket(Socket, InetSocketAddress, InetSocketAddress,
* HttpParams)}
*/
@Deprecated
public Socket connectSocket(
final Socket socket,
final String host, int port,
final InetAddress localAddress, int localPort,
final InetAddress local, int localPort,
final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException {
InetSocketAddress local = null;
if (localAddress != null || localPort > 0) {
InetAddress remote;
if (this.nameResolver != null) {
remote = this.nameResolver.resolve(host);
} else {
remote = InetAddress.getByName(host);
}
InetSocketAddress localAddress = null;
if (local != null || localPort > 0) {
// we need to bind explicitly
if (localPort < 0) {
localPort = 0; // indicates "any"
}
local = new InetSocketAddress(localAddress, localPort);
localAddress = new InetSocketAddress(local, localPort);
}
InetAddress remoteAddress;
if (this.nameResolver != null) {
remoteAddress = this.nameResolver.resolve(host);
} else {
remoteAddress = InetAddress.getByName(host);
}
InetSocketAddress remote = new HttpInetSocketAddress(new HttpHost(host, port), remoteAddress, port);
return connectSocket(socket, remote, local, params);
InetSocketAddress remoteAddress = new HttpInetSocketAddress(
new HttpHost(host, port), remote, port);
return connectSocket(socket, remoteAddress, localAddress, params);
}
/**
* @deprecated Use {@link #createLayeredSocket(Socket, String, int, boolean)}
* @deprecated (4.1) Use {@link #createLayeredSocket(Socket, String, int, boolean)}
*/
@Deprecated
public Socket createSocket(
@ -715,4 +673,75 @@ public class SSLSocketFactory implements SchemeLayeredSocketFactory,
*/
protected void prepareSocket(final SSLSocket socket) throws IOException {
}
/**
* {@inheritDoc}
*
* @since 4.3
*/
public Socket createSocket(final HttpContext context) throws IOException {
SSLSocket sock = (SSLSocket) this.socketfactory.createSocket();
prepareSocket(sock);
return sock;
}
/**
* {@inheritDoc}
*
* @since 4.3
*/
public Socket connectSocket(
final int connectTimeout,
final Socket socket,
final SocketConfig config,
final HttpHost host,
final InetSocketAddress remoteAddress,
final InetSocketAddress localAddress,
final HttpContext context) throws IOException, ConnectTimeoutException {
if (host == null) {
throw new IllegalArgumentException("HTTP host may not be null");
}
if (remoteAddress == null) {
throw new IllegalArgumentException("Remote address may not be null");
}
Socket sock = socket != null ? socket : createSocket(context);
PlainSocketFactory.INSTANCE.connectSocket(
connectTimeout, socket, config, host, remoteAddress, localAddress, context);
// Setup SSL layering if necessary
if (sock instanceof SSLSocket) {
verifyHostname((SSLSocket) sock, host.getHostName());
} else {
sock = createLayeredSocket(sock, host.getHostName(), remoteAddress.getPort(), context);
}
return sock;
}
public Socket createLayeredSocket(
final Socket socket,
final String target,
int port,
final HttpContext context) throws IOException, UnknownHostException {
SSLSocket sslSocket = (SSLSocket) this.socketfactory.createSocket(
socket,
target,
port,
true);
prepareSocket(sslSocket);
verifyHostname(sslSocket, target);
return sslSocket;
}
private void verifyHostname(final SSLSocket sslsock, final String hostname) throws IOException {
if (this.hostnameVerifier != null) {
try {
this.hostnameVerifier.verify(hostname, sslsock);
// verifyHostName() didn't blowup - good!
} catch (IOException iox) {
// close the socket before re-throwing the exception
try { sslsock.close(); } catch (Exception x) { /*ignore*/ }
throw iox;
}
}
}
}