001: /*
002: * $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 $
003: * $Revision: 483949 $
004: * $Date: 2006-12-08 12:34:50 +0100 (Fri, 08 Dec 2006) $
005: *
006: * ====================================================================
007: *
008: * Licensed to the Apache Software Foundation (ASF) under one or more
009: * contributor license agreements. See the NOTICE file distributed with
010: * this work for additional information regarding copyright ownership.
011: * The ASF licenses this file to You under the Apache License, Version 2.0
012: * (the "License"); you may not use this file except in compliance with
013: * the License. You may obtain a copy of the License at
014: *
015: * http://www.apache.org/licenses/LICENSE-2.0
016: *
017: * Unless required by applicable law or agreed to in writing, software
018: * distributed under the License is distributed on an "AS IS" BASIS,
019: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
020: * See the License for the specific language governing permissions and
021: * limitations under the License.
022: * ====================================================================
023: *
024: * This software consists of voluntary contributions made by many
025: * individuals on behalf of the Apache Software Foundation. For more
026: * information on the Apache Software Foundation, please see
027: * <http://www.apache.org/>.
028: *
029: */
030:
031: package org.apache.commons.httpclient;
032:
033: import java.io.IOException;
034:
035: import org.apache.commons.logging.Log;
036: import org.apache.commons.logging.LogFactory;
037:
038: /**
039: * Establishes a tunneled HTTP connection via the CONNECT method.
040: *
041: * @author Ortwin Gl???ck
042: * @author dIon Gillard
043: * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
044: * @author <a href="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
045: * @since 2.0
046: * @version $Revision: 483949 $ $Date: 2006-12-08 12:34:50 +0100 (Fri, 08 Dec 2006) $
047: */
048: public class ConnectMethod extends HttpMethodBase {
049:
050: /** the name of this method */
051: public static final String NAME = "CONNECT";
052:
053: private final HostConfiguration targethost;
054:
055: /**
056: * @deprecated use #ConnectMethod(HttpHost);
057: *
058: * Create a connect method.
059: *
060: * @since 3.0
061: */
062: public ConnectMethod() {
063: super ();
064: this .targethost = null;
065: }
066:
067: /**
068: * @deprecated the wrapped method is no longer used
069: *
070: * Create a connect method wrapping the existing method
071: *
072: * @param method the {@link HttpMethod method} to execute after connecting
073: * to the server
074: */
075: public ConnectMethod(HttpMethod method) {
076: super ();
077: this .targethost = null;
078: }
079:
080: /**
081: * Create a connect method.
082: *
083: * @since 3.0
084: */
085: public ConnectMethod(final HostConfiguration targethost) {
086: super ();
087: if (targethost == null) {
088: throw new IllegalArgumentException(
089: "Target host may not be null");
090: }
091: this .targethost = targethost;
092: }
093:
094: /**
095: * Provide the {@link #NAME name} of this method.
096: *
097: * @return the String "CONNECT"
098: */
099: public String getName() {
100: return NAME;
101: }
102:
103: public String getPath() {
104: if (this .targethost != null) {
105: StringBuffer buffer = new StringBuffer();
106: buffer.append(this .targethost.getHost());
107: int port = this .targethost.getPort();
108: if (port == -1) {
109: port = this .targethost.getProtocol().getDefaultPort();
110: }
111: buffer.append(':');
112: buffer.append(port);
113: return buffer.toString();
114: } else {
115: return "/";
116: }
117: }
118:
119: public URI getURI() throws URIException {
120: String charset = getParams().getUriCharset();
121: return new URI(getPath(), true, charset);
122: }
123:
124: /**
125: * This method does nothing. <tt>CONNECT</tt> request is not supposed
126: * to contain <tt>Cookie</tt> request header.
127: *
128: * @param state current state of http requests
129: * @param conn the connection to use for I/O
130: *
131: * @throws IOException when errors occur reading or writing to/from the
132: * connection
133: * @throws HttpException when a recoverable error occurs
134: *
135: * @see HttpMethodBase#addCookieRequestHeader(HttpState, HttpConnection)
136: */
137: protected void addCookieRequestHeader(HttpState state,
138: HttpConnection conn) throws IOException, HttpException {
139: // Do nothing. Not applicable to CONNECT method
140: }
141:
142: /**
143: * Populates the request headers map to with additional {@link Header
144: * headers} to be submitted to the given {@link HttpConnection}.
145: *
146: * <p>
147: * This implementation adds <tt>User-Agent</tt>, <tt>Host</tt>,
148: * and <tt>Proxy-Authorization</tt> headers, when appropriate.
149: * </p>
150: *
151: * @param state the client state
152: * @param conn the {@link HttpConnection} the headers will eventually be
153: * written to
154: * @throws IOException when an error occurs writing the request
155: * @throws HttpException when a HTTP protocol error occurs
156: *
157: * @see #writeRequestHeaders
158: */
159: protected void addRequestHeaders(HttpState state,
160: HttpConnection conn) throws IOException, HttpException {
161: LOG.trace("enter ConnectMethod.addRequestHeaders(HttpState, "
162: + "HttpConnection)");
163: addUserAgentRequestHeader(state, conn);
164: addHostRequestHeader(state, conn);
165: addProxyConnectionHeader(state, conn);
166: }
167:
168: /**
169: * Execute this method and create a tunneled HttpConnection. If the method
170: * is successful (i.e. the status is a 2xx) tunnelCreated() will be called
171: * on the connection.
172: *
173: * @param state the current http state
174: * @param conn the connection to write to
175: * @return the http status code from execution
176: * @throws HttpException when an error occurs writing the headers
177: * @throws IOException when an error occurs writing the headers
178: *
179: * @see HttpConnection#tunnelCreated()
180: */
181: public int execute(HttpState state, HttpConnection conn)
182: throws IOException, HttpException {
183:
184: LOG
185: .trace("enter ConnectMethod.execute(HttpState, HttpConnection)");
186: int code = super .execute(state, conn);
187: if (LOG.isDebugEnabled()) {
188: LOG.debug("CONNECT status code " + code);
189: }
190: return code;
191: }
192:
193: /**
194: * Special Connect request.
195: *
196: * @param state the current http state
197: * @param conn the connection to write to
198: * @throws IOException when an error occurs writing the request
199: * @throws HttpException when an error occurs writing the request
200: */
201: protected void writeRequestLine(HttpState state, HttpConnection conn)
202: throws IOException, HttpException {
203: StringBuffer buffer = new StringBuffer();
204: buffer.append(getName());
205: buffer.append(' ');
206: if (this .targethost != null) {
207: buffer.append(getPath());
208: } else {
209: int port = conn.getPort();
210: if (port == -1) {
211: port = conn.getProtocol().getDefaultPort();
212: }
213: buffer.append(conn.getHost());
214: buffer.append(':');
215: buffer.append(port);
216: }
217: buffer.append(" ");
218: buffer.append(getEffectiveVersion());
219: String line = buffer.toString();
220: conn.printLine(line, getParams().getHttpElementCharset());
221: if (Wire.HEADER_WIRE.enabled()) {
222: Wire.HEADER_WIRE.output(line);
223: }
224: }
225:
226: /**
227: * Returns <code>true</code> if the status code is anything other than
228: * SC_OK, <code>false</code> otherwise.
229: *
230: * @see HttpMethodBase#shouldCloseConnection(HttpConnection)
231: * @see HttpStatus#SC_OK
232: *
233: * @return <code>true</code> if the connection should be closed
234: */
235: protected boolean shouldCloseConnection(HttpConnection conn) {
236: if (getStatusCode() == HttpStatus.SC_OK) {
237: Header connectionHeader = null;
238: if (!conn.isTransparent()) {
239: connectionHeader = getResponseHeader("proxy-connection");
240: }
241: if (connectionHeader == null) {
242: connectionHeader = getResponseHeader("connection");
243: }
244: if (connectionHeader != null) {
245: if (connectionHeader.getValue().equalsIgnoreCase(
246: "close")) {
247: if (LOG.isWarnEnabled()) {
248: LOG.warn("Invalid header encountered '"
249: + connectionHeader.toExternalForm()
250: + "' in response "
251: + getStatusLine().toString());
252: }
253: }
254: }
255: return false;
256: } else {
257: return super .shouldCloseConnection(conn);
258: }
259: }
260:
261: /** Log object for this class. */
262: private static final Log LOG = LogFactory
263: .getLog(ConnectMethod.class);
264:
265: }
|