1 /*
2 * $Header: /home/cvs/jakarta-commons/httpclient/src/java/org/apache/commons/httpclient/MultiThreadedHttpConnectionManager.java,v 1.16 2003/05/08 17:33:52 olegk Exp $
3 * $Revision: 1.16 $
4 * $Date: 2003/05/08 17:33:52 $
5 *
6 * ====================================================================
7 *
8 * The Apache Software License, Version 1.1
9 *
10 * Copyright (c) 2002-2003 The Apache Software Foundation. All rights
11 * reserved.
12 *
13 * Redistribution and use in source and binary forms, with or without
14 * modification, are permitted provided that the following conditions
15 * are met:
16 *
17 * 1. Redistributions of source code must retain the above copyright
18 * notice, this list of conditions and the following disclaimer.
19 *
20 * 2. Redistributions in binary form must reproduce the above copyright
21 * notice, this list of conditions and the following disclaimer in
22 * the documentation and/or other materials provided with the
23 * distribution.
24 *
25 * 3. The end-user documentation included with the redistribution, if
26 * any, must include the following acknowlegement:
27 * "This product includes software developed by the
28 * Apache Software Foundation (http://www.apache.org/)."
29 * Alternately, this acknowlegement may appear in the software itself,
30 * if and wherever such third-party acknowlegements normally appear.
31 *
32 * 4. The names "The Jakarta Project", "Commons", and "Apache Software
33 * Foundation" must not be used to endorse or promote products derived
34 * from this software without prior written permission. For written
35 * permission, please contact apache@apache.org.
36 *
37 * 5. Products derived from this software may not be called "Apache"
38 * nor may "Apache" appear in their names without prior written
39 * permission of the Apache Group.
40 *
41 * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
42 * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
43 * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
44 * DISCLAIMED. IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
45 * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
46 * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
47 * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
48 * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
49 * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
50 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
51 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
52 * SUCH DAMAGE.
53 * ====================================================================
54 *
55 * This software consists of voluntary contributions made by many
56 * individuals on behalf of the Apache Software Foundation. For more
57 * information on the Apache Software Foundation, please see
58 * <http://www.apache.org/>.
59 *
60 * [Additional notices, if required by prior licensing conditions]
61 *
62 */
63
64 package org.apache.commons.httpclient;
65
66 import java.io.IOException;
67 import java.io.InputStream;
68 import java.io.OutputStream;
69 import java.lang.ref.Reference;
70 import java.lang.ref.ReferenceQueue;
71 import java.lang.ref.WeakReference;
72 import java.net.SocketException;
73 import java.util.Collections;
74 import java.util.HashMap;
75 import java.util.Iterator;
76 import java.util.LinkedList;
77 import java.util.Map;
78
79 import org.apache.commons.httpclient.protocol.Protocol;
80 import org.apache.commons.logging.Log;
81 import org.apache.commons.logging.LogFactory;
82
83 /***
84 * Manages a set of HttpConnections for various HostConfigurations.
85 *
86 * @author <a href="mailto:becke@u.washington.edu">Michael Becke</a>
87 * @author Eric Johnson
88 * @author <a href="mailto:mbowler@GargoyleSoftware.com">Mike Bowler</a>
89 * @author Carl A. Dunham
90 *
91 * @since 2.0
92 */
93 public class MultiThreadedHttpConnectionManager implements HttpConnectionManager {
94
95 // -------------------------------------------------------- Class Variables
96 /*** Log object for this class. */
97 private static final Log LOG = LogFactory.getLog(MultiThreadedHttpConnectionManager.class);
98
99 // ----------------------------------------------------- Instance Variables
100
101 /*** Maximum number of connections allowed per host */
102 private int maxHostConnections = 2; // Per RFC 2616 sec 8.1.4
103
104 /*** Maximum number of connections allowed overall */
105 private int maxTotalConnections = 20;
106
107 /*** Connection Pool */
108 private ConnectionPool connectionPool;
109
110 /*** mapping from reference to hostConfiguration */
111 private Map referenceToHostConfig;
112
113 /***
114 * the reference queue used to track when HttpConnections are lost to the
115 * garbage collector
116 */
117 private ReferenceQueue referenceQueue;
118
119 /***
120 * No-args constructor
121 */
122 public MultiThreadedHttpConnectionManager() {
123
124 this.referenceToHostConfig = Collections.synchronizedMap(new HashMap());
125 this.connectionPool = new ConnectionPool();
126
127 this.referenceQueue = new ReferenceQueue();
128
129 new ReferenceQueueThread().start();
130
131 }
132
133 /***
134 * Sets the maximum number of connections allowed for a given
135 * HostConfiguration. Per RFC 2616 section 8.1.4, this value defaults to 2.
136 *
137 * @param maxHostConnections the number of connections allowed for each
138 * hostConfiguration
139 */
140 public void setMaxConnectionsPerHost(int maxHostConnections) {
141 this.maxHostConnections = maxHostConnections;
142 }
143
144 /***
145 * Gets the maximum number of connections allowed for a given
146 * hostConfiguration.
147 *
148 * @return The maximum number of connections allowed for a given
149 * hostConfiguration.
150 */
151 public int getMaxConnectionsPerHost() {
152 return maxHostConnections;
153 }
154
155 /***
156 * Sets the maximum number of connections allowed in the system.
157 *
158 * @param maxTotalConnections the maximum number of connections allowed
159 */
160 public void setMaxTotalConnections(int maxTotalConnections) {
161 this.maxTotalConnections = maxTotalConnections;
162 }
163
164 /***
165 * Gets the maximum number of connections allowed in the system.
166 *
167 * @return The maximum number of connections allowed
168 */
169 public int getMaxTotalConnections() {
170 return maxTotalConnections;
171 }
172
173 /***
174 * @see HttpConnectionManager#getConnection(HostConfiguration)
175 */
176 public HttpConnection getConnection(HostConfiguration hostConfiguration) {
177
178 while (true) {
179 try {
180 return getConnection(hostConfiguration, 0);
181 } catch (HttpException e) {
182 // we'll go ahead and log this, but it should never happen. HttpExceptions
183 // are only thrown when the timeout occurs and since we have no timeout
184 // it should never happen.
185 LOG.debug(
186 "Unexpected exception while waiting for connection",
187 e
188 );
189 };
190 }
191 }
192
193 /***
194 * @see HttpConnectionManager#getConnection(HostConfiguration, long)
195 */
196 public HttpConnection getConnection(HostConfiguration hostConfiguration,
197 long timeout) throws HttpException {
198
199 LOG.trace("enter HttpConnectionManager.getConnection(HostConfiguration, long)");
200
201 if (hostConfiguration == null) {
202 throw new IllegalArgumentException("hostConfiguration is null");
203 }
204
205 if (LOG.isDebugEnabled()) {
206 LOG.debug("HttpConnectionManager.getConnection: config = "
207 + hostConfiguration + ", timeout = " + timeout);
208 }
209
210 final HttpConnection conn = doGetConnection(hostConfiguration, timeout);
211
212 // wrap the connection in an adapter so we can ensure it is used
213 // only once
214 return new HttpConnectionAdapter(conn);
215 }
216
217 /***
218 * Gets a connection or waits if one is not available. A connection is
219 * available if one exists that is not being used or if fewer than
220 * maxHostConnections have been created in the connectionPool, and fewer
221 * than maxTotalConnections have been created in all connectionPools.
222 *
223 * @param hostConfiguration The host configuration.
224 * @param timeout the number of milliseconds to wait for a connection, 0 to
225 * wait indefinitely
226 *
227 * @return HttpConnection an available connection
228 *
229 * @throws HttpException if a connection does not become available in
230 * 'timeout' milliseconds
231 */
232 private HttpConnection doGetConnection(HostConfiguration hostConfiguration,
233 long timeout) throws HttpException {
234
235 HttpConnection connection = null;
236
237 synchronized (connectionPool) {
238
239 // we clone the hostConfiguration
240 // so that it cannot be changed once the connection has been retrieved
241 hostConfiguration = new HostConfiguration(hostConfiguration);
242 HostConnectionPool hostPool = connectionPool.getHostPool(hostConfiguration);
243 WaitingThread waitingThread = null;
244
245 boolean useTimeout = (timeout > 0);
246 long timeToWait = timeout;
247 long startWait = 0;
248 long endWait = 0;
249
250 while (connection == null) {
251
252 // happen to have a free connection with the right specs
253 //
254 if (hostPool.freeConnections.size() > 0) {
255 connection = connectionPool.getFreeConnection(hostConfiguration);
256
257 // have room to make more
258 //
259 } else if ((hostPool.numConnections < maxHostConnections)
260 && (connectionPool.numConnections < maxTotalConnections)) {
261
262 connection = connectionPool.createConnection(hostConfiguration);
263
264 // have room to add host connection, and there is at least one free
265 // connection that can be liberated to make overall room
266 //
267 } else if ((hostPool.numConnections < maxHostConnections)
268 && (connectionPool.freeConnections.size() > 0)) {
269
270 connectionPool.deleteLeastUsedConnection();
271 connection = connectionPool.createConnection(hostConfiguration);
272
273 // otherwise, we have to wait for one of the above conditions to
274 // become true
275 //
276 } else {
277 // todo: keep track of which hostConfigurations have waiting
278 // threads, so they avoid being sacrificed before necessary
279
280 try {
281
282 if (useTimeout && timeToWait <= 0) {
283 throw new HttpException("Timeout waiting for connection");
284 }
285
286 if (LOG.isDebugEnabled()) {
287 LOG.debug("Waiting for a connection ");
288 }
289
290 if (waitingThread == null) {
291 waitingThread = new WaitingThread();
292 waitingThread.hostConnectionPool = hostPool;
293 waitingThread.thread = Thread.currentThread();
294 }
295
296 if (useTimeout) {
297 startWait = System.currentTimeMillis();
298 }
299
300 hostPool.waitingThreads.addLast(waitingThread);
301 connectionPool.waitingThreads.addLast(waitingThread);
302 connectionPool.wait(timeToWait);
303
304 // we have not been interrupted so we need to remove ourselves from the
305 // wait queue
306 hostPool.waitingThreads.remove(waitingThread);
307 connectionPool.waitingThreads.remove(waitingThread);
308 } catch (InterruptedException e) {
309 // do nothing
310 } finally {
311 if (useTimeout) {
312 endWait = System.currentTimeMillis();
313 timeToWait -= (endWait - startWait);
314 }
315 }
316 }
317 }
318 }
319 return connection;
320 }
321
322 /***
323 * Gets the number of connections in use for this configuration.
324 *
325 * @param hostConfiguration the key that connections are tracked on
326 * @return the number of connections in use
327 */
328 public int getConnectionsInUse(HostConfiguration hostConfiguration) {
329 synchronized (connectionPool) {
330 HostConnectionPool hostPool = connectionPool.getHostPool(hostConfiguration);
331 return hostPool.numConnections;
332 }
333 }
334
335 /***
336 * Gets the total number of connections in use.
337 *
338 * @return the total number of connections in use
339 */
340 public int getConnectionsInUse() {
341 synchronized (connectionPool) {
342 return connectionPool.numConnections;
343 }
344 }
345
346 /***
347 * Make the given HttpConnection available for use by other requests.
348 * If another thread is blocked in getConnection() that could use this
349 * connection, it will be woken up.
350 *
351 * @param conn the HttpConnection to make available.
352 */
353 public void releaseConnection(HttpConnection conn) {
354 LOG.trace("enter HttpConnectionManager.releaseConnection(HttpConnection)");
355
356 if (conn instanceof HttpConnectionAdapter) {
357 // connections given out are wrapped in an HttpConnectionAdapter
358 conn = ((HttpConnectionAdapter) conn).getWrappedConnection();
359 } else {
360 // this is okay, when an HttpConnectionAdapter is released
361 // is releases the real connection
362 }
363
364 // make sure that the response has been read.
365 SimpleHttpConnectionManager.finishLastResponse(conn);
366
367 connectionPool.freeConnection(conn);
368 }
369
370 /***
371 * Gets the host configuration for a connection.
372 * @param conn the connection to get the configuration of
373 * @return a new HostConfiguration
374 */
375 private HostConfiguration configurationForConnection(HttpConnection conn) {
376
377 HostConfiguration connectionConfiguration = new HostConfiguration();
378 connectionConfiguration.setHost(
379 conn.getHost(),
380 conn.getVirtualHost(),
381 conn.getPort(),
382 conn.getProtocol());
383 if (conn.getProxyHost() != null) {
384 connectionConfiguration.setProxy(conn.getProxyHost(), conn.getProxyPort());
385 }
386
387 return connectionConfiguration;
388 }
389
390
391 /***
392 * Global Connection Pool, including per-host pools
393 */
394 private class ConnectionPool {
395
396 /*** The list of free connections */
397 private LinkedList freeConnections = new LinkedList();
398
399 /*** The list of WaitingThreads waiting for a connection */
400 private LinkedList waitingThreads = new LinkedList();
401
402 /***
403 * Map where keys are {@link HostConfiguration}s and values are {@link
404 * HostConnectionPool}s
405 */
406 private final Map mapHosts = new HashMap();
407
408 /*** The number of created connections */
409 private int numConnections = 0;
410
411 /***
412 * Creates a new connection and returns is for use of the calling method.
413 *
414 * @param hostConfiguration the configuration for the connection
415 * @return a new connection or <code>null</code> if none are available
416 */
417 public synchronized HttpConnection createConnection(HostConfiguration hostConfiguration) {
418 HttpConnection connection = null;
419
420 HostConnectionPool hostPool = getHostPool(hostConfiguration);
421
422 if ((hostPool.numConnections < getMaxConnectionsPerHost())
423 && (numConnections < getMaxTotalConnections())) {
424
425 connection = new HttpConnection(hostConfiguration);
426 connection.setHttpConnectionManager(MultiThreadedHttpConnectionManager.this);
427 numConnections++;
428 hostPool.numConnections++;
429
430 // add a weak reference to this connection
431 referenceToHostConfig.put(new WeakReference(connection, referenceQueue),
432 hostConfiguration);
433 }
434 return connection;
435 }
436
437 /***
438 * Get the pool (list) of connections available for the given hostConfig.
439 *
440 * @param hostConfiguration the configuraton for the connection pool
441 * @return a pool (list) of connections available for the given config
442 */
443 public synchronized HostConnectionPool getHostPool(HostConfiguration hostConfiguration) {
444 LOG.trace("enter HttpConnectionManager.ConnectionPool.getHostPool(HostConfiguration)");
445
446 // Look for a list of connections for the given config
447 HostConnectionPool listConnections = (HostConnectionPool)
448 mapHosts.get(hostConfiguration);
449 if (listConnections == null) {
450 // First time for this config
451 listConnections = new HostConnectionPool();
452 mapHosts.put(hostConfiguration, listConnections);
453 }
454
455 return listConnections;
456 }
457
458 /***
459 * If available, get a free connection for this host
460 *
461 * @param hostConfiguration the configuraton for the connection pool
462 * @return an available connection for the given config
463 */
464 public synchronized HttpConnection getFreeConnection(HostConfiguration hostConfiguration) {
465
466 HttpConnection connection = null;
467
468 HostConnectionPool hostPool = getHostPool(hostConfiguration);
469
470 if (hostPool.freeConnections.size() > 0) {
471 connection = (HttpConnection) hostPool.freeConnections.removeFirst();
472 freeConnections.remove(connection);
473 }
474 return connection;
475 }
476
477 /***
478 * Close and delete an old, unused connection to make room for a new one.
479 */
480 public synchronized void deleteLeastUsedConnection() {
481
482 HttpConnection connection = (HttpConnection) freeConnections.removeFirst();
483
484 if (connection != null) {
485 HostConfiguration connectionConfiguration = configurationForConnection(connection);
486
487 if (LOG.isDebugEnabled()) {
488 LOG.debug("Reclaiming unused connection for hostConfig: "
489 + connectionConfiguration);
490 }
491
492 connection.close();
493
494 // make sure this connection will not be cleaned up again when garbage
495 // collected
496 for (Iterator iter = referenceToHostConfig.keySet().iterator(); iter.hasNext();) {
497 WeakReference connectionRef = (WeakReference) iter.next();
498 if (connectionRef.get() == connection) {
499 iter.remove();
500 connectionRef.enqueue();
501 break;
502 }
503 }
504
505 HostConnectionPool hostPool = getHostPool(connectionConfiguration);
506
507 hostPool.freeConnections.remove(connection);
508 hostPool.numConnections--;
509 numConnections--;
510 }
511 }
512
513 /***
514 * Notifies a waiting thread that a connection for the given configuration is
515 * available.
516 * @param configuration the host config to use for notifying
517 * @see #notifyWaitingThread(HostConnectionPool)
518 */
519 public synchronized void notifyWaitingThread(HostConfiguration configuration) {
520 notifyWaitingThread(getHostPool(configuration));
521 }
522
523 /***
524 * Notifies a waiting thread that a connection for the given configuration is
525 * available. This will wake a thread witing in tis hostPool or if there is not
526 * one a thread in the ConnectionPool will be notified.
527 *
528 * @param hostPool the host pool to use for notifying
529 */
530 public synchronized void notifyWaitingThread(HostConnectionPool hostPool) {
531
532 // find the thread we are going to notify, we want to ensure that each
533 // waiting thread is only interrupted once so we will remove it from
534 // all wait queues before interrupting it
535 WaitingThread waitingThread = null;
536
537 if (hostPool.waitingThreads.size() > 0) {
538 if (LOG.isDebugEnabled()) {
539 LOG.debug("Notifying thread waiting on hostPool");
540 }
541 waitingThread = (WaitingThread) hostPool.waitingThreads.removeFirst();
542 waitingThreads.remove(waitingThread);
543 } else if (waitingThreads.size() > 0) {
544 if (LOG.isDebugEnabled()) {
545 LOG.debug("Notifying next waiting thread");
546 }
547 waitingThread = (WaitingThread) waitingThreads.removeFirst();
548 waitingThread.hostConnectionPool.waitingThreads.remove(waitingThread);
549 } else if (LOG.isDebugEnabled()) {
550 LOG.debug("Notifying no-one, there are no waiting threads");
551 }
552
553 if (waitingThread != null) {
554 waitingThread.thread.interrupt();
555 }
556 }
557
558 /***
559 * Marks the given connection as free.
560 * @param conn a connection that is no longer being used
561 */
562 public void freeConnection(HttpConnection conn) {
563
564 HostConfiguration connectionConfiguration = configurationForConnection(conn);
565
566 if (LOG.isDebugEnabled()) {
567 LOG.debug("Freeing connection: " + conn);
568 }
569
570 synchronized (this) {
571 HostConnectionPool hostPool = getHostPool(connectionConfiguration);
572
573 // Put the connect back in the available list and notify a waiter
574 hostPool.freeConnections.add(conn);
575 if (hostPool.numConnections == 0) {
576 // for some reason this connection pool didn't already exist
577 LOG.error("host connection pool not found for: "
578 + connectionConfiguration);
579 hostPool.numConnections = 1;
580 }
581
582 freeConnections.add(conn);
583 if (numConnections == 0) {
584 // for some reason this connection pool didn't already exist
585 LOG.error("connection pool not found for: "
586 + connectionConfiguration);
587 numConnections = 1;
588 }
589
590 notifyWaitingThread(hostPool);
591 }
592
593 }
594 }
595
596 /***
597 * A simple struct-like class to combine the connection list and the count
598 * of created connections.
599 */
600 private class HostConnectionPool {
601 /*** The list of free connections */
602 public LinkedList freeConnections = new LinkedList();
603
604 /*** The list of WaitingThreads for this host */
605 public LinkedList waitingThreads = new LinkedList();
606
607 /*** The number of created connections */
608 public int numConnections = 0;
609 }
610
611 /***
612 * A simple struct-like class to combine the waiting thread and the connection
613 * pool it is waiting on.
614 */
615 private class WaitingThread {
616 /*** The thread that is waiting for a connection */
617 public Thread thread;
618
619 /*** The connection pool the thread is waiting for */
620 public HostConnectionPool hostConnectionPool;
621 }
622
623 /***
624 * A thread for listening for HttpConnections reclaimed by the garbage
625 * collector.
626 */
627 private class ReferenceQueueThread extends Thread {
628
629 /***
630 * Create an instance and make this a daemon thread.
631 */
632 public ReferenceQueueThread() {
633 setDaemon(true);
634 }
635
636 /***
637 * Handles cleaning up for the given reference. Decrements any connection counts
638 * and notifies waiting threads, if appropriate.
639 *
640 * @param ref the reference to clean up
641 */
642 private void handleReference(Reference ref) {
643 synchronized (connectionPool) {
644 // only clean up for this reference if it is still associated with
645 // a HostConfiguration
646 if (referenceToHostConfig.containsKey(ref)) {
647 HostConfiguration config = (HostConfiguration) referenceToHostConfig.get(ref);
648 referenceToHostConfig.remove(ref);
649
650 HostConnectionPool hostPool = connectionPool.getHostPool(config);
651 hostPool.numConnections--;
652
653 connectionPool.numConnections--;
654 connectionPool.notifyWaitingThread(config);
655 }
656 }
657 }
658
659 /***
660 * Start execution.
661 */
662 public void run() {
663 while (true) {
664 try {
665 Reference ref = referenceQueue.remove();
666 if (ref != null) {
667 handleReference(ref);
668 }
669 } catch (InterruptedException e) {
670 LOG.debug("ReferenceQueueThread interrupted", e);
671 }
672 }
673 }
674
675 }
676
677 /***
678 * An HttpConnection wrapper that ensures a connection cannot be used
679 * once released.
680 */
681 private static class HttpConnectionAdapter extends HttpConnection {
682
683 // the wrapped connection
684 private HttpConnection wrappedConnection;
685
686 /***
687 * Creates a new HttpConnectionAdapter.
688 * @param connection the connection to be wrapped
689 */
690 public HttpConnectionAdapter(HttpConnection connection) {
691 super(connection.getHost(), connection.getPort(), connection.getProtocol());
692 this.wrappedConnection = connection;
693 }
694
695 /***
696 * Tests if the wrapped connection is still available.
697 * @return boolean
698 */
699 protected boolean hasConnection() {
700 return wrappedConnection != null;
701 }
702
703 /***
704 * @return HttpConnection
705 */
706 HttpConnection getWrappedConnection() {
707 return wrappedConnection;
708 }
709
710 public void close() {
711 if (hasConnection()) {
712 wrappedConnection.close();
713 } else {
714 // do nothing
715 }
716 }
717
718 public String getHost() {
719 if (hasConnection()) {
720 return wrappedConnection.getHost();
721 } else {
722 return null;
723 }
724 }
725
726 public HttpConnectionManager getHttpConnectionManager() {
727 if (hasConnection()) {
728 return wrappedConnection.getHttpConnectionManager();
729 } else {
730 return null;
731 }
732 }
733
734 public InputStream getLastResponseInputStream() {
735 if (hasConnection()) {
736 return wrappedConnection.getLastResponseInputStream();
737 } else {
738 return null;
739 }
740 }
741
742 public int getPort() {
743 if (hasConnection()) {
744 return wrappedConnection.getPort();
745 } else {
746 return -1;
747 }
748 }
749
750 public Protocol getProtocol() {
751 if (hasConnection()) {
752 return wrappedConnection.getProtocol();
753 } else {
754 return null;
755 }
756 }
757
758 public String getProxyHost() {
759 if (hasConnection()) {
760 return wrappedConnection.getProxyHost();
761 } else {
762 return null;
763 }
764 }
765
766 public int getProxyPort() {
767 if (hasConnection()) {
768 return wrappedConnection.getProxyPort();
769 } else {
770 return -1;
771 }
772 }
773
774 public OutputStream getRequestOutputStream()
775 throws IOException, IllegalStateException {
776 if (hasConnection()) {
777 return wrappedConnection.getRequestOutputStream();
778 } else {
779 return null;
780 }
781 }
782
783 public OutputStream getRequestOutputStream(boolean useChunking)
784 throws IOException, IllegalStateException {
785 if (hasConnection()) {
786 return wrappedConnection.getRequestOutputStream(useChunking);
787 } else {
788 return null;
789 }
790 }
791
792 public InputStream getResponseInputStream()
793 throws IOException, IllegalStateException {
794 if (hasConnection()) {
795 return wrappedConnection.getResponseInputStream();
796 } else {
797 return null;
798 }
799 }
800
801 public InputStream getResponseInputStream(HttpMethod method)
802 throws IOException, IllegalStateException {
803 if (hasConnection()) {
804 return wrappedConnection.getResponseInputStream(method);
805 } else {
806 return null;
807 }
808 }
809
810 public boolean isOpen() {
811 if (hasConnection()) {
812 return wrappedConnection.isOpen();
813 } else {
814 return false;
815 }
816 }
817
818 public boolean isProxied() {
819 if (hasConnection()) {
820 return wrappedConnection.isProxied();
821 } else {
822 return false;
823 }
824 }
825
826 public boolean isResponseAvailable() throws IOException {
827 if (hasConnection()) {
828 return wrappedConnection.isResponseAvailable();
829 } else {
830 return false;
831 }
832 }
833
834 public boolean isResponseAvailable(int timeout) throws IOException {
835 if (hasConnection()) {
836 return wrappedConnection.isResponseAvailable(timeout);
837 } else {
838 return false;
839 }
840 }
841
842 public boolean isSecure() {
843 if (hasConnection()) {
844 return wrappedConnection.isSecure();
845 } else {
846 return false;
847 }
848 }
849
850 public boolean isTransparent() {
851 if (hasConnection()) {
852 return wrappedConnection.isTransparent();
853 } else {
854 return false;
855 }
856 }
857
858 public void open() throws IOException {
859 if (hasConnection()) {
860 wrappedConnection.open();
861 } else {
862 throw new IllegalStateException("Connection has been released");
863 }
864 }
865
866 public void print(String data)
867 throws IOException, IllegalStateException, HttpRecoverableException {
868 if (hasConnection()) {
869 wrappedConnection.print(data);
870 } else {
871 throw new IllegalStateException("Connection has been released");
872 }
873 }
874
875 public void printLine()
876 throws IOException, IllegalStateException, HttpRecoverableException {
877 if (hasConnection()) {
878 wrappedConnection.printLine();
879 } else {
880 throw new IllegalStateException("Connection has been released");
881 }
882 }
883
884 public void printLine(String data)
885 throws IOException, IllegalStateException, HttpRecoverableException {
886 if (hasConnection()) {
887 wrappedConnection.printLine(data);
888 } else {
889 throw new IllegalStateException("Connection has been released");
890 }
891 }
892
893 public String readLine() throws IOException, IllegalStateException {
894 if (hasConnection()) {
895 return wrappedConnection.readLine();
896 } else {
897 throw new IllegalStateException("Connection has been released");
898 }
899 }
900
901 public void releaseConnection() {
902 if (hasConnection()) {
903 HttpConnection wrappedConnection = this.wrappedConnection;
904 this.wrappedConnection = null;
905 wrappedConnection.releaseConnection();
906 } else {
907 // do nothing
908 }
909 }
910
911 public void setConnectionTimeout(int timeout) {
912 if (hasConnection()) {
913 wrappedConnection.setConnectionTimeout(timeout);
914 } else {
915 // do nothing
916 }
917 }
918
919 public void setHost(String host) throws IllegalStateException {
920 if (hasConnection()) {
921 wrappedConnection.setHost(host);
922 } else {
923 // do nothing
924 }
925 }
926
927 public void setHttpConnectionManager(HttpConnectionManager httpConnectionManager) {
928 if (hasConnection()) {
929 wrappedConnection.setHttpConnectionManager(httpConnectionManager);
930 } else {
931 // do nothing
932 }
933 }
934
935 public void setLastResponseInputStream(InputStream inStream) {
936 if (hasConnection()) {
937 wrappedConnection.setLastResponseInputStream(inStream);
938 } else {
939 // do nothing
940 }
941 }
942
943 public void setPort(int port) throws IllegalStateException {
944 if (hasConnection()) {
945 wrappedConnection.setPort(port);
946 } else {
947 // do nothing
948 }
949 }
950
951 public void setProtocol(Protocol protocol) {
952 if (hasConnection()) {
953 wrappedConnection.setProtocol(protocol);
954 } else {
955 // do nothing
956 }
957 }
958
959 public void setProxyHost(String host) throws IllegalStateException {
960 if (hasConnection()) {
961 wrappedConnection.setProxyHost(host);
962 } else {
963 // do nothing
964 }
965 }
966
967 public void setProxyPort(int port) throws IllegalStateException {
968 if (hasConnection()) {
969 wrappedConnection.setProxyPort(port);
970 } else {
971 // do nothing
972 }
973 }
974
975 public void setSecure(boolean secure) throws IllegalStateException {
976 if (hasConnection()) {
977 wrappedConnection.setSecure(secure);
978 } else {
979 // do nothing
980 }
981 }
982
983 public void setSoTimeout(int timeout)
984 throws SocketException, IllegalStateException {
985 if (hasConnection()) {
986 wrappedConnection.setSoTimeout(timeout);
987 } else {
988 // do nothing
989 }
990 }
991
992 public void shutdownOutput() {
993 if (hasConnection()) {
994 wrappedConnection.shutdownOutput();
995 } else {
996 // do nothing
997 }
998 }
999
1000 public void tunnelCreated() throws IllegalStateException, IOException {
1001 if (hasConnection()) {
1002 wrappedConnection.tunnelCreated();
1003 } else {
1004 // do nothing
1005 }
1006 }
1007
1008 public void write(byte[] data, int offset, int length)
1009 throws IOException, IllegalStateException, HttpRecoverableException {
1010 if (hasConnection()) {
1011 wrappedConnection.write(data, offset, length);
1012 } else {
1013 throw new IllegalStateException("Connection has been released");
1014 }
1015 }
1016
1017 public void write(byte[] data)
1018 throws IOException, IllegalStateException, HttpRecoverableException {
1019 if (hasConnection()) {
1020 wrappedConnection.write(data);
1021 } else {
1022 throw new IllegalStateException("Connection has been released");
1023 }
1024 }
1025
1026 public void writeLine()
1027 throws IOException, IllegalStateException, HttpRecoverableException {
1028 if (hasConnection()) {
1029 wrappedConnection.writeLine();
1030 } else {
1031 throw new IllegalStateException("Connection has been released");
1032 }
1033 }
1034
1035 public void writeLine(byte[] data)
1036 throws IOException, IllegalStateException, HttpRecoverableException {
1037 if (hasConnection()) {
1038 wrappedConnection.writeLine(data);
1039 } else {
1040 throw new IllegalStateException("Connection has been released");
1041 }
1042 }
1043
1044 public void flushRequestOutputStream() throws IOException {
1045 if (hasConnection()) {
1046 wrappedConnection.flushRequestOutputStream();
1047 } else {
1048 throw new IllegalStateException("Connection has been released");
1049 }
1050 }
1051
1052 public int getSoTimeout() throws SocketException {
1053 if (hasConnection()) {
1054 return wrappedConnection.getSoTimeout();
1055 } else {
1056 throw new IllegalStateException("Connection has been released");
1057 }
1058 }
1059
1060 public String getVirtualHost() {
1061 if (hasConnection()) {
1062 return wrappedConnection.getVirtualHost();
1063 } else {
1064 throw new IllegalStateException("Connection has been released");
1065 }
1066 }
1067
1068 public void setVirtualHost(String host) throws IllegalStateException {
1069 if (hasConnection()) {
1070 wrappedConnection.setVirtualHost(host);
1071 } else {
1072 throw new IllegalStateException("Connection has been released");
1073 }
1074 }
1075
1076 public int getSendBufferSize() throws SocketException {
1077 if (hasConnection()) {
1078 return wrappedConnection.getSendBufferSize();
1079 } else {
1080 throw new IllegalStateException("Connection has been released");
1081 }
1082 }
1083
1084 public void setSendBufferSize(int sendBufferSize) throws SocketException {
1085 if (hasConnection()) {
1086 wrappedConnection.setSendBufferSize(sendBufferSize);
1087 } else {
1088 throw new IllegalStateException("Connection has been released");
1089 }
1090 }
1091
1092 }
1093
1094 }
1095
This page was automatically generated by Maven