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 5b72c1f78..00fbf65db 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 @@ -37,7 +37,10 @@ import org.apache.http.HttpResponse; import org.apache.http.ProtocolVersion; import org.apache.http.StatusLine; import org.apache.http.annotation.Immutable; +import org.apache.http.impl.cookie.DateParseException; +import org.apache.http.impl.cookie.DateUtils; import org.apache.http.message.HeaderGroup; +import org.apache.http.protocol.HTTP; import org.apache.http.util.Args; /** @@ -60,6 +63,7 @@ public class HttpCacheEntry implements Serializable { private final HeaderGroup responseHeaders; private final Resource resource; private final Map variantMap; + private final Date date; /** * Create a new {@link HttpCacheEntry} with variants. @@ -100,6 +104,7 @@ public class HttpCacheEntry implements Serializable { this.variantMap = variantMap != null ? new HashMap(variantMap) : null; + this.date = parseDate(); } /** @@ -123,6 +128,22 @@ public class HttpCacheEntry implements Serializable { new HashMap()); } + /** + * Find the "Date" response header and parse it into a java.util.Date + * @return the Date value of the header or null if the header is not present + */ + private Date parseDate() { + final Header dateHdr = getFirstHeader(HTTP.DATE_HEADER); + if (dateHdr == null) + return null; + try { + return DateUtils.parseDate(dateHdr.getValue()); + } catch (final DateParseException dpe) { + // ignore malformed date + } + return null; + } + /** * Returns the {@link StatusLine} from the origin {@link HttpResponse}. */ @@ -192,6 +213,16 @@ public class HttpCacheEntry implements Serializable { return responseHeaders.getHeaders(name); } + /** + * Gets the Date value of the "Date" header or null if the header is missing or cannot be + * parsed. + * + * @since 4.3 + */ + public Date getDate() { + return date; + } + /** * Returns the {@link Resource} containing the origin response body. */ @@ -231,4 +262,5 @@ public class HttpCacheEntry implements Serializable { return "[request date=" + this.requestDate + "; response date=" + this.responseDate + "; statusLine=" + this.statusLine + "]"; } + } 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 4c5d8df9e..3f4ff6057 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 @@ -60,7 +60,7 @@ class CacheValidityPolicy { return maxage; } - final Date dateValue = getDateValue(entry); + final Date dateValue = entry.getDate(); if (dateValue == null) { return 0L; } @@ -97,7 +97,7 @@ class CacheValidityPolicy { public long getHeuristicFreshnessLifetimeSecs(final HttpCacheEntry entry, final float coefficient, final long defaultLifetime) { - final Date dateValue = getDateValue(entry); + final Date dateValue = entry.getDate(); final Date lastModifiedValue = getLastModifiedValue(entry); if (dateValue != null && lastModifiedValue != null) { @@ -172,17 +172,14 @@ class CacheValidityPolicy { return result; } + /** + * @deprecated (4.3) use {@link HttpCacheEntry#getDate()}. + * @param entry + * @return + */ + @Deprecated protected Date getDateValue(final HttpCacheEntry entry) { - final Header dateHdr = entry.getFirstHeader(HTTP.DATE_HEADER); - if (dateHdr == null) { - return null; - } - try { - return DateUtils.parseDate(dateHdr.getValue()); - } catch (final DateParseException dpe) { - // ignore malformed date - } - return null; + return entry.getDate(); } protected Date getLastModifiedValue(final HttpCacheEntry entry) { @@ -227,7 +224,7 @@ class CacheValidityPolicy { } protected long getApparentAgeSecs(final HttpCacheEntry entry) { - final Date dateValue = getDateValue(entry); + final Date dateValue = entry.getDate(); if (dateValue == null) { return MAX_AGE; } diff --git a/httpclient-cache/src/test/java/org/apache/http/client/cache/TestHttpCacheEntry.java b/httpclient-cache/src/test/java/org/apache/http/client/cache/TestHttpCacheEntry.java index 6f3833a71..66b326896 100644 --- a/httpclient-cache/src/test/java/org/apache/http/client/cache/TestHttpCacheEntry.java +++ b/httpclient-cache/src/test/java/org/apache/http/client/cache/TestHttpCacheEntry.java @@ -30,6 +30,7 @@ import static org.easymock.classextension.EasyMock.createNiceMock; import static org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; +import static org.junit.Assert.assertNull; import static org.junit.Assert.assertSame; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; @@ -304,4 +305,34 @@ public class TestHttpCacheEntry { assertNotNull(entry.toString()); assertFalse("".equals(entry.toString())); } + + @Test + public void testMissingDateHeaderIsIgnored() { + final Header[] headers = new Header[] {}; + entry = new HttpCacheEntry(new Date(), new Date(), statusLine, + headers, mockResource); + assertNull(entry.getDate()); + } + + @Test + public void testMalformedDateHeaderIsIgnored() { + final Header[] headers = new Header[] { new BasicHeader("Date", "asdf") }; + entry = new HttpCacheEntry(new Date(), new Date(), statusLine, + headers, mockResource); + assertNull(entry.getDate()); + } + + @Test + public void testValidDateHeaderIsParsed() { + final long now = System.currentTimeMillis(); + // round down to nearest second to make comparison easier + final Date date = new Date(now - (now % 1000L)); + final Header[] headers = new Header[] { new BasicHeader("Date", DateUtils.formatDate(date)) }; + entry = new HttpCacheEntry(new Date(), new Date(), statusLine, + headers, mockResource); + final Date dateHeaderValue = entry.getDate(); + assertNotNull(dateHeaderValue); + assertEquals(date.getTime(), dateHeaderValue.getTime()); + } + } diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheValidityPolicy.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheValidityPolicy.java index 6235bf3c9..8e1a8c62a 100644 --- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheValidityPolicy.java +++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheValidityPolicy.java @@ -355,13 +355,6 @@ public class TestCacheValidityPolicy { assertFalse(impl.contentLengthHeaderMatchesActualLength(entry)); } - @Test - public void testMalformedDateHeaderIsIgnored() { - final Header[] headers = new Header[] { new BasicHeader("Date", "asdf") }; - final HttpCacheEntry entry = HttpTestUtils.makeCacheEntry(headers); - assertNull(impl.getDateValue(entry)); - } - @Test public void testMalformedContentLengthReturnsNegativeOne() { final Header[] headers = new Header[] { new BasicHeader("Content-Length", "asdf") };