From 4ae188acbbad19fb59e5552e216a442f4a22fdde Mon Sep 17 00:00:00 2001 From: Oleg Kalnichevski Date: Fri, 30 Jul 2010 12:44:44 +0000 Subject: [PATCH] Made possible for cache entries to depend on system resources that may require deallocation git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@980767 13f79535-47bb-0310-9956-ffa450edef68 --- .../http/client/cache/HttpCacheEntry.java | 20 +++--- .../apache/http/client/cache/Resource.java | 38 +++++++++++ .../impl/client/cache/BasicHttpCache.java | 31 +++------ .../client/cache/BasicHttpCacheEntry.java | 63 +++++++++++++++++++ .../http/impl/client/cache/CacheConfig.java | 26 ++++++++ .../client/cache/CacheEntryGenerator.java | 19 +++++- .../impl/client/cache/CacheEntryUpdater.java | 2 +- .../http/impl/client/cache/CacheMap.java | 50 +++++++++++++++ .../impl/client/cache/CachingHttpClient.java | 4 +- .../http/impl/client/cache/CacheEntry.java | 15 +++-- .../impl/client/cache/TestCacheEntry.java | 6 +- .../client/cache/TestCachingHttpClient.java | 17 +++-- .../impl/client/cache/TestResponseCache.java | 2 +- 13 files changed, 232 insertions(+), 61 deletions(-) create mode 100644 httpclient-cache/src/main/java/org/apache/http/client/cache/Resource.java create mode 100644 httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheEntry.java create mode 100644 httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheMap.java 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 f43bf2b9a..cb7e1266b 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 @@ -44,12 +44,15 @@ import org.apache.http.annotation.Immutable; import org.apache.http.message.BasicHeader; /** - * Structure used to store an {@link HttpResponse} in a cache + * Structure used to store an {@link HttpResponse} in a cache. Some entries can optionally depend + * on system resources that may require explicit deallocation. In such a case {@link #getResource()} + * should return a non-null instance of {@link Resource} that must be deallocated by calling + * {@link Resource#dispose()} method when no longer used. * * @since 4.1 */ @Immutable -public class HttpCacheEntry implements Serializable { +public abstract class HttpCacheEntry implements Serializable { private static final long serialVersionUID = -6300496422359477413L; @@ -198,21 +201,12 @@ public 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 + "; statusLine=" + this.statusLine + "]"; } - public static HttpCacheEntry copyWithVariant(final HttpCacheEntry entry, final String variantURI){ - Set variants = new HashSet(entry.getVariantURIs()); - variants.add(variantURI); - return new HttpCacheEntry( - entry.getRequestDate(), - entry.getResponseDate(), - entry.getStatusLine(), - entry.getAllHeaders(), - entry.getBody(), variants); - } - } diff --git a/httpclient-cache/src/main/java/org/apache/http/client/cache/Resource.java b/httpclient-cache/src/main/java/org/apache/http/client/cache/Resource.java new file mode 100644 index 000000000..0815089cf --- /dev/null +++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/Resource.java @@ -0,0 +1,38 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.client.cache; + +/** + * Represents a disposable system resource. + * + * @since 4.1 + */ +public interface Resource { + + void dispose(); + +} diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCache.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCache.java index 991530ce2..3c2e00eb9 100644 --- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCache.java +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCache.java @@ -28,7 +28,6 @@ package org.apache.http.impl.client.cache; import java.io.IOException; import java.util.LinkedHashMap; -import java.util.Map; import org.apache.http.annotation.ThreadSafe; import org.apache.http.client.cache.HttpCache; @@ -36,29 +35,19 @@ import org.apache.http.client.cache.HttpCacheEntry; import org.apache.http.client.cache.HttpCacheUpdateCallback; /** - * Implements {@link HttpCache} using LinkedHashMap for backing store + * Basic {@link HttpCache} implementation backed by an instance of {@link LinkedHashMap}. + * This cache does NOT deallocate resources associated with the cache entries. It is intended + * for use with {@link BasicHttpCacheEntry} and similar. * * @since 4.1 */ @ThreadSafe public class BasicHttpCache implements HttpCache { - private final LinkedHashMap baseMap = new LinkedHashMap( - 20, 0.75f, true) { - - private static final long serialVersionUID = -7750025207539768511L; - - @Override - protected boolean removeEldestEntry(Map.Entry eldest) { - return size() > maxEntries; - } - - }; - - private final int maxEntries; + private final CacheMap entries; public BasicHttpCache(int maxEntries) { - this.maxEntries = maxEntries; + this.entries = new CacheMap(maxEntries); } /** @@ -70,7 +59,7 @@ public class BasicHttpCache implements HttpCache { * HttpCacheEntry to place in the cache */ public synchronized void putEntry(String url, HttpCacheEntry entry) throws IOException { - baseMap.put(url, entry); + entries.put(url, entry); } /** @@ -81,7 +70,7 @@ public class BasicHttpCache implements HttpCache { * @return HttpCacheEntry if one exists, or null for cache miss */ public synchronized HttpCacheEntry getEntry(String url) throws IOException { - return baseMap.get(url); + return entries.get(url); } /** @@ -91,14 +80,14 @@ public class BasicHttpCache implements HttpCache { * Url that is the cache key */ public synchronized void removeEntry(String url) throws IOException { - baseMap.remove(url); + entries.remove(url); } public synchronized void updateEntry( String url, HttpCacheUpdateCallback callback) throws IOException { - HttpCacheEntry existingEntry = baseMap.get(url); - baseMap.put(url, callback.update(existingEntry)); + HttpCacheEntry existingEntry = entries.get(url); + entries.put(url, callback.update(existingEntry)); } } 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 new file mode 100644 index 000000000..784a16495 --- /dev/null +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheEntry.java @@ -0,0 +1,63 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.impl.client.cache; + +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; +import org.apache.http.client.cache.Resource; + +/** + * Basic {@link HttpCacheEntry} that does not depend on any system resources that may require + * explicit deallocation. + */ +@Immutable +public class BasicHttpCacheEntry extends HttpCacheEntry { + + private static final long serialVersionUID = -8464486112875881235L; + + public BasicHttpCacheEntry( + final Date requestDate, + final Date responseDate, + final StatusLine statusLine, + final Header[] responseHeaders, + final HttpEntity body, + final Set variants) { + super(requestDate, responseDate, statusLine, responseHeaders, body, variants); + } + + @Override + public Resource getResource() { + return null; + } + +} 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 index 025a8772d..c4f1a88bc 100644 --- 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 @@ -1,3 +1,29 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ package org.apache.http.impl.client.cache; /** 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 4b72780cb..12bf983d9 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 @@ -27,6 +27,8 @@ package org.apache.http.impl.client.cache; import java.util.Date; +import java.util.HashSet; +import java.util.Set; import org.apache.http.Header; import org.apache.http.HttpResponse; @@ -50,10 +52,10 @@ class CacheEntryGenerator { Header ct = response.getFirstHeader(HTTP.CONTENT_TYPE); Header ce = response.getFirstHeader(HTTP.CONTENT_ENCODING); CacheEntity entity = new CacheEntity( - body, - ct != null ? ct.getValue() : null, + body, + ct != null ? ct.getValue() : null, ce != null ? ce.getValue() : null); - return new HttpCacheEntry(requestDate, + return new BasicHttpCacheEntry(requestDate, responseDate, response.getStatusLine(), response.getAllHeaders(), @@ -61,4 +63,15 @@ class CacheEntryGenerator { null); } + public HttpCacheEntry copyWithVariant(final HttpCacheEntry entry, final String variantURI){ + Set variants = new HashSet(entry.getVariantURIs()); + variants.add(variantURI); + return new BasicHttpCacheEntry( + entry.getRequestDate(), + entry.getResponseDate(), + entry.getStatusLine(), + entry.getAllHeaders(), + entry.getBody(), 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 a4e316c6b..42ca2b7e4 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 @@ -69,7 +69,7 @@ class CacheEntryUpdater { HttpResponse response) throws IOException { Header[] mergedHeaders = mergeHeaders(entry, response); - HttpCacheEntry updated = new HttpCacheEntry(requestDate, responseDate, + HttpCacheEntry updated = new BasicHttpCacheEntry(requestDate, responseDate, entry.getStatusLine(), mergedHeaders, entry.getBody(), diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheMap.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheMap.java new file mode 100644 index 000000000..1bb1e3a2b --- /dev/null +++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheMap.java @@ -0,0 +1,50 @@ +/* + * ==================================================================== + * Licensed to the Apache Software Foundation (ASF) under one + * or more contributor license agreements. See the NOTICE file + * distributed with this work for additional information + * regarding copyright ownership. The ASF licenses this file + * to you under the Apache License, Version 2.0 (the + * "License"); you may not use this file except in compliance + * with the License. You may obtain a copy of the License at + * + * http://www.apache.org/licenses/LICENSE-2.0 + * + * Unless required by applicable law or agreed to in writing, + * software distributed under the License is distributed on an + * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY + * KIND, either express or implied. See the License for the + * specific language governing permissions and limitations + * under the License. + * ==================================================================== + * + * This software consists of voluntary contributions made by many + * individuals on behalf of the Apache Software Foundation. For more + * information on the Apache Software Foundation, please see + * . + * + */ +package org.apache.http.impl.client.cache; + +import java.util.LinkedHashMap; +import java.util.Map; + +import org.apache.http.client.cache.HttpCacheEntry; + +final class CacheMap extends LinkedHashMap { + + private static final long serialVersionUID = -7750025207539768511L; + + private final int maxEntries; + + CacheMap(int maxEntries) { + super(20, 0.75f, true); + this.maxEntries = maxEntries; + } + + @Override + protected boolean removeEldestEntry(final Map.Entry eldest) { + return size() > this.maxEntries; + } + +} \ No newline at end of file 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 6b54c3349..8fe1794fa 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 @@ -532,9 +532,9 @@ public class CachingHttpClient implements HttpClient { HttpCacheEntry existing, HttpCacheEntry entry, String variantURI) { if (existing != null) { - return HttpCacheEntry.copyWithVariant(existing, variantURI); + return cacheEntryGenerator.copyWithVariant(existing, variantURI); } else { - return HttpCacheEntry.copyWithVariant(entry, variantURI); + return cacheEntryGenerator.copyWithVariant(entry, variantURI); } } 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 0edbd04e6..cf8f702b4 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 @@ -31,9 +31,8 @@ import java.util.Date; import org.apache.http.Header; import org.apache.http.HttpEntity; import org.apache.http.StatusLine; -import org.apache.http.client.cache.HttpCacheEntry; -public class CacheEntry extends HttpCacheEntry { +public class CacheEntry extends BasicHttpCacheEntry { private static final long serialVersionUID = 7964121802841871079L; @@ -51,7 +50,7 @@ public class CacheEntry extends HttpCacheEntry { public CacheEntry( Date requestDate, Date responseDate) { - super(requestDate, responseDate, new OKStatus(), new Header[] {}, + super(requestDate, responseDate, new OKStatus(), new Header[] {}, new CacheEntity(new byte[] {}), null); } @@ -59,7 +58,7 @@ public class CacheEntry extends HttpCacheEntry { Date requestDate, Date responseDate, Header[] headers) { - super(requestDate, responseDate, new OKStatus(), headers, + super(requestDate, responseDate, new OKStatus(), headers, new CacheEntity(new byte[] {}), null); } @@ -68,19 +67,19 @@ public class CacheEntry extends HttpCacheEntry { Date responseDate, Header[] headers, byte[] content) { - super(requestDate, responseDate, new OKStatus(), headers, + super(requestDate, responseDate, new OKStatus(), headers, new CacheEntity(content), null); } public CacheEntry( Header[] headers, byte[] content) { - super(new Date(), new Date(), new OKStatus(), headers, + super(new Date(), new Date(), new OKStatus(), headers, new CacheEntity(content), null); } public CacheEntry(Header[] headers) { - super(new Date(), new Date(), new OKStatus(), headers, + super(new Date(), new Date(), new OKStatus(), headers, new CacheEntity(new byte[] {}), null); } @@ -89,7 +88,7 @@ public class CacheEntry extends HttpCacheEntry { } public CacheEntry(byte[] content) { - super(new Date(), new Date(), new OKStatus(), new Header[] {}, + super(new Date(), new Date(), new OKStatus(), new Header[] {}, new CacheEntity(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 2b3acb144..35c47da2e 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 @@ -108,8 +108,10 @@ public class TestCacheEntry { Header[] headers = new Header[]{}; CacheEntry entry = new CacheEntry(headers); - HttpCacheEntry addedOne = HttpCacheEntry.copyWithVariant(entry, "foo"); - HttpCacheEntry addedTwo = HttpCacheEntry.copyWithVariant(addedOne, "bar"); + CacheEntryGenerator entryGenerator = new CacheEntryGenerator(); + + HttpCacheEntry addedOne = entryGenerator.copyWithVariant(entry, "foo"); + HttpCacheEntry addedTwo = entryGenerator.copyWithVariant(addedOne, "bar"); Set variants = addedTwo.getVariantURIs(); 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 e8f2d960a..b398e29b5 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 @@ -26,8 +26,6 @@ */ package org.apache.http.impl.client.cache; -import static junit.framework.Assert.assertTrue; - import java.io.ByteArrayOutputStream; import java.io.IOException; import java.io.InputStream; @@ -319,18 +317,12 @@ public class TestCachingHttpClient { @Test public void testCacheUpdateAddsVariantURIToParentEntry() throws Exception { - final String variantURI = "variantURI"; - final CacheEntry entry = new CacheEntry(); - + copyCacheEntry(entry, variantURI); replayMocks(); - - HttpCacheEntry updatedEntry = impl.doGetUpdatedParentEntry(null, entry, variantURI); - + impl.doGetUpdatedParentEntry(null, entry, variantURI); verifyMocks(); - - assertTrue(updatedEntry.getVariantURIs().contains(variantURI)); } @@ -1228,6 +1220,11 @@ public class TestCachingHttpClient { bytes)).andReturn(mockCacheEntry); } + private void copyCacheEntry(CacheEntry entry, String variantURI) { + EasyMock.expect( + mockEntryGenerator.copyWithVariant(entry, variantURI)).andReturn(entry); + } + private void handleBackendResponseReturnsResponse(HttpRequest request, HttpResponse response) throws IOException { EasyMock.expect( 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 36dd3601b..6fa43364b 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 @@ -143,7 +143,7 @@ public class TestResponseCache { cache.updateEntry("foo", new HttpCacheUpdateCallback() { public HttpCacheEntry update(HttpCacheEntry existing) { - HttpCacheEntry updated = new HttpCacheEntry( + HttpCacheEntry updated = new BasicHttpCacheEntry( existing.getRequestDate(), existing.getRequestDate(), existing.getStatusLine(),