001: /* HeritixSSLProtocolSocketFactory
002: *
003: * Created on Feb 18, 2004
004: *
005: * Copyright (C) 2004 Internet Archive.
006: *
007: * This file is part of the Heritrix web crawler (crawler.archive.org).
008: *
009: * Heritrix is free software; you can redistribute it and/or modify
010: * it under the terms of the GNU Lesser Public License as published by
011: * the Free Software Foundation; either version 2.1 of the License, or
012: * any later version.
013: *
014: * Heritrix is distributed in the hope that it will be useful,
015: * but WITHOUT ANY WARRANTY; without even the implied warranty of
016: * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
017: * GNU Lesser Public License for more details.
018: *
019: * You should have received a copy of the GNU Lesser Public License
020: * along with Heritrix; if not, write to the Free Software
021: * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
022: */
023: package org.archive.crawler.fetcher;
024:
025: import java.io.IOException;
026: import java.net.InetAddress;
027: import java.net.InetSocketAddress;
028: import java.net.Socket;
029: import java.net.SocketTimeoutException;
030: import java.net.UnknownHostException;
031: import java.security.KeyManagementException;
032: import java.security.KeyStoreException;
033: import java.security.NoSuchAlgorithmException;
034:
035: import javax.net.ssl.SSLContext;
036: import javax.net.ssl.SSLSocketFactory;
037: import javax.net.ssl.TrustManager;
038:
039: import org.apache.commons.httpclient.params.HttpConnectionParams;
040: import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
041: import org.archive.crawler.datamodel.ServerCache;
042: import org.archive.httpclient.ConfigurableX509TrustManager;
043:
044: /**
045: * Implementation of the commons-httpclient SSLProtocolSocketFactory so we
046: * can return SSLSockets whose trust manager is
047: * {@link org.archive.httpclient.ConfigurableX509TrustManager}.
048: *
049: * We also go to the heritrix cache to get IPs to use making connection.
050: * To this, we have dependency on {@link HeritrixProtocolSocketFactory};
051: * its assumed this class and it are used together.
052: * See {@link HeritrixProtocolSocketFactory#getHostAddress(ServerCache,String)}.
053: *
054: * @author stack
055: * @version $Id: HeritrixSSLProtocolSocketFactory.java 4553 2006-08-29 22:47:03Z stack-sf $
056: * @see org.archive.httpclient.ConfigurableX509TrustManager
057: */
058: public class HeritrixSSLProtocolSocketFactory implements
059: SecureProtocolSocketFactory {
060: /***
061: * Socket factory with default trust manager installed.
062: */
063: private SSLSocketFactory sslDefaultFactory = null;
064:
065: /**
066: * Shutdown constructor.
067: * @throws KeyManagementException
068: * @throws KeyStoreException
069: * @throws NoSuchAlgorithmException
070: */
071: public HeritrixSSLProtocolSocketFactory()
072: throws KeyManagementException, KeyStoreException,
073: NoSuchAlgorithmException {
074: // Get an SSL context and initialize it.
075: SSLContext context = SSLContext.getInstance("SSL");
076:
077: // I tried to get the default KeyManagers but doesn't work unless you
078: // point at a physical keystore. Passing null seems to do the right
079: // thing so we'll go w/ that.
080: context.init(null,
081: new TrustManager[] { new ConfigurableX509TrustManager(
082: ConfigurableX509TrustManager.DEFAULT) }, null);
083: this .sslDefaultFactory = context.getSocketFactory();
084: }
085:
086: public Socket createSocket(String host, int port,
087: InetAddress clientHost, int clientPort) throws IOException,
088: UnknownHostException {
089: return this .sslDefaultFactory.createSocket(host, port,
090: clientHost, clientPort);
091: }
092:
093: public Socket createSocket(String host, int port)
094: throws IOException, UnknownHostException {
095: return this .sslDefaultFactory.createSocket(host, port);
096: }
097:
098: public synchronized Socket createSocket(String host, int port,
099: InetAddress localAddress, int localPort,
100: HttpConnectionParams params) throws IOException,
101: UnknownHostException {
102: // Below code is from the DefaultSSLProtocolSocketFactory#createSocket
103: // method only it has workarounds to deal with pre-1.4 JVMs. I've
104: // cut these out.
105: if (params == null) {
106: throw new IllegalArgumentException(
107: "Parameters may not be null");
108: }
109: Socket socket = null;
110: int timeout = params.getConnectionTimeout();
111: if (timeout == 0) {
112: socket = createSocket(host, port, localAddress, localPort);
113: } else {
114: SSLSocketFactory factory = (SSLSocketFactory) params
115: .getParameter(FetchHTTP.SSL_FACTORY_KEY);
116: SSLSocketFactory f = (factory != null) ? factory
117: : this .sslDefaultFactory;
118: socket = f.createSocket();
119: ServerCache cache = (ServerCache) params
120: .getParameter(FetchHTTP.SERVER_CACHE_KEY);
121: InetAddress hostAddress = (cache != null) ? HeritrixProtocolSocketFactory
122: .getHostAddress(cache, host)
123: : null;
124: InetSocketAddress address = (hostAddress != null) ? new InetSocketAddress(
125: hostAddress, port)
126: : new InetSocketAddress(host, port);
127: socket.bind(new InetSocketAddress(localAddress, localPort));
128: try {
129: socket.connect(address, timeout);
130: } catch (SocketTimeoutException e) {
131: // Add timeout info. to the exception.
132: throw new SocketTimeoutException(e.getMessage()
133: + ": timeout set at "
134: + Integer.toString(timeout) + "ms.");
135: }
136: assert socket.isConnected() : "Socket not connected "
137: + host;
138: }
139: return socket;
140: }
141:
142: public Socket createSocket(Socket socket, String host, int port,
143: boolean autoClose) throws IOException, UnknownHostException {
144: return this .sslDefaultFactory.createSocket(socket, host, port,
145: autoClose);
146: }
147:
148: public boolean equals(Object obj) {
149: return ((obj != null) && obj.getClass().equals(
150: HeritrixSSLProtocolSocketFactory.class));
151: }
152:
153: public int hashCode() {
154: return HeritrixSSLProtocolSocketFactory.class.hashCode();
155: }
156: }
|