Refactored HttpCacheEntry; new API should allow for cache entries backed by a temporary file
git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@980937 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
4ae188acbb
commit
e0d37d5502
|
@ -27,6 +27,7 @@
|
|||
package org.apache.http.client.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.ObjectInputStream;
|
||||
import java.io.ObjectOutputStream;
|
||||
import java.io.Serializable;
|
||||
|
@ -36,7 +37,6 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.StatusLine;
|
||||
|
@ -60,7 +60,6 @@ public abstract class HttpCacheEntry implements Serializable {
|
|||
private final Date responseDate;
|
||||
private final StatusLine statusLine;
|
||||
private final CachedHeaderGroup responseHeaders;
|
||||
private final HttpEntity body;
|
||||
private final Set<String> variantURIs;
|
||||
|
||||
/**
|
||||
|
@ -72,23 +71,16 @@ public abstract class HttpCacheEntry implements Serializable {
|
|||
* @param responseDate
|
||||
* Date/time that the response came back (Used for age
|
||||
* calculations)
|
||||
* @param version
|
||||
* HTTP Response Version
|
||||
* @param statusLine
|
||||
* HTTP status line
|
||||
* @param responseHeaders
|
||||
* Header[] from original HTTP Response
|
||||
* @param body
|
||||
* HttpEntity representing the body of the response
|
||||
* @param status
|
||||
* Numeric HTTP Status Code
|
||||
* @param reason
|
||||
* String message from HTTP Status Line
|
||||
*/
|
||||
public HttpCacheEntry(
|
||||
final Date requestDate,
|
||||
final Date responseDate,
|
||||
final StatusLine statusLine,
|
||||
final Header[] responseHeaders,
|
||||
final HttpEntity body,
|
||||
final Set<String> variants) {
|
||||
super();
|
||||
if (requestDate == null) {
|
||||
|
@ -103,17 +95,12 @@ public abstract class HttpCacheEntry implements Serializable {
|
|||
if (responseHeaders == null) {
|
||||
throw new IllegalArgumentException("Response headers may not be null");
|
||||
}
|
||||
if (body == null) {
|
||||
throw new IllegalArgumentException("Response body may not be null");
|
||||
}
|
||||
this.requestDate = requestDate;
|
||||
this.responseDate = responseDate;
|
||||
this.statusLine = statusLine;
|
||||
this.responseHeaders = new CachedHeaderGroup();
|
||||
this.responseHeaders.setHeaders(responseHeaders);
|
||||
this.body = body;
|
||||
this.variantURIs = variants != null ? new HashSet<String>(variants) : new HashSet<String>();
|
||||
|
||||
}
|
||||
|
||||
public StatusLine getStatusLine() {
|
||||
|
@ -140,10 +127,6 @@ public abstract class HttpCacheEntry implements Serializable {
|
|||
return responseDate;
|
||||
}
|
||||
|
||||
public HttpEntity getBody() {
|
||||
return body;
|
||||
}
|
||||
|
||||
public Header[] getAllHeaders() {
|
||||
return responseHeaders.getAllHeaders();
|
||||
}
|
||||
|
@ -164,6 +147,12 @@ public abstract class HttpCacheEntry implements Serializable {
|
|||
return Collections.unmodifiableSet(this.variantURIs);
|
||||
}
|
||||
|
||||
public abstract Resource getResource();
|
||||
|
||||
public abstract InputStream getBody();
|
||||
|
||||
public abstract long getBodyLength();
|
||||
|
||||
private void writeObject(ObjectOutputStream out) throws IOException {
|
||||
|
||||
// write CacheEntry
|
||||
|
@ -201,8 +190,6 @@ public abstract class HttpCacheEntry implements Serializable {
|
|||
this.responseHeaders.setHeaders(headers);
|
||||
}
|
||||
|
||||
public abstract Resource getResource();
|
||||
|
||||
@Override
|
||||
public String toString() {
|
||||
return "[request date=" + this.requestDate + "; response date=" + this.responseDate
|
||||
|
|
|
@ -26,11 +26,12 @@
|
|||
*/
|
||||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.StatusLine;
|
||||
import org.apache.http.annotation.Immutable;
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
|
@ -45,14 +46,27 @@ public class BasicHttpCacheEntry extends HttpCacheEntry {
|
|||
|
||||
private static final long serialVersionUID = -8464486112875881235L;
|
||||
|
||||
private final byte[] body;
|
||||
|
||||
public BasicHttpCacheEntry(
|
||||
final Date requestDate,
|
||||
final Date responseDate,
|
||||
final StatusLine statusLine,
|
||||
final Header[] responseHeaders,
|
||||
final HttpEntity body,
|
||||
final byte[] body,
|
||||
final Set<String> variants) {
|
||||
super(requestDate, responseDate, statusLine, responseHeaders, body, variants);
|
||||
super(requestDate, responseDate, statusLine, responseHeaders, variants);
|
||||
this.body = body;
|
||||
}
|
||||
|
||||
@Override
|
||||
public long getBodyLength() {
|
||||
return this.body.length;
|
||||
}
|
||||
|
||||
@Override
|
||||
public InputStream getBody() {
|
||||
return new ByteArrayInputStream(this.body);
|
||||
}
|
||||
|
||||
@Override
|
||||
|
|
|
@ -26,7 +26,6 @@
|
|||
*/
|
||||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.OutputStream;
|
||||
|
@ -35,43 +34,27 @@ import java.io.Serializable;
|
|||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.annotation.Immutable;
|
||||
import org.apache.http.message.BasicHeader;
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
import org.apache.http.protocol.HTTP;
|
||||
|
||||
@Immutable
|
||||
class CacheEntity implements HttpEntity, Cloneable, Serializable {
|
||||
class CacheEntity implements HttpEntity, Serializable {
|
||||
|
||||
private static final long serialVersionUID = -3467082284120936233L;
|
||||
|
||||
private final byte[] content;
|
||||
private final String contentType;
|
||||
private final String contentEncoding;
|
||||
private final HttpCacheEntry cacheEntry;
|
||||
|
||||
public CacheEntity(final byte[] b, final String contentType, final String contentEncoding) {
|
||||
public CacheEntity(final HttpCacheEntry cacheEntry) {
|
||||
super();
|
||||
this.content = b;
|
||||
this.contentType = contentType;
|
||||
this.contentEncoding = contentEncoding;
|
||||
}
|
||||
|
||||
public CacheEntity(final byte[] b) {
|
||||
this(b, null, null);
|
||||
this.cacheEntry = cacheEntry;
|
||||
}
|
||||
|
||||
public Header getContentType() {
|
||||
if (this.contentType == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new BasicHeader(HTTP.CONTENT_TYPE, this.contentType);
|
||||
return this.cacheEntry.getFirstHeader(HTTP.CONTENT_TYPE);
|
||||
}
|
||||
|
||||
public Header getContentEncoding() {
|
||||
if (this.contentEncoding == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
return new BasicHeader(HTTP.CONTENT_ENCODING, this.contentEncoding);
|
||||
return this.cacheEntry.getFirstHeader(HTTP.CONTENT_ENCODING);
|
||||
}
|
||||
|
||||
public boolean isChunked() {
|
||||
|
@ -83,19 +66,23 @@ class CacheEntity implements HttpEntity, Cloneable, Serializable {
|
|||
}
|
||||
|
||||
public long getContentLength() {
|
||||
return this.content.length;
|
||||
return this.cacheEntry.getBodyLength();
|
||||
}
|
||||
|
||||
public InputStream getContent() {
|
||||
return new ByteArrayInputStream(this.content);
|
||||
return this.cacheEntry.getBody();
|
||||
}
|
||||
|
||||
public void writeTo(final OutputStream outstream) throws IOException {
|
||||
if (outstream == null) {
|
||||
throw new IllegalArgumentException("Output stream may not be null");
|
||||
}
|
||||
outstream.write(this.content);
|
||||
outstream.flush();
|
||||
InputStream instream = this.cacheEntry.getBody();
|
||||
byte[] buf = new byte[2048];
|
||||
int len;
|
||||
while ((len = instream.read(buf)) != -1) {
|
||||
outstream.write(buf, 0, len);
|
||||
}
|
||||
}
|
||||
|
||||
public boolean isStreaming() {
|
||||
|
|
|
@ -26,15 +26,16 @@
|
|||
*/
|
||||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.annotation.Immutable;
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
import org.apache.http.protocol.HTTP;
|
||||
|
||||
/**
|
||||
* Generates a {@link CacheEntry} from a {@link HttpResponse}
|
||||
|
@ -49,29 +50,32 @@ class CacheEntryGenerator {
|
|||
Date responseDate,
|
||||
HttpResponse response,
|
||||
byte[] body) {
|
||||
Header ct = response.getFirstHeader(HTTP.CONTENT_TYPE);
|
||||
Header ce = response.getFirstHeader(HTTP.CONTENT_ENCODING);
|
||||
CacheEntity entity = new CacheEntity(
|
||||
body,
|
||||
ct != null ? ct.getValue() : null,
|
||||
ce != null ? ce.getValue() : null);
|
||||
return new BasicHttpCacheEntry(requestDate,
|
||||
responseDate,
|
||||
response.getStatusLine(),
|
||||
response.getAllHeaders(),
|
||||
entity,
|
||||
body,
|
||||
null);
|
||||
}
|
||||
|
||||
public HttpCacheEntry copyWithVariant(final HttpCacheEntry entry, final String variantURI){
|
||||
public HttpCacheEntry copyWithVariant(
|
||||
final HttpCacheEntry entry, final String variantURI) throws IOException {
|
||||
Set<String> variants = new HashSet<String>(entry.getVariantURIs());
|
||||
variants.add(variantURI);
|
||||
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
|
||||
InputStream instream = entry.getBody();
|
||||
byte[] buf = new byte[2048];
|
||||
int len;
|
||||
while ((len = instream.read(buf)) != -1) {
|
||||
outstream.write(buf, 0, len);
|
||||
}
|
||||
return new BasicHttpCacheEntry(
|
||||
entry.getRequestDate(),
|
||||
entry.getResponseDate(),
|
||||
entry.getStatusLine(),
|
||||
entry.getAllHeaders(),
|
||||
entry.getBody(), variants);
|
||||
outstream.toByteArray(),
|
||||
variants);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -26,7 +26,9 @@
|
|||
*/
|
||||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.Date;
|
||||
|
@ -69,10 +71,17 @@ class CacheEntryUpdater {
|
|||
HttpResponse response) throws IOException {
|
||||
|
||||
Header[] mergedHeaders = mergeHeaders(entry, response);
|
||||
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
|
||||
InputStream instream = entry.getBody();
|
||||
byte[] buf = new byte[2048];
|
||||
int len;
|
||||
while ((len = instream.read(buf)) != -1) {
|
||||
outstream.write(buf, 0, len);
|
||||
}
|
||||
HttpCacheEntry updated = new BasicHttpCacheEntry(requestDate, responseDate,
|
||||
entry.getStatusLine(),
|
||||
mergedHeaders,
|
||||
entry.getBody(),
|
||||
outstream.toByteArray(),
|
||||
null);
|
||||
return updated;
|
||||
}
|
||||
|
|
|
@ -140,7 +140,7 @@ class CacheValidityPolicy {
|
|||
* @return boolean indicating whether actual length matches Content-Length
|
||||
*/
|
||||
protected boolean contentLengthHeaderMatchesActualLength(final HttpCacheEntry entry) {
|
||||
return getContentLengthValue(entry) == entry.getBody().getContentLength();
|
||||
return getContentLengthValue(entry) == entry.getBodyLength();
|
||||
}
|
||||
|
||||
protected long getApparentAgeSecs(final HttpCacheEntry entry) {
|
||||
|
|
|
@ -70,10 +70,10 @@ class CachedHttpResponseGenerator {
|
|||
.getStatusCode(), entry.getReasonPhrase());
|
||||
|
||||
if (entry.getStatusCode() != HttpStatus.SC_NOT_MODIFIED) {
|
||||
HttpEntity entity = entry.getBody();
|
||||
response.setEntity(entity);
|
||||
HttpEntity entity = new CacheEntity(entry);
|
||||
response.setHeaders(entry.getAllHeaders());
|
||||
addMissingContentLengthHeader(response, entity);
|
||||
response.setEntity(entity);
|
||||
}
|
||||
|
||||
long age = this.validityStrategy.getCurrentAgeSecs(entry);
|
||||
|
|
|
@ -519,7 +519,7 @@ public class CachingHttpClient implements HttpClient {
|
|||
|
||||
HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() {
|
||||
|
||||
public HttpCacheEntry update(HttpCacheEntry existing) {
|
||||
public HttpCacheEntry update(HttpCacheEntry existing) throws IOException {
|
||||
return doGetUpdatedParentEntry(existing, entry, variantURI);
|
||||
}
|
||||
|
||||
|
@ -530,7 +530,7 @@ public class CachingHttpClient implements HttpClient {
|
|||
|
||||
HttpCacheEntry doGetUpdatedParentEntry(
|
||||
HttpCacheEntry existing,
|
||||
HttpCacheEntry entry, String variantURI) {
|
||||
HttpCacheEntry entry, String variantURI) throws IOException {
|
||||
if (existing != null) {
|
||||
return cacheEntryGenerator.copyWithVariant(existing, variantURI);
|
||||
} else {
|
||||
|
|
|
@ -29,8 +29,6 @@ package org.apache.http.impl.client.cache;
|
|||
import java.util.Date;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.StatusLine;
|
||||
|
||||
public class CacheEntry extends BasicHttpCacheEntry {
|
||||
|
||||
|
@ -38,28 +36,17 @@ public class CacheEntry extends BasicHttpCacheEntry {
|
|||
|
||||
public static final long MAX_AGE = CacheValidityPolicy.MAX_AGE;
|
||||
|
||||
public CacheEntry(
|
||||
Date requestDate,
|
||||
Date responseDate,
|
||||
StatusLine statusLine,
|
||||
Header[] responseHeaders,
|
||||
HttpEntity body) {
|
||||
super(requestDate, responseDate, statusLine, responseHeaders, body, null);
|
||||
}
|
||||
|
||||
public CacheEntry(
|
||||
Date requestDate,
|
||||
Date responseDate) {
|
||||
super(requestDate, responseDate, new OKStatus(), new Header[] {},
|
||||
new CacheEntity(new byte[] {}), null);
|
||||
super(requestDate, responseDate, new OKStatus(), new Header[] {}, new byte[] {}, null);
|
||||
}
|
||||
|
||||
public CacheEntry(
|
||||
Date requestDate,
|
||||
Date responseDate,
|
||||
Header[] headers) {
|
||||
super(requestDate, responseDate, new OKStatus(), headers,
|
||||
new CacheEntity(new byte[] {}), null);
|
||||
super(requestDate, responseDate, new OKStatus(), headers, new byte[] {}, null);
|
||||
}
|
||||
|
||||
public CacheEntry(
|
||||
|
@ -67,20 +54,17 @@ public class CacheEntry extends BasicHttpCacheEntry {
|
|||
Date responseDate,
|
||||
Header[] headers,
|
||||
byte[] content) {
|
||||
super(requestDate, responseDate, new OKStatus(), headers,
|
||||
new CacheEntity(content), null);
|
||||
super(requestDate, responseDate, new OKStatus(), headers, content, null);
|
||||
}
|
||||
|
||||
public CacheEntry(
|
||||
Header[] headers,
|
||||
byte[] content) {
|
||||
super(new Date(), new Date(), new OKStatus(), headers,
|
||||
new CacheEntity(content), null);
|
||||
super(new Date(), new Date(), new OKStatus(), headers, content, null);
|
||||
}
|
||||
|
||||
public CacheEntry(Header[] headers) {
|
||||
super(new Date(), new Date(), new OKStatus(), headers,
|
||||
new CacheEntity(new byte[] {}), null);
|
||||
super(new Date(), new Date(), new OKStatus(), headers, new byte[] {}, null);
|
||||
}
|
||||
|
||||
public CacheEntry() {
|
||||
|
@ -88,8 +72,7 @@ public class CacheEntry extends BasicHttpCacheEntry {
|
|||
}
|
||||
|
||||
public CacheEntry(byte[] content) {
|
||||
super(new Date(), new Date(), new OKStatus(), new Header[] {},
|
||||
new CacheEntity(content), null);
|
||||
super(new Date(), new Date(), new OKStatus(), new Header[] {}, content, null);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -103,7 +103,7 @@ public class TestCacheEntry {
|
|||
}
|
||||
|
||||
@Test
|
||||
public void testCacheEntryCanStoreMultipleVariantUris() {
|
||||
public void testCacheEntryCanStoreMultipleVariantUris() throws Exception {
|
||||
|
||||
Header[] headers = new Header[]{};
|
||||
CacheEntry entry = new CacheEntry(headers);
|
||||
|
|
|
@ -1220,7 +1220,7 @@ public class TestCachingHttpClient {
|
|||
bytes)).andReturn(mockCacheEntry);
|
||||
}
|
||||
|
||||
private void copyCacheEntry(CacheEntry entry, String variantURI) {
|
||||
private void copyCacheEntry(CacheEntry entry, String variantURI) throws IOException {
|
||||
EasyMock.expect(
|
||||
mockEntryGenerator.copyWithVariant(entry, variantURI)).andReturn(entry);
|
||||
}
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
import org.apache.http.client.cache.HttpCacheUpdateCallback;
|
||||
|
@ -148,7 +149,7 @@ public class TestResponseCache {
|
|||
existing.getRequestDate(),
|
||||
existing.getStatusLine(),
|
||||
existing.getAllHeaders(),
|
||||
new CacheEntity(expectedArray),
|
||||
expectedArray,
|
||||
null);
|
||||
return updated;
|
||||
}
|
||||
|
@ -156,9 +157,14 @@ public class TestResponseCache {
|
|||
|
||||
HttpCacheEntry afterUpdate = cache.getEntry("foo");
|
||||
|
||||
ByteArrayOutputStream stream = new ByteArrayOutputStream();
|
||||
afterUpdate.getBody().writeTo(stream);
|
||||
byte[] bytes = stream.toByteArray();
|
||||
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
|
||||
InputStream instream = afterUpdate.getBody();
|
||||
byte[] buf = new byte[2048];
|
||||
int len;
|
||||
while ((len = instream.read(buf)) != -1) {
|
||||
outstream.write(buf, 0, len);
|
||||
}
|
||||
byte[] bytes = outstream.toByteArray();
|
||||
Assert.assertArrayEquals(expectedArray, bytes);
|
||||
}
|
||||
|
||||
|
|
|
@ -632,10 +632,16 @@ public abstract class AbstractHttpClient implements HttpClient {
|
|||
|
||||
URI requestURI = request.getURI();
|
||||
if (requestURI.isAbsolute()) {
|
||||
String host = requestURI.getHost();
|
||||
String ssp = requestURI.getSchemeSpecificPart();
|
||||
ssp = ssp.substring(2, ssp.length()); //remove "//" prefix
|
||||
int end = ssp.indexOf(':') > 0 ? ssp.indexOf(':') :
|
||||
ssp.indexOf('/') > 0 ? ssp.indexOf('/') :
|
||||
ssp.indexOf('?') > 0 ? ssp.indexOf('?') : ssp.length();
|
||||
String host = ssp.substring(0, end);
|
||||
|
||||
int port = requestURI.getPort();
|
||||
String scheme = requestURI.getScheme();
|
||||
if (host == null) {
|
||||
if (host == null || "".equals(host)) {
|
||||
throw new ClientProtocolException(
|
||||
"URI does not specify a valid host name: " + requestURI);
|
||||
}
|
||||
|
|
|
@ -37,11 +37,11 @@ import org.apache.http.client.HttpClient;
|
|||
import org.apache.http.client.UserTokenHandler;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.conn.ManagedClientConnection;
|
||||
import org.apache.http.conn.params.ConnManagerParams;
|
||||
import org.apache.http.entity.StringEntity;
|
||||
import org.apache.http.impl.conn.tsccm.ThreadSafeClientConnManager;
|
||||
import org.apache.http.localserver.ServerTestBase;
|
||||
import org.apache.http.params.BasicHttpParams;
|
||||
import org.apache.http.params.HttpConnectionParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
import org.apache.http.protocol.BasicHttpContext;
|
||||
import org.apache.http.protocol.ExecutionContext;
|
||||
|
@ -83,7 +83,7 @@ public class TestStatefulConnManagement extends ServerTestBase {
|
|||
HttpHost target = new HttpHost("localhost", port);
|
||||
|
||||
HttpParams params = new BasicHttpParams();
|
||||
ConnManagerParams.setTimeout(params, 10L);
|
||||
HttpConnectionParams.setConnectionTimeout(params, 10);
|
||||
|
||||
ThreadSafeClientConnManager mgr = new ThreadSafeClientConnManager(supportedSchemes);
|
||||
mgr.setMaxTotal(workerCount);
|
||||
|
|
Loading…
Reference in New Issue