ProxyClient.java
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 }