38 |
|
|
39 |
package gnu.java.net.protocol.http; |
package gnu.java.net.protocol.http; |
40 |
|
|
|
import java.io.ByteArrayInputStream; |
|
41 |
import java.io.ByteArrayOutputStream; |
import java.io.ByteArrayOutputStream; |
42 |
import java.io.FileNotFoundException; |
import java.io.FileNotFoundException; |
43 |
import java.io.IOException; |
import java.io.IOException; |
74 |
/** |
/** |
75 |
* Pool of reusable connections, used if keepAlive is true. |
* Pool of reusable connections, used if keepAlive is true. |
76 |
*/ |
*/ |
77 |
private static final Map connectionPool = new LinkedHashMap(); |
private static final LinkedHashMap connectionPool = new LinkedHashMap(); |
78 |
|
static int maxConnections; |
79 |
|
|
80 |
/* |
/* |
81 |
* The underlying connection. |
* The underlying connection. |
87 |
int proxyPort; |
int proxyPort; |
88 |
String agent; |
String agent; |
89 |
boolean keepAlive; |
boolean keepAlive; |
|
int maxConnections; |
|
90 |
|
|
91 |
private Request request; |
private Request request; |
92 |
private Headers requestHeaders; |
private Headers requestHeaders; |
94 |
private boolean requestMethodSetExplicitly; |
private boolean requestMethodSetExplicitly; |
95 |
|
|
96 |
private Response response; |
private Response response; |
97 |
private ByteArrayInputStream responseSink; |
private InputStream responseSink; |
98 |
private ByteArrayInputStream errorSink; |
private InputStream errorSink; |
99 |
|
|
100 |
private HandshakeCompletedEvent handshakeEvent; |
private HandshakeCompletedEvent handshakeEvent; |
101 |
|
|
201 |
} |
} |
202 |
connection.setProxy(proxyHostname, proxyPort); |
connection.setProxy(proxyHostname, proxyPort); |
203 |
} |
} |
204 |
request = connection.newRequest(method, file); |
try |
|
if (!keepAlive) |
|
|
{ |
|
|
request.setHeader("Connection", "close"); |
|
|
} |
|
|
if (agent != null) |
|
|
{ |
|
|
request.setHeader("User-Agent", agent); |
|
|
} |
|
|
request.getHeaders().putAll(requestHeaders); |
|
|
if (requestSink != null) |
|
205 |
{ |
{ |
206 |
byte[] content = requestSink.toByteArray(); |
request = connection.newRequest(method, file); |
207 |
RequestBodyWriter writer = new ByteArrayRequestBodyWriter(content); |
if (!keepAlive) |
208 |
request.setRequestBodyWriter(writer); |
{ |
209 |
|
request.setHeader("Connection", "close"); |
210 |
|
} |
211 |
|
if (agent != null) |
212 |
|
{ |
213 |
|
request.setHeader("User-Agent", agent); |
214 |
|
} |
215 |
|
request.getHeaders().putAll(requestHeaders); |
216 |
|
if (requestSink != null) |
217 |
|
{ |
218 |
|
byte[] content = requestSink.toByteArray(); |
219 |
|
RequestBodyWriter writer = new ByteArrayRequestBodyWriter(content); |
220 |
|
request.setRequestBodyWriter(writer); |
221 |
|
} |
222 |
|
if (creds != null) |
223 |
|
{ |
224 |
|
request.setAuthenticator(new Authenticator() { |
225 |
|
public Credentials getCredentials(String realm, int attempts) |
226 |
|
{ |
227 |
|
return (attempts < 2) ? creds : null; |
228 |
|
} |
229 |
|
}); |
230 |
|
} |
231 |
|
response = request.dispatch(); |
232 |
} |
} |
233 |
ByteArrayResponseBodyReader reader = new ByteArrayResponseBodyReader(); |
catch (IOException ioe) |
|
request.setResponseBodyReader(reader); |
|
|
if (creds != null) |
|
234 |
{ |
{ |
235 |
request.setAuthenticator(new Authenticator() { |
if (connection.useCount > 0) |
236 |
public Credentials getCredentials(String realm, int attempts) |
{ |
237 |
|
// Connection re-use failed: Try a new connection. |
238 |
|
try |
239 |
|
{ |
240 |
|
connection.close(); |
241 |
|
} |
242 |
|
catch (IOException _) |
243 |
|
{ |
244 |
|
// Ignore. |
245 |
|
} |
246 |
|
connection = null; |
247 |
|
retry = true; |
248 |
|
continue; |
249 |
|
} |
250 |
|
else |
251 |
{ |
{ |
252 |
return (attempts < 2) ? creds : null; |
// First time the connection was used: Hard failure. |
253 |
|
throw ioe; |
254 |
} |
} |
|
}); |
|
255 |
} |
} |
256 |
response = request.dispatch(); |
|
257 |
if (response.getCodeClass() == 3 && getInstanceFollowRedirects()) |
if (response.getCodeClass() == 3 && getInstanceFollowRedirects()) |
258 |
{ |
{ |
259 |
// Follow redirect |
// Follow redirect |
331 |
} |
} |
332 |
else |
else |
333 |
{ |
{ |
334 |
responseSink = new ByteArrayInputStream(reader.toByteArray ()); |
responseSink = response.getBody(); |
335 |
|
|
336 |
if (response.getCode() == 404) |
if (response.getCode() == 404) |
337 |
{ |
{ |
338 |
errorSink = responseSink; |
errorSink = responseSink; |
353 |
HTTPConnection connection; |
HTTPConnection connection; |
354 |
if (keepAlive) |
if (keepAlive) |
355 |
{ |
{ |
356 |
StringBuffer buf = new StringBuffer(secure ? "https://" : "http://"); |
Object key = HTTPConnection.getPoolKey(host, port, secure); |
|
buf.append(Thread.currentThread().hashCode()); |
|
|
buf.append('@'); |
|
|
buf.append(host); |
|
|
buf.append(':'); |
|
|
buf.append(port); |
|
|
String key = buf.toString(); |
|
357 |
synchronized (connectionPool) |
synchronized (connectionPool) |
358 |
{ |
{ |
359 |
connection = (HTTPConnection) connectionPool.get(key); |
connection = (HTTPConnection) connectionPool.remove(key); |
360 |
if (connection == null) |
if (connection == null) |
361 |
{ |
{ |
362 |
connection = new HTTPConnection(host, port, secure); |
connection = new HTTPConnection(host, port, secure); |
363 |
// Good housekeeping |
connection.setPool(connectionPool); |
|
if (connectionPool.size() == maxConnections) |
|
|
{ |
|
|
// maxConnections must always be >= 1 |
|
|
Object lru = connectionPool.keySet().iterator().next(); |
|
|
connectionPool.remove(lru); |
|
|
} |
|
|
connectionPool.put(key, connection); |
|
364 |
} |
} |
365 |
} |
} |
366 |
} |
} |
514 |
return null; |
return null; |
515 |
} |
} |
516 |
} |
} |
517 |
Map headers = response.getHeaders(); |
Headers headers = response.getHeaders(); |
518 |
Map ret = new LinkedHashMap(); |
LinkedHashMap ret = new LinkedHashMap(); |
519 |
ret.put("", Collections.singletonList(getStatusLine(response))); |
ret.put(null, Collections.singletonList(getStatusLine(response))); |
520 |
for (Iterator i = headers.entrySet().iterator(); i.hasNext(); ) |
for (Iterator i = headers.entrySet().iterator(); i.hasNext(); ) |
521 |
{ |
{ |
522 |
Map.Entry entry = (Map.Entry) i.next(); |
Map.Entry entry = (Map.Entry) i.next(); |
524 |
String value = (String) entry.getValue(); |
String value = (String) entry.getValue(); |
525 |
ret.put(key, Collections.singletonList(value)); |
ret.put(key, Collections.singletonList(value)); |
526 |
} |
} |
527 |
return ret; |
return Collections.unmodifiableMap(ret); |
528 |
} |
} |
529 |
|
|
530 |
String getStatusLine(Response response) |
String getStatusLine(Response response) |