View Javadoc
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