HTTPCLIENT-1213: Avoid parsing HttpCacheEntry date attribute multiple times.

Contributed by Sam Perman <sam at permans.com>

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@1463551 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2013-04-02 14:05:12 +00:00
parent 2f310c3744
commit 0bbbd742b8
4 changed files with 73 additions and 20 deletions

View File

@ -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<String,String> 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<String,String>(variantMap)
: null;
this.date = parseDate();
}
/**
@ -123,6 +128,22 @@ public class HttpCacheEntry implements Serializable {
new HashMap<String,String>());
}
/**
* 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 + "]";
}
}

View File

@ -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;
}

View File

@ -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());
}
}

View File

@ -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") };