KickJava   Java API By Example, From Geeks To Geeks.

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


1 /*
2  * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/HttpConnection.java,v 1.67.2.12 2004/07/19 20:06:26 olegk Exp $
3  * $Revision: 1.67.2.12 $
4  * $Date: 2004/07/19 20:06:26 $
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.BufferedOutputStream JavaDoc;
35 import java.io.IOException JavaDoc;
36 import java.io.InputStream JavaDoc;
37 import java.io.InterruptedIOException JavaDoc;
38 import java.io.OutputStream JavaDoc;
39 import java.io.PushbackInputStream JavaDoc;
40 import java.lang.reflect.Method JavaDoc;
41 import java.net.InetAddress JavaDoc;
42 import java.net.Socket JavaDoc;
43 import java.net.SocketException JavaDoc;
44
45 import org.apache.commons.httpclient.protocol.DefaultProtocolSocketFactory;
46 import org.apache.commons.httpclient.protocol.Protocol;
47 import org.apache.commons.httpclient.protocol.ProtocolSocketFactory;
48 import org.apache.commons.httpclient.protocol.SecureProtocolSocketFactory;
49 import org.apache.commons.httpclient.util.TimeoutController;
50 import org.apache.commons.logging.Log;
51 import org.apache.commons.logging.LogFactory;
52
53 /**
54  * An abstraction of an HTTP {@link InputStream} and {@link OutputStream}
55  * pair, together with the relevant attributes.
56  * <p>
57  * The following options are set on the socket before getting the input/output
58  * streams in the {@link #open()} method:
59  * <table border=1><tr>
60  * <th>Socket Method
61  * <th>Sockets Option
62  * <th>Configuration
63  * </tr><tr>
64  * <td>{@link java.net.Socket#setTcpNoDelay(boolean)}
65  * <td>SO_NODELAY
66  * <td>None
67  * </tr><tr>
68  * <td>{@link java.net.Socket#setSoTimeout(int)}
69  * <td>SO_TIMEOUT
70  * <td>{@link #setConnectionTimeout(int)}
71  * </tr></table>
72  *
73  * @author Rod Waldhoff
74  * @author Sean C. Sullivan
75  * @author Ortwin Gl??ck
76  * @author <a HREF="mailto:jsdever@apache.org">Jeff Dever</a>
77  * @author <a HREF="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
78  * @author <a HREF="mailto:oleg@ural.ru">Oleg Kalnichevski</a>
79  * @author Michael Becke
80  * @author Eric E Johnson
81  * @author Laura Werner
82  *
83  * @version $Revision: 1.67.2.12 $ $Date: 2004/07/19 20:06:26 $
84  */

85 public class HttpConnection {
86
87     // ----------------------------------------------------------- Constructors
88

89     /**
90      * Creates a new HTTP connection for the given host and port.
91      *
92      * @param host the host to connect to
93      * @param port the port to connect to
94      */

95     public HttpConnection(String JavaDoc host, int port) {
96         this(null, -1, host, port, false);
97     }
98
99     /**
100      * Creates a new HTTP connection for the given host and port.
101      * If secure attribute is set, use SSL to establish the connection.
102      *
103      * @param host the host to connect to
104      * @param port the port to connect to
105      * @param secure when <tt>true</tt>, connect via HTTPS (SSL)
106      *
107      * @deprecated use HttpConnection(String, int, Protocol)
108      *
109      * @see #HttpConnection(String,int,Protocol)
110      *
111      */

112     public HttpConnection(String JavaDoc host, int port, boolean secure) {
113         this(null, -1, host, port, secure);
114     }
115
116     /**
117      * Creates a new HTTP connection for the given host and port
118      * using the given protocol.
119      *
120      * @param host the host to connect to
121      * @param port the port to connect to
122      * @param protocol the protocol to use
123      */

124     public HttpConnection(String JavaDoc host, int port, Protocol protocol) {
125         this(null, -1, host, null, port, protocol);
126     }
127
128     /**
129      * Creates a new HTTP connection for the given host with the virtual
130      * alias and port using given protocol.
131      *
132      * @param host the host to connect to
133      * @param virtualHost the virtual host requests will be sent to
134      * @param port the port to connect to
135      * @param protocol the protocol to use
136      */

137     public HttpConnection(String JavaDoc host, String JavaDoc virtualHost, int port, Protocol protocol) {
138         this(null, -1, host, virtualHost, port, protocol);
139     }
140
141     /**
142      * Creates a new HTTP connection for the given host and port via the
143      * given proxy host and port using the default protocol.
144      *
145      * @param proxyHost the host to proxy via
146      * @param proxyPort the port to proxy via
147      * @param host the host to connect to
148      * @param port the port to connect to
149      */

150     public HttpConnection(
151         String JavaDoc proxyHost,
152         int proxyPort,
153         String JavaDoc host,
154         int port) {
155         this(proxyHost, proxyPort, host, port, false);
156     }
157
158     /**
159      * Creates a new HTTP connection for the given host and port via
160      * the given proxy host and port. If secure attribute is set,
161      * use SSL to establish the connection.
162      *
163      * @param proxyHost the host I should proxy via
164      * @param proxyPort the port I should proxy via
165      * @param host the host to connect to. Parameter value must be non-null.
166      * @param port the port to connect to
167      * @param secure when <tt>true</tt>, connect via HTTPS (SSL)
168      *
169      * @deprecated use HttpConnection(String, int, String, int, Protocol)
170      *
171      * @see #HttpConnection(String, int, String, String, int, Protocol)
172      *
173      */

174     public HttpConnection(
175         String JavaDoc proxyHost,
176         int proxyPort,
177         String JavaDoc host,
178         int port,
179         boolean secure) {
180         this(proxyHost, proxyPort, host, null, port,
181             Protocol.getProtocol(secure ? "https" : "http"));
182     }
183
184     /**
185      * Creates a new HTTP connection for the given host configuration.
186      *
187      * @param hostConfiguration the host/proxy/protocol to use
188      */

189     public HttpConnection(HostConfiguration hostConfiguration) {
190         this(hostConfiguration.getProxyHost(),
191              hostConfiguration.getProxyPort(),
192              hostConfiguration.getHost(),
193              hostConfiguration.getVirtualHost(),
194              hostConfiguration.getPort(),
195              hostConfiguration.getProtocol());
196         this.localAddress = hostConfiguration.getLocalAddress();
197     }
198
199     /**
200      * Creates a new HTTP connection for the given host with the virtual
201      * alias and port via the given proxy host and port using the given
202      * protocol.
203      *
204      * @param proxyHost the host to proxy via
205      * @param proxyPort the port to proxy via
206      * @param host the host to connect to. Parameter value must be non-null.
207      * @param virtualHost the virtual host requests will be sent to
208      * @param port the port to connect to
209      * @param protocol The protocol to use. Parameter value must be non-null.
210      */

211     public HttpConnection(
212         String JavaDoc proxyHost,
213         int proxyPort,
214         String JavaDoc host,
215         String JavaDoc virtualHost,
216         int port,
217         Protocol protocol) {
218
219         if (host == null) {
220             throw new IllegalArgumentException JavaDoc("host parameter is null");
221         }
222         if (protocol == null) {
223             throw new IllegalArgumentException JavaDoc("protocol is null");
224         }
225
226         proxyHostName = proxyHost;
227         proxyPortNumber = proxyPort;
228         hostName = host;
229         virtualName = virtualHost;
230         portNumber = protocol.resolvePort(port);
231         protocolInUse = protocol;
232     }
233
234     // ------------------------------------------ Attribute Setters and Getters
235

236     /**
237      * Returns the host.
238      *
239      * @return the host.
240      */

241     public String JavaDoc getHost() {
242         return hostName;
243     }
244
245     /**
246      * Sets the host to connect to.
247      *
248      * @param host the host to connect to. Parameter value must be non-null.
249      * @throws IllegalStateException if the connection is already open
250      */

251     public void setHost(String JavaDoc host) throws IllegalStateException JavaDoc {
252         if (host == null) {
253             throw new IllegalArgumentException JavaDoc("host parameter is null");
254         }
255         assertNotOpen();
256         hostName = host;
257     }
258
259     /**
260      * Returns the target virtual host.
261      *
262      * @return the virtual host.
263      */

264     public String JavaDoc getVirtualHost() {
265         return virtualName;
266     }
267
268     /**
269      * Sets the virtual host to target.
270      *
271      * @param host the virtual host name that should be used instead of
272      * physical host name when sending HTTP requests. Virtual host
273      * name can be set to <tt> null</tt> if virtual host name is not
274      * to be used
275      *
276      * @throws IllegalStateException if the connection is already open
277      */

278     public void setVirtualHost(String JavaDoc host) throws IllegalStateException JavaDoc {
279         assertNotOpen();
280         virtualName = host;
281     }
282
283     /**
284      * Returns the port of the host.
285      *
286      * If the port is -1 (or less than 0) the default port for
287      * the current protocol is returned.
288      *
289      * @return the port.
290      */

291     public int getPort() {
292         if (portNumber < 0) {
293             return isSecure() ? 443 : 80;
294         } else {
295             return portNumber;
296         }
297     }
298
299     /**
300      * Sets the port to connect to.
301      *
302      * @param port the port to connect to
303      *
304      * @throws IllegalStateException if the connection is already open
305      */

306     public void setPort(int port) throws IllegalStateException JavaDoc {
307         assertNotOpen();
308         portNumber = port;
309     }
310
311     /**
312      * Returns the proxy host.
313      *
314      * @return the proxy host.
315      */

316     public String JavaDoc getProxyHost() {
317         return proxyHostName;
318     }
319
320     /**
321      * Sets the host to proxy through.
322      *
323      * @param host the host to proxy through.
324      *
325      * @throws IllegalStateException if the connection is already open
326      */

327     public void setProxyHost(String JavaDoc host) throws IllegalStateException JavaDoc {
328         assertNotOpen();
329         proxyHostName = host;
330     }
331
332     /**
333      * Returns the port of the proxy host.
334      *
335      * @return the proxy port.
336      */

337     public int getProxyPort() {
338         return proxyPortNumber;
339     }
340
341     /**
342      * Sets the port of the host to proxy through.
343      *
344      * @param port the port of the host to proxy through.
345      *
346      * @throws IllegalStateException if the connection is already open
347      */

348     public void setProxyPort(int port) throws IllegalStateException JavaDoc {
349         assertNotOpen();
350         proxyPortNumber = port;
351     }
352
353     /**
354      * Returns <tt>true</tt> if the connection is established over
355      * a secure protocol.
356      *
357      * @return <tt>true</tt> if connected over a secure protocol.
358      */

359     public boolean isSecure() {
360         return protocolInUse.isSecure();
361     }
362
363     /**
364      * Returns the protocol used to establish the connection.
365      * @return The protocol
366      */

367     public Protocol getProtocol() {
368         return protocolInUse;
369     }
370
371     /**
372      * Defines whether the connection should be established over a
373      * secure protocol.
374      *
375      * @param secure whether or not to connect over a secure protocol.
376      *
377      * @throws IllegalStateException if the connection is already open
378      *
379      * @deprecated use setProtocol(Protocol)
380      *
381      * @see #setProtocol(Protocol)
382      */

383     public void setSecure(boolean secure) throws IllegalStateException JavaDoc {
384         assertNotOpen();
385         protocolInUse = secure
386             ? Protocol.getProtocol("https")
387             : Protocol.getProtocol("http");
388     }
389
390     /**
391      * Sets the protocol used to establish the connection
392      *
393      * @param protocol The protocol to use.
394      *
395      * @throws IllegalStateException if the connection is already open
396      */

397     public void setProtocol(Protocol protocol) {
398         assertNotOpen();
399
400         if (protocol == null) {
401             throw new IllegalArgumentException JavaDoc("protocol is null");
402         }
403
404         protocolInUse = protocol;
405
406     }
407
408     /**
409      * Return the local address used when creating the connection.
410      * If <tt>null</tt>, the default address is used.
411      *
412      * @return InetAddress the local address to be used when creating Sockets
413      */

414     public InetAddress JavaDoc getLocalAddress() {
415         return this.localAddress;
416     }
417     
418     /**
419      * Set the local address used when creating the connection.
420      * If unset or <tt>null</tt>, the default address is used.
421      *
422      * @param localAddress the local address to use
423      */

424     public void setLocalAddress(InetAddress JavaDoc localAddress) {
425         assertNotOpen();
426         this.localAddress = localAddress;
427     }
428
429     /**
430      * Returns <tt>true</tt> if the connection is open,
431      * <tt>false</tt> otherwise.
432      *
433      * @return <tt>true</tt> if the connection is open
434      */

435     public boolean isOpen() {
436         if (used && isOpen && isStaleCheckingEnabled() && isStale()) {
437             LOG.debug("Connection is stale, closing...");
438             close();
439         }
440         return isOpen;
441     }
442
443     /**
444      * Tests if stale checking is enabled.
445      *
446      * @return <code>true</code> if enabled
447      *
448      * @see #isStale()
449      */

450     public boolean isStaleCheckingEnabled() {
451         return staleCheckingEnabled;
452     }
453
454     /**
455      * Sets whether or not isStale() will be called when testing if this connection is open.
456      *
457      * <p>Setting this flag to <code>false</code> will increase performance when reusing
458      * connections, but it will also make them less reliable. Stale checking ensures that
459      * connections are viable before they are used. When set to <code>false</code> some
460      * method executions will result in IOExceptions and they will have to be retried.</p>
461      *
462      * @param staleCheckEnabled <code>true</code> to enable isStale()
463      *
464      * @see #isStale()
465      * @see #isOpen()
466      */

467     public void setStaleCheckingEnabled(boolean staleCheckEnabled) {
468         this.staleCheckingEnabled = staleCheckEnabled;
469     }
470
471     /**
472      * Determines whether this connection is "stale", which is to say that either
473      * it is no longer open, or an attempt to read the connection would fail.
474      *
475      * <p>Unfortunately, due to the limitations of the JREs prior to 1.4, it is
476      * not possible to test a connection to see if both the read and write channels
477      * are open - except by reading and writing. This leads to a difficulty when
478      * some connections leave the "write" channel open, but close the read channel
479      * and ignore the request. This function attempts to ameliorate that
480      * problem by doing a test read, assuming that the caller will be doing a
481      * write followed by a read, rather than the other way around.
482      * </p>
483      *
484      * <p>To avoid side-effects, the underlying connection is wrapped by a
485      * {@link PushbackInputStream}, so although data might be read, what is visible
486      * to clients of the connection will not change with this call.</p.
487      *
488      * @return <tt>true</tt> if the connection is already closed, or a read would
489      * fail.
490      */

491     protected boolean isStale() {
492         boolean isStale = true;
493         if (isOpen) {
494             // the connection is open, but now we have to see if we can read it
495
// assume the connection is not stale.
496
isStale = false;
497             try {
498                 if (inputStream.available() == 0) {
499                     try {
500                         socket.setSoTimeout(1);
501                         int byteRead = inputStream.read();
502                         if (byteRead == -1) {
503                             // again - if the socket is reporting all data read,
504
// probably stale
505
isStale = true;
506                         } else {
507                             inputStream.unread(byteRead);
508                         }
509                     } finally {
510                         socket.setSoTimeout(soTimeout);
511                     }
512                 }
513             } catch (InterruptedIOException JavaDoc e) {
514                 // aha - the connection is NOT stale - continue on!
515
} catch (IOException JavaDoc e) {
516                 // oops - the connection is stale, the read or soTimeout failed.
517
LOG.debug(
518                     "An error occurred while reading from the socket, is appears to be stale",
519                     e
520                 );
521                 isStale = true;
522             }
523         }
524
525         return isStale;
526     }
527
528     /**
529      * Returns <tt>true</tt> if the connection is established via a proxy,
530      * <tt>false</tt> otherwise.
531      *
532      * @return <tt>true</tt> if a proxy is used to establish the connection,
533      * <tt>false</tt> otherwise.
534      */

535     public boolean isProxied() {
536         return (!(null == proxyHostName || 0 >= proxyPortNumber));
537     }
538
539     /**
540      * Set the state to keep track of the last response for the last request.
541      *
542      * <p>The connection managers use this to ensure that previous requests are
543      * properly closed before a new request is attempted. That way, a GET
544      * request need not be read in its entirety before a new request is issued.
545      * Instead, this stream can be closed as appropriate.</p>
546      *
547      * @param inStream The stream associated with an HttpMethod.
548      */

549     public void setLastResponseInputStream(InputStream JavaDoc inStream) {
550         lastResponseInputStream = inStream;
551     }
552
553     /**
554      * Returns the stream used to read the last response's body.
555      *
556      * <p>Clients will generally not need to call this function unless
557      * using HttpConnection directly, instead of calling {@link HttpClient#executeMethod}.
558      * For those clients, call this function, and if it returns a non-null stream,
559      * close the stream before attempting to execute a method. Note that
560      * calling "close" on the stream returned by this function <i>may</i> close
561      * the connection if the previous response contained a "Connection: close" header. </p>
562      *
563      * @return An {@link InputStream} corresponding to the body of the last
564      * response.
565      */

566     public InputStream JavaDoc getLastResponseInputStream() {
567         return lastResponseInputStream;
568     }
569
570     // --------------------------------------------------- Other Public Methods
571

572     /**
573      * Sets the {@link Socket}'s timeout, via {@link Socket#setSoTimeout}. If the
574      * connection is already open, the SO_TIMEOUT is changed. If no connection
575      * is open, then subsequent connections will use the timeout value.
576      * <p>
577      * Note: This is not a connection timeout but a timeout on network traffic!
578      *
579      * @param timeout the timeout value
580      * @throws SocketException - if there is an error in the underlying
581      * protocol, such as a TCP error.
582      */

583     public void setSoTimeout(int timeout)
584         throws SocketException JavaDoc, IllegalStateException JavaDoc {
585         LOG.debug("HttpConnection.setSoTimeout(" + timeout + ")");
586         soTimeout = timeout;
587         if (socket != null) {
588             socket.setSoTimeout(timeout);
589         }
590     }
591
592     /**
593      * Returns the {@link Socket}'s timeout, via {@link Socket#getSoTimeout}, if the
594      * connection is already open. If no connection is open, return the value subsequent
595      * connection will use.
596      * <p>
597      * Note: This is not a connection timeout but a timeout on network traffic!
598      *
599      * @return the timeout value
600      */

601     public int getSoTimeout() throws SocketException JavaDoc {
602         LOG.debug("HttpConnection.getSoTimeout()");
603         if (this.socket != null) {
604             return this.socket.getSoTimeout();
605         } else {
606             return this.soTimeout;
607         }
608     }
609
610     /**
611      * Sets the connection timeout. This is the maximum time that may be spent
612      * until a connection is established. The connection will fail after this
613      * amount of time.
614      * @param timeout The timeout in milliseconds. 0 means timeout is not used.
615      */

616     public void setConnectionTimeout(int timeout) {
617         this.connectTimeout = timeout;
618     }
619
620     /**
621      * Establishes a connection to the specified host and port
622      * (via a proxy if specified).
623      * The underlying socket is created from the {@link ProtocolSocketFactory}.
624      *
625      * @throws IOException if an attempt to establish the connection results in an
626      * I/O error.
627      */

628     public void open() throws IOException JavaDoc {
629         LOG.trace("enter HttpConnection.open()");
630
631         assertNotOpen();
632         try {
633             if (null == socket) {
634
635                 final String JavaDoc host = (null == proxyHostName) ? hostName : proxyHostName;
636                 final int port = (null == proxyHostName) ? portNumber : proxyPortNumber;
637
638                 usingSecureSocket = isSecure() && !isProxied();
639
640                 // use the protocol's socket factory unless this is a secure
641
// proxied connection
642
final ProtocolSocketFactory socketFactory =
643                     (isSecure() && isProxied()
644                             ? new DefaultProtocolSocketFactory()
645                             : protocolInUse.getSocketFactory());
646
647                 if (connectTimeout == 0) {
648                     if (localAddress != null) {
649                         socket = socketFactory.createSocket(host, port, localAddress, 0);
650                     } else {
651                         socket = socketFactory.createSocket(host, port);
652                     }
653                 } else {
654                     SocketTask task = new SocketTask() {
655                         public void doit() throws IOException JavaDoc {
656                             if (localAddress != null) {
657                                 setSocket(socketFactory.createSocket(host, port, localAddress, 0));
658                             } else {
659                                 setSocket(socketFactory.createSocket(host, port));
660                             }
661                         }
662                     };
663                     TimeoutController.execute(task, connectTimeout);
664                     socket = task.getSocket();
665                     if (task.exception != null) {
666                         throw task.exception;
667                     }
668                 }
669
670             }
671
672             /*
673             "Nagling has been broadly implemented across networks,
674             including the Internet, and is generally performed by default
675             - although it is sometimes considered to be undesirable in
676             highly interactive environments, such as some client/server
677             situations. In such cases, nagling may be turned off through
678             use of the TCP_NODELAY sockets option." */

679
680             socket.setTcpNoDelay(soNodelay);
681             socket.setSoTimeout(soTimeout);
682             if (sendBufferSize != -1) {
683                 socket.setSendBufferSize(sendBufferSize);
684             }
685             int outbuffersize = socket.getSendBufferSize();
686             if (outbuffersize > 2048) {
687                 outbuffersize = 2048;
688             }
689             inputStream = new PushbackInputStream JavaDoc(socket.getInputStream());
690             outputStream = new BufferedOutputStream JavaDoc(
691                 new WrappedOutputStream(socket.getOutputStream()),
692                 outbuffersize
693             );
694             isOpen = true;
695             used = false;
696         } catch (IOException JavaDoc e) {
697             // Connection wasn't opened properly
698
// so close everything out
699
closeSocketAndStreams();
700             throw e;
701         } catch (TimeoutController.TimeoutException e) {
702             if (LOG.isWarnEnabled()) {
703                 LOG.warn("The host " + hostName + ":" + portNumber
704                         + " (or proxy " + proxyHostName + ":" + proxyPortNumber
705                         + ") did not accept the connection within timeout of "
706                         + connectTimeout + " milliseconds");
707             }
708             throw new ConnectionTimeoutException();
709         }
710     }
711
712     /**
713      * Instructs the proxy to establish a secure tunnel to the host. The socket will
714      * be switched to the secure socket. Subsequent communication is done via the secure
715      * socket. The method can only be called once on a proxied secure connection.
716      *
717      * @throws IllegalStateException if connection is not secure and proxied or
718      * if the socket is already secure.
719      * @throws IOException if an attempt to establish the secure tunnel results in an
720      * I/O error.
721      */

722     public void tunnelCreated() throws IllegalStateException JavaDoc, IOException JavaDoc {
723         LOG.trace("enter HttpConnection.tunnelCreated()");
724
725         if (!isSecure() || !isProxied()) {
726             throw new IllegalStateException JavaDoc(
727                 "Connection must be secure "
728                     + "and proxied to use this feature");
729         }
730
731         if (usingSecureSocket) {
732             throw new IllegalStateException JavaDoc("Already using a secure socket");
733         }
734
735         SecureProtocolSocketFactory socketFactory =
736             (SecureProtocolSocketFactory) protocolInUse.getSocketFactory();
737
738         socket = socketFactory.createSocket(socket, hostName, portNumber, true);
739         if (sendBufferSize != -1) {
740             socket.setSendBufferSize(sendBufferSize);
741         }
742         int outbuffersize = socket.getSendBufferSize();
743         if (outbuffersize > 2048) {
744             outbuffersize = 2048;
745         }
746         inputStream = new PushbackInputStream JavaDoc(socket.getInputStream());
747         outputStream = new BufferedOutputStream JavaDoc(
748             new WrappedOutputStream(socket.getOutputStream()),
749             outbuffersize
750         );
751         usingSecureSocket = true;
752         tunnelEstablished = true;
753         LOG.debug("Secure tunnel created");
754     }
755
756     /**
757      * Indicates if the connection is completely transparent from end to end.
758      *
759      * @return true if conncetion is not proxied or tunneled through a transparent
760      * proxy; false otherwise.
761      */

762     public boolean isTransparent() {
763         return !isProxied() || tunnelEstablished;
764     }
765
766     /**
767      * Flushes the output request stream. This method should be called to
768      * ensure that data written to the request OutputStream is sent to the server.
769      *
770      * @throws IOException if an I/O problem occurs
771      */

772     public void flushRequestOutputStream() throws IOException JavaDoc {
773         LOG.trace("enter HttpConnection.flushRequestOutputStream()");
774         assertOpen();
775         outputStream.flush();
776     }
777
778     /**
779      * Returns an {@link OutputStream} suitable for writing the request.
780      *
781      * @throws IllegalStateException if the connection is not open
782      * @throws IOException if an I/O problem occurs
783      * @return a stream to write the request to
784      */

785     public OutputStream JavaDoc getRequestOutputStream()
786         throws IOException JavaDoc, IllegalStateException JavaDoc {
787         LOG.trace("enter HttpConnection.getRequestOutputStream()");
788         assertOpen();
789         OutputStream JavaDoc out = this.outputStream;
790         if (Wire.CONTENT_WIRE.enabled()) {
791             out = new WireLogOutputStream(out, Wire.CONTENT_WIRE);
792         }
793         return out;
794     }
795
796     /**
797      * Returns an {@link OutputStream} suitable for writing the request.
798      *
799      * @param useChunking when <tt>true</tt> the chunked transfer-encoding will
800      * be used
801      * @throws IllegalStateException if the connection is not open
802      * @throws IOException if an I/O problem occurs
803      * @return a stream to write the request to
804      * @deprecated Use new ChunkedOutputStream(httpConnecion.getRequestOutputStream());
805      */

806     public OutputStream JavaDoc getRequestOutputStream(boolean useChunking)
807         throws IOException JavaDoc, IllegalStateException JavaDoc {
808         LOG.trace("enter HttpConnection.getRequestOutputStream(boolean)");
809
810         OutputStream JavaDoc out = getRequestOutputStream();
811         if (useChunking) {
812             out = new ChunkedOutputStream(out);
813         }
814         return out;
815     }
816
817     /**
818      * Return a {@link InputStream} suitable for reading the response.
819      * <p>
820      * If the given {@link HttpMethod} contains
821      * a <tt>Transfer-Encoding: chunked</tt> header,
822      * the returned stream will be configured
823      * to read chunked bytes.
824      *
825      * @param method This argument is ignored.
826      * @throws IllegalStateException if the connection is not open
827      * @throws IOException if an I/O problem occurs
828      * @return a stream to read the response from
829      * @deprecated Use getResponseInputStream() instead.
830      */

831     public InputStream JavaDoc getResponseInputStream(HttpMethod method)
832         throws IOException JavaDoc, IllegalStateException JavaDoc {
833         LOG.trace("enter HttpConnection.getResponseInputStream(HttpMethod)");
834         return getResponseInputStream();
835     }
836
837     /**
838      * Return a {@link InputStream} suitable for reading the response.
839      * @return InputStream The response input stream.
840      * @throws IOException If an IO problem occurs
841      * @throws IllegalStateException If the connection isn't open.
842      */

843     public InputStream JavaDoc getResponseInputStream()
844         throws IOException JavaDoc, IllegalStateException JavaDoc {
845         LOG.trace("enter HttpConnection.getResponseInputStream()");
846         assertOpen();
847         return inputStream;
848     }
849
850     /**
851      * Tests if input data avaialble. This method returns immediately
852      * and does not perform any read operations on the input socket
853      *
854      * @return boolean <tt>true</tt> if input data is available,
855      * <tt>false</tt> otherwise.
856      *
857      * @throws IOException If an IO problem occurs
858      * @throws IllegalStateException If the connection isn't open.
859      */

860     public boolean isResponseAvailable()
861         throws IOException JavaDoc {
862         LOG.trace("enter HttpConnection.isResponseAvailable()");
863         assertOpen();
864         return this.inputStream.available() > 0;
865     }
866
867     /**
868      * Tests if input data becomes available within the given period time in milliseconds.
869      *
870      * @param timeout The number milliseconds to wait for input data to become available
871      * @return boolean <tt>true</tt> if input data is availble,
872      * <tt>false</tt> otherwise.
873      *
874      * @throws IOException If an IO problem occurs
875      * @throws IllegalStateException If the connection isn't open.
876      */

877     public boolean isResponseAvailable(int timeout)
878         throws IOException JavaDoc {
879         LOG.trace("enter HttpConnection.isResponseAvailable(int)");
880         assertOpen();
881         boolean result = false;
882         if (this.inputStream.available() > 0) {
883             result = true;
884         } else {
885             try {
886                 this.socket.setSoTimeout(timeout);
887                 int byteRead = inputStream.read();
888                 if (byteRead != -1) {
889                     inputStream.unread(byteRead);
890                     LOG.debug("Input data available");
891                     result = true;
892                 } else {
893                     LOG.debug("Input data not available");
894                 }
895             } catch (InterruptedIOException JavaDoc e) {
896                 if (LOG.isDebugEnabled()) {
897                     LOG.debug("Input data not available after " + timeout + " ms");
898                 }
899             } finally {
900                 try {
901                     socket.setSoTimeout(soTimeout);
902                 } catch (IOException