View Javadoc

1   /* HeritixSSLProtocolSocketFactory
2    *
3    * Created on Feb 18, 2004
4    *
5    * Copyright (C) 2004 Internet Archive.
6    *
7    * This file is part of the Heritrix web crawler (crawler.archive.org).
8    *
9    * Heritrix is free software; you can redistribute it and/or modify
10   * it under the terms of the GNU Lesser Public License as published by
11   * the Free Software Foundation; either version 2.1 of the License, or
12   * any later version.
13   *
14   * Heritrix is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
17   * GNU Lesser Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser Public License
20   * along with Heritrix; if not, write to the Free Software
21   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
22   */
23  package org.archive.crawler.fetcher;
24  
25  import java.io.IOException;
26  import java.net.InetAddress;
27  import java.net.InetSocketAddress;
28  import java.net.Socket;
29  import java.net.SocketTimeoutException;
30  import java.net.UnknownHostException;
31  import java.security.KeyManagementException;
32  import java.security.KeyStoreException;
33  import java.security.NoSuchAlgorithmException;
34  
35  import javax.net.ssl.SSLContext;
36  import javax.net.ssl.SSLSocketFactory;
37  import javax.net.ssl.TrustManager;
38  
39  import org.apache.commons.httpclient.params.HttpConnectionParams;
40  import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
41  import org.archive.crawler.datamodel.ServerCache;
42  import org.archive.httpclient.ConfigurableX509TrustManager;
43  
44  
45  /***
46   * Implementation of the commons-httpclient SSLProtocolSocketFactory so we
47   * can return SSLSockets whose trust manager is
48   * {@link org.archive.httpclient.ConfigurableX509TrustManager}.
49   * 
50   * We also go to the heritrix cache to get IPs to use making connection.
51   * To this, we have dependency on {@link HeritrixProtocolSocketFactory};
52   * its assumed this class and it are used together.
53   * See {@link HeritrixProtocolSocketFactory#getHostAddress(ServerCache,String)}.
54   *
55   * @author stack
56   * @version $Id: HeritrixSSLProtocolSocketFactory.java 4553 2006-08-29 22:47:03Z stack-sf $
57   * @see org.archive.httpclient.ConfigurableX509TrustManager
58   */
59  public class HeritrixSSLProtocolSocketFactory
60  implements SecureProtocolSocketFactory {
61      /****
62       * Socket factory with default trust manager installed.
63       */
64      private SSLSocketFactory sslDefaultFactory = null;
65      
66      /***
67       * Shutdown constructor.
68       * @throws KeyManagementException
69       * @throws KeyStoreException
70       * @throws NoSuchAlgorithmException
71       */
72      public HeritrixSSLProtocolSocketFactory()
73      throws KeyManagementException, KeyStoreException, NoSuchAlgorithmException{
74          // Get an SSL context and initialize it.
75          SSLContext context = SSLContext.getInstance("SSL");
76  
77          // I tried to get the default KeyManagers but doesn't work unless you
78          // point at a physical keystore. Passing null seems to do the right
79          // thing so we'll go w/ that.
80          context.init(null, new TrustManager[] {
81              new ConfigurableX509TrustManager(
82                  ConfigurableX509TrustManager.DEFAULT)}, null);
83          this.sslDefaultFactory = context.getSocketFactory();
84      }
85  
86      public Socket createSocket(String host, int port, InetAddress clientHost,
87          int clientPort)
88      throws IOException, UnknownHostException {
89      	return this.sslDefaultFactory.createSocket(host, port,
90      	    clientHost, clientPort);
91      }
92  
93      public Socket createSocket(String host, int port)
94      throws IOException, UnknownHostException {
95          return this.sslDefaultFactory.createSocket(host, port);
96      }
97  
98      public synchronized Socket createSocket(String host, int port,
99      	InetAddress localAddress, int localPort, HttpConnectionParams params)
100     throws IOException, UnknownHostException {
101         // Below code is from the DefaultSSLProtocolSocketFactory#createSocket
102         // method only it has workarounds to deal with pre-1.4 JVMs.  I've
103         // cut these out.
104         if (params == null) {
105             throw new IllegalArgumentException("Parameters may not be null");
106         }
107         Socket socket = null;
108         int timeout = params.getConnectionTimeout();
109         if (timeout == 0) {
110             socket = createSocket(host, port, localAddress, localPort);
111         } else {
112         	SSLSocketFactory factory = (SSLSocketFactory)params.
113                 getParameter(FetchHTTP.SSL_FACTORY_KEY);
114         	SSLSocketFactory f = (factory != null)? factory: this.sslDefaultFactory;
115             socket = f.createSocket();
116             ServerCache cache = (ServerCache)params.
117                 getParameter(FetchHTTP.SERVER_CACHE_KEY);
118             InetAddress hostAddress = (cache !=  null)?
119                 HeritrixProtocolSocketFactory.getHostAddress(cache, host): null;
120             InetSocketAddress address = (hostAddress != null)?
121                     new InetSocketAddress(hostAddress, port):
122                     new InetSocketAddress(host, port);
123             socket.bind(new InetSocketAddress(localAddress, localPort));
124             try {
125                 socket.connect(address, timeout);
126             } catch (SocketTimeoutException e) {
127                 // Add timeout info. to the exception.
128                 throw new SocketTimeoutException(e.getMessage() +
129                     ": timeout set at " + Integer.toString(timeout) + "ms.");
130             }
131             assert socket.isConnected(): "Socket not connected " + host;
132         }
133         return socket;
134     }
135     
136 	public Socket createSocket(Socket socket, String host, int port,
137         boolean autoClose)
138     throws IOException, UnknownHostException {
139         return this.sslDefaultFactory.createSocket(socket, host,
140             port, autoClose);
141 	}
142     
143     public boolean equals(Object obj) {
144         return ((obj != null) && obj.getClass().
145             equals(HeritrixSSLProtocolSocketFactory.class));
146     }
147 
148     public int hashCode() {
149         return HeritrixSSLProtocolSocketFactory.class.hashCode();
150     }
151 }