From 8690e96fa67e146b6160d279d448f4abae273a3b Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Thu, 29 Jul 2010 08:30:43 +0000 Subject: [PATCH] HTTPCLIENT-972: Cache config Contributed by Jonathan Moore git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@980358 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/impl/client/cache/CacheConfig.java | 51 ++++++++++++++++++ .../impl/client/cache/CachingHttpClient.java | 54 +++++++++++++++---- .../cache/DoNotTestProtocolRequirements.java | 4 +- .../client/cache/TestCachingHttpClient.java | 2 +- .../client/cache/TestProtocolDeviations.java | 5 +- .../cache/TestProtocolRequirements.java | 19 ++++--- 6 files changed, 114 insertions(+), 21 deletions(-) create mode 100644 httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java new file mode 100644 index 000000000..025a8772d --- /dev/null +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheConfig.java @@ -0,0 +1,51 @@ +package org.apache.http.impl.client.cache; + +/** + * Java Beans-style configuration for a + * {@link org.apache.http.impl.client.cache.CachingHttpClient}. + */ +public class CacheConfig { + + /** Default setting for the maximum object size that will be + * cached, in bytes. + */ + public final static int DEFAULT_MAX_OBJECT_SIZE_BYTES = 8192; + + private int maxObjectSizeBytes = DEFAULT_MAX_OBJECT_SIZE_BYTES; + private boolean isSharedCache = true; + + /** + * Returns the current maximum object size that will be cached. + * @return size in bytes + */ + public int getMaxObjectSizeBytes() { + return maxObjectSizeBytes; + } + + /** + * Specifies the maximum object size that will be eligible for caching. + * @param maxObjectSizeBytes size in bytes + */ + public void setMaxObjectSizeBytes(int maxObjectSizeBytes) { + this.maxObjectSizeBytes = maxObjectSizeBytes; + } + + /** + * Returns whether the cache will behave as a shared cache or not. + * @return true for a shared cache, false for a non-shared (private) + * cache + */ + public boolean isSharedCache() { + return isSharedCache; + } + + /** + * Sets whether the cache should behave as a shared cache or not. + * @param isSharedCache true to behave as a shared cache, false to + * behave as a non-shared (private) cache. + */ + public void setSharedCache(boolean isSharedCache) { + this.isSharedCache = isSharedCache; + } + +} 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 7521eb1b1..d6f298bc2 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 @@ -67,8 +67,6 @@ import org.apache.http.protocol.HttpContext; public class CachingHttpClient implements HttpClient { private final static int MAX_CACHE_ENTRIES = 1000; - private final static int DEFAULT_MAX_OBJECT_SIZE_BYTES = 8192; - private final static boolean SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS = false; private final AtomicLong cacheHits = new AtomicLong(); @@ -87,16 +85,30 @@ public class CachingHttpClient implements HttpClient { private final CachedResponseSuitabilityChecker suitabilityChecker; private final ConditionalRequestBuilder conditionalRequestBuilder; - private final int maxObjectSizeBytes; + private final CacheEntryUpdater cacheEntryUpdater; + private final int maxObjectSizeBytes; + private final boolean sharedCache; + private final ResponseProtocolCompliance responseCompliance; private final RequestProtocolCompliance requestCompliance; private final Log log = LogFactory.getLog(getClass()); - public CachingHttpClient(HttpClient client, HttpCache cache, int maxObjectSizeBytes) { + public CachingHttpClient(HttpClient client, HttpCache cache, CacheConfig config) { super(); + if (client == null) { + throw new IllegalArgumentException("HttpClient may not be null"); + } + if (cache == null) { + throw new IllegalArgumentException("HttpCache may not be null"); + } + if (config == null) { + throw new IllegalArgumentException("CacheConfig may not be null"); + } + this.maxObjectSizeBytes = config.getMaxObjectSizeBytes(); + this.sharedCache = config.isSharedCache(); this.backend = client; this.responseCache = cache; this.validityPolicy = new CacheValidityPolicy(); @@ -109,17 +121,37 @@ public class CachingHttpClient implements HttpClient { this.suitabilityChecker = new CachedResponseSuitabilityChecker(this.validityPolicy); this.conditionalRequestBuilder = new ConditionalRequestBuilder(); this.cacheEntryUpdater = new CacheEntryUpdater(); - this.maxObjectSizeBytes = maxObjectSizeBytes; + this.responseCompliance = new ResponseProtocolCompliance(); this.requestCompliance = new RequestProtocolCompliance(); } public CachingHttpClient() { - this(new DefaultHttpClient(), new BasicHttpCache(MAX_CACHE_ENTRIES), DEFAULT_MAX_OBJECT_SIZE_BYTES); + this(new DefaultHttpClient(), new BasicHttpCache(MAX_CACHE_ENTRIES), new CacheConfig()); } - public CachingHttpClient(HttpCache cache, int maxObjectSizeBytes) { - this(new DefaultHttpClient(), cache, maxObjectSizeBytes); + public CachingHttpClient(CacheConfig config) { + this(new DefaultHttpClient(), new BasicHttpCache(MAX_CACHE_ENTRIES), config); + } + + public CachingHttpClient(HttpClient client) { + this(client, new BasicHttpCache(MAX_CACHE_ENTRIES), new CacheConfig()); + } + + public CachingHttpClient(HttpClient client, CacheConfig config) { + this(client, new BasicHttpCache(MAX_CACHE_ENTRIES), config); + } + + public CachingHttpClient(HttpCache cache) { + this(new DefaultHttpClient(), cache, new CacheConfig()); + } + + public CachingHttpClient(HttpCache cache, CacheConfig config) { + this(new DefaultHttpClient(), cache, config); + } + + public CachingHttpClient(HttpClient client, HttpCache cache) { + this(client, cache, new CacheConfig()); } CachingHttpClient(HttpClient backend, CacheValidityPolicy validityPolicy, ResponseCachingPolicy responseCachingPolicy, @@ -130,7 +162,9 @@ public class CachingHttpClient implements HttpClient { ConditionalRequestBuilder conditionalRequestBuilder, CacheEntryUpdater entryUpdater, ResponseProtocolCompliance responseCompliance, RequestProtocolCompliance requestCompliance) { - this.maxObjectSizeBytes = DEFAULT_MAX_OBJECT_SIZE_BYTES; + CacheConfig config = new CacheConfig(); + this.maxObjectSizeBytes = config.getMaxObjectSizeBytes(); + this.sharedCache = config.isSharedCache(); this.backend = backend; this.validityPolicy = validityPolicy; this.responseCachingPolicy = responseCachingPolicy; @@ -383,7 +417,7 @@ public class CachingHttpClient implements HttpClient { } public boolean isSharedCache() { - return true; + return sharedCache; } Date getCurrentDate() { diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DoNotTestProtocolRequirements.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DoNotTestProtocolRequirements.java index 7b2ce3b0e..36d8383af 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DoNotTestProtocolRequirements.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/DoNotTestProtocolRequirements.java @@ -80,7 +80,9 @@ public class DoNotTestProtocolRequirements { mockBackend = EasyMock.createMock(HttpClient.class); mockEntity = EasyMock.createMock(HttpEntity.class); mockCache = EasyMock.createMock(HttpCache.class); - impl = new CachingHttpClient(mockBackend, cache, MAX_BYTES); + CacheConfig params = new CacheConfig(); + params.setMaxObjectSizeBytes(MAX_BYTES); + impl = new CachingHttpClient(mockBackend, cache, params); } private HttpResponse make200Response() { 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 f785be01c..e8f2d960a 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 @@ -884,7 +884,7 @@ public class TestCachingHttpClient { HttpCache cacheImpl = new BasicHttpCache(100); - CachingHttpClient cachingClient = new CachingHttpClient(httpClient, cacheImpl, 8192); + CachingHttpClient cachingClient = new CachingHttpClient(httpClient, cacheImpl); HttpUriRequest request = new HttpGet("http://www.fancast.com/static-28262/styles/base.css"); diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java index 28b7562bd..d6a7b2619 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolDeviations.java @@ -97,7 +97,10 @@ public class TestProtocolDeviations { mockBackend = EasyMock.createMock(HttpClient.class); mockEntity = EasyMock.createMock(HttpEntity.class); mockCache = EasyMock.createMock(HttpCache.class); - impl = new CachingHttpClient(mockBackend, cache, MAX_BYTES); + + CacheConfig params = new CacheConfig(); + params.setMaxObjectSizeBytes(MAX_BYTES); + impl = new CachingHttpClient(mockBackend, cache, params); } private HttpResponse make200Response() { diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java index 001d5c2fa..492f726b4 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestProtocolRequirements.java @@ -84,6 +84,7 @@ public class TestProtocolRequirements { private HttpCache mockCache; private HttpRequest request; private HttpResponse originResponse; + private CacheConfig params; private CachingHttpClient impl; @@ -101,7 +102,9 @@ public class TestProtocolRequirements { mockBackend = EasyMock.createMock(HttpClient.class); mockEntity = EasyMock.createMock(HttpEntity.class); mockCache = EasyMock.createMock(HttpCache.class); - impl = new CachingHttpClient(mockBackend, cache, MAX_BYTES); + params = new CacheConfig(); + params.setMaxObjectSizeBytes(MAX_BYTES); + impl = new CachingHttpClient(mockBackend, cache, params); } private void replayMocks() { @@ -140,7 +143,7 @@ public class TestProtocolRequirements { mockCache = EasyMock.createMock(HttpCache.class); mockEntity = EasyMock.createMock(HttpEntity.class); - impl = new CachingHttpClient(mockBackend, mockCache, MAX_BYTES); + impl = new CachingHttpClient(mockBackend, mockCache, params); EasyMock.expect(mockCache.getEntry((String) EasyMock.anyObject())).andReturn(null) .anyTimes(); @@ -2307,7 +2310,7 @@ public class TestProtocolRequirements { mockCache.putEntry(EasyMock.eq("http://foo.example.com/thing"), EasyMock.isA(HttpCacheEntry.class)); - impl = new CachingHttpClient(mockBackend, mockCache, MAX_BYTES); + impl = new CachingHttpClient(mockBackend, mockCache, params); HttpRequest validate = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1); validate.setHeader("If-None-Match", "\"etag\""); @@ -2337,7 +2340,7 @@ public class TestProtocolRequirements { Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L); Date nineSecondsAgo = new Date(now.getTime() - 9 * 1000L); Date eightSecondsAgo = new Date(now.getTime() - 8 * 1000L); - + Header[] hdrs = new Header[] { new BasicHeader("Date", DateUtils.formatDate(nineSecondsAgo)), new BasicHeader("Cache-Control", "max-age=3600"), @@ -2349,7 +2352,7 @@ public class TestProtocolRequirements { CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes); - impl = new CachingHttpClient(mockBackend, mockCache, MAX_BYTES); + impl = new CachingHttpClient(mockBackend, mockCache, params); EasyMock.expect(mockCache.getEntry("http://foo.example.com/thing")).andReturn(entry); @@ -2390,7 +2393,7 @@ public class TestProtocolRequirements { CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes); - impl = new CachingHttpClient(mockBackend, mockCache, MAX_BYTES); + impl = new CachingHttpClient(mockBackend, mockCache, params); EasyMock.expect(mockCache.getEntry("http://foo.example.com/thing")).andReturn(entry); EasyMock.expect( @@ -2591,7 +2594,7 @@ public class TestProtocolRequirements { CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes); - impl = new CachingHttpClient(mockBackend, mockCache, MAX_BYTES); + impl = new CachingHttpClient(mockBackend, mockCache, params); EasyMock.expect(mockCache.getEntry("http://foo.example.com/thing")).andReturn(entry); @@ -2635,7 +2638,7 @@ public class TestProtocolRequirements { CacheEntry entry = new CacheEntry(requestTime, responseTime, hdrs, bytes); - impl = new CachingHttpClient(mockBackend, mockCache, MAX_BYTES); + impl = new CachingHttpClient(mockBackend, mockCache, params); HttpResponse validated = make200Response(); validated.setHeader("Cache-Control", "public");