1 18 package org.archive.httpclient; 19 20 import java.io.IOException ; 21 import java.io.InputStream ; 22 import java.util.ArrayList ; 23 import java.util.Iterator ; 24 import java.util.List ; 25 import java.util.logging.Level ; 26 import java.util.logging.Logger ; 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 41 public final class ThreadLocalHttpConnectionManager implements 42 HttpConnectionManager { 43 44 private static final CloserThread closer = new CloserThread(); 45 private static final Logger logger = Logger 46 .getLogger(ThreadLocalHttpConnectionManager.class.getName()); 47 48 private final ThreadLocal tl = new ThreadLocal () { 49 protected synchronized Object 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 60 private HttpConnection conn = null; 61 62 65 private long idleStartTime = Long.MAX_VALUE; 66 } 67 68 public ThreadLocalHttpConnectionManager() { 69 } 70 71 78 private static boolean finishLastResponse(final HttpConnection conn) { 79 InputStream lastResponse = conn.getLastResponseInputStream(); 80 if(lastResponse != null) { 81 conn.setLastResponseInputStream(null); 82 try { 83 lastResponse.close(); 84 return true; 85 } catch (IOException ioe) { 86 return false; 88 } 89 } else { 90 return false; 91 } 92 } 93 94 97 private HttpConnectionManagerParams params = new HttpConnectionManagerParams(); 98 99 102 public HttpConnection getConnection( 103 final HostConfiguration hostConfiguration) { 104 return getConnection(hostConfiguration, 0); 105 } 106 107 117 public boolean isConnectionStaleCheckingEnabled() { 118 return this.params.isStaleCheckingEnabled(); 119 } 120 121 132 public void setConnectionStaleCheckingEnabled( 133 final boolean connectionStaleCheckingEnabled) { 134 this.params.setStaleCheckingEnabled(connectionStaleCheckingEnabled); 135 } 136 137 142 public HttpConnection getConnectionWithTimeout( 143 final HostConfiguration hostConfiguration, final long timeout) { 144 145 final ConnectionInfo ci = getConnectionInfo(); 146 HttpConnection httpConnection = ci.conn; 147 148 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 ci.idleStartTime = Long.MAX_VALUE; 174 175 return httpConnection; 176 } 177 178 183 public HttpConnection getConnection( 184 final HostConfiguration hostConfiguration, final long timeout) { 185 return getConnectionWithTimeout(hostConfiguration, timeout); 186 } 187 188 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 ( 197 "Unexpected release of an unknown connection."); 198 } 199 200 finishLastResponse(httpConnection); 201 202 ci.idleStartTime = System.currentTimeMillis(); 204 } 205 206 214 public HttpConnectionManagerParams getParams() { 215 return this.params; 216 } 217 218 226 public void setParams(final HttpConnectionManagerParams p) { 227 if(p == null) { 228 throw new IllegalArgumentException ("Parameters may not be null"); 229 } 230 this.params = p; 231 } 232 233 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 { 247 private List <HttpConnection> connections 248 = new ArrayList <HttpConnection>(); 249 250 private static final int SLEEP_INTERVAL = 5000; 251 252 public CloserThread() { 253 super("HttpConnection closer"); 254 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 <HttpConnection> s; 272 synchronized (connections) { 273 s = connections; 274 connections = new ArrayList <HttpConnection>(); 275 } 276 logger.log(Level.INFO, "Closing " + s.size() 277 + " HttpConnections"); 278 for(final Iterator <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 e) { 287 return; 288 } 289 } 290 } 291 } 292 | Popular Tags |