KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > archive > httpclient > ThreadLocalHttpConnectionManager


1 /**
2  * ====================================================================
3  *
4  * Licensed under the Apache License, Version 2.0 (the "License");
5  * you may not use this file except in compliance with the License.
6  * You may obtain a copy of the License at
7  *
8  * http://www.apache.org/licenses/LICENSE-2.0
9  *
10  * Unless required by applicable law or agreed to in writing, software
11  * distributed under the License is distributed on an "AS IS" BASIS,
12  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13  * See the License for the specific language governing permissions and
14  * limitations under the License.
15  * ====================================================================
16  *
17  */

18 package org.archive.httpclient;
19
20 import java.io.IOException JavaDoc;
21 import java.io.InputStream JavaDoc;
22 import java.util.ArrayList JavaDoc;
23 import java.util.Iterator JavaDoc;
24 import java.util.List JavaDoc;
25 import java.util.logging.Level JavaDoc;
26 import java.util.logging.Logger JavaDoc;
27
28 import org.apache.commons.httpclient.HostConfiguration;
29 import org.apache.commons.httpclient.HttpConnection;
30 import org.apache.commons.httpclient.HttpConnectionManager;
31 import org.apache.commons.httpclient.params.HttpConnectionManagerParams;
32
33 /**
34  * A simple, but thread-safe HttpClient {@link HttpConnectionManager}.
35  * Based on {@link org.apache.commons.httpclient.SimpleHttpConnectionManager}.
36  *
37  * <b>Java &gt;= 1.4 is recommended.</b>
38  *
39  * @author Christian Kohlschuetter
40  */

41 public final class ThreadLocalHttpConnectionManager implements
42     HttpConnectionManager {
43
44     private static final CloserThread closer = new CloserThread();
45     private static final Logger JavaDoc logger = Logger
46         .getLogger(ThreadLocalHttpConnectionManager.class.getName());
47
48     private final ThreadLocal JavaDoc tl = new ThreadLocal JavaDoc() {
49         protected synchronized Object JavaDoc initialValue() {
50             return new ConnectionInfo();
51         }
52     };
53
54     private ConnectionInfo getConnectionInfo() {
55         return (ConnectionInfo) tl.get();
56     }
57
58     private final class ConnectionInfo {
59         /** The http connection */
60         private HttpConnection conn = null;
61
62         /**
63          * The time the connection was made idle.
64          */

65         private long idleStartTime = Long.MAX_VALUE;
66     }
67
68     public ThreadLocalHttpConnectionManager() {
69     }
70
71     /**
72      * Since the same connection is about to be reused, make sure the
73      * previous request was completely processed, and if not
74      * consume it now.
75      * @param conn The connection
76      * @return true, if the connection is reusable
77      */

78     private static boolean finishLastResponse(final HttpConnection conn) {
79         InputStream JavaDoc lastResponse = conn.getLastResponseInputStream();
80         if(lastResponse != null) {
81             conn.setLastResponseInputStream(null);
82             try {
83                 lastResponse.close();
84                 return true;
85             } catch (IOException JavaDoc ioe) {
86                 // force reconnect.
87
return false;
88             }
89         } else {
90             return false;
91         }
92     }
93
94     /**
95      * Collection of parameters associated with this connection manager.
96      */

97     private HttpConnectionManagerParams params = new HttpConnectionManagerParams();
98
99     /**
100      * @see HttpConnectionManager#getConnection(HostConfiguration)
101      */

102     public HttpConnection getConnection(
103         final HostConfiguration hostConfiguration) {
104         return getConnection(hostConfiguration, 0);
105     }
106
107     /**
108      * Gets the staleCheckingEnabled value to be set on HttpConnections that are created.
109      *
110      * @return <code>true</code> if stale checking will be enabled on HttpConections
111      *
112      * @see HttpConnection#isStaleCheckingEnabled()
113      *
114      * @deprecated Use {@link HttpConnectionManagerParams#isStaleCheckingEnabled()},
115      * {@link HttpConnectionManager#getParams()}.
116      */

117     public boolean isConnectionStaleCheckingEnabled() {
118         return this.params.isStaleCheckingEnabled();
119     }
120
121     /**
122      * Sets the staleCheckingEnabled value to be set on HttpConnections that are created.
123      *
124      * @param connectionStaleCheckingEnabled <code>true</code> if stale checking will be enabled
125      * on HttpConections
126      *
127      * @see HttpConnection#setStaleCheckingEnabled(boolean)
128      *
129      * @deprecated Use {@link HttpConnectionManagerParams#setStaleCheckingEnabled(boolean)},
130      * {@link HttpConnectionManager#getParams()}.
131      */

132     public void setConnectionStaleCheckingEnabled(
133         final boolean connectionStaleCheckingEnabled) {
134         this.params.setStaleCheckingEnabled(connectionStaleCheckingEnabled);
135     }
136
137     /**
138      * @see HttpConnectionManager#getConnectionWithTimeout(HostConfiguration, long)
139      *
140      * @since 3.0
141      */

142     public HttpConnection getConnectionWithTimeout(
143         final HostConfiguration hostConfiguration, final long timeout) {
144
145         final ConnectionInfo ci = getConnectionInfo();
146         HttpConnection httpConnection = ci.conn;
147
148         // make sure the host and proxy are correct for this connection
149
// close it and set the values if they are not
150
if(httpConnection == null || !finishLastResponse(httpConnection)
151             || !hostConfiguration.hostEquals(httpConnection)
152             || !hostConfiguration.proxyEquals(httpConnection)) {
153
154             if(httpConnection != null && httpConnection.isOpen()) {
155                 closer.closeConnection(httpConnection);
156             }
157
158             httpConnection = new HttpConnection(hostConfiguration);
159             httpConnection.setHttpConnectionManager(this);
160             httpConnection.getParams().setDefaults(this.params);
161             ci.conn = httpConnection;
162
163             httpConnection.setHost(hostConfiguration.getHost());
164             httpConnection.setPort(hostConfiguration.getPort());
165             httpConnection.setProtocol(hostConfiguration.getProtocol());
166             httpConnection.setLocalAddress(hostConfiguration.getLocalAddress());
167
168             httpConnection.setProxyHost(hostConfiguration.getProxyHost());
169             httpConnection.setProxyPort(hostConfiguration.getProxyPort());
170         }
171
172         // remove the connection from the timeout handler
173
ci.idleStartTime = Long.MAX_VALUE;
174
175         return httpConnection;
176     }
177
178     /**
179      * @see HttpConnectionManager#getConnection(HostConfiguration, long)
180      *
181      * @deprecated Use #getConnectionWithTimeout(HostConfiguration, long)
182      */

183     public HttpConnection getConnection(
184         final HostConfiguration hostConfiguration, final long timeout) {
185         return getConnectionWithTimeout(hostConfiguration, timeout);
186     }
187
188     /**
189      * @see HttpConnectionManager#releaseConnection(org.apache.commons.httpclient.HttpConnection)
190      */

191     public void releaseConnection(final HttpConnection conn) {
192         final ConnectionInfo ci = getConnectionInfo();
193         HttpConnection httpConnection = ci.conn;
194
195         if(conn != httpConnection) {
196             throw new IllegalStateException JavaDoc(
197                 "Unexpected release of an unknown connection.");
198         }
199
200         finishLastResponse(httpConnection);
201
202         // track the time the connection was made idle
203
ci.idleStartTime = System.currentTimeMillis();
204     }
205
206     /**
207      * Returns {@link HttpConnectionManagerParams parameters} associated
208      * with this connection manager.
209      *
210      * @since 2.1
211      *
212      * @see HttpConnectionManagerParams
213      */

214     public HttpConnectionManagerParams getParams() {
215         return this.params;
216     }
217
218     /**
219      * Assigns {@link HttpConnectionManagerParams parameters} for this
220      * connection manager.
221      *
222      * @since 2.1
223      *
224      * @see HttpConnectionManagerParams
225      */

226     public void setParams(final HttpConnectionManagerParams p) {
227         if(p == null) {
228             throw new IllegalArgumentException JavaDoc("Parameters may not be null");
229         }
230         this.params = p;
231     }
232
233     /**
234      * @since 3.0
235      */

236     public void closeIdleConnections(final long idleTimeout) {
237         long maxIdleTime = System.currentTimeMillis() - idleTimeout;
238
239         final ConnectionInfo ci = getConnectionInfo();
240
241         if(ci.idleStartTime <= maxIdleTime) {
242             ci.conn.close();
243         }
244     }
245
246     private static final class CloserThread extends Thread JavaDoc {
247         private List JavaDoc<HttpConnection> connections
248          = new ArrayList JavaDoc<HttpConnection>();
249         
250         private static final int SLEEP_INTERVAL = 5000;
251
252         public CloserThread() {
253             super("HttpConnection closer");
254             // Make this a daemon thread so it can't be responsible for the JVM
255
// not shutting down.
256
setDaemon(true);
257             start();
258         }
259
260         public void closeConnection(final HttpConnection conn) {
261             synchronized (connections) {
262                 connections.add(conn);
263             }
264         }
265
266         public void run() {
267             try {
268                 while (!Thread.interrupted()) {
269                     Thread.sleep(SLEEP_INTERVAL);
270
271                     List JavaDoc<HttpConnection> s;
272                     synchronized (connections) {
273                         s = connections;
274                         connections = new ArrayList JavaDoc<HttpConnection>();
275                     }
276                     logger.log(Level.INFO, "Closing " + s.size()
277                         + " HttpConnections");
278                     for(final Iterator JavaDoc<HttpConnection> it = s.iterator();
279                       it.hasNext();) {
280                         HttpConnection conn = it.next();
281                         conn.close();
282                         conn.setHttpConnectionManager(null);
283                         it.remove();
284                     }
285                 }
286             } catch (InterruptedException JavaDoc e) {
287                 return;
288             }
289         }
290     }
291 }
292
Popular Tags