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 package org.apache.http.impl.conn;
29
30 import java.io.IOException;
31 import java.util.concurrent.TimeUnit;
32 import java.util.concurrent.atomic.AtomicLong;
33
34 import org.apache.commons.logging.Log;
35 import org.apache.commons.logging.LogFactory;
36 import org.apache.http.HttpClientConnection;
37 import org.apache.http.annotation.Contract;
38 import org.apache.http.annotation.ThreadingBehavior;
39 import org.apache.http.conn.ClientConnectionManager;
40 import org.apache.http.conn.ClientConnectionOperator;
41 import org.apache.http.conn.ClientConnectionRequest;
42 import org.apache.http.conn.ManagedClientConnection;
43 import org.apache.http.conn.OperatedClientConnection;
44 import org.apache.http.conn.routing.HttpRoute;
45 import org.apache.http.conn.scheme.SchemeRegistry;
46 import org.apache.http.util.Args;
47 import org.apache.http.util.Asserts;
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69 @Contract(threading = ThreadingBehavior.SAFE)
70 @Deprecated
71 public class BasicClientConnectionManager implements ClientConnectionManager {
72
73 private final Log log = LogFactory.getLog(getClass());
74
75 private static final AtomicLong COUNTER = new AtomicLong();
76
77
78 public final static String MISUSE_MESSAGE =
79 "Invalid use of BasicClientConnManager: connection still allocated.\n" +
80 "Make sure to release the connection before allocating another one.";
81
82
83 private final SchemeRegistry schemeRegistry;
84
85
86 private final ClientConnectionOperator connOperator;
87
88
89 private HttpPoolEntry poolEntry;
90
91
92 private ManagedClientConnectionImpl conn;
93
94
95 private volatile boolean shutdown;
96
97
98
99
100
101
102 public BasicClientConnectionManager(final SchemeRegistry schreg) {
103 Args.notNull(schreg, "Scheme registry");
104 this.schemeRegistry = schreg;
105 this.connOperator = createConnectionOperator(schreg);
106 }
107
108 public BasicClientConnectionManager() {
109 this(SchemeRegistryFactory.createDefault());
110 }
111
112 @Override
113 protected void finalize() throws Throwable {
114 try {
115 shutdown();
116 } finally {
117 super.finalize();
118 }
119 }
120
121 @Override
122 public SchemeRegistry getSchemeRegistry() {
123 return this.schemeRegistry;
124 }
125
126 protected ClientConnectionOperator createConnectionOperator(final SchemeRegistry schreg) {
127 return new DefaultClientConnectionOperator(schreg);
128 }
129
130 @Override
131 public final ClientConnectionRequest requestConnection(
132 final HttpRoute route,
133 final Object state) {
134
135 return new ClientConnectionRequest() {
136
137 @Override
138 public void abortRequest() {
139
140 }
141
142 @Override
143 public ManagedClientConnection getConnection(
144 final long timeout, final TimeUnit timeUnit) {
145 return BasicClientConnectionManager.this.getConnection(
146 route, state);
147 }
148
149 };
150 }
151
152 private void assertNotShutdown() {
153 Asserts.check(!this.shutdown, "Connection manager has been shut down");
154 }
155
156 ManagedClientConnection getConnection(final HttpRoute route, final Object state) {
157 Args.notNull(route, "Route");
158 synchronized (this) {
159 assertNotShutdown();
160 if (this.log.isDebugEnabled()) {
161 this.log.debug("Get connection for route " + route);
162 }
163 Asserts.check(this.conn == null, MISUSE_MESSAGE);
164 if (this.poolEntry != null && !this.poolEntry.getPlannedRoute().equals(route)) {
165 this.poolEntry.close();
166 this.poolEntry = null;
167 }
168 if (this.poolEntry == null) {
169 final String id = Long.toString(COUNTER.getAndIncrement());
170 final OperatedClientConnection opconn = this.connOperator.createConnection();
171 this.poolEntry = new HttpPoolEntry(this.log, id, route, opconn, 0, TimeUnit.MILLISECONDS);
172 }
173 final long now = System.currentTimeMillis();
174 if (this.poolEntry.isExpired(now)) {
175 this.poolEntry.close();
176 this.poolEntry.getTracker().reset();
177 }
178 this.conn = new ManagedClientConnectionImpl(this, this.connOperator, this.poolEntry);
179 return this.conn;
180 }
181 }
182
183 private void shutdownConnection(final HttpClientConnection conn) {
184 try {
185 conn.shutdown();
186 } catch (final IOException iox) {
187 if (this.log.isDebugEnabled()) {
188 this.log.debug("I/O exception shutting down connection", iox);
189 }
190 }
191 }
192
193 @Override
194 public void releaseConnection(final ManagedClientConnection conn, final long keepalive, final TimeUnit timeUnit) {
195 Args.check(conn instanceof ManagedClientConnectionImpl, "Connection class mismatch, " +
196 "connection not obtained from this manager");
197 final ManagedClientConnectionImplhttp/impl/conn/ManagedClientConnectionImpl.html#ManagedClientConnectionImpl">ManagedClientConnectionImpl managedConn = (ManagedClientConnectionImpl) conn;
198 synchronized (managedConn) {
199 if (this.log.isDebugEnabled()) {
200 this.log.debug("Releasing connection " + conn);
201 }
202 if (managedConn.getPoolEntry() == null) {
203 return;
204 }
205 final ClientConnectionManager manager = managedConn.getManager();
206 Asserts.check(manager == this, "Connection not obtained from this manager");
207 synchronized (this) {
208 if (this.shutdown) {
209 shutdownConnection(managedConn);
210 return;
211 }
212 try {
213 if (managedConn.isOpen() && !managedConn.isMarkedReusable()) {
214 shutdownConnection(managedConn);
215 }
216 if (managedConn.isMarkedReusable()) {
217 this.poolEntry.updateExpiry(keepalive, timeUnit != null ? timeUnit : TimeUnit.MILLISECONDS);
218 if (this.log.isDebugEnabled()) {
219 final String s;
220 if (keepalive > 0) {
221 s = "for " + keepalive + " " + timeUnit;
222 } else {
223 s = "indefinitely";
224 }
225 this.log.debug("Connection can be kept alive " + s);
226 }
227 }
228 } finally {
229 managedConn.detach();
230 this.conn = null;
231 if (this.poolEntry.isClosed()) {
232 this.poolEntry = null;
233 }
234 }
235 }
236 }
237 }
238
239 @Override
240 public void closeExpiredConnections() {
241 synchronized (this) {
242 assertNotShutdown();
243 final long now = System.currentTimeMillis();
244 if (this.poolEntry != null && this.poolEntry.isExpired(now)) {
245 this.poolEntry.close();
246 this.poolEntry.getTracker().reset();
247 }
248 }
249 }
250
251 @Override
252 public void closeIdleConnections(final long idletime, final TimeUnit timeUnit) {
253 Args.notNull(timeUnit, "Time unit");
254 synchronized (this) {
255 assertNotShutdown();
256 long time = timeUnit.toMillis(idletime);
257 if (time < 0) {
258 time = 0;
259 }
260 final long deadline = System.currentTimeMillis() - time;
261 if (this.poolEntry != null && this.poolEntry.getUpdated() <= deadline) {
262 this.poolEntry.close();
263 this.poolEntry.getTracker().reset();
264 }
265 }
266 }
267
268 @Override
269 public void shutdown() {
270 synchronized (this) {
271 this.shutdown = true;
272 try {
273 if (this.poolEntry != null) {
274 this.poolEntry.close();
275 }
276 } finally {
277 this.poolEntry = null;
278 this.conn = null;
279 }
280 }
281 }
282
283 }