[prev in list] [next in list] [prev in thread] [next in thread]
List: httpcomponents-commits
Subject: svn commit: r1051865 - in
From: jonm () apache ! org
Date: 2010-12-22 11:59:23
Message-ID: 20101222115923.D4C652388994 () eris ! apache ! org
[Download RAW message or body]
Author: jonm
Date: Wed Dec 22 11:59:23 2010
New Revision: 1051865
URL: http://svn.apache.org/viewvc?rev=1051865&view=rev
Log:
HTTPCLIENT-1035: begin adding functionality for flushing updated
entries mentioned by Content-Location in responses. Not yet hooked
in to be used.
Modified:
httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java
httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java
Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src \
/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java?rev=1051865&r1=1051864&r2=1051865&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java \
(original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java \
Wed Dec 22 11:59:23 2010 @@ -29,16 +29,20 @@ package org.apache.http.impl.client.cach
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
+import java.util.Date;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
import org.apache.http.annotation.ThreadSafe;
import org.apache.http.client.cache.HeaderConstants;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheStorage;
+import org.apache.http.impl.cookie.DateParseException;
+import org.apache.http.impl.cookie.DateUtils;
/**
* Given a particular HttpRequest, flush any cache entries that this request
@@ -150,4 +154,45 @@ class CacheInvalidator {
return !(HeaderConstants.GET_METHOD.equals(method) || \
HeaderConstants.HEAD_METHOD
.equals(method));
}
+
+ /** Flushes entries that were invalidated by the given response
+ * received for the given host/request pair.
+ * @throws IOException
+ */
+ public void flushInvalidatedCacheEntries(HttpHost host,
+ HttpRequest request, HttpResponse response) throws IOException {
+ Header contentLocation = response.getFirstHeader("Content-Location");
+ if (contentLocation == null) return;
+ HttpCacheEntry entry = storage.getEntry(contentLocation.getValue());
+ if (entry == null) return;
+
+ if (!responseDateNewerThanEntryDate(response, entry)) return;
+ if (!responseAndEntryEtagsDiffer(response, entry)) return;
+
+ storage.removeEntry(contentLocation.getValue());
+ }
+
+ private boolean responseAndEntryEtagsDiffer(HttpResponse response,
+ HttpCacheEntry entry) {
+ Header entryEtag = entry.getFirstHeader("ETag");
+ Header responseEtag = response.getFirstHeader("ETag");
+ if (entryEtag == null || responseEtag == null) return false;
+ return (!entryEtag.getValue().equals(responseEtag.getValue()));
+ }
+
+ private boolean responseDateNewerThanEntryDate(HttpResponse response,
+ HttpCacheEntry entry) {
+ Header entryDateHeader = entry.getFirstHeader("Date");
+ Header responseDateHeader = response.getFirstHeader("Date");
+ if (entryDateHeader == null || responseDateHeader == null) {
+ return false;
+ }
+ try {
+ Date entryDate = DateUtils.parseDate(entryDateHeader.getValue());
+ Date responseDate = DateUtils.parseDate(responseDateHeader.getValue());
+ return responseDate.after(entryDate);
+ } catch (DateParseException e) {
+ return false;
+ }
+ }
}
Modified: httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java
URL: http://svn.apache.org/viewvc/httpcomponents/httpclient/trunk/httpclient-cache/src \
/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java?rev=1051865&r1=1051864&r2=1051865&view=diff
==============================================================================
--- httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java \
(original)
+++ httpcomponents/httpclient/trunk/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java \
Wed Dec 22 11:59:23 2010 @@ -27,17 +27,24 @@
package org.apache.http.impl.client.cache;
import java.io.IOException;
+import java.util.Date;
import java.util.HashMap;
import java.util.Map;
+
+import org.apache.http.Header;
import org.apache.http.HttpEntityEnclosingRequest;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
+import org.apache.http.HttpResponse;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheStorage;
+import static org.apache.http.impl.cookie.DateUtils.formatDate;
+
+import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.apache.http.message.BasicHttpRequest;
-import org.easymock.classextension.EasyMock;
+import static org.easymock.classextension.EasyMock.*;
import org.junit.Before;
import org.junit.Test;
@@ -48,34 +55,42 @@ public class TestCacheInvalidator {
private CacheInvalidator impl;
private HttpCacheStorage mockStorage;
private HttpHost host;
- private CacheKeyGenerator extractor;
+ private CacheKeyGenerator cacheKeyGenerator;
private HttpCacheEntry mockEntry;
+ private HttpRequest request;
+ private HttpResponse response;
+
+ private Date now;
+ private Date tenSecondsAgo;
@Before
public void setUp() {
+ now = new Date();
+ tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
+
host = new HttpHost("foo.example.com");
- mockStorage = EasyMock.createMock(HttpCacheStorage.class);
- extractor = new CacheKeyGenerator();
- mockEntry = EasyMock.createMock(HttpCacheEntry.class);
+ mockStorage = createMock(HttpCacheStorage.class);
+ cacheKeyGenerator = new CacheKeyGenerator();
+ mockEntry = createMock(HttpCacheEntry.class);
+ response = HttpTestUtils.make200Response();
- impl = new CacheInvalidator(extractor, mockStorage);
+ impl = new CacheInvalidator(cacheKeyGenerator, mockStorage);
}
private void replayMocks() {
- EasyMock.replay(mockStorage);
- EasyMock.replay(mockEntry);
+ replay(mockStorage);
+ replay(mockEntry);
}
private void verifyMocks() {
- EasyMock.verify(mockStorage);
- EasyMock.verify(mockEntry);
+ verify(mockStorage);
+ verify(mockEntry);
}
// Tests
@Test
public void testInvalidatesRequestsThatArentGETorHEAD() throws Exception {
- HttpRequest request = new BasicHttpRequest("POST","/path", HTTP_1_1);
-
+ request = new BasicHttpRequest("POST","/path", HTTP_1_1);
final String theUri = "http://foo.example.com:80/path";
Map<String,String> variantMap = new HashMap<String,String>();
cacheEntryHasVariantMap(variantMap);
@@ -126,7 +141,7 @@ public class TestCacheInvalidator {
cacheReturnsEntryForUri(theUri);
entryIsRemoved(theUri);
- entryIsRemoved(extractor.canonicalizeUri(contentLocation));
+ entryIsRemoved(cacheKeyGenerator.canonicalizeUri(contentLocation));
replayMocks();
@@ -182,54 +197,41 @@ public class TestCacheInvalidator {
@Test
public void testDoesNotInvalidateGETRequest() throws Exception {
- HttpRequest request = new BasicHttpRequest("GET","/",HTTP_1_1);
-
+ request = new BasicHttpRequest("GET","/",HTTP_1_1);
replayMocks();
-
impl.flushInvalidatedCacheEntries(host, request);
-
verifyMocks();
}
@Test
public void testDoesNotInvalidateHEADRequest() throws Exception {
- HttpRequest request = new BasicHttpRequest("HEAD","/",HTTP_1_1);
-
+ request = new BasicHttpRequest("HEAD","/",HTTP_1_1);
replayMocks();
-
impl.flushInvalidatedCacheEntries(host, request);
-
verifyMocks();
}
@Test
public void testDoesNotInvalidateRequestsWithClientCacheControlHeaders() throws \
Exception {
- HttpRequest request = new BasicHttpRequest("GET","/",HTTP_1_1);
+ request = new BasicHttpRequest("GET","/",HTTP_1_1);
request.setHeader("Cache-Control","no-cache");
-
replayMocks();
-
impl.flushInvalidatedCacheEntries(host, request);
-
verifyMocks();
}
@Test
public void testDoesNotInvalidateRequestsWithClientPragmaHeaders() throws \
Exception {
- HttpRequest request = new BasicHttpRequest("GET","/",HTTP_1_1);
+ request = new BasicHttpRequest("GET","/",HTTP_1_1);
request.setHeader("Pragma","no-cache");
-
replayMocks();
-
impl.flushInvalidatedCacheEntries(host, request);
-
verifyMocks();
}
@Test
public void testVariantURIsAreFlushedAlso() throws Exception {
- HttpRequest request = new BasicHttpRequest("POST","/",HTTP_1_1);
-
+ request = new BasicHttpRequest("POST","/",HTTP_1_1);
final String theUri = "http://foo.example.com:80/";
final String variantUri = "theVariantURI";
@@ -249,7 +251,7 @@ public class TestCacheInvalidator {
@Test(expected=IOException.class)
public void testCacheFlushException() throws Exception {
- HttpRequest request = new BasicHttpRequest("POST","/",HTTP_1_1);
+ request = new BasicHttpRequest("POST","/",HTTP_1_1);
String theURI = "http://foo.example.com:80/";
cacheReturnsExceptionForUri(theURI);
@@ -257,18 +259,182 @@ public class TestCacheInvalidator {
replayMocks();
impl.flushInvalidatedCacheEntries(host, request);
}
+
+ @Test
+ public void doesNotFlushForResponsesWithoutContentLocation()
+ throws Exception {
+ request = HttpTestUtils.makeDefaultRequest();
+ replayMocks();
+ impl.flushInvalidatedCacheEntries(host, request, response);
+ verifyMocks();
+ }
+
+ @Test
+ public void flushesEntryIfFresherAndSpecifiedByContentLocation()
+ throws Exception {
+ response.setHeader("ETag","\"new-etag\"");
+ response.setHeader("Date", formatDate(now));
+ String theURI = "http://foo.example.com:80/bar";
+ response.setHeader("Content-Location", theURI);
+
+ HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
+ new BasicHeader("Date", formatDate(tenSecondsAgo)),
+ new BasicHeader("ETag", "\"old-etag\"")
+ });
+
+ expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
+ mockStorage.removeEntry(theURI);
+
+ replayMocks();
+ impl.flushInvalidatedCacheEntries(host, request, response);
+ verifyMocks();
+ }
+
+ @Test
+ public void doesNotFlushEntrySpecifiedByContentLocationIfEtagsMatch()
+ throws Exception {
+ response.setHeader("ETag","\"same-etag\"");
+ response.setHeader("Date", formatDate(now));
+ String theURI = "http://foo.example.com:80/bar";
+ response.setHeader("Content-Location", theURI);
+
+ HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
+ new BasicHeader("Date", formatDate(tenSecondsAgo)),
+ new BasicHeader("ETag", "\"same-etag\"")
+ });
+
+ expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
+
+ replayMocks();
+ impl.flushInvalidatedCacheEntries(host, request, response);
+ verifyMocks();
+ }
+
+ @Test
+ public void doesNotFlushEntrySpecifiedByContentLocationIfNotNewer()
+ throws Exception {
+ response.setHeader("ETag","\"new-etag\"");
+ response.setHeader("Date", formatDate(now));
+ String theURI = "http://foo.example.com:80/bar";
+ response.setHeader("Content-Location", theURI);
+
+ HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
+ new BasicHeader("Date", formatDate(now)),
+ new BasicHeader("ETag", "\"old-etag\"")
+ });
+
+ expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
+
+ replayMocks();
+ impl.flushInvalidatedCacheEntries(host, request, response);
+ verifyMocks();
+ }
+
+ @Test
+ public void doesNotFlushEntryIfNotInCache()
+ throws Exception {
+ response.setHeader("ETag","\"new-etag\"");
+ response.setHeader("Date", formatDate(now));
+ String theURI = "http://foo.example.com:80/bar";
+ response.setHeader("Content-Location", theURI);
+
+ expect(mockStorage.getEntry(theURI)).andReturn(null).anyTimes();
+
+ replayMocks();
+ impl.flushInvalidatedCacheEntries(host, request, response);
+ verifyMocks();
+ }
+
+ @Test
+ public void doesNotFlushEntrySpecifiedByContentLocationIfResponseHasNoEtag()
+ throws Exception {
+ response.removeHeaders("ETag");
+ response.setHeader("Date", formatDate(now));
+ String theURI = "http://foo.example.com:80/bar";
+ response.setHeader("Content-Location", theURI);
+
+ HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
+ new BasicHeader("Date", formatDate(tenSecondsAgo)),
+ new BasicHeader("ETag", "\"old-etag\"")
+ });
+
+ expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
+
+ replayMocks();
+ impl.flushInvalidatedCacheEntries(host, request, response);
+ verifyMocks();
+ }
+
+ @Test
+ public void doesNotFlushEntrySpecifiedByContentLocationIfEntryHasNoEtag()
+ throws Exception {
+ response.setHeader("ETag", "\"some-etag\"");
+ response.setHeader("Date", formatDate(now));
+ String theURI = "http://foo.example.com:80/bar";
+ response.setHeader("Content-Location", theURI);
+
+ HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
+ new BasicHeader("Date", formatDate(tenSecondsAgo)),
+ });
+
+ expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
+
+ replayMocks();
+ impl.flushInvalidatedCacheEntries(host, request, response);
+ verifyMocks();
+ }
+
+ @Test
+ public void doesNotFlushEntrySpecifiedByContentLocationIfResponseHasNoDate()
+ throws Exception {
+ response.setHeader("ETag", "\"new-etag\"");
+ response.removeHeaders("Date");
+ String theURI = "http://foo.example.com:80/bar";
+ response.setHeader("Content-Location", theURI);
+
+ HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
+ new BasicHeader("ETag", "\"old-etag\""),
+ new BasicHeader("Date", formatDate(tenSecondsAgo)),
+ });
+
+ expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
+
+ replayMocks();
+ impl.flushInvalidatedCacheEntries(host, request, response);
+ verifyMocks();
+ }
+
+ @Test
+ public void doesNotFlushEntrySpecifiedByContentLocationIfEntryHasNoDate()
+ throws Exception {
+ response.setHeader("ETag","\"new-etag\"");
+ response.setHeader("Date", formatDate(now));
+ String theURI = "http://foo.example.com:80/bar";
+ response.setHeader("Content-Location", theURI);
+
+ HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(new Header[] {
+ new BasicHeader("ETag", "\"old-etag\"")
+ });
+
+ expect(mockStorage.getEntry(theURI)).andReturn(entry).anyTimes();
+
+ replayMocks();
+ impl.flushInvalidatedCacheEntries(host, request, response);
+ verifyMocks();
+ }
+
// Expectations
private void cacheEntryHasVariantMap(Map<String,String> variantMap) {
- org.easymock.EasyMock.expect(mockEntry.getVariantMap()).andReturn(variantMap);
+ expect(mockEntry.getVariantMap()).andReturn(variantMap);
}
private void cacheReturnsEntryForUri(String theUri) throws IOException {
- org.easymock.EasyMock.expect(mockStorage.getEntry(theUri)).andReturn(mockEntry);
+ expect(mockStorage.getEntry(theUri)).andReturn(mockEntry);
}
private void cacheReturnsExceptionForUri(String theUri) throws IOException {
- org.easymock.EasyMock.expect(mockStorage.getEntry(theUri)).andThrow(
+ expect(mockStorage.getEntry(theUri)).andThrow(
new IOException("TOTAL FAIL"));
}
[prev in list] [next in list] [prev in thread] [next in thread]
Configure |
About |
News |
Add a list |
Sponsored by KoreLogic