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 }