From e0d37d550227a61cad176086be919a142cbad148 Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 30 Jul 2010 20:15:39 +0000 Subject: [PATCH] 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 --- .../http/client/cache/HttpCacheEntry.java | 31 ++++--------- .../client/cache/BasicHttpCacheEntry.java | 20 +++++++-- .../http/impl/client/cache/CacheEntity.java | 43 +++++++------------ .../client/cache/CacheEntryGenerator.java | 26 ++++++----- .../impl/client/cache/CacheEntryUpdater.java | 11 ++++- .../client/cache/CacheValidityPolicy.java | 2 +- .../cache/CachedHttpResponseGenerator.java | 4 +- .../impl/client/cache/CachingHttpClient.java | 4 +- .../http/impl/client/cache/CacheEntry.java | 29 +++---------- .../impl/client/cache/TestCacheEntry.java | 2 +- .../client/cache/TestCachingHttpClient.java | 2 +- .../impl/client/cache/TestResponseCache.java | 14 ++++-- .../http/impl/client/AbstractHttpClient.java | 10 ++++- .../client/TestStatefulConnManagement.java | 4 +- 14 files changed, 99 insertions(+), 103 deletions(-) diff --git a/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheEntry.java b/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheEntry.java index cb7e1266b..0c7292cba 100644 --- a/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheEntry.java +++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheEntry.java @@ -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.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 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 variants) { super(); if (requestDate == null) { @@ -103,17 +95,12 @@ public HttpCacheEntry( 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(variants) : new HashSet(); - } public StatusLine getStatusLine() { @@ -140,10 +127,6 @@ public Date getResponseDate() { return responseDate; } - public HttpEntity getBody() { - return body; - } - public Header[] getAllHeaders() { return responseHeaders.getAllHeaders(); } @@ -164,6 +147,12 @@ public Set getVariantURIs() { 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 @@ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundE this.responseHeaders.setHeaders(headers); } - public abstract Resource getResource(); - @Override public String toString() { return "[request date=" + this.requestDate + "; response date=" + this.responseDate diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheEntry.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheEntry.java index 784a16495..870a12f42 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheEntry.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheEntry.java @@ -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 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 diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java index 6b4f17a08..0319dfd0e 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntity.java @@ -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 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 @@ public boolean isRepeatable() { } 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() { diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryGenerator.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryGenerator.java index 12bf983d9..f8f7e48bc 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryGenerator.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryGenerator.java @@ -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 @@ public HttpCacheEntry generateEntry( 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 variants = new HashSet(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); } } diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java index 42ca2b7e4..05542cf4a 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntryUpdater.java @@ -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 @@ public HttpCacheEntry updateCacheEntry( 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; } diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheValidityPolicy.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheValidityPolicy.java index 51be10c29..5bdb0e780 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheValidityPolicy.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheValidityPolicy.java @@ -140,7 +140,7 @@ protected long getContentLengthValue(final HttpCacheEntry entry) { * @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) { diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java index c56ec276b..14a4ad353 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java @@ -70,10 +70,10 @@ HttpResponse generateResponse(HttpCacheEntry entry) { .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); diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java index 8fe1794fa..e5dec67d7 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachingHttpClient.java @@ -519,7 +519,7 @@ void storeVariantEntry( 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 HttpCacheEntry update(HttpCacheEntry existing) { HttpCacheEntry doGetUpdatedParentEntry( HttpCacheEntry existing, - HttpCacheEntry entry, String variantURI) { + HttpCacheEntry entry, String variantURI) throws IOException { if (existing != null) { return cacheEntryGenerator.copyWithVariant(existing, variantURI); } else { diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/CacheEntry.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/CacheEntry.java index cf8f702b4..4fa270b01 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/CacheEntry.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/CacheEntry.java @@ -29,8 +29,6 @@ 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 CacheEntry( 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 CacheEntry() { } 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); } } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntry.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntry.java index 35c47da2e..055a6f41a 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntry.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntry.java @@ -103,7 +103,7 @@ public void testCacheEntryWithVaryStarHasVariants(){ } @Test - public void testCacheEntryCanStoreMultipleVariantUris() { + public void testCacheEntryCanStoreMultipleVariantUris() throws Exception { Header[] headers = new Header[]{}; CacheEntry entry = new CacheEntry(headers); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingHttpClient.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingHttpClient.java index b398e29b5..9dfa6a1d9 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingHttpClient.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachingHttpClient.java @@ -1220,7 +1220,7 @@ private void generateCacheEntry(Date requestDate, Date responseDate, byte[] byte 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); } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestResponseCache.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestResponseCache.java index 6fa43364b..ef34461ca 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestResponseCache.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestResponseCache.java @@ -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 HttpCacheEntry update(HttpCacheEntry existing) { existing.getRequestDate(), existing.getStatusLine(), existing.getAllHeaders(), - new CacheEntity(expectedArray), + expectedArray, null); return updated; } @@ -156,9 +157,14 @@ public HttpCacheEntry update(HttpCacheEntry existing) { 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); } diff --git a/httpclient/src/main/java/org/apache/http/impl/client/AbstractHttpClient.java b/httpclient/src/main/java/org/apache/http/impl/client/AbstractHttpClient.java index bb16301fe..2b4173639 100644 --- a/httpclient/src/main/java/org/apache/http/impl/client/AbstractHttpClient.java +++ b/httpclient/src/main/java/org/apache/http/impl/client/AbstractHttpClient.java @@ -632,10 +632,16 @@ private HttpHost determineTarget(HttpUriRequest request) throws ClientProtocolEx 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); } diff --git a/httpclient/src/test/java/org/apache/http/impl/client/TestStatefulConnManagement.java b/httpclient/src/test/java/org/apache/http/impl/client/TestStatefulConnManagement.java index 4f16849ff..85ac46f7d 100644 --- a/httpclient/src/test/java/org/apache/http/impl/client/TestStatefulConnManagement.java +++ b/httpclient/src/test/java/org/apache/http/impl/client/TestStatefulConnManagement.java @@ -37,11 +37,11 @@ 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 void testStatefulConnections() throws Exception { 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);