View Javadoc

1   /*
2    * $Header: /home/jerenkrantz/tmp/commons/commons-convert/cvs/home/cvs/jakarta-commons//httpclient/src/java/org/apache/commons/httpclient/ConnectMethod.java,v 1.29 2004/06/24 21:39:52 mbecke Exp $
3    * $Revision: 390058 $
4    * $Date: 2006-03-30 12:09:57 +0200 (Thu, 30 Mar 2006) $
5    *
6    * ====================================================================
7    *
8    *  Copyright 1999-2004 The Apache Software Foundation
9    *
10   *  Licensed under the Apache License, Version 2.0 (the "License");
11   *  you may not use this file except in compliance with the License.
12   *  You may obtain a copy of the License at
13   *
14   *      http://www.apache.org/licenses/LICENSE-2.0
15   *
16   *  Unless required by applicable law or agreed to in writing, software
17   *  distributed under the License is distributed on an "AS IS" BASIS,
18   *  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19   *  See the License for the specific language governing permissions and
20   *  limitations under the License.
21   * ====================================================================
22   *
23   * This software consists of voluntary contributions made by many
24   * individuals on behalf of the Apache Software Foundation.  For more
25   * information on the Apache Software Foundation, please see
26   * <http://www.apache.org/>.
27   *
28   */
29  
30  package org.apache.commons.httpclient;
31  
32  import java.io.IOException;
33  
34  import org.apache.commons.logging.Log;
35  import org.apache.commons.logging.LogFactory;
36  
37  /***
38   * Establishes a tunneled HTTP connection via the CONNECT method.
39   *
40   * @author Ortwin Gl???ck
41   * @author dIon Gillard
42   * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
43   * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
44   * @since 2.0
45   * @version $Revision: 390058 $ $Date: 2006-03-30 12:09:57 +0200 (Thu, 30 Mar 2006) $
46   */
47  public class ConnectMethod extends HttpMethodBase {
48      
49      /*** the name of this method */
50      public static final String NAME = "CONNECT";
51  
52      private final HostConfiguration targethost;
53  
54      /***
55       * @deprecated use #ConnectMethod(HttpHost);
56       * 
57       * Create a connect method.
58       * 
59       * @since 3.0
60       */
61      public ConnectMethod() {
62          super();
63          this.targethost = null;
64      }
65  
66      /***
67       * @deprecated the wrapped method is no longer used
68       * 
69       * Create a connect method wrapping the existing method
70       *
71       * @param method the {@link HttpMethod method} to execute after connecting
72       *      to the server
73       */
74      public ConnectMethod(HttpMethod method) {
75          super();
76          this.targethost = null;
77      }
78  
79      /***
80       * Create a connect method.
81       * 
82       * @since 3.0
83       */
84      public ConnectMethod(final HostConfiguration targethost) {
85          super();
86          if (targethost == null) {
87              throw new IllegalArgumentException("Target host may not be null");
88          }
89          this.targethost = targethost;
90      }
91  
92      /***
93       * Provide the {@link #NAME name} of this method.
94       *
95       * @return the String "CONNECT"
96       */
97      public String getName() {
98          return NAME;
99      }
100     
101     public String getPath() {
102         if (this.targethost != null) {
103             StringBuffer buffer = new StringBuffer();
104             buffer.append(this.targethost.getHost()); 
105             int port = this.targethost.getPort();
106             if (port == -1) {
107                 port = this.targethost.getProtocol().getDefaultPort();  
108             }
109             buffer.append(':'); 
110             buffer.append(port);
111             return buffer.toString();
112         } else {
113             return "/";
114         }
115     }
116 
117     public URI getURI() throws URIException {
118         return new URI(getPath(), true);
119     }
120 
121     /***
122      * This method does nothing. <tt>CONNECT</tt> request is not supposed 
123      * to contain <tt>Cookie</tt> request header.
124      *
125      * @param state current state of http requests
126      * @param conn the connection to use for I/O
127      *
128      * @throws IOException when errors occur reading or writing to/from the
129      *         connection
130      * @throws HttpException when a recoverable error occurs
131      *  
132      * @see HttpMethodBase#addCookieRequestHeader(HttpState, HttpConnection)
133      */
134     protected void addCookieRequestHeader(HttpState state, HttpConnection conn)
135         throws IOException, HttpException {
136         // Do nothing. Not applicable to CONNECT method
137     }
138 
139 
140     /***
141      * Populates the request headers map to with additional {@link Header
142      * headers} to be submitted to the given {@link HttpConnection}.
143      *
144      * <p>
145      * This implementation adds <tt>User-Agent</tt>, <tt>Host</tt>,
146      * and <tt>Proxy-Authorization</tt> headers, when appropriate.
147      * </p>
148      *
149      * @param state the client state
150      * @param conn the {@link HttpConnection} the headers will eventually be
151      *        written to
152      * @throws IOException when an error occurs writing the request
153      * @throws HttpException when a HTTP protocol error occurs
154      *
155      * @see #writeRequestHeaders
156      */
157     protected void addRequestHeaders(HttpState state, HttpConnection conn)
158         throws IOException, HttpException {
159         LOG.trace("enter ConnectMethod.addRequestHeaders(HttpState, "
160             + "HttpConnection)");
161         addUserAgentRequestHeader(state, conn);
162         addHostRequestHeader(state, conn);
163         addProxyConnectionHeader(state, conn);
164     }
165 
166     /***
167      * Execute this method and create a tunneled HttpConnection.  If the method
168      * is successful (i.e. the status is a 2xx) tunnelCreated() will be called
169      * on the connection.
170      *
171      * @param state the current http state
172      * @param conn the connection to write to
173      * @return the http status code from execution
174      * @throws HttpException when an error occurs writing the headers
175      * @throws IOException when an error occurs writing the headers
176      * 
177      * @see HttpConnection#tunnelCreated()
178      */
179     public int execute(HttpState state, HttpConnection conn) 
180     throws IOException, HttpException {
181 
182         LOG.trace("enter ConnectMethod.execute(HttpState, HttpConnection)");
183         int code = super.execute(state, conn);
184         if (LOG.isDebugEnabled()) {
185             LOG.debug("CONNECT status code " + code);
186         }
187         return code;
188     }
189 
190     /***
191      * Special Connect request.
192      *
193      * @param state the current http state
194      * @param conn the connection to write to
195      * @throws IOException when an error occurs writing the request
196      * @throws HttpException when an error occurs writing the request
197      */
198     protected void writeRequestLine(HttpState state, HttpConnection conn)
199     throws IOException, HttpException {
200         StringBuffer buffer = new StringBuffer();
201         buffer.append(getName()); 
202         buffer.append(' '); 
203         if (this.targethost != null) {
204             buffer.append(getPath()); 
205         } else {
206             int port = conn.getPort();
207             if (port == -1) {
208                 port = conn.getProtocol().getDefaultPort();  
209             }
210             buffer.append(conn.getHost()); 
211             buffer.append(':'); 
212             buffer.append(port); 
213         }
214         buffer.append(" "); 
215         buffer.append(getEffectiveVersion()); 
216         String line = buffer.toString();
217         conn.printLine(line, getParams().getHttpElementCharset());
218         if (Wire.HEADER_WIRE.enabled()) {
219             Wire.HEADER_WIRE.output(line);
220         }
221     }
222 
223     /***
224      * Returns <code>true</code> if the status code is anything other than
225      * SC_OK, <code>false</code> otherwise.
226      * 
227      * @see HttpMethodBase#shouldCloseConnection(HttpConnection)
228      * @see HttpStatus#SC_OK
229      * 
230      * @return <code>true</code> if the connection should be closed
231      */
232     protected boolean shouldCloseConnection(HttpConnection conn) {
233         if (getStatusCode() == HttpStatus.SC_OK) {
234             Header connectionHeader = null;
235             if (!conn.isTransparent()) {
236                 connectionHeader = getResponseHeader("proxy-connection");
237             }
238             if (connectionHeader == null) {
239                 connectionHeader = getResponseHeader("connection");
240             }
241             if (connectionHeader != null) {
242                 if (connectionHeader.getValue().equalsIgnoreCase("close")) {
243                     if (LOG.isWarnEnabled()) {
244                         LOG.warn("Invalid header encountered '" + connectionHeader.toExternalForm() 
245                         + "' in response " + getStatusLine().toString());
246                     }
247                 }
248             }
249             return false;
250         } else {
251             return super.shouldCloseConnection(conn);
252         }
253     }
254     
255     /*** Log object for this class. */
256     private static final Log LOG = LogFactory.getLog(ConnectMethod.class);
257 
258 }