41 |
import gnu.classpath.Configuration; |
import gnu.classpath.Configuration; |
42 |
import gnu.classpath.SystemProperties; |
import gnu.classpath.SystemProperties; |
43 |
import gnu.java.net.EmptyX509TrustManager; |
import gnu.java.net.EmptyX509TrustManager; |
|
import gnu.java.net.protocol.http.event.ConnectionEvent; |
|
|
import gnu.java.net.protocol.http.event.ConnectionListener; |
|
|
import gnu.java.net.protocol.http.event.RequestEvent; |
|
|
import gnu.java.net.protocol.http.event.RequestListener; |
|
44 |
|
|
45 |
import java.io.BufferedInputStream; |
import java.io.BufferedInputStream; |
46 |
import java.io.BufferedOutputStream; |
import java.io.BufferedOutputStream; |
53 |
import java.util.ArrayList; |
import java.util.ArrayList; |
54 |
import java.util.HashMap; |
import java.util.HashMap; |
55 |
import java.util.Iterator; |
import java.util.Iterator; |
56 |
|
import java.util.LinkedHashMap; |
57 |
import java.util.List; |
import java.util.List; |
58 |
import java.util.Map; |
import java.util.Map; |
59 |
|
|
128 |
*/ |
*/ |
129 |
protected int minorVersion; |
protected int minorVersion; |
130 |
|
|
|
private final List connectionListeners; |
|
|
private final List requestListeners; |
|
131 |
private final List handshakeCompletedListeners; |
private final List handshakeCompletedListeners; |
132 |
|
|
133 |
/** |
/** |
160 |
*/ |
*/ |
161 |
protected CookieManager cookieManager; |
protected CookieManager cookieManager; |
162 |
|
|
163 |
|
|
164 |
|
/** |
165 |
|
* The pool that this connection is a member of (if any). |
166 |
|
*/ |
167 |
|
private LinkedHashMap pool; |
168 |
|
|
169 |
/** |
/** |
170 |
* Creates a new HTTP connection. |
* Creates a new HTTP connection. |
171 |
* @param hostname the name of the host to connect to |
* @param hostname the name of the host to connect to |
237 |
this.connectionTimeout = connectionTimeout; |
this.connectionTimeout = connectionTimeout; |
238 |
this.timeout = timeout; |
this.timeout = timeout; |
239 |
majorVersion = minorVersion = 1; |
majorVersion = minorVersion = 1; |
|
connectionListeners = new ArrayList(4); |
|
|
requestListeners = new ArrayList(4); |
|
240 |
handshakeCompletedListeners = new ArrayList(2); |
handshakeCompletedListeners = new ArrayList(2); |
241 |
} |
} |
242 |
|
|
331 |
} |
} |
332 |
|
|
333 |
/** |
/** |
334 |
|
* The number of times this HTTPConnection has be used via keep-alive. |
335 |
|
*/ |
336 |
|
int useCount; |
337 |
|
|
338 |
|
/** |
339 |
|
* Generates a key for connections in the connection pool. |
340 |
|
* |
341 |
|
* @param h the host name. |
342 |
|
* @param p the port. |
343 |
|
* @param sec true if using https. |
344 |
|
* |
345 |
|
* @return the key. |
346 |
|
*/ |
347 |
|
static Object getPoolKey(String h, int p, boolean sec) |
348 |
|
{ |
349 |
|
StringBuilder buf = new StringBuilder(sec ? "https://" : "http://"); |
350 |
|
buf.append(h); |
351 |
|
buf.append(':'); |
352 |
|
buf.append(p); |
353 |
|
return buf.toString(); |
354 |
|
} |
355 |
|
|
356 |
|
/** |
357 |
|
* Set the connection pool that this HTTPConnection is a member of. |
358 |
|
* If left unset or set to null, it will not be a member of any pool |
359 |
|
* and will not be a candidate for reuse. |
360 |
|
* |
361 |
|
* @param p the pool. |
362 |
|
*/ |
363 |
|
void setPool(LinkedHashMap p) |
364 |
|
{ |
365 |
|
pool = p; |
366 |
|
} |
367 |
|
|
368 |
|
/** |
369 |
|
* Signal that this HTTPConnection is no longer needed and can be |
370 |
|
* returned to the connection pool. |
371 |
|
* |
372 |
|
*/ |
373 |
|
void release() |
374 |
|
{ |
375 |
|
if (pool != null) |
376 |
|
{ |
377 |
|
synchronized (pool) |
378 |
|
{ |
379 |
|
useCount++; |
380 |
|
Object key = HTTPConnection.getPoolKey(hostname, port, secure); |
381 |
|
pool.put(key, this); |
382 |
|
while (pool.size() >= HTTPURLConnection.maxConnections) |
383 |
|
{ |
384 |
|
// maxConnections must always be >= 1 |
385 |
|
Object lru = pool.keySet().iterator().next(); |
386 |
|
HTTPConnection c = (HTTPConnection)pool.remove(lru); |
387 |
|
try |
388 |
|
{ |
389 |
|
c.closeConnection(); |
390 |
|
} |
391 |
|
catch (IOException ioe) |
392 |
|
{ |
393 |
|
// Ignore it. We are just cleaning up. |
394 |
|
} |
395 |
|
} |
396 |
|
} |
397 |
|
} |
398 |
|
} |
399 |
|
|
400 |
|
/** |
401 |
* Creates a new request using this connection. |
* Creates a new request using this connection. |
402 |
* @param method the HTTP method to invoke |
* @param method the HTTP method to invoke |
403 |
* @param path the URI-escaped RFC2396 <code>abs_path</code> with |
* @param path the URI-escaped RFC2396 <code>abs_path</code> with |
433 |
Cookie[] cookies = cookieManager.getCookies(hostname, secure, path); |
Cookie[] cookies = cookieManager.getCookies(hostname, secure, path); |
434 |
if (cookies != null && cookies.length > 0) |
if (cookies != null && cookies.length > 0) |
435 |
{ |
{ |
436 |
StringBuffer buf = new StringBuffer(); |
StringBuilder buf = new StringBuilder(); |
437 |
buf.append("$Version=1"); |
buf.append("$Version=1"); |
438 |
for (int i = 0; i < cookies.length; i++) |
for (int i = 0; i < cookies.length; i++) |
439 |
{ |
{ |
444 |
ret.setHeader("Cookie", buf.toString()); |
ret.setHeader("Cookie", buf.toString()); |
445 |
} |
} |
446 |
} |
} |
|
fireRequestEvent(RequestEvent.REQUEST_CREATED, ret); |
|
447 |
return ret; |
return ret; |
448 |
} |
} |
449 |
|
|
453 |
public void close() |
public void close() |
454 |
throws IOException |
throws IOException |
455 |
{ |
{ |
456 |
try |
closeConnection(); |
|
{ |
|
|
closeConnection(); |
|
|
} |
|
|
finally |
|
|
{ |
|
|
fireConnectionEvent(ConnectionEvent.CONNECTION_CLOSED); |
|
|
} |
|
457 |
} |
} |
458 |
|
|
459 |
/** |
/** |
592 |
*/ |
*/ |
593 |
protected String getURI() |
protected String getURI() |
594 |
{ |
{ |
595 |
StringBuffer buf = new StringBuffer(); |
StringBuilder buf = new StringBuilder(); |
596 |
buf.append(secure ? "https://" : "http://"); |
buf.append(secure ? "https://" : "http://"); |
597 |
buf.append(hostname); |
buf.append(hostname); |
598 |
if (secure) |
if (secure) |
642 |
|
|
643 |
// -- Events -- |
// -- Events -- |
644 |
|
|
|
public void addConnectionListener(ConnectionListener l) |
|
|
{ |
|
|
synchronized (connectionListeners) |
|
|
{ |
|
|
connectionListeners.add(l); |
|
|
} |
|
|
} |
|
|
|
|
|
public void removeConnectionListener(ConnectionListener l) |
|
|
{ |
|
|
synchronized (connectionListeners) |
|
|
{ |
|
|
connectionListeners.remove(l); |
|
|
} |
|
|
} |
|
|
|
|
|
protected void fireConnectionEvent(int type) |
|
|
{ |
|
|
ConnectionEvent event = new ConnectionEvent(this, type); |
|
|
ConnectionListener[] l = null; |
|
|
synchronized (connectionListeners) |
|
|
{ |
|
|
l = new ConnectionListener[connectionListeners.size()]; |
|
|
connectionListeners.toArray(l); |
|
|
} |
|
|
for (int i = 0; i < l.length; i++) |
|
|
{ |
|
|
switch (type) |
|
|
{ |
|
|
case ConnectionEvent.CONNECTION_CLOSED: |
|
|
l[i].connectionClosed(event); |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
|
public void addRequestListener(RequestListener l) |
|
|
{ |
|
|
synchronized (requestListeners) |
|
|
{ |
|
|
requestListeners.add(l); |
|
|
} |
|
|
} |
|
|
|
|
|
public void removeRequestListener(RequestListener l) |
|
|
{ |
|
|
synchronized (requestListeners) |
|
|
{ |
|
|
requestListeners.remove(l); |
|
|
} |
|
|
} |
|
|
|
|
|
protected void fireRequestEvent(int type, Request request) |
|
|
{ |
|
|
RequestEvent event = new RequestEvent(this, type, request); |
|
|
RequestListener[] l = null; |
|
|
synchronized (requestListeners) |
|
|
{ |
|
|
l = new RequestListener[requestListeners.size()]; |
|
|
requestListeners.toArray(l); |
|
|
} |
|
|
for (int i = 0; i < l.length; i++) |
|
|
{ |
|
|
switch (type) |
|
|
{ |
|
|
case RequestEvent.REQUEST_CREATED: |
|
|
l[i].requestCreated(event); |
|
|
break; |
|
|
case RequestEvent.REQUEST_SENDING: |
|
|
l[i].requestSent(event); |
|
|
break; |
|
|
case RequestEvent.REQUEST_SENT: |
|
|
l[i].requestSent(event); |
|
|
break; |
|
|
} |
|
|
} |
|
|
} |
|
|
|
|
645 |
void addHandshakeCompletedListener(HandshakeCompletedListener l) |
void addHandshakeCompletedListener(HandshakeCompletedListener l) |
646 |
{ |
{ |
647 |
synchronized (handshakeCompletedListeners) |
synchronized (handshakeCompletedListeners) |