View Javadoc

    1   /*
    2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/ProxyClient.java,v 1.5 2004/12/20 11:39:04 olegk Exp $
    3    * $Revision: 480424 $
    4    * $Date: 2006-11-29 06:56:49 +0100 (Wed, 29 Nov 2006) $
    5    *
    6    * ====================================================================
    7    *
    8    *  Licensed to the Apache Software Foundation (ASF) under one or more
    9    *  contributor license agreements.  See the NOTICE file distributed with
    10   *  this work for additional information regarding copyright ownership.
    11   *  The ASF licenses this file to You under the Apache License, Version 2.0
    12   *  (the "License"); you may not use this file except in compliance with
    13   *  the License.  You may obtain a copy of the License at
    14   *
    15   *      http://www.apache.org/licenses/LICENSE-2.0
    16   *
    17   *  Unless required by applicable law or agreed to in writing, software
    18   *  distributed under the License is distributed on an "AS IS" BASIS,
    19   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
    20   *  See the License for the specific language governing permissions and
    21   *  limitations under the License.
    22   * ====================================================================
    23   *
    24   * This software consists of voluntary contributions made by many
    25   * individuals on behalf of the Apache Software Foundation.  For more
    26   * information on the Apache Software Foundation, please see
    27   * <http://www.apache.org/>.
    28   *
    29   */
    30
    31  package org.apache.commons.httpclient;
    32
    33  import java.io.IOException;
    34  import java.net.Socket;
    35
    36  import org.apache.commons.httpclient.params.HttpClientParams;
    37  import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
    38  import org.apache.commons.httpclient.params.HttpParams;
    39
    40  /**
    41   * A client that provides {@link java.net.Socket sockets} for communicating through HTTP proxies
    42   * via the HTTP CONNECT method.  This is primarily needed for non-HTTP protocols that wish to
    43   * communicate via an HTTP proxy.
    44   *
    45   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
    46   * @author Michael Becke
    47   *
    48   * @since 3.0
    49   *
    50   * @version $Revision: 480424 $
    51   */
    52  public class ProxyClient {
    53
    54      // ----------------------------------------------------- Instance Variables
    55
    56      /**
    57       * The {@link HttpState HTTP state} associated with this ProxyClient.
    58       */
    59      private HttpState state = new HttpState();
    60
    61      /**
    62       * The {@link HttpClientParams collection of parameters} associated with this ProxyClient.
    63       */
    64      private HttpClientParams params = null;
    65
    66      /**
    67       * The {@link HostConfiguration host configuration} associated with
    68       * the ProxyClient
    69       */
    70      private HostConfiguration hostConfiguration = new HostConfiguration();
    71
    72      /**
    73       * Creates an instance of ProxyClient using default {@link HttpClientParams parameter set}.
    74       *
    75       * @see HttpClientParams
    76       */
    77      public ProxyClient() {
    78          this(new HttpClientParams());
    79      }
    80
    81      /**
    82       * Creates an instance of ProxyClient using the given
    83       * {@link HttpClientParams parameter set}.
    84       *
    85       * @param params The {@link HttpClientParams parameters} to use.
    86       *
    87       * @see HttpClientParams
    88       */
    89      public ProxyClient(HttpClientParams params) {
    90          super();
    91          if (params == null) {
    92              throw new IllegalArgumentException("Params may not be null");
    93          }
    94          this.params = params;
    95      }
    96
    97      // ------------------------------------------------------------- Properties
    98
    99      /**
    100      * Returns {@link HttpState HTTP state} associated with the ProxyClient.
    101      *
    102      * @see #setState(HttpState)
    103      * @return the shared client state
    104      */
    105     public synchronized HttpState getState() {
    106         return state;
    107     }
    108
    109     /**
    110      * Assigns {@link HttpState HTTP state} for the ProxyClient.
    111      *
    112      * @see #getState()
    113      * @param state the new {@link HttpState HTTP state} for the client
    114      */
    115     public synchronized void setState(HttpState state) {
    116         this.state = state;
    117     }
    118
    119     /**
    120      * Returns the {@link HostConfiguration host configuration} associated with the
    121      * ProxyClient.
    122      *
    123      * @return {@link HostConfiguration host configuration}
    124      */
    125     public synchronized HostConfiguration getHostConfiguration() {
    126         return hostConfiguration;
    127     }
    128
    129     /**
    130      * Assigns the {@link HostConfiguration host configuration} to use with the
    131      * ProxyClient.
    132      *
    133      * @param hostConfiguration The {@link HostConfiguration host configuration} to set
    134      */
    135     public synchronized void setHostConfiguration(HostConfiguration hostConfiguration) {
    136         this.hostConfiguration = hostConfiguration;
    137     }
    138
    139     /**
    140      * Returns {@link HttpClientParams HTTP protocol parameters} associated with this ProxyClient.
    141      *
    142      * @see HttpClientParams
    143      */
    144     public synchronized HttpClientParams getParams() {
    145         return this.params;
    146     }
    147
    148     /**
    149      * Assigns {@link HttpClientParams HTTP protocol parameters} for this ProxyClient.
    150      *
    151      * @see HttpClientParams
    152      */
    153     public synchronized void setParams(final HttpClientParams params) {
    154         if (params == null) {
    155             throw new IllegalArgumentException("Parameters may not be null");
    156         }
    157         this.params = params;
    158     }
    159
    160     /**
    161      * Creates a socket that is connected, via the HTTP CONNECT method, to a proxy.
    162      *
    163      * <p>
    164      * Even though HTTP CONNECT proxying is generally used for HTTPS tunneling, the returned
    165      * socket will not have been wrapped in an SSL socket.
    166      * </p>
    167      *
    168      * <p>
    169      * Both the proxy and destination hosts must be set via the
    170      * {@link #getHostConfiguration() host configuration} prior to calling this method.
    171      * </p>
    172      *
    173      * @return the connect response
    174      *
    175      * @throws IOException
    176      * @throws HttpException
    177      *
    178      * @see #getHostConfiguration()
    179      */
    180     public ConnectResponse connect() throws IOException, HttpException {
    181
    182         HostConfiguration hostconf = getHostConfiguration();
    183         if (hostconf.getProxyHost() == null) {
    184             throw new IllegalStateException("proxy host must be configured");
    185         }
    186         if (hostconf.getHost() == null) {
    187             throw new IllegalStateException("destination host must be configured");
    188         }
    189         if (hostconf.getProtocol().isSecure()) {
    190             throw new IllegalStateException("secure protocol socket factory may not be used");
    191         }
    192
    193         ConnectMethod method = new ConnectMethod(getHostConfiguration());
    194         method.getParams().setDefaults(getParams());
    195
    196         DummyConnectionManager connectionManager = new DummyConnectionManager();
    197         connectionManager.setConnectionParams(getParams());
    198
    199         HttpMethodDirector director = new HttpMethodDirector(
    200             connectionManager,
    201             hostconf,
    202             getParams(),
    203             getState()
    204         );
    205
    206         director.executeMethod(method);
    207
    208         ConnectResponse response = new ConnectResponse();
    209         response.setConnectMethod(method);
    210
    211         // only set the socket if the connect was successful
    212         if (method.getStatusCode() == HttpStatus.SC_OK) {
    213             response.setSocket(connectionManager.getConnection().getSocket());
    214         } else {
    215             connectionManager.getConnection().close();
    216         }
    217
    218         return response;
    219     }
    220
    221     /**
    222      * Contains the method used to execute the connect along with the created socket.
    223      */
    224     public static class ConnectResponse {
    225
    226         private ConnectMethod connectMethod;
    227
    228         private Socket socket;
    229
    230         private ConnectResponse() {}
    231
    232         /**
    233          * Gets the method that was used to execute the connect.  This method is useful for
    234          * analyzing the proxy's response when a connect fails.
    235          *
    236          * @return the connectMethod.
    237          */
    238         public ConnectMethod getConnectMethod() {
    239             return connectMethod;
    240         }
    241         /**
    242          * @param connectMethod The connectMethod to set.
    243          */
    244         private void setConnectMethod(ConnectMethod connectMethod) {
    245             this.connectMethod = connectMethod;
    246         }
    247         /**
    248          * Gets the socket connected and authenticated (if appropriate) to the configured
    249          * HTTP proxy, or <code>null</code> if a connection could not be made.  It is the
    250          * responsibility of the user to close this socket when it is no longer needed.
    251          *
    252          * @return the socket.
    253          */
    254         public Socket getSocket() {
    255             return socket;
    256         }
    257         /**
    258          * @param socket The socket to set.
    259          */
    260         private void setSocket(Socket socket) {
    261             this.socket = socket;
    262         }
    263     }
    264
    265     /**
    266      * A connection manager that creates a single connection.  Meant to be used only once.
    267      */
    268     static class DummyConnectionManager implements HttpConnectionManager {
    269
    270         private HttpConnection httpConnection;
    271
    272         private HttpParams connectionParams;
    273
    274         public void closeIdleConnections(long idleTimeout) {
    275         }
    276
    277         public HttpConnection getConnection() {
    278             return httpConnection;
    279         }
    280
    281         public void setConnectionParams(HttpParams httpParams) {
    282             this.connectionParams = httpParams;
    283         }
    284
    285         public HttpConnection getConnectionWithTimeout(
    286             HostConfiguration hostConfiguration, long timeout) {
    287
    288             httpConnection = new HttpConnection(hostConfiguration);
    289             httpConnection.setHttpConnectionManager(this);
    290             httpConnection.getParams().setDefaults(connectionParams);
    291             return httpConnection;
    292         }
    293
    294         /**
    295          * @deprecated
    296          */
    297         public HttpConnection getConnection(HostConfiguration hostConfiguration, long timeout)
    298             throws HttpException {
    299             return getConnectionWithTimeout(hostConfiguration, timeout);
    300         }
    301
    302         public HttpConnection getConnection(HostConfiguration hostConfiguration) {
    303             return getConnectionWithTimeout(hostConfiguration, -1);
    304         }
    305
    306         public void releaseConnection(HttpConnection conn) {
    307         }
    308
    309         public HttpConnectionManagerParams getParams() {
    310             return null;
    311         }
    312
    313         public void setParams(HttpConnectionManagerParams params) {
    314         }
    315     }
    316 }