Java tutorial
/******************************************************************************* * Copyright (c) 2009 IBM Corporation and others. * All rights reserved. This program and the accompanying materials * are made available under the terms of the Eclipse Public License v1.0 * which accompanies this distribution, and is available at * http://www.eclipse.org/legal/epl-v10.html * * Contributors: * IBM Corporation - initial API and implementation * Thomas Joiner - HttpClient 4 implementation *******************************************************************************/ package org.eclipse.ecf.internal.provider.filetransfer.httpclient4; import java.io.IOException; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketException; import java.net.UnknownHostException; import javax.net.ssl.SSLSocket; import javax.net.ssl.SSLSocketFactory; import org.apache.http.conn.ConnectTimeoutException; import org.apache.http.conn.scheme.LayeredSchemeSocketFactory; import org.apache.http.params.HttpConnectionParams; import org.apache.http.params.HttpParams; import org.eclipse.ecf.core.util.Trace; import org.eclipse.ecf.filetransfer.events.socket.ISocketEvent; import org.eclipse.ecf.filetransfer.events.socket.ISocketEventSource; import org.eclipse.ecf.filetransfer.events.socket.ISocketListener; import org.eclipse.ecf.provider.filetransfer.events.socket.SocketClosedEvent; import org.eclipse.ecf.provider.filetransfer.events.socket.SocketConnectedEvent; import org.eclipse.ecf.provider.filetransfer.events.socket.SocketCreatedEvent; public final class ECFHttpClientSecureProtocolSocketFactory implements LayeredSchemeSocketFactory { private final SSLSocketFactory sslSocketFactory; private final ISocketEventSource source; private final ISocketListener socketConnectListener; public ECFHttpClientSecureProtocolSocketFactory(final SSLSocketFactory sslSocketFactory, ISocketEventSource source, ISocketListener socketConnectListener) { this.sslSocketFactory = sslSocketFactory; this.source = source; this.socketConnectListener = socketConnectListener; } public Socket createSocket(final HttpParams params) { Trace.entering(Activator.PLUGIN_ID, DebugOptions.METHODS_ENTERING, ECFHttpClientSecureProtocolSocketFactory.class, "createSocket"); //$NON-NLS-1$ Socket socket = new Socket(); fireEvent(socketConnectListener, new SocketCreatedEvent(source, socket)); Trace.exiting(Activator.PLUGIN_ID, DebugOptions.METHODS_EXITING, ECFHttpClientSecureProtocolSocketFactory.class, "socketCreated " + socket); //$NON-NLS-1$ return socket; } public Socket connectSocket(final Socket socket, final InetSocketAddress remoteAddress, final InetSocketAddress localAddress, final HttpParams params) throws IOException, UnknownHostException, ConnectTimeoutException { if (remoteAddress == null) { throw new IllegalArgumentException("Remote address must not be null"); //$NON-NLS-1$ } if (params == null) { throw new IllegalArgumentException("HTTP parameters must not be null"); //$NON-NLS-1$ } if (socket == null) { SSLSocket sslSocket = (SSLSocket) this.sslSocketFactory.createSocket(); performConnection(sslSocket, remoteAddress, localAddress, params); return wrapSocket(sslSocket); } else if (socket instanceof SSLSocket) { performConnection(socket, remoteAddress, localAddress, params); return wrapSocket(socket); } // If we were given a unconnected socket, we need to connect it first if (!socket.isConnected()) { performConnection(socket, remoteAddress, localAddress, params); } Socket layeredSocket = this.sslSocketFactory.createSocket(socket, remoteAddress.getHostName(), remoteAddress.getPort(), true); return wrapSocket(layeredSocket); } private void performConnection(final Socket socket, final InetSocketAddress remoteAddress, final InetSocketAddress localAddress, final HttpParams params) throws SocketException, IOException { try { socket.setReuseAddress(HttpConnectionParams.getSoReuseaddr(params)); socket.bind(localAddress); int connectionTimeout = HttpConnectionParams.getConnectionTimeout(params); int socketTimeout = HttpConnectionParams.getSoTimeout(params); socket.connect(remoteAddress, connectionTimeout); socket.setSoTimeout(socketTimeout); } catch (SocketException e) { Trace.catching(Activator.PLUGIN_ID, DebugOptions.EXCEPTIONS_CATCHING, ECFHttpClientSecureProtocolSocketFactory.class, "performConnection", e); //$NON-NLS-1$ fireEvent(this.socketConnectListener, new SocketClosedEvent(source, socket, socket)); Trace.throwing(Activator.PLUGIN_ID, DebugOptions.EXCEPTIONS_THROWING, ECFHttpClientSecureProtocolSocketFactory.class, "performConnection", e); //$NON-NLS-1$ throw e; } catch (IOException e) { Trace.catching(Activator.PLUGIN_ID, DebugOptions.EXCEPTIONS_CATCHING, ECFHttpClientSecureProtocolSocketFactory.class, "performConnection", e); //$NON-NLS-1$ fireEvent(this.socketConnectListener, new SocketClosedEvent(source, socket, socket)); Trace.throwing(Activator.PLUGIN_ID, DebugOptions.EXCEPTIONS_THROWING, ECFHttpClientSecureProtocolSocketFactory.class, "performConnection", e); //$NON-NLS-1$ throw e; } } public boolean isSecure(final Socket sock) throws IllegalArgumentException { if (sock == null) { throw new IllegalArgumentException("Socket must not be null"); //$NON-NLS-1$ } if (sock instanceof CloseMonitoringSocket) { return ((CloseMonitoringSocket) sock).isSecure(); } if (!(sock instanceof SSLSocket)) { throw new IllegalArgumentException("Socket not created by this factory"); //$NON-NLS-1$ } if (sock.isClosed()) { throw new IllegalArgumentException("Socket is closed"); //$NON-NLS-1$ } return true; } public Socket createLayeredSocket(final Socket socket, final String host, final int port, final boolean autoClose) throws IOException { Trace.entering(Activator.PLUGIN_ID, DebugOptions.METHODS_ENTERING, ECFHttpClientSecureProtocolSocketFactory.class, "createLayeredSocket " + host + ":" + port + ",socket=" + socket); //$NON-NLS-1$ //$NON-NLS-2$ //$NON-NLS-3$ SSLSocket sslSocket = null; try { Trace.trace(Activator.PLUGIN_ID, "connectingLayeredSocket(original=" + socket + ",dest=" + host + ":" + port + ")"); //$NON-NLS-1$//$NON-NLS-2$//$NON-NLS-3$//$NON-NLS-4$ sslSocket = (SSLSocket) this.sslSocketFactory.createSocket(socket, host, port, autoClose); Trace.trace(Activator.PLUGIN_ID, "connected"); //$NON-NLS-1$ } catch (IOException e) { Trace.catching(Activator.PLUGIN_ID, DebugOptions.EXCEPTIONS_CATCHING, ECFHttpClientSecureProtocolSocketFactory.class, "createLayeredSocket", e); //$NON-NLS-1$ fireEvent(this.socketConnectListener, new SocketClosedEvent(source, sslSocket, sslSocket)); Trace.throwing(Activator.PLUGIN_ID, DebugOptions.EXCEPTIONS_THROWING, ECFHttpClientSecureProtocolSocketFactory.class, "createSocket", e); //$NON-NLS-1$ throw e; } return wrapSocket(sslSocket); } private Socket wrapSocket(Socket toWrap) { CloseMonitoringSocket wrappedSocket = new CloseMonitoringSocket(toWrap, socketConnectListener, source); SocketConnectedEvent connectedEvent = new SocketConnectedEvent(source, toWrap, wrappedSocket); fireEvent(socketConnectListener, connectedEvent); // Change the wrapped socket if one of the receivers of the SocketConnectedEvent changed it Socket connectedEventSocket = connectedEvent.getSocket(); if (connectedEventSocket != wrappedSocket) { wrappedSocket.setWrappedSocket(connectedEventSocket); return connectedEventSocket; } return wrappedSocket; } static void fireEvent(final ISocketListener spyListener, ISocketEvent event) { if (spyListener != null) { spyListener.handleSocketEvent(event); } event.getSource().fireEvent(event); } public boolean equals(Object obj) { return ((obj != null) && obj.getClass().equals(ECFHttpClientSecureProtocolSocketFactory.class)); } public int hashCode() { return ECFHttpClientSecureProtocolSocketFactory.class.hashCode(); } }