1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46 package edu.internet2.middleware.grouperInstallerExt.org.apache.commons.httpclient;
47
48 import java.io.IOException;
49 import java.io.InputStream;
50 import java.io.OutputStream;
51 import java.lang.ref.Reference;
52 import java.lang.ref.ReferenceQueue;
53 import java.lang.ref.WeakReference;
54 import java.net.InetAddress;
55 import java.net.SocketException;
56 import java.util.ArrayList;
57 import java.util.HashMap;
58 import java.util.Iterator;
59 import java.util.LinkedList;
60 import java.util.Map;
61 import java.util.WeakHashMap;
62
63 import edu.internet2.middleware.grouperInstallerExt.org.apache.commons.httpclient.params.HttpConnectionManagerParams;
64 import edu.internet2.middleware.grouperInstallerExt.org.apache.commons.httpclient.params.HttpConnectionParams;
65 import edu.internet2.middleware.grouperInstallerExt.org.apache.commons.httpclient.protocol.Protocol;
66 import edu.internet2.middleware.grouperInstallerExt.org.apache.commons.httpclient.util.IdleConnectionHandler;
67 import edu.internet2.middleware.grouperInstallerExt.org.apache.commons.logging.Log;
68 import edu.internet2.middleware.grouperInstallerExt.org.apache.commons.logging.LogFactory;
69
70
71
72
73
74
75
76
77
78
79
80 public class MultiThreadedHttpConnectionManager implements HttpConnectionManager {
81
82
83
84
85 private static final Log LOG = LogFactory.getLog(MultiThreadedHttpConnectionManager.class);
86
87
88 public static final int DEFAULT_MAX_HOST_CONNECTIONS = 2;
89
90
91 public static final int DEFAULT_MAX_TOTAL_CONNECTIONS = 20;
92
93
94
95
96
97 private static final Map REFERENCE_TO_CONNECTION_SOURCE = new HashMap();
98
99
100
101
102
103 private static final ReferenceQueue REFERENCE_QUEUE = new ReferenceQueue();
104
105
106
107
108 private static ReferenceQueueThread REFERENCE_QUEUE_THREAD;
109
110
111
112
113 private static WeakHashMap ALL_CONNECTION_MANAGERS = new WeakHashMap();
114
115
116
117
118
119
120
121
122
123
124
125
126 public static void shutdownAll() {
127
128 synchronized (REFERENCE_TO_CONNECTION_SOURCE) {
129
130 synchronized (ALL_CONNECTION_MANAGERS) {
131
132
133 MultiThreadedHttpConnectionManager[]
134 connManagers = (MultiThreadedHttpConnectionManager[])
135 ALL_CONNECTION_MANAGERS.keySet().toArray(
136 new MultiThreadedHttpConnectionManager
137 [ALL_CONNECTION_MANAGERS.size()]
138 );
139
140
141
142 for (int i=0; i<connManagers.length; i++) {
143 if (connManagers[i] != null)
144 connManagers[i].shutdown();
145 }
146 }
147
148
149 if (REFERENCE_QUEUE_THREAD != null) {
150 REFERENCE_QUEUE_THREAD.shutdown();
151 REFERENCE_QUEUE_THREAD = null;
152 }
153 REFERENCE_TO_CONNECTION_SOURCE.clear();
154 }
155 }
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174 private static void storeReferenceToConnection(
175 HttpConnectionWithReference connection,
176 HostConfiguration hostConfiguration,
177 ConnectionPool connectionPool
178 ) {
179
180 ConnectionSource source = new ConnectionSource();
181 source.connectionPool = connectionPool;
182 source.hostConfiguration = hostConfiguration;
183
184 synchronized (REFERENCE_TO_CONNECTION_SOURCE) {
185
186
187 if (REFERENCE_QUEUE_THREAD == null) {
188 REFERENCE_QUEUE_THREAD = new ReferenceQueueThread();
189 REFERENCE_QUEUE_THREAD.start();
190 }
191
192 REFERENCE_TO_CONNECTION_SOURCE.put(
193 connection.reference,
194 source
195 );
196 }
197 }
198
199
200
201
202
203 private static void shutdownCheckedOutConnections(ConnectionPool connectionPool) {
204
205
206 ArrayList connectionsToClose = new ArrayList();
207
208 synchronized (REFERENCE_TO_CONNECTION_SOURCE) {
209
210 Iterator referenceIter = REFERENCE_TO_CONNECTION_SOURCE.keySet().iterator();
211 while (referenceIter.hasNext()) {
212 Reference ref = (Reference) referenceIter.next();
213 ConnectionSource source =
214 (ConnectionSource) REFERENCE_TO_CONNECTION_SOURCE.get(ref);
215 if (source.connectionPool == connectionPool) {
216 referenceIter.remove();
217 HttpConnection../../../../edu/internet2/middleware/grouperInstallerExt/org/apache/commons/httpclient/HttpConnection.html#HttpConnection">HttpConnection connection = (HttpConnection) ref.get();
218 if (connection != null) {
219 connectionsToClose.add(connection);
220 }
221 }
222 }
223 }
224
225
226
227 for (Iterator i = connectionsToClose.iterator(); i.hasNext();) {
228 HttpConnection../../../../edu/internet2/middleware/grouperInstallerExt/org/apache/commons/httpclient/HttpConnection.html#HttpConnection">HttpConnection connection = (HttpConnection) i.next();
229 connection.close();
230
231
232 connection.setHttpConnectionManager(null);
233 connection.releaseConnection();
234 }
235 }
236
237
238
239
240
241
242
243
244
245 private static void removeReferenceToConnection(HttpConnectionWithReference connection) {
246
247 synchronized (REFERENCE_TO_CONNECTION_SOURCE) {
248 REFERENCE_TO_CONNECTION_SOURCE.remove(connection.reference);
249 }
250 }
251
252
253
254
255
256
257
258 private HttpConnectionManagerParamsllerExt/org/apache/commons/httpclient/params/HttpConnectionManagerParams.html#HttpConnectionManagerParams">HttpConnectionManagerParams params = new HttpConnectionManagerParams();
259
260
261 private ConnectionPool connectionPool;
262
263 private volatile boolean shutdown = false;
264
265
266
267
268
269
270
271 public MultiThreadedHttpConnectionManager() {
272 this.connectionPool = new ConnectionPool();
273 synchronized(ALL_CONNECTION_MANAGERS) {
274 ALL_CONNECTION_MANAGERS.put(this, null);
275 }
276 }
277
278
279
280
281
282
283
284
285
286
287
288
289 public synchronized void shutdown() {
290 synchronized (connectionPool) {
291 if (!shutdown) {
292 shutdown = true;
293 connectionPool.shutdown();
294 }
295 }
296 }
297
298
299
300
301
302
303
304
305
306
307
308 public boolean isConnectionStaleCheckingEnabled() {
309 return this.params.isStaleCheckingEnabled();
310 }
311
312
313
314
315
316
317
318
319
320
321
322
323 public void setConnectionStaleCheckingEnabled(boolean connectionStaleCheckingEnabled) {
324 this.params.setStaleCheckingEnabled(connectionStaleCheckingEnabled);
325 }
326
327
328
329
330
331
332
333
334
335
336
337 public void setMaxConnectionsPerHost(int maxHostConnections) {
338 this.params.setDefaultMaxConnectionsPerHost(maxHostConnections);
339 }
340
341
342
343
344
345
346
347
348
349
350
351 public int getMaxConnectionsPerHost() {
352 return this.params.getDefaultMaxConnectionsPerHost();
353 }
354
355
356
357
358
359
360
361
362
363 public void setMaxTotalConnections(int maxTotalConnections) {
364 this.params.setMaxTotalConnections(maxTotalConnections);
365 }
366
367
368
369
370
371
372
373
374
375 public int getMaxTotalConnections() {
376 return this.params.getMaxTotalConnections();
377 }
378
379
380
381
382 public HttpConnection getConnection(HostConfiguration hostConfiguration) {
383
384 while (true) {
385 try {
386 return getConnectionWithTimeout(hostConfiguration, 0);
387 } catch (ConnectionPoolTimeoutException e) {
388
389
390
391 LOG.debug(
392 "Unexpected exception while waiting for connection",
393 e
394 );
395 }
396 }
397 }
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417 public HttpConnection getConnectionWithTimeout(HostConfiguration hostConfiguration,
418 long timeout) throws ConnectionPoolTimeoutException {
419
420 LOG.trace("enter HttpConnectionManager.getConnectionWithTimeout(HostConfiguration, long)");
421
422 if (hostConfiguration == null) {
423 throw new IllegalArgumentException("hostConfiguration is null");
424 }
425
426 if (LOG.isDebugEnabled()) {
427 LOG.debug("HttpConnectionManager.getConnection: config = "
428 + hostConfiguration + ", timeout = " + timeout);
429 }
430
431 final HttpConnection conn = doGetConnection(hostConfiguration, timeout);
432
433
434
435 return new HttpConnectionAdapter(conn);
436 }
437
438
439
440
441
442
443 public HttpConnection getConnection(HostConfiguration hostConfiguration,
444 long timeout) throws HttpException {
445
446 LOG.trace("enter HttpConnectionManager.getConnection(HostConfiguration, long)");
447 try {
448 return getConnectionWithTimeout(hostConfiguration, timeout);
449 } catch(ConnectionPoolTimeoutException e) {
450 throw new HttpException(e.getMessage());
451 }
452 }
453
454 private HttpConnection doGetConnection(HostConfiguration hostConfiguration,
455 long timeout) throws ConnectionPoolTimeoutException {
456
457 HttpConnection connection = null;
458
459 int maxHostConnections = this.params.getMaxConnectionsPerHost(hostConfiguration);
460 int maxTotalConnections = this.params.getMaxTotalConnections();
461
462 synchronized (connectionPool) {
463
464
465
466 hostConfiguration = new HostConfiguration(hostConfiguration);
467 HostConnectionPool hostPool = connectionPool.getHostPool(hostConfiguration, true);
468 WaitingThread waitingThread = null;
469
470 boolean useTimeout = (timeout > 0);
471 long timeToWait = timeout;
472 long startWait = 0;
473 long endWait = 0;
474
475 while (connection == null) {
476
477 if (shutdown) {
478 throw new IllegalStateException("Connection factory has been shutdown.");
479 }
480
481
482
483 if (hostPool.freeConnections.size() > 0) {
484 connection = connectionPool.getFreeConnection(hostConfiguration);
485
486
487
488 } else if ((hostPool.numConnections < maxHostConnections)
489 && (connectionPool.numConnections < maxTotalConnections)) {
490
491 connection = connectionPool.createConnection(hostConfiguration);
492
493
494
495
496 } else if ((hostPool.numConnections < maxHostConnections)
497 && (connectionPool.freeConnections.size() > 0)) {
498
499 connectionPool.deleteLeastUsedConnection();
500 connection = connectionPool.createConnection(hostConfiguration);
501
502
503
504
505 } else {
506
507
508
509 try {
510
511 if (useTimeout && timeToWait <= 0) {
512 throw new ConnectionPoolTimeoutException("Timeout waiting for connection");
513 }
514
515 if (LOG.isDebugEnabled()) {
516 LOG.debug("Unable to get a connection, waiting..., hostConfig=" + hostConfiguration);
517 }
518
519 if (waitingThread == null) {
520 waitingThread = new WaitingThread();
521 waitingThread.hostConnectionPool = hostPool;
522 waitingThread.thread = Thread.currentThread();
523 } else {
524 waitingThread.interruptedByConnectionPool = false;
525 }
526
527 if (useTimeout) {
528 startWait = System.currentTimeMillis();
529 }
530
531 hostPool.waitingThreads.addLast(waitingThread);
532 connectionPool.waitingThreads.addLast(waitingThread);
533 connectionPool.wait(timeToWait);
534 } catch (InterruptedException e) {
535 if (!waitingThread.interruptedByConnectionPool) {
536 LOG.debug("Interrupted while waiting for connection", e);
537 throw new IllegalThreadStateException(
538 "Interrupted while waiting in MultiThreadedHttpConnectionManager");
539 }
540
541
542
543 } finally {
544 if (!waitingThread.interruptedByConnectionPool) {
545
546
547
548 hostPool.waitingThreads.remove(waitingThread);
549 connectionPool.waitingThreads.remove(waitingThread);
550 }
551
552 if (useTimeout) {
553 endWait = System.currentTimeMillis();
554 timeToWait -= (endWait - startWait);
555 }
556 }
557 }
558 }
559 }
560 return connection;
561 }
562
563
564
565
566
567
568
569
570
571
572
573 public int getConnectionsInPool(HostConfiguration hostConfiguration) {
574 synchronized (connectionPool) {
575 HostConnectionPool hostPool = connectionPool.getHostPool(hostConfiguration, false);
576 return (hostPool != null) ? hostPool.numConnections : 0;
577 }
578 }
579
580
581
582
583
584
585
586
587
588 public int getConnectionsInPool() {
589 synchronized (connectionPool) {
590 return connectionPool.numConnections;
591 }
592 }
593
594
595
596
597
598
599
600
601
602 public int getConnectionsInUse(HostConfiguration hostConfiguration) {
603 return getConnectionsInPool(hostConfiguration);
604 }
605
606
607
608
609
610
611
612
613 public int getConnectionsInUse() {
614 return getConnectionsInPool();
615 }
616
617
618
619
620
621
622
623
624
625 public void deleteClosedConnections() {
626 connectionPool.deleteClosedConnections();
627 }
628
629
630
631
632 public void closeIdleConnections(long idleTimeout) {
633 connectionPool.closeIdleConnections(idleTimeout);
634 deleteClosedConnections();
635 }
636
637
638
639
640
641
642
643
644 public void releaseConnection(HttpConnection conn) {
645 LOG.trace("enter HttpConnectionManager.releaseConnection(HttpConnection)");
646
647 if (conn instanceof HttpConnectionAdapter) {
648
649 conn = ((HttpConnectionAdapter) conn).getWrappedConnection();
650 } else {
651
652
653 }
654
655
656 SimpleHttpConnectionManager.finishLastResponse(conn);
657
658 connectionPool.freeConnection(conn);
659 }
660
661
662
663
664
665
666 private HostConfiguration configurationForConnection(HttpConnection conn) {
667
668 HostConfiguration/org/apache/commons/httpclient/HostConfiguration.html#HostConfiguration">HostConfiguration connectionConfiguration = new HostConfiguration();
669
670 connectionConfiguration.setHost(
671 conn.getHost(),
672 conn.getPort(),
673 conn.getProtocol()
674 );
675 if (conn.getLocalAddress() != null) {
676 connectionConfiguration.setLocalAddress(conn.getLocalAddress());
677 }
678 if (conn.getProxyHost() != null) {
679 connectionConfiguration.setProxy(conn.getProxyHost(), conn.getProxyPort());
680 }
681
682 return connectionConfiguration;
683 }
684
685
686
687
688
689
690
691
692
693 public HttpConnectionManagerParams getParams() {
694 return this.params;
695 }
696
697
698
699
700
701
702
703
704
705 public void setParams(final HttpConnectionManagerParams params) {
706 if (params == null) {
707 throw new IllegalArgumentException("Parameters may not be null");
708 }
709 this.params = params;
710 }
711
712
713
714
715 private class ConnectionPool {
716
717
718 private LinkedList freeConnections = new LinkedList();
719
720
721 private LinkedList waitingThreads = new LinkedList();
722
723
724
725
726
727 private final Map mapHosts = new HashMap();
728
729 private IdleConnectionHandlerrg/apache/commons/httpclient/util/IdleConnectionHandler.html#IdleConnectionHandler">IdleConnectionHandler idleConnectionHandler = new IdleConnectionHandler();
730
731
732 private int numConnections = 0;
733
734
735
736
737 public synchronized void shutdown() {
738
739
740 Iterator iter = freeConnections.iterator();
741 while (iter.hasNext()) {
742 HttpConnection../../../../../../edu/internet2/middleware/grouperInstallerExt/org/apache/commons/httpclient/HttpConnection.html#HttpConnection">HttpConnection conn = (HttpConnection) iter.next();
743 iter.remove();
744 conn.close();
745 }
746
747
748 shutdownCheckedOutConnections(this);
749
750
751 iter = waitingThreads.iterator();
752 while (iter.hasNext()) {
753 WaitingThread waiter = (WaitingThread) iter.next();
754 iter.remove();
755 waiter.interruptedByConnectionPool = true;
756 waiter.thread.interrupt();
757 }
758
759
760 mapHosts.clear();
761
762
763 idleConnectionHandler.removeAll();
764 }
765
766
767
768
769
770
771
772 public synchronized HttpConnection createConnection(HostConfiguration hostConfiguration) {
773 HostConnectionPool hostPool = getHostPool(hostConfiguration, true);
774 if (LOG.isDebugEnabled()) {
775 LOG.debug("Allocating new connection, hostConfig=" + hostConfiguration);
776 }
777 HttpConnectionWithReference connection = new HttpConnectionWithReference(
778 hostConfiguration);
779 connection.getParams().setDefaults(MultiThreadedHttpConnectionManager.this.params);
780 connection.setHttpConnectionManager(MultiThreadedHttpConnectionManager.this);
781 numConnections++;
782 hostPool.numConnections++;
783
784
785
786 storeReferenceToConnection(connection, hostConfiguration, this);
787 return connection;
788 }
789
790
791
792
793
794
795
796 public synchronized void handleLostConnection(HostConfiguration config) {
797 HostConnectionPool hostPool = getHostPool(config, true);
798 hostPool.numConnections--;
799 if ((hostPool.numConnections == 0) &&
800 hostPool.waitingThreads.isEmpty()) {
801
802 mapHosts.remove(config);
803 }
804
805 numConnections--;
806 notifyWaitingThread(config);
807 }
808
809
810
811
812
813
814
815
816
817
818
819 public synchronized HostConnectionPool getHostPool(HostConfiguration hostConfiguration, boolean create) {
820 LOG.trace("enter HttpConnectionManager.ConnectionPool.getHostPool(HostConfiguration)");
821
822
823 HostConnectionPool listConnections = (HostConnectionPool)
824 mapHosts.get(hostConfiguration);
825 if ((listConnections == null) && create) {
826
827 listConnections = new HostConnectionPool();
828 listConnections.hostConfiguration = hostConfiguration;
829 mapHosts.put(hostConfiguration, listConnections);
830 }
831
832 return listConnections;
833 }
834
835
836
837
838
839
840
841 public synchronized HttpConnection getFreeConnection(HostConfiguration hostConfiguration) {
842
843 HttpConnectionWithReference connection = null;
844
845 HostConnectionPool hostPool = getHostPool(hostConfiguration, false);
846
847 if ((hostPool != null) && (hostPool.freeConnections.size() > 0)) {
848 connection = (HttpConnectionWithReference) hostPool.freeConnections.removeLast();
849 freeConnections.remove(connection);
850
851
852 storeReferenceToConnection(connection, hostConfiguration, this);
853 if (LOG.isDebugEnabled()) {
854 LOG.debug("Getting free connection, hostConfig=" + hostConfiguration);
855 }
856
857
858 idleConnectionHandler.remove(connection);
859 } else if (LOG.isDebugEnabled()) {
860 LOG.debug("There were no free connections to get, hostConfig="
861 + hostConfiguration);
862 }
863 return connection;
864 }
865
866
867
868
869 public synchronized void deleteClosedConnections() {
870
871 Iterator iter = freeConnections.iterator();
872
873 while (iter.hasNext()) {
874 HttpConnection../../../../../../edu/internet2/middleware/grouperInstallerExt/org/apache/commons/httpclient/HttpConnection.html#HttpConnection">HttpConnection conn = (HttpConnection) iter.next();
875 if (!conn.isOpen()) {
876 iter.remove();
877 deleteConnection(conn);
878 }
879 }
880 }
881
882
883
884
885
886 public synchronized void closeIdleConnections(long idleTimeout) {
887 idleConnectionHandler.closeIdleConnections(idleTimeout);
888 }
889
890
891
892
893
894
895
896
897
898
899 private synchronized void deleteConnection(HttpConnection connection) {
900
901 HostConfiguration connectionConfiguration = configurationForConnection(connection);
902
903 if (LOG.isDebugEnabled()) {
904 LOG.debug("Reclaiming connection, hostConfig=" + connectionConfiguration);
905 }
906
907 connection.close();
908
909 HostConnectionPool hostPool = getHostPool(connectionConfiguration, true);
910
911 hostPool.freeConnections.remove(connection);
912 hostPool.numConnections--;
913 numConnections--;
914 if ((hostPool.numConnections == 0) &&
915 hostPool.waitingThreads.isEmpty()) {
916
917 mapHosts.remove(connectionConfiguration);
918 }
919
920
921 idleConnectionHandler.remove(connection);
922 }
923
924
925
926
927 public synchronized void deleteLeastUsedConnection() {
928
929 HttpConnection../../../../edu/internet2/middleware/grouperInstallerExt/org/apache/commons/httpclient/HttpConnection.html#HttpConnection">HttpConnection connection = (HttpConnection) freeConnections.removeFirst();
930
931 if (connection != null) {
932 deleteConnection(connection);
933 } else if (LOG.isDebugEnabled()) {
934 LOG.debug("Attempted to reclaim an unused connection but there were none.");
935 }
936 }
937
938
939
940
941
942
943
944 public synchronized void notifyWaitingThread(HostConfiguration configuration) {
945 notifyWaitingThread(getHostPool(configuration, true));
946 }
947
948
949
950
951
952
953
954
955 public synchronized void notifyWaitingThread(HostConnectionPool hostPool) {
956
957
958
959
960 WaitingThread waitingThread = null;
961
962 if (hostPool.waitingThreads.size() > 0) {
963 if (LOG.isDebugEnabled()) {
964 LOG.debug("Notifying thread waiting on host pool, hostConfig="
965 + hostPool.hostConfiguration);
966 }
967 waitingThread = (WaitingThread) hostPool.waitingThreads.removeFirst();
968 waitingThreads.remove(waitingThread);
969 } else if (waitingThreads.size() > 0) {
970 if (LOG.isDebugEnabled()) {
971 LOG.debug("No-one waiting on host pool, notifying next waiting thread.");
972 }
973 waitingThread = (WaitingThread) waitingThreads.removeFirst();
974 waitingThread.hostConnectionPool.waitingThreads.remove(waitingThread);
975 } else if (LOG.isDebugEnabled()) {
976 LOG.debug("Notifying no-one, there are no waiting threads");
977 }
978
979 if (waitingThread != null) {
980 waitingThread.interruptedByConnectionPool = true;
981 waitingThread.thread.interrupt();
982 }
983 }
984
985
986
987
988
989 public void freeConnection(HttpConnection conn) {
990
991 HostConfiguration connectionConfiguration = configurationForConnection(conn);
992
993 if (LOG.isDebugEnabled()) {
994 LOG.debug("Freeing connection, hostConfig=" + connectionConfiguration);
995 }
996
997 synchronized (this) {
998
999 if (shutdown) {
1000
1001
1002 conn.close();
1003 return;
1004 }
1005
1006 HostConnectionPool hostPool = getHostPool(connectionConfiguration, true);
1007
1008
1009 hostPool.freeConnections.add(conn);
1010 if (hostPool.numConnections == 0) {
1011
1012 LOG.error("Host connection pool not found, hostConfig="
1013 + connectionConfiguration);
1014 hostPool.numConnections = 1;
1015 }
1016
1017 freeConnections.add(conn);
1018
1019
1020 removeReferenceToConnection((HttpConnectionWithReference) conn);
1021 if (numConnections == 0) {
1022
1023 LOG.error("Host connection pool not found, hostConfig="
1024 + connectionConfiguration);
1025 numConnections = 1;
1026 }
1027
1028
1029 idleConnectionHandler.add(conn);
1030
1031 notifyWaitingThread(hostPool);
1032 }
1033 }
1034 }
1035
1036
1037
1038
1039
1040 private static class ConnectionSource {
1041
1042
1043 public ConnectionPool connectionPool;
1044
1045
1046 public HostConfiguration hostConfiguration;
1047 }
1048
1049
1050
1051
1052
1053 private static class HostConnectionPool {
1054
1055 public HostConfiguration hostConfiguration;
1056
1057
1058 public LinkedList freeConnections = new LinkedList();
1059
1060
1061 public LinkedList waitingThreads = new LinkedList();
1062
1063
1064 public int numConnections = 0;
1065 }
1066
1067
1068
1069
1070
1071 private static class WaitingThread {
1072
1073 public Thread thread;
1074
1075
1076 public HostConnectionPool hostConnectionPool;
1077
1078
1079
1080
1081 public boolean interruptedByConnectionPool = false;
1082 }
1083
1084
1085
1086
1087
1088 private static class ReferenceQueueThread extends Thread {
1089
1090 private volatile boolean shutdown = false;
1091
1092
1093
1094
1095 public ReferenceQueueThread() {
1096 setDaemon(true);
1097 setName("MultiThreadedHttpConnectionManager cleanup");
1098 }
1099
1100 public void shutdown() {
1101 this.shutdown = true;
1102 this.interrupt();
1103 }
1104
1105
1106
1107
1108
1109
1110 private void handleReference(Reference ref) {
1111
1112 ConnectionSource source = null;
1113
1114 synchronized (REFERENCE_TO_CONNECTION_SOURCE) {
1115 source = (ConnectionSource) REFERENCE_TO_CONNECTION_SOURCE.remove(ref);
1116 }
1117
1118
1119 if (source != null) {
1120 if (LOG.isDebugEnabled()) {
1121 LOG.debug(
1122 "Connection reclaimed by garbage collector, hostConfig="
1123 + source.hostConfiguration);
1124 }
1125
1126 source.connectionPool.handleLostConnection(source.hostConfiguration);
1127 }
1128 }
1129
1130
1131
1132
1133 public void run() {
1134 while (!shutdown) {
1135 try {
1136
1137 Reference ref = REFERENCE_QUEUE.remove();
1138 if (ref != null) {
1139 handleReference(ref);
1140 }
1141 } catch (InterruptedException e) {
1142 LOG.debug("ReferenceQueueThread interrupted", e);
1143 }
1144 }
1145 }
1146
1147 }
1148
1149
1150
1151
1152 private static class HttpConnectionWithReference extends HttpConnection {
1153
1154 public WeakReference reference = new WeakReference(this, REFERENCE_QUEUE);
1155
1156
1157
1158
1159 public HttpConnectionWithReference(HostConfiguration hostConfiguration) {
1160 super(hostConfiguration);
1161 }
1162
1163 }
1164
1165
1166
1167
1168
1169 private static class HttpConnectionAdapter extends HttpConnection {
1170
1171
1172 private HttpConnection wrappedConnection;
1173
1174
1175
1176
1177
1178 public HttpConnectionAdapter(HttpConnection connection) {
1179 super(connection.getHost(), connection.getPort(), connection.getProtocol());
1180 this.wrappedConnection = connection;
1181 }
1182
1183
1184
1185
1186
1187 protected boolean hasConnection() {
1188 return wrappedConnection != null;
1189 }
1190
1191
1192
1193
1194 HttpConnection getWrappedConnection() {
1195 return wrappedConnection;
1196 }
1197
1198 public void close() {
1199 if (hasConnection()) {
1200 wrappedConnection.close();
1201 } else {
1202
1203 }
1204 }
1205
1206 public InetAddress getLocalAddress() {
1207 if (hasConnection()) {
1208 return wrappedConnection.getLocalAddress();
1209 } else {
1210 return null;
1211 }
1212 }
1213
1214
1215
1216
1217 public boolean isStaleCheckingEnabled() {
1218 if (hasConnection()) {
1219 return wrappedConnection.isStaleCheckingEnabled();
1220 } else {
1221 return false;
1222 }
1223 }
1224
1225 public void setLocalAddress(InetAddress localAddress) {
1226 if (hasConnection()) {
1227 wrappedConnection.setLocalAddress(localAddress);
1228 } else {
1229 throw new IllegalStateException("Connection has been released");
1230 }
1231 }
1232
1233
1234
1235
1236 public void setStaleCheckingEnabled(boolean staleCheckEnabled) {
1237 if (hasConnection()) {
1238 wrappedConnection.setStaleCheckingEnabled(staleCheckEnabled);
1239 } else {
1240 throw new IllegalStateException("Connection has been released");
1241 }
1242 }
1243
1244 public String getHost() {
1245 if (hasConnection()) {
1246 return wrappedConnection.getHost();
1247 } else {
1248 return null;
1249 }
1250 }
1251
1252 public HttpConnectionManager getHttpConnectionManager() {
1253 if (hasConnection()) {
1254 return wrappedConnection.getHttpConnectionManager();
1255 } else {
1256 return null;
1257 }
1258 }
1259
1260 public InputStream getLastResponseInputStream() {
1261 if (hasConnection()) {
1262 return wrappedConnection.getLastResponseInputStream();
1263 } else {
1264 return null;
1265 }
1266 }
1267
1268 public int getPort() {
1269 if (hasConnection()) {
1270 return wrappedConnection.getPort();
1271 } else {
1272 return -1;
1273 }
1274 }
1275
1276 public Protocol getProtocol() {
1277 if (hasConnection()) {
1278 return wrappedConnection.getProtocol();
1279 } else {
1280 return null;
1281 }
1282 }
1283
1284 public String getProxyHost() {
1285 if (hasConnection()) {
1286 return wrappedConnection.getProxyHost();
1287 } else {
1288 return null;
1289 }
1290 }
1291
1292 public int getProxyPort() {
1293 if (hasConnection()) {
1294 return wrappedConnection.getProxyPort();
1295 } else {
1296 return -1;
1297 }
1298 }
1299
1300 public OutputStream getRequestOutputStream()
1301 throws IOException, IllegalStateException {
1302 if (hasConnection()) {
1303 return wrappedConnection.getRequestOutputStream();
1304 } else {
1305 return null;
1306 }
1307 }
1308
1309 public InputStream getResponseInputStream()
1310 throws IOException, IllegalStateException {
1311 if (hasConnection()) {
1312 return wrappedConnection.getResponseInputStream();
1313 } else {
1314 return null;
1315 }
1316 }
1317
1318 public boolean isOpen() {
1319 if (hasConnection()) {
1320 return wrappedConnection.isOpen();
1321 } else {
1322 return false;
1323 }
1324 }
1325
1326 public boolean closeIfStale() throws IOException {
1327 if (hasConnection()) {
1328 return wrappedConnection.closeIfStale();
1329 } else {
1330 return false;
1331 }
1332 }
1333
1334 public boolean isProxied() {
1335 if (hasConnection()) {
1336 return wrappedConnection.isProxied();
1337 } else {
1338 return false;
1339 }
1340 }
1341
1342 public boolean isResponseAvailable() throws IOException {
1343 if (hasConnection()) {
1344 return wrappedConnection.isResponseAvailable();
1345 } else {
1346 return false;
1347 }
1348 }
1349
1350 public boolean isResponseAvailable(int timeout) throws IOException {
1351 if (hasConnection()) {
1352 return wrappedConnection.isResponseAvailable(timeout);
1353 } else {
1354 return false;
1355 }
1356 }
1357
1358 public boolean isSecure() {
1359 if (hasConnection()) {
1360 return wrappedConnection.isSecure();
1361 } else {
1362 return false;
1363 }
1364 }
1365
1366 public boolean isTransparent() {
1367 if (hasConnection()) {
1368 return wrappedConnection.isTransparent();
1369 } else {
1370 return false;
1371 }
1372 }
1373
1374 public void open() throws IOException {
1375 if (hasConnection()) {
1376 wrappedConnection.open();
1377 } else {
1378 throw new IllegalStateException("Connection has been released");
1379 }
1380 }
1381
1382
1383
1384
1385 public void print(String data)
1386 throws IOException, IllegalStateException {
1387 if (hasConnection()) {
1388 wrappedConnection.print(data);
1389 } else {
1390 throw new IllegalStateException("Connection has been released");
1391 }
1392 }
1393
1394 public void printLine()
1395 throws IOException, IllegalStateException {
1396 if (hasConnection()) {
1397 wrappedConnection.printLine();
1398 } else {
1399 throw new IllegalStateException("Connection has been released");
1400 }
1401 }
1402
1403
1404
1405
1406 public void printLine(String data)
1407 throws IOException, IllegalStateException {
1408 if (hasConnection()) {
1409 wrappedConnection.printLine(data);
1410 } else {
1411 throw new IllegalStateException("Connection has been released");
1412 }
1413 }
1414
1415
1416
1417
1418 public String readLine() throws IOException, IllegalStateException {
1419 if (hasConnection()) {
1420 return wrappedConnection.readLine();
1421 } else {
1422 throw new IllegalStateException("Connection has been released");
1423 }
1424 }
1425
1426 public String readLine(String charset) throws IOException, IllegalStateException {
1427 if (hasConnection()) {
1428 return wrappedConnection.readLine(charset);
1429 } else {
1430 throw new IllegalStateException("Connection has been released");
1431 }
1432 }
1433
1434 public void releaseConnection() {
1435 if (!isLocked() && hasConnection()) {
1436 HttpConnection wrappedConnection = this.wrappedConnection;
1437 this.wrappedConnection = null;
1438 wrappedConnection.releaseConnection();
1439 } else {
1440
1441 }
1442 }
1443
1444
1445
1446
1447 public void setConnectionTimeout(int timeout) {
1448 if (hasConnection()) {
1449 wrappedConnection.setConnectionTimeout(timeout);
1450 } else {
1451
1452 }
1453 }
1454
1455 public void setHost(String host) throws IllegalStateException {
1456 if (hasConnection()) {
1457 wrappedConnection.setHost(host);
1458 } else {
1459
1460 }
1461 }
1462
1463 public void setHttpConnectionManager(HttpConnectionManager httpConnectionManager) {
1464 if (hasConnection()) {
1465 wrappedConnection.setHttpConnectionManager(httpConnectionManager);
1466 } else {
1467
1468 }
1469 }
1470
1471 public void setLastResponseInputStream(InputStream inStream) {
1472 if (hasConnection()) {
1473 wrappedConnection.setLastResponseInputStream(inStream);
1474 } else {
1475
1476 }
1477 }
1478
1479 public void setPort(int port) throws IllegalStateException {
1480 if (hasConnection()) {
1481 wrappedConnection.setPort(port);
1482 } else {
1483
1484 }
1485 }
1486
1487 public void setProtocol(Protocol protocol) {
1488 if (hasConnection()) {
1489 wrappedConnection.setProtocol(protocol);
1490 } else {
1491
1492 }
1493 }
1494
1495 public void setProxyHost(String host) throws IllegalStateException {
1496 if (hasConnection()) {
1497 wrappedConnection.setProxyHost(host);
1498 } else {
1499
1500 }
1501 }
1502
1503 public void setProxyPort(int port) throws IllegalStateException {
1504 if (hasConnection()) {
1505 wrappedConnection.setProxyPort(port);
1506 } else {
1507
1508 }
1509 }
1510
1511
1512
1513
1514 public void setSoTimeout(int timeout)
1515 throws SocketException, IllegalStateException {
1516 if (hasConnection()) {
1517 wrappedConnection.setSoTimeout(timeout);
1518 } else {
1519
1520 }
1521 }
1522
1523
1524
1525
1526 public void shutdownOutput() {
1527 if (hasConnection()) {
1528 wrappedConnection.shutdownOutput();
1529 } else {
1530
1531 }
1532 }
1533
1534 public void tunnelCreated() throws IllegalStateException, IOException {
1535 if (hasConnection()) {
1536 wrappedConnection.tunnelCreated();
1537 } else {
1538
1539 }
1540 }
1541
1542 public void write(byte[] data, int offset, int length)
1543 throws IOException, IllegalStateException {
1544 if (hasConnection()) {
1545 wrappedConnection.write(data, offset, length);
1546 } else {
1547 throw new IllegalStateException("Connection has been released");
1548 }
1549 }
1550
1551 public void write(byte[] data)
1552 throws IOException, IllegalStateException {
1553 if (hasConnection()) {
1554 wrappedConnection.write(data);
1555 } else {
1556 throw new IllegalStateException("Connection has been released");
1557 }
1558 }
1559
1560 public void writeLine()
1561 throws IOException, IllegalStateException {
1562 if (hasConnection()) {
1563 wrappedConnection.writeLine();
1564 } else {
1565 throw new IllegalStateException("Connection has been released");
1566 }
1567 }
1568
1569 public void writeLine(byte[] data)
1570 throws IOException, IllegalStateException {
1571 if (hasConnection()) {
1572 wrappedConnection.writeLine(data);
1573 } else {
1574 throw new IllegalStateException("Connection has been released");
1575 }
1576 }
1577
1578 public void flushRequestOutputStream() throws IOException {
1579 if (hasConnection()) {
1580 wrappedConnection.flushRequestOutputStream();
1581 } else {
1582 throw new IllegalStateException("Connection has been released");
1583 }
1584 }
1585
1586
1587
1588
1589 public int getSoTimeout() throws SocketException {
1590 if (hasConnection()) {
1591 return wrappedConnection.getSoTimeout();
1592 } else {
1593 throw new IllegalStateException("Connection has been released");
1594 }
1595 }
1596
1597
1598
1599
1600 public String getVirtualHost() {
1601 if (hasConnection()) {
1602 return wrappedConnection.getVirtualHost();
1603 } else {
1604 throw new IllegalStateException("Connection has been released");
1605 }
1606 }
1607
1608
1609
1610
1611 public void setVirtualHost(String host) throws IllegalStateException {
1612 if (hasConnection()) {
1613 wrappedConnection.setVirtualHost(host);
1614 } else {
1615 throw new IllegalStateException("Connection has been released");
1616 }
1617 }
1618
1619 public int getSendBufferSize() throws SocketException {
1620 if (hasConnection()) {
1621 return wrappedConnection.getSendBufferSize();
1622 } else {
1623 throw new IllegalStateException("Connection has been released");
1624 }
1625 }
1626
1627
1628
1629
1630 public void setSendBufferSize(int sendBufferSize) throws SocketException {
1631 if (hasConnection()) {
1632 wrappedConnection.setSendBufferSize(sendBufferSize);
1633 } else {
1634 throw new IllegalStateException("Connection has been released");
1635 }
1636 }
1637
1638 public HttpConnectionParams getParams() {
1639 if (hasConnection()) {
1640 return wrappedConnection.getParams();
1641 } else {
1642 throw new IllegalStateException("Connection has been released");
1643 }
1644 }
1645
1646 public void setParams(final HttpConnectionParams params) {
1647 if (hasConnection()) {
1648 wrappedConnection.setParams(params);
1649 } else {
1650 throw new IllegalStateException("Connection has been released");
1651 }
1652 }
1653
1654
1655
1656
1657 public void print(String data, String charset) throws IOException, IllegalStateException {
1658 if (hasConnection()) {
1659 wrappedConnection.print(data, charset);
1660 } else {
1661 throw new IllegalStateException("Connection has been released");
1662 }
1663 }
1664
1665
1666
1667
1668 public void printLine(String data, String charset)
1669 throws IOException, IllegalStateException {
1670 if (hasConnection()) {
1671 wrappedConnection.printLine(data, charset);
1672 } else {
1673 throw new IllegalStateException("Connection has been released");
1674 }
1675 }
1676
1677
1678
1679
1680 public void setSocketTimeout(int timeout) throws SocketException, IllegalStateException {
1681 if (hasConnection()) {
1682 wrappedConnection.setSocketTimeout(timeout);
1683 } else {
1684 throw new IllegalStateException("Connection has been released");
1685 }
1686 }
1687
1688 }
1689
1690 }
1691