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