KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > httpclient > ConnectMethod


1 /*
2  * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/ConnectMethod.java,v 1.18.2.3 2004/06/25 03:27:40 mbecke Exp $
3  * $Revision: 1.18.2.3 $
4  * $Date: 2004/06/25 03:27:40 $
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  * [Additional notices, if required by prior licensing conditions]
29  *
30  */

31
32 package org.apache.commons.httpclient;
33
34 import java.io.IOException JavaDoc;
35
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38
39 /**
40  * <p>Wraps another method to tunnel through a proxy.</p>
41  *
42  * @author Ortwin Gl�ck
43  * @author dIon Gillard
44  * @author <a HREF="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
45  * @author <a HREF="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
46  * @since 2.0
47  * @version $Revision: 1.18.2.3 $ $Date: 2004/06/25 03:27:40 $
48  */

49 public class ConnectMethod extends HttpMethodBase {
50     /** the name of this method */
51     public static final String JavaDoc NAME = "CONNECT";
52
53     /**
54      * Create a connect method wrapping the existing method
55      *
56      * @param method the {@link HttpMethod method} to execute after connecting
57      * to the server
58      */

59     public ConnectMethod(HttpMethod method) {
60         LOG.trace("enter ConnectMethod(HttpMethod)");
61         this.method = method;
62     }
63
64     /**
65      * Provide the {@link #NAME name} of this method.
66      *
67      * @return the String "CONNECT"
68      */

69     public String JavaDoc getName() {
70         return NAME;
71     }
72
73
74     /**
75      * This method does nothing. <tt>CONNECT</tt> request is not supposed
76      * to contain <tt>Authorization</tt> request header.
77      *
78      * @param state current state of http requests
79      * @param conn the connection to use for I/O
80      *
81      * @throws IOException when errors occur reading or writing to/from the
82      * connection
83      * @throws HttpException when a recoverable error occurs
84      *
85      * @see HttpMethodBase#addAuthorizationRequestHeader(HttpState, HttpConnection)
86      */

87     protected void addAuthorizationRequestHeader(HttpState state, HttpConnection conn)
88         throws IOException JavaDoc, HttpException {
89         // Do nothing. Not applicable to CONNECT method
90
}
91
92     /**
93      * This method does nothing. <tt>CONNECT</tt> request is not supposed
94      * to contain <tt>Content-Length</tt> request header.
95      *
96      * @param state current state of http requests
97      * @param conn the connection to use for I/O
98      *
99      * @throws IOException when errors occur reading or writing to/from the
100      * connection
101      * @throws HttpException when a recoverable error occurs
102      *
103      * @see HttpMethodBase#addContentLengthRequestHeader(HttpState, HttpConnection)
104      */

105     protected void addContentLengthRequestHeader(HttpState state, HttpConnection conn)
106         throws IOException JavaDoc, HttpException {
107         // Do nothing. Not applicable to CONNECT method
108
}
109
110     /**
111      * This method does nothing. <tt>CONNECT</tt> request is not supposed
112      * to contain <tt>Cookie</tt> request header.
113      *
114      * @param state current state of http requests
115      * @param conn the connection to use for I/O
116      *
117      * @throws IOException when errors occur reading or writing to/from the
118      * connection
119      * @throws HttpException when a recoverable error occurs
120      *
121      * @see HttpMethodBase#addCookieRequestHeader(HttpState, HttpConnection)
122      */

123     protected void addCookieRequestHeader(HttpState state, HttpConnection conn)
124         throws IOException JavaDoc, HttpException {
125         // Do nothing. Not applicable to CONNECT method
126
}
127
128
129     /**
130      * Populates the request headers map to with additional {@link Header
131      * headers} to be submitted to the given {@link HttpConnection}.
132      *
133      * <p>
134      * This implementation adds <tt>User-Agent</tt>, <tt>Host</tt>,
135      * and <tt>Proxy-Authorization</tt> headers, when appropriate.
136      * </p>
137      *
138      * @param state the client state
139      * @param conn the {@link HttpConnection} the headers will eventually be
140      * written to
141      * @throws IOException when an error occurs writing the request
142      * @throws HttpException when a HTTP protocol error occurs
143      *
144      * @see #writeRequestHeaders
145      */

146     protected void addRequestHeaders(HttpState state, HttpConnection conn)
147         throws IOException JavaDoc, HttpException {
148         LOG.trace("enter ConnectMethod.addRequestHeaders(HttpState, "
149             + "HttpConnection)");
150         addUserAgentRequestHeader(state, conn);
151         addHostRequestHeader(state, conn);
152         addProxyAuthorizationRequestHeader(state, conn);
153         addProxyConnectionHeader(state, conn);
154     }
155
156     /**
157      * Execute this method by tunnelling and then executing the wrapped method.
158      *
159      * @param state the current http state
160      * @param conn the connection to write to
161      * @return the http status code from execution
162      * @throws HttpException when an error occurs writing the headers
163      * @throws IOException when an error occurs writing the headers
164      */

165     public int execute(HttpState state, HttpConnection conn)
166     throws IOException JavaDoc, HttpException {
167
168         LOG.trace("enter ConnectMethod.execute(HttpState, HttpConnection)");
169         int code = super.execute(state, conn);
170         LOG.debug("CONNECT status code " + code);
171         if ((code >= 200) && (code < 300)) {
172             conn.tunnelCreated();
173             code = method.execute(state, conn);
174         } else {
175             // What is to follow is an ugly hack.
176
// I REALLY hate having to resort to such
177
// an appalling trick
178
// TODO: Connect method must be redesigned.
179
// The only feasible solution is to split monolithic
180
// HttpMethod into HttpRequest/HttpResponse pair.
181
// That would allow to execute CONNECT method
182
// behind the scene and return CONNECT HttpResponse
183
// object in response to the original request that
184
// contains the correct status line, headers &
185
// response body.
186

187             LOG.debug("CONNECT failed, fake the response for the original method");
188             if (method instanceof HttpMethodBase) {
189                 // Pass the status, headers and response stream to the wrapped
190
// method.
191
// To ensure that the connection is not released more than once
192
// this method is still responsible for releasing the connection.
193
// This will happen when the response body is consumed, or when
194
// the wrapped method closes the response connection in
195
// releaseConnection().
196
((HttpMethodBase) method).fakeResponse(
197                     getStatusLine(),
198                     getResponseHeaderGroup(),
199                     getResponseStream()
200                 );
201             } else {
202                 releaseConnection();
203             }
204         }
205         return code;
206     }
207
208     /**
209      * Special Connect request.
210      *
211      * @param state the current http state
212      * @param conn the connection to write to
213      * @throws IOException when an error occurs writing the request
214      * @throws HttpException when an error occurs writing the request
215      */

216     protected void writeRequestLine(HttpState state, HttpConnection conn)
217     throws IOException JavaDoc, HttpException {
218         int port = conn.getPort();
219         if (port == -1) {
220             port = conn.getProtocol().getDefaultPort();
221         }
222         StringBuffer JavaDoc buffer = new StringBuffer JavaDoc();
223         buffer.append(getName());
224         buffer.append(' ');
225         buffer.append(conn.getHost());
226         if (port > -1) {
227             buffer.append(':');
228             buffer.append(port);
229         }
230         buffer.append(" HTTP/1.1");
231         String JavaDoc line = buffer.toString();
232         conn.printLine(line);
233         if (Wire.HEADER_WIRE.enabled()) {
234             Wire.HEADER_WIRE.output(line);
235         }
236     }
237
238     /**
239      * Returns <code>true</code> if the status code is anything other than
240      * SC_OK, <code>false</code> otherwise.
241      *
242      * @param conn the connection to test
243      *
244      * @return <code>true</code> if the connection should be closed
245      *
246      * @see HttpMethodBase#shouldCloseConnection(HttpConnection)
247      * @see HttpStatus#SC_OK
248      */

249     protected boolean shouldCloseConnection(HttpConnection conn) {
250         if (getStatusCode() == HttpStatus.SC_OK) {
251             Header connectionHeader = null;
252             if (!conn.isTransparent()) {
253                 connectionHeader = getResponseHeader("proxy-connection");
254             }
255             if (connectionHeader == null) {
256                 connectionHeader = getResponseHeader("connection");
257             }
258             if (connectionHeader != null) {
259                 if (connectionHeader.getValue().equalsIgnoreCase("close")) {
260                     if (LOG.isWarnEnabled()) {
261                         LOG.warn("Invalid header encountered '" + connectionHeader.toExternalForm()
262                             + "' in response " + getStatusLine().toString());
263                     }
264                 }
265             }
266             return false;
267         } else {
268             return super.shouldCloseConnection(conn);
269         }
270     }
271     
272     /** Log object for this class. */
273     private static final Log LOG = LogFactory.getLog(ConnectMethod.class);
274
275     /** The wrapped method */
276     private HttpMethod method;
277
278 }
279
Popular Tags