diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHeaderGroup.java b/httpclient-cache/src/main/java/org/apache/http/client/cache/CachedHeaderGroup.java
similarity index 96%
rename from httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHeaderGroup.java
rename to httpclient-cache/src/main/java/org/apache/http/client/cache/CachedHeaderGroup.java
index 062995e45..8140ca6fa 100644
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHeaderGroup.java
+++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/CachedHeaderGroup.java
@@ -24,7 +24,7 @@
* .
*
*/
-package org.apache.http.impl.client.cache;
+package org.apache.http.client.cache;
import java.io.Serializable;
@@ -35,5 +35,5 @@ import org.apache.http.message.HeaderGroup;
class CachedHeaderGroup extends HeaderGroup implements Serializable {
private static final long serialVersionUID = -4572663568087431896L;
-
+
}
diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeaderConstants.java b/httpclient-cache/src/main/java/org/apache/http/client/cache/HeaderConstants.java
similarity index 97%
rename from httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeaderConstants.java
rename to httpclient-cache/src/main/java/org/apache/http/client/cache/HeaderConstants.java
index 6fee69843..b49362878 100644
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/HeaderConstants.java
+++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/HeaderConstants.java
@@ -24,7 +24,7 @@
* .
*
*/
-package org.apache.http.impl.client.cache;
+package org.apache.http.client.cache;
import org.apache.http.annotation.Immutable;
@@ -32,7 +32,7 @@ import org.apache.http.annotation.Immutable;
* @since 4.1
*/
@Immutable
-class HeaderConstants {
+public class HeaderConstants {
public static final String GET_METHOD = "GET";
public static final String HEAD_METHOD = "HEAD";
diff --git a/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCache.java b/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCache.java
index 5ec55a841..3d595ac7f 100644
--- a/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCache.java
+++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCache.java
@@ -29,15 +29,15 @@ package org.apache.http.client.cache;
/**
* @since 4.1
*/
-public interface HttpCache {
+public interface HttpCache {
- void putEntry(K key, E entry) throws HttpCacheOperationException;
+ void putEntry(String key, HttpCacheEntry entry) throws HttpCacheOperationException;
- E getEntry(K key) throws HttpCacheOperationException;
+ HttpCacheEntry getEntry(String key) throws HttpCacheOperationException;
- void removeEntry(K key) throws HttpCacheOperationException;
+ void removeEntry(String key) throws HttpCacheOperationException;
void updateEntry(
- K key, HttpCacheUpdateCallback callback) throws HttpCacheOperationException;
+ String key, HttpCacheUpdateCallback callback) throws HttpCacheOperationException;
}
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
new file mode 100644
index 000000000..f43bf2b9a
--- /dev/null
+++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheEntry.java
@@ -0,0 +1,218 @@
+/*
+ * ====================================================================
+ * 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;
+
+import java.io.IOException;
+import java.io.ObjectInputStream;
+import java.io.ObjectOutputStream;
+import java.io.Serializable;
+import java.util.Collections;
+import java.util.Date;
+import java.util.HashSet;
+import java.util.Set;
+
+import org.apache.http.Header;
+import org.apache.http.HttpEntity;
+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.message.BasicHeader;
+
+/**
+ * Structure used to store an {@link HttpResponse} in a cache
+ *
+ * @since 4.1
+ */
+@Immutable
+public class HttpCacheEntry implements Serializable {
+
+ private static final long serialVersionUID = -6300496422359477413L;
+
+ private final Date requestDate;
+ private final Date responseDate;
+ private final StatusLine statusLine;
+ private final CachedHeaderGroup responseHeaders;
+ private final HttpEntity body;
+ private final Set variantURIs;
+
+ /**
+ * Create a new {@link HttpCacheEntry}
+ *
+ * @param requestDate
+ * Date/time when the request was made (Used for age
+ * calculations)
+ * @param responseDate
+ * Date/time that the response came back (Used for age
+ * calculations)
+ * @param version
+ * HTTP Response Version
+ * @param responseHeaders
+ * Header[] from original HTTP Response
+ * @param body
+ * HttpEntity representing the body of the response
+ * @param status
+ * Numeric HTTP Status Code
+ * @param reason
+ * String message from HTTP Status Line
+ */
+ public HttpCacheEntry(
+ final Date requestDate,
+ final Date responseDate,
+ final StatusLine statusLine,
+ final Header[] responseHeaders,
+ final HttpEntity body,
+ final Set variants) {
+ super();
+ if (requestDate == null) {
+ throw new IllegalArgumentException("Request date may not be null");
+ }
+ if (responseDate == null) {
+ throw new IllegalArgumentException("Response date may not be null");
+ }
+ if (statusLine == null) {
+ throw new IllegalArgumentException("Status line may not be null");
+ }
+ if (responseHeaders == null) {
+ throw new IllegalArgumentException("Response headers may not be null");
+ }
+ if (body == null) {
+ throw new IllegalArgumentException("Response body may not be null");
+ }
+ this.requestDate = requestDate;
+ this.responseDate = responseDate;
+ this.statusLine = statusLine;
+ this.responseHeaders = new CachedHeaderGroup();
+ this.responseHeaders.setHeaders(responseHeaders);
+ this.body = body;
+ this.variantURIs = variants != null ? new HashSet(variants) : new HashSet();
+
+ }
+
+ public StatusLine getStatusLine() {
+ return this.statusLine;
+ }
+
+ public ProtocolVersion getProtocolVersion() {
+ return this.statusLine.getProtocolVersion();
+ }
+
+ public String getReasonPhrase() {
+ return this.statusLine.getReasonPhrase();
+ }
+
+ public int getStatusCode() {
+ return this.statusLine.getStatusCode();
+ }
+
+ public Date getRequestDate() {
+ return requestDate;
+ }
+
+ public Date getResponseDate() {
+ return responseDate;
+ }
+
+ public HttpEntity getBody() {
+ return body;
+ }
+
+ public Header[] getAllHeaders() {
+ return responseHeaders.getAllHeaders();
+ }
+
+ public Header getFirstHeader(String name) {
+ return responseHeaders.getFirstHeader(name);
+ }
+
+ public Header[] getHeaders(String name) {
+ return responseHeaders.getHeaders(name);
+ }
+
+ public boolean hasVariants() {
+ return getFirstHeader(HeaderConstants.VARY) != null;
+ }
+
+ public Set getVariantURIs() {
+ return Collections.unmodifiableSet(this.variantURIs);
+ }
+
+ private void writeObject(ObjectOutputStream out) throws IOException {
+
+ // write CacheEntry
+ out.defaultWriteObject();
+
+ // write (non-serializable) responseHeaders
+ if (null == responseHeaders || responseHeaders.getAllHeaders().length < 1)
+ return;
+ int headerCount = responseHeaders.getAllHeaders().length;
+ Header[] headers = responseHeaders.getAllHeaders();
+ String[][] sheaders = new String[headerCount][2];
+ for (int i = 0; i < headerCount; i++) {
+ sheaders[i][0] = headers[i].getName();
+ sheaders[i][1] = headers[i].getValue();
+ }
+ out.writeObject(sheaders);
+
+ }
+
+ private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
+
+ // read CacheEntry
+ in.defaultReadObject();
+
+ // read (non-serializable) responseHeaders
+ String[][] sheaders = (String[][]) in.readObject();
+ if (null == sheaders || sheaders.length < 1)
+ return;
+ BasicHeader[] headers = new BasicHeader[sheaders.length];
+ for (int i = 0; i < sheaders.length; i++) {
+ String[] sheader = sheaders[i];
+ headers[i] = new BasicHeader(sheader[0], sheader[1]);
+ }
+
+ this.responseHeaders.setHeaders(headers);
+ }
+
+ @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/HttpCacheUpdateCallback.java b/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheUpdateCallback.java
index 36a1de226..b09b64d3e 100644
--- a/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheUpdateCallback.java
+++ b/httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheUpdateCallback.java
@@ -26,7 +26,7 @@
*/
package org.apache.http.client.cache;
-public interface HttpCacheUpdateCallback {
+public interface HttpCacheUpdateCallback {
/**
* Returns the new cache entry that should replace an existing one.
@@ -41,6 +41,6 @@ public interface HttpCacheUpdateCallback {
*
* @since 4.1
*/
- E update(E existing) throws HttpCacheOperationException;
+ HttpCacheEntry update(HttpCacheEntry existing) throws HttpCacheOperationException;
}
\ No newline at end of file
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 8efac0cb5..013305dc5 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
@@ -31,6 +31,7 @@ import java.util.Map;
import org.apache.http.annotation.ThreadSafe;
import org.apache.http.client.cache.HttpCache;
+import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheOperationException;
import org.apache.http.client.cache.HttpCacheUpdateCallback;
@@ -40,15 +41,15 @@ import org.apache.http.client.cache.HttpCacheUpdateCallback;
* @since 4.1
*/
@ThreadSafe
-public class BasicHttpCache implements HttpCache {
+public class BasicHttpCache implements HttpCache {
- private final LinkedHashMap baseMap = new LinkedHashMap(
+ private final LinkedHashMap baseMap = new LinkedHashMap(
20, 0.75f, true) {
private static final long serialVersionUID = -7750025207539768511L;
@Override
- protected boolean removeEldestEntry(Map.Entry eldest) {
+ protected boolean removeEldestEntry(Map.Entry eldest) {
return size() > maxEntries;
}
@@ -61,14 +62,14 @@ public class BasicHttpCache implements HttpCache {
}
/**
- * Places a CacheEntry in the cache
+ * Places a HttpCacheEntry in the cache
*
* @param url
* Url to use as the cache key
* @param entry
- * CacheEntry to place in the cache
+ * HttpCacheEntry to place in the cache
*/
- public synchronized void putEntry(String url, CacheEntry entry) {
+ public synchronized void putEntry(String url, HttpCacheEntry entry) {
baseMap.put(url, entry);
}
@@ -77,14 +78,14 @@ public class BasicHttpCache implements HttpCache {
*
* @param url
* Url that is the cache key
- * @return CacheEntry if one exists, or null for cache miss
+ * @return HttpCacheEntry if one exists, or null for cache miss
*/
- public synchronized CacheEntry getEntry(String url) {
+ public synchronized HttpCacheEntry getEntry(String url) {
return baseMap.get(url);
}
/**
- * Removes a CacheEntry from the cache
+ * Removes a HttpCacheEntry from the cache
*
* @param url
* Url that is the cache key
@@ -95,8 +96,8 @@ public class BasicHttpCache implements HttpCache {
public synchronized void updateEntry(
String url,
- HttpCacheUpdateCallback callback) throws HttpCacheOperationException {
- CacheEntry existingEntry = baseMap.get(url);
+ HttpCacheUpdateCallback callback) throws HttpCacheOperationException {
+ HttpCacheEntry existingEntry = baseMap.get(url);
baseMap.put(url, callback.update(existingEntry));
}
diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntry.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntry.java
deleted file mode 100644
index c9cc6fa96..000000000
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheEntry.java
+++ /dev/null
@@ -1,412 +0,0 @@
-/*
- * ====================================================================
- * 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.io.IOException;
-import java.io.ObjectInputStream;
-import java.io.ObjectOutputStream;
-import java.io.Serializable;
-import java.util.Collections;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.Set;
-
-import org.apache.http.Header;
-import org.apache.http.HeaderElement;
-import org.apache.http.HttpEntity;
-import org.apache.http.HttpRequest;
-import org.apache.http.HttpResponse;
-import org.apache.http.ProtocolVersion;
-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.BasicHeader;
-import org.apache.http.protocol.HTTP;
-
-/**
- * Structure used to store an {@link HttpResponse} in a cache
- *
- * @since 4.1
- */
-@Immutable
-public class CacheEntry implements Serializable {
-
- private static final long serialVersionUID = -6300496422359477413L;
-
- public static final long MAX_AGE = 2147483648L;
-
- private final Date requestDate;
- private final Date responseDate;
- private final ProtocolVersion version;
- private final int status;
- private final String reason;
- private final CachedHeaderGroup responseHeaders;
- private final HttpEntity body;
- private final Set variantURIs;
-
- /**
- * Create a new {@link CacheEntry}
- *
- * @param requestDate
- * Date/time when the request was made (Used for age
- * calculations)
- * @param responseDate
- * Date/time that the response came back (Used for age
- * calculations)
- * @param version
- * HTTP Response Version
- * @param responseHeaders
- * Header[] from original HTTP Response
- * @param body
- * HttpEntity representing the body of the response
- * @param status
- * Numeric HTTP Status Code
- * @param reason
- * String message from HTTP Status Line
- */
- public CacheEntry(Date requestDate, Date responseDate, ProtocolVersion version,
- Header[] responseHeaders, HttpEntity body, int status, String reason) {
- super();
- this.requestDate = requestDate;
- this.responseDate = responseDate;
- this.version = version;
- this.responseHeaders = new CachedHeaderGroup();
- this.responseHeaders.setHeaders(responseHeaders);
- this.status = status;
- this.reason = reason;
- this.body = body;
- this.variantURIs = new HashSet();
-
- }
-
- /**
- * Constructor used to create a copy of an existing entry, while adding another variant URI to it.
- *
- * @param entry CacheEntry to be duplicated
- * @param variantURI URI to add
- */
- private CacheEntry(CacheEntry entry, String variantURI){
- this(entry.getRequestDate(),
- entry.getResponseDate(),
- entry.getProtocolVersion(),
- entry.getAllHeaders(),
- entry.body,
- entry.getStatusCode(),
- entry.getReasonPhrase());
- this.variantURIs.addAll(entry.getVariantURIs());
- this.variantURIs.add(variantURI);
- }
-
- public CacheEntry copyWithVariant(String variantURI){
- return new CacheEntry(this,variantURI);
- }
-
- public ProtocolVersion getProtocolVersion() {
- return version;
- }
-
- public String getReasonPhrase() {
- return reason;
- }
-
- public int getStatusCode() {
- return status;
- }
-
- public Date getRequestDate() {
- return requestDate;
- }
-
- public Date getResponseDate() {
- return responseDate;
- }
-
- public HttpEntity getBody() {
- return body;
- }
-
- public Header[] getAllHeaders() {
- return responseHeaders.getAllHeaders();
- }
-
- public Header getFirstHeader(String name) {
- return responseHeaders.getFirstHeader(name);
- }
-
- public Header[] getHeaders(String name) {
- return responseHeaders.getHeaders(name);
- }
-
- public long getCurrentAgeSecs() {
- return getCorrectedInitialAgeSecs() + getResidentTimeSecs();
- }
-
- public long getFreshnessLifetimeSecs() {
- long maxage = getMaxAge();
- if (maxage > -1)
- return maxage;
-
- Date dateValue = getDateValue();
- if (dateValue == null)
- return 0L;
-
- Date expiry = getExpirationDate();
- if (expiry == null)
- return 0;
- long diff = expiry.getTime() - dateValue.getTime();
- return (diff / 1000);
- }
-
- public boolean isResponseFresh() {
- return (getCurrentAgeSecs() < getFreshnessLifetimeSecs());
- }
-
- /**
- *
- * @return boolean indicating whether ETag or Last-Modified responseHeaders
- * are present
- */
- public boolean isRevalidatable() {
- return getFirstHeader(HeaderConstants.ETAG) != null
- || getFirstHeader(HeaderConstants.LAST_MODIFIED) != null;
-
- }
-
- public boolean modifiedSince(HttpRequest request) {
- Header unmodHeader = request.getFirstHeader(HeaderConstants.IF_UNMODIFIED_SINCE);
-
- if (unmodHeader == null) {
- return false;
- }
-
- try {
- Date unmodifiedSinceDate = DateUtils.parseDate(unmodHeader.getValue());
- Date lastModifiedDate = DateUtils.parseDate(getFirstHeader(
- HeaderConstants.LAST_MODIFIED).getValue());
-
- if (unmodifiedSinceDate.before(lastModifiedDate)) {
- return true;
- }
- } catch (DateParseException e) {
- return false;
- }
-
- return false;
- }
-
- /**
- *
- * @return boolean indicating whether any Vary responseHeaders are present
- */
- public boolean hasVariants() {
- return (getFirstHeader(HeaderConstants.VARY) != null);
- }
-
- public Set getVariantURIs() {
- return Collections.unmodifiableSet(this.variantURIs);
- }
-
- public boolean mustRevalidate() {
- return hasCacheControlDirective("must-revalidate");
- }
- public boolean proxyRevalidate() {
- return hasCacheControlDirective("proxy-revalidate");
- }
-
- Date getDateValue() {
- Header dateHdr = getFirstHeader(HTTP.DATE_HEADER);
- if (dateHdr == null)
- return null;
- try {
- return DateUtils.parseDate(dateHdr.getValue());
- } catch (DateParseException dpe) {
- // ignore malformed date
- }
- return null;
- }
-
- long getContentLengthValue() {
- Header cl = getFirstHeader(HTTP.CONTENT_LEN);
- if (cl == null)
- return -1;
-
- try {
- return Long.parseLong(cl.getValue());
- } catch (NumberFormatException ex) {
- return -1;
- }
- }
-
- /**
- * This matters for deciding whether the cache entry is valid to serve as a
- * response. If these values do not match, we might have a partial response
- *
- * @return boolean indicating whether actual length matches Content-Length
- */
- boolean contentLengthHeaderMatchesActualLength() {
- return getContentLengthValue() == body.getContentLength();
- }
-
- long getApparentAgeSecs() {
- Date dateValue = getDateValue();
- if (dateValue == null)
- return MAX_AGE;
- long diff = responseDate.getTime() - dateValue.getTime();
- if (diff < 0L)
- return 0;
- return (diff / 1000);
- }
-
- long getAgeValue() {
- long ageValue = 0;
- for (Header hdr : getHeaders(HeaderConstants.AGE)) {
- long hdrAge;
- try {
- hdrAge = Long.parseLong(hdr.getValue());
- if (hdrAge < 0) {
- hdrAge = MAX_AGE;
- }
- } catch (NumberFormatException nfe) {
- hdrAge = MAX_AGE;
- }
- ageValue = (hdrAge > ageValue) ? hdrAge : ageValue;
- }
- return ageValue;
- }
-
- long getCorrectedReceivedAgeSecs() {
- long apparentAge = getApparentAgeSecs();
- long ageValue = getAgeValue();
- return (apparentAge > ageValue) ? apparentAge : ageValue;
- }
-
- long getResponseDelaySecs() {
- long diff = responseDate.getTime() - requestDate.getTime();
- return (diff / 1000L);
- }
-
- long getCorrectedInitialAgeSecs() {
- return getCorrectedReceivedAgeSecs() + getResponseDelaySecs();
- }
-
- Date getCurrentDate() {
- return new Date();
- }
-
- long getResidentTimeSecs() {
- long diff = getCurrentDate().getTime() - responseDate.getTime();
- return (diff / 1000L);
- }
-
- long getMaxAge() {
- long maxage = -1;
- for (Header hdr : getHeaders(HeaderConstants.CACHE_CONTROL)) {
- for (HeaderElement elt : hdr.getElements()) {
- if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())
- || "s-maxage".equals(elt.getName())) {
- try {
- long currMaxAge = Long.parseLong(elt.getValue());
- if (maxage == -1 || currMaxAge < maxage) {
- maxage = currMaxAge;
- }
- } catch (NumberFormatException nfe) {
- // be conservative if can't parse
- maxage = 0;
- }
- }
- }
- }
- return maxage;
- }
-
- Date getExpirationDate() {
- Header expiresHeader = getFirstHeader(HeaderConstants.EXPIRES);
- if (expiresHeader == null)
- return null;
- try {
- return DateUtils.parseDate(expiresHeader.getValue());
- } catch (DateParseException dpe) {
- // malformed expires header
- }
- return null;
- }
-
- boolean hasCacheControlDirective(String directive) {
- for(Header h : responseHeaders.getHeaders("Cache-Control")) {
- for(HeaderElement elt : h.getElements()) {
- if (directive.equalsIgnoreCase(elt.getName())) {
- return true;
- }
- }
- }
- return false;
- }
-
- private void writeObject(ObjectOutputStream out) throws IOException {
-
- // write CacheEntry
- out.defaultWriteObject();
-
- // write (non-serializable) responseHeaders
- if (null == responseHeaders || responseHeaders.getAllHeaders().length < 1)
- return;
- int headerCount = responseHeaders.getAllHeaders().length;
- Header[] headers = responseHeaders.getAllHeaders();
- String[][] sheaders = new String[headerCount][2];
- for (int i = 0; i < headerCount; i++) {
- sheaders[i][0] = headers[i].getName();
- sheaders[i][1] = headers[i].getValue();
- }
- out.writeObject(sheaders);
-
- }
-
- private void readObject(ObjectInputStream in) throws IOException, ClassNotFoundException {
-
- // read CacheEntry
- in.defaultReadObject();
-
- // read (non-serializable) responseHeaders
- String[][] sheaders = (String[][]) in.readObject();
- if (null == sheaders || sheaders.length < 1)
- return;
- BasicHeader[] headers = new BasicHeader[sheaders.length];
- for (int i = 0; i < sheaders.length; i++) {
- String[] sheader = sheaders[i];
- headers[i] = new BasicHeader(sheader[0], sheader[1]);
- }
-
- this.responseHeaders.setHeaders(headers);
- }
-
- @Override
- public String toString() {
- return "[request date=" + requestDate + "; response date=" + responseDate
- + "; status=" + status + "]";
- }
-
-}
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 ae58e51fb..3718f0b75 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
@@ -30,6 +30,7 @@ import java.util.Date;
import org.apache.http.HttpResponse;
import org.apache.http.annotation.Immutable;
+import org.apache.http.client.cache.HttpCacheEntry;
/**
* Generates a {@link CacheEntry} from a {@link HttpResponse}
@@ -39,18 +40,18 @@ import org.apache.http.annotation.Immutable;
@Immutable
class CacheEntryGenerator {
- public CacheEntry generateEntry(
- Date requestDate,
- Date responseDate,
+ public HttpCacheEntry generateEntry(
+ Date requestDate,
+ Date responseDate,
HttpResponse response,
byte[] body) {
CacheEntity entity = new CacheEntity(body, response);
- return new CacheEntry(requestDate,
+ return new HttpCacheEntry(requestDate,
responseDate,
- response.getProtocolVersion(),
+ response.getStatusLine(),
response.getAllHeaders(),
entity,
- response.getStatusLine().getStatusCode(),
- response.getStatusLine().getReasonPhrase());
+ null);
}
+
}
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 a987721a7..a4e316c6b 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
@@ -36,12 +36,14 @@ import java.util.ListIterator;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.annotation.Immutable;
+import org.apache.http.client.cache.HeaderConstants;
+import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.impl.cookie.DateParseException;
import org.apache.http.impl.cookie.DateUtils;
import org.apache.http.protocol.HTTP;
/**
- * Update a {@link CacheEntry} with new or updated information based on the latest
+ * Update a {@link HttpCacheEntry} with new or updated information based on the latest
* 200 or 304 status responses from the Server. Use the {@link HttpResponse} to perform
* the update.
*
@@ -57,27 +59,25 @@ class CacheEntryUpdater {
* @param requestDate When the request was performed
* @param responseDate When the response was gotten
* @param response The HttpResponse from the backend server call
- * @return CacheEntry an updated version of the cache entry
+ * @return HttpCacheEntry an updated version of the cache entry
* @throws java.io.IOException if something bad happens while trying to read the body from the original entry
*/
- public CacheEntry updateCacheEntry(
- CacheEntry entry,
+ public HttpCacheEntry updateCacheEntry(
+ HttpCacheEntry entry,
Date requestDate,
Date responseDate,
HttpResponse response) throws IOException {
Header[] mergedHeaders = mergeHeaders(entry, response);
- CacheEntry updated = new CacheEntry(requestDate, responseDate,
- entry.getProtocolVersion(),
+ HttpCacheEntry updated = new HttpCacheEntry(requestDate, responseDate,
+ entry.getStatusLine(),
mergedHeaders,
entry.getBody(),
- entry.getStatusCode(),
- entry.getReasonPhrase());
-
+ null);
return updated;
}
- protected Header[] mergeHeaders(CacheEntry entry, HttpResponse response) {
+ protected Header[] mergeHeaders(HttpCacheEntry entry, HttpResponse response) {
List cacheEntryHeaderList = new ArrayList(Arrays.asList(entry
.getAllHeaders()));
@@ -112,7 +112,7 @@ class CacheEntryUpdater {
}
}
- private void removeCacheEntry1xxWarnings(List cacheEntryHeaderList, CacheEntry entry) {
+ private void removeCacheEntry1xxWarnings(List cacheEntryHeaderList, HttpCacheEntry entry) {
ListIterator cacheEntryHeaderListIter = cacheEntryHeaderList.listIterator();
while (cacheEntryHeaderListIter.hasNext()) {
@@ -128,7 +128,7 @@ class CacheEntryUpdater {
}
}
- private boolean entryDateHeaderNewerThenResponse(CacheEntry entry, HttpResponse response) {
+ private boolean entryDateHeaderNewerThenResponse(HttpCacheEntry entry, HttpResponse response) {
try {
Date entryDate = DateUtils.parseDate(entry.getFirstHeader(HTTP.DATE_HEADER)
.getValue());
@@ -145,7 +145,7 @@ class CacheEntryUpdater {
return true;
}
- private boolean entryAndResponseHaveDateHeader(CacheEntry entry, HttpResponse response) {
+ private boolean entryAndResponseHaveDateHeader(HttpCacheEntry entry, HttpResponse response) {
if (entry.getFirstHeader(HTTP.DATE_HEADER) != null
&& response.getFirstHeader(HTTP.DATE_HEADER) != null) {
return true;
diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java
index fb748c48c..d1cd64c8f 100644
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java
+++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheInvalidator.java
@@ -36,7 +36,9 @@ import org.apache.http.HeaderElement;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.annotation.ThreadSafe;
+import org.apache.http.client.cache.HeaderConstants;
import org.apache.http.client.cache.HttpCache;
+import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheOperationException;
/**
@@ -48,7 +50,7 @@ import org.apache.http.client.cache.HttpCacheOperationException;
@ThreadSafe // so long as the cache implementation is thread-safe
class CacheInvalidator {
- private final HttpCache cache;
+ private final HttpCache cache;
private final URIExtractor uriExtractor;
private final Log log = LogFactory.getLog(getClass());
@@ -60,7 +62,9 @@ class CacheInvalidator {
* @param uriExtractor Provides identifiers for the keys to store cache entries
* @param cache the cache to store items away in
*/
- public CacheInvalidator(URIExtractor uriExtractor, HttpCache cache) {
+ public CacheInvalidator(
+ final URIExtractor uriExtractor,
+ final HttpCache cache) {
this.uriExtractor = uriExtractor;
this.cache = cache;
}
@@ -79,7 +83,7 @@ class CacheInvalidator {
try {
String theUri = uriExtractor.getURI(host, req);
- CacheEntry parent = cache.getEntry(theUri);
+ HttpCacheEntry parent = cache.getEntry(theUri);
log.debug("parent entry: " + parent);
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
new file mode 100644
index 000000000..51be10c29
--- /dev/null
+++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheValidityPolicy.java
@@ -0,0 +1,241 @@
+/*
+ * ====================================================================
+ * 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 org.apache.http.Header;
+import org.apache.http.HeaderElement;
+import org.apache.http.HttpRequest;
+import org.apache.http.annotation.Immutable;
+import org.apache.http.client.cache.HeaderConstants;
+import org.apache.http.client.cache.HttpCacheEntry;
+import org.apache.http.impl.cookie.DateParseException;
+import org.apache.http.impl.cookie.DateUtils;
+import org.apache.http.protocol.HTTP;
+
+/**
+ * @since 4.1
+ */
+@Immutable
+class CacheValidityPolicy {
+
+ public static final long MAX_AGE = 2147483648L;
+
+ CacheValidityPolicy() {
+ super();
+ }
+
+ public long getCurrentAgeSecs(final HttpCacheEntry entry) {
+ return getCorrectedInitialAgeSecs(entry) + getResidentTimeSecs(entry);
+ }
+
+ public long getFreshnessLifetimeSecs(final HttpCacheEntry entry) {
+ long maxage = getMaxAge(entry);
+ if (maxage > -1)
+ return maxage;
+
+ Date dateValue = getDateValue(entry);
+ if (dateValue == null)
+ return 0L;
+
+ Date expiry = getExpirationDate(entry);
+ if (expiry == null)
+ return 0;
+ long diff = expiry.getTime() - dateValue.getTime();
+ return (diff / 1000);
+ }
+
+ public boolean isResponseFresh(final HttpCacheEntry entry) {
+ return (getCurrentAgeSecs(entry) < getFreshnessLifetimeSecs(entry));
+ }
+
+ public boolean isRevalidatable(final HttpCacheEntry entry) {
+ return entry.getFirstHeader(HeaderConstants.ETAG) != null
+ || entry.getFirstHeader(HeaderConstants.LAST_MODIFIED) != null;
+ }
+
+ public boolean modifiedSince(final HttpCacheEntry entry, final HttpRequest request) {
+ Header unmodHeader = request.getFirstHeader(HeaderConstants.IF_UNMODIFIED_SINCE);
+
+ if (unmodHeader == null) {
+ return false;
+ }
+
+ try {
+ Date unmodifiedSinceDate = DateUtils.parseDate(unmodHeader.getValue());
+ Date lastModifiedDate = DateUtils.parseDate(entry.getFirstHeader(
+ HeaderConstants.LAST_MODIFIED).getValue());
+
+ if (unmodifiedSinceDate.before(lastModifiedDate)) {
+ return true;
+ }
+ } catch (DateParseException e) {
+ return false;
+ }
+
+ return false;
+ }
+
+ public boolean mustRevalidate(final HttpCacheEntry entry) {
+ return hasCacheControlDirective(entry, "must-revalidate");
+ }
+
+ public boolean proxyRevalidate(final HttpCacheEntry entry) {
+ return hasCacheControlDirective(entry, "proxy-revalidate");
+ }
+
+ protected Date getDateValue(final HttpCacheEntry entry) {
+ Header dateHdr = entry.getFirstHeader(HTTP.DATE_HEADER);
+ if (dateHdr == null)
+ return null;
+ try {
+ return DateUtils.parseDate(dateHdr.getValue());
+ } catch (DateParseException dpe) {
+ // ignore malformed date
+ }
+ return null;
+ }
+
+ protected long getContentLengthValue(final HttpCacheEntry entry) {
+ Header cl = entry.getFirstHeader(HTTP.CONTENT_LEN);
+ if (cl == null)
+ return -1;
+
+ try {
+ return Long.parseLong(cl.getValue());
+ } catch (NumberFormatException ex) {
+ return -1;
+ }
+ }
+
+ /**
+ * This matters for deciding whether the cache entry is valid to serve as a
+ * response. If these values do not match, we might have a partial response
+ *
+ * @return boolean indicating whether actual length matches Content-Length
+ */
+ protected boolean contentLengthHeaderMatchesActualLength(final HttpCacheEntry entry) {
+ return getContentLengthValue(entry) == entry.getBody().getContentLength();
+ }
+
+ protected long getApparentAgeSecs(final HttpCacheEntry entry) {
+ Date dateValue = getDateValue(entry);
+ if (dateValue == null)
+ return MAX_AGE;
+ long diff = entry.getResponseDate().getTime() - dateValue.getTime();
+ if (diff < 0L)
+ return 0;
+ return (diff / 1000);
+ }
+
+ protected long getAgeValue(final HttpCacheEntry entry) {
+ long ageValue = 0;
+ for (Header hdr : entry.getHeaders(HeaderConstants.AGE)) {
+ long hdrAge;
+ try {
+ hdrAge = Long.parseLong(hdr.getValue());
+ if (hdrAge < 0) {
+ hdrAge = MAX_AGE;
+ }
+ } catch (NumberFormatException nfe) {
+ hdrAge = MAX_AGE;
+ }
+ ageValue = (hdrAge > ageValue) ? hdrAge : ageValue;
+ }
+ return ageValue;
+ }
+
+ protected long getCorrectedReceivedAgeSecs(final HttpCacheEntry entry) {
+ long apparentAge = getApparentAgeSecs(entry);
+ long ageValue = getAgeValue(entry);
+ return (apparentAge > ageValue) ? apparentAge : ageValue;
+ }
+
+ protected long getResponseDelaySecs(final HttpCacheEntry entry) {
+ long diff = entry.getResponseDate().getTime() - entry.getRequestDate().getTime();
+ return (diff / 1000L);
+ }
+
+ protected long getCorrectedInitialAgeSecs(final HttpCacheEntry entry) {
+ return getCorrectedReceivedAgeSecs(entry) + getResponseDelaySecs(entry);
+ }
+
+ protected Date getCurrentDate() {
+ return new Date();
+ }
+
+ protected long getResidentTimeSecs(final HttpCacheEntry entry) {
+ long diff = getCurrentDate().getTime() - entry.getResponseDate().getTime();
+ return (diff / 1000L);
+ }
+
+ protected long getMaxAge(final HttpCacheEntry entry) {
+ long maxage = -1;
+ for (Header hdr : entry.getHeaders(HeaderConstants.CACHE_CONTROL)) {
+ for (HeaderElement elt : hdr.getElements()) {
+ if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())
+ || "s-maxage".equals(elt.getName())) {
+ try {
+ long currMaxAge = Long.parseLong(elt.getValue());
+ if (maxage == -1 || currMaxAge < maxage) {
+ maxage = currMaxAge;
+ }
+ } catch (NumberFormatException nfe) {
+ // be conservative if can't parse
+ maxage = 0;
+ }
+ }
+ }
+ }
+ return maxage;
+ }
+
+ protected Date getExpirationDate(final HttpCacheEntry entry) {
+ Header expiresHeader = entry.getFirstHeader(HeaderConstants.EXPIRES);
+ if (expiresHeader == null)
+ return null;
+ try {
+ return DateUtils.parseDate(expiresHeader.getValue());
+ } catch (DateParseException dpe) {
+ // malformed expires header
+ }
+ return null;
+ }
+
+ protected boolean hasCacheControlDirective(final HttpCacheEntry entry, final String directive) {
+ for (Header h : entry.getHeaders("Cache-Control")) {
+ for(HeaderElement elt : h.getElements()) {
+ if (directive.equalsIgnoreCase(elt.getName())) {
+ return true;
+ }
+ }
+ }
+ return false;
+ }
+
+}
diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheableRequestPolicy.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheableRequestPolicy.java
index b93b7684f..d9b1ab014 100644
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheableRequestPolicy.java
+++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CacheableRequestPolicy.java
@@ -34,6 +34,7 @@ import org.apache.http.HttpRequest;
import org.apache.http.HttpVersion;
import org.apache.http.ProtocolVersion;
import org.apache.http.annotation.Immutable;
+import org.apache.http.client.cache.HeaderConstants;
/**
* Determines if an HttpRequest is allowed to be served from the cache.
diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java
index 39affe940..c56ec276b 100644
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java
+++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedHttpResponseGenerator.java
@@ -32,6 +32,8 @@ import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.annotation.Immutable;
+import org.apache.http.client.cache.HeaderConstants;
+import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.protocol.HTTP;
@@ -44,6 +46,17 @@ import org.apache.http.protocol.HTTP;
@Immutable
class CachedHttpResponseGenerator {
+ private final CacheValidityPolicy validityStrategy;
+
+ CachedHttpResponseGenerator(final CacheValidityPolicy validityStrategy) {
+ super();
+ this.validityStrategy = validityStrategy;
+ }
+
+ CachedHttpResponseGenerator() {
+ this(new CacheValidityPolicy());
+ }
+
/**
* If I was able to use a {@link CacheEntry} to response to the {@link org.apache.http.HttpRequest} then
* generate an {@link HttpResponse} based on the cache entry.
@@ -51,7 +64,7 @@ class CachedHttpResponseGenerator {
* {@link CacheEntry} to transform into an {@link HttpResponse}
* @return {@link HttpResponse} that was constructed
*/
- HttpResponse generateResponse(CacheEntry entry) {
+ HttpResponse generateResponse(HttpCacheEntry entry) {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, entry
.getStatusCode(), entry.getReasonPhrase());
@@ -63,7 +76,7 @@ class CachedHttpResponseGenerator {
addMissingContentLengthHeader(response, entity);
}
- long age = entry.getCurrentAgeSecs();
+ long age = this.validityStrategy.getCurrentAgeSecs(entry);
if (age > 0) {
if (age >= Integer.MAX_VALUE) {
response.setHeader(HeaderConstants.AGE, "2147483648");
diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedResponseSuitabilityChecker.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedResponseSuitabilityChecker.java
index 8ec66145c..697ac1fed 100644
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedResponseSuitabilityChecker.java
+++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/CachedResponseSuitabilityChecker.java
@@ -33,9 +33,11 @@ import org.apache.http.HeaderElement;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.annotation.Immutable;
+import org.apache.http.client.cache.HeaderConstants;
+import org.apache.http.client.cache.HttpCacheEntry;
/**
- * Determines whether a given {@link CacheEntry} is suitable to be
+ * Determines whether a given {@link HttpCacheEntry} is suitable to be
* used as a response for a given {@link HttpRequest}.
*
* @since 4.1
@@ -45,8 +47,19 @@ class CachedResponseSuitabilityChecker {
private final Log log = LogFactory.getLog(getClass());
+ private final CacheValidityPolicy validityStrategy;
+
+ CachedResponseSuitabilityChecker(final CacheValidityPolicy validityStrategy) {
+ super();
+ this.validityStrategy = validityStrategy;
+ }
+
+ CachedResponseSuitabilityChecker() {
+ this(new CacheValidityPolicy());
+ }
+
/**
- * Determine if I can utilize a {@link CacheEntry} to respond to the given
+ * Determine if I can utilize a {@link HttpCacheEntry} to respond to the given
* {@link HttpRequest}
*
* @param host
@@ -54,21 +67,21 @@ class CachedResponseSuitabilityChecker {
* @param request
* {@link HttpRequest}
* @param entry
- * {@link CacheEntry}
+ * {@link HttpCacheEntry}
* @return boolean yes/no answer
*/
- public boolean canCachedResponseBeUsed(HttpHost host, HttpRequest request, CacheEntry entry) {
- if (!entry.isResponseFresh()) {
+ public boolean canCachedResponseBeUsed(HttpHost host, HttpRequest request, HttpCacheEntry entry) {
+ if (!validityStrategy.isResponseFresh(entry)) {
log.debug("Cache entry was not fresh enough");
return false;
}
- if (!entry.contentLengthHeaderMatchesActualLength()) {
+ if (!validityStrategy.contentLengthHeaderMatchesActualLength(entry)) {
log.debug("Cache entry Content-Length and header information do not match");
return false;
}
- if (entry.modifiedSince(request)) {
+ if (validityStrategy.modifiedSince(entry, request)) {
log.debug("Cache entry modified times didn't line up. Cache Entry should not be used");
return false;
}
@@ -88,7 +101,7 @@ class CachedResponseSuitabilityChecker {
if (HeaderConstants.CACHE_CONTROL_MAX_AGE.equals(elt.getName())) {
try {
int maxage = Integer.parseInt(elt.getValue());
- if (entry.getCurrentAgeSecs() > maxage) {
+ if (validityStrategy.getCurrentAgeSecs(entry) > maxage) {
log.debug("Response from cache was NOT suitable due to max age");
return false;
}
@@ -102,7 +115,7 @@ class CachedResponseSuitabilityChecker {
if (HeaderConstants.CACHE_CONTROL_MAX_STALE.equals(elt.getName())) {
try {
int maxstale = Integer.parseInt(elt.getValue());
- if (entry.getFreshnessLifetimeSecs() > maxstale) {
+ if (validityStrategy.getFreshnessLifetimeSecs(entry) > maxstale) {
log.debug("Response from cache was not suitable due to Max stale freshness");
return false;
}
@@ -116,7 +129,7 @@ class CachedResponseSuitabilityChecker {
if (HeaderConstants.CACHE_CONTROL_MIN_FRESH.equals(elt.getName())) {
try {
int minfresh = Integer.parseInt(elt.getValue());
- if (entry.getFreshnessLifetimeSecs() < minfresh) {
+ if (validityStrategy.getFreshnessLifetimeSecs(entry) < minfresh) {
log.debug("Response from cache was not suitable due to min fresh " +
"freshness requirement");
return false;
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 81d3cbbf9..45d52b4f4 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
@@ -47,7 +47,9 @@ import org.apache.http.annotation.ThreadSafe;
import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
+import org.apache.http.client.cache.HeaderConstants;
import org.apache.http.client.cache.HttpCache;
+import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheOperationException;
import org.apache.http.client.cache.HttpCacheUpdateCallback;
import org.apache.http.client.methods.HttpUriRequest;
@@ -75,10 +77,11 @@ public class CachingHttpClient implements HttpClient {
private final AtomicLong cacheUpdates = new AtomicLong();
private final HttpClient backend;
+ private final HttpCache responseCache;
+ private final CacheValidityPolicy validityPolicy;
private final ResponseCachingPolicy responseCachingPolicy;
private final CacheEntryGenerator cacheEntryGenerator;
private final URIExtractor uriExtractor;
- private final HttpCache responseCache;
private final CachedHttpResponseGenerator responseGenerator;
private final CacheInvalidator cacheInvalidator;
private final CacheableRequestPolicy cacheableRequestPolicy;
@@ -93,17 +96,18 @@ public class CachingHttpClient implements HttpClient {
private final Log log = LogFactory.getLog(getClass());
- public CachingHttpClient(HttpClient client, HttpCache cache, int maxObjectSizeBytes) {
+ public CachingHttpClient(HttpClient client, HttpCache cache, int maxObjectSizeBytes) {
super();
- this.responseCache = cache;
this.backend = client;
+ this.responseCache = cache;
+ this.validityPolicy = new CacheValidityPolicy();
this.responseCachingPolicy = new ResponseCachingPolicy(maxObjectSizeBytes);
+ this.responseGenerator = new CachedHttpResponseGenerator(this.validityPolicy);
this.cacheEntryGenerator = new CacheEntryGenerator();
this.uriExtractor = new URIExtractor();
- this.responseGenerator = new CachedHttpResponseGenerator();
this.cacheInvalidator = new CacheInvalidator(this.uriExtractor, this.responseCache);
this.cacheableRequestPolicy = new CacheableRequestPolicy();
- this.suitabilityChecker = new CachedResponseSuitabilityChecker();
+ this.suitabilityChecker = new CachedResponseSuitabilityChecker(this.validityPolicy);
this.conditionalRequestBuilder = new ConditionalRequestBuilder();
this.cacheEntryUpdater = new CacheEntryUpdater();
this.maxObjectSizeBytes = maxObjectSizeBytes;
@@ -115,13 +119,13 @@ public class CachingHttpClient implements HttpClient {
this(new DefaultHttpClient(), new BasicHttpCache(MAX_CACHE_ENTRIES), DEFAULT_MAX_OBJECT_SIZE_BYTES);
}
- public CachingHttpClient(HttpCache cache, int maxObjectSizeBytes) {
+ public CachingHttpClient(HttpCache cache, int maxObjectSizeBytes) {
this(new DefaultHttpClient(), cache, maxObjectSizeBytes);
}
- CachingHttpClient(HttpClient backend, ResponseCachingPolicy responseCachingPolicy,
+ CachingHttpClient(HttpClient backend, CacheValidityPolicy validityPolicy, ResponseCachingPolicy responseCachingPolicy,
CacheEntryGenerator cacheEntryGenerator, URIExtractor uriExtractor,
- HttpCache responseCache, CachedHttpResponseGenerator responseGenerator,
+ HttpCache responseCache, CachedHttpResponseGenerator responseGenerator,
CacheInvalidator cacheInvalidator, CacheableRequestPolicy cacheableRequestPolicy,
CachedResponseSuitabilityChecker suitabilityChecker,
ConditionalRequestBuilder conditionalRequestBuilder, CacheEntryUpdater entryUpdater,
@@ -129,6 +133,7 @@ public class CachingHttpClient implements HttpClient {
RequestProtocolCompliance requestCompliance) {
this.maxObjectSizeBytes = DEFAULT_MAX_OBJECT_SIZE_BYTES;
this.backend = backend;
+ this.validityPolicy = validityPolicy;
this.responseCachingPolicy = responseCachingPolicy;
this.cacheEntryGenerator = cacheEntryGenerator;
this.uriExtractor = uriExtractor;
@@ -330,7 +335,7 @@ public class CachingHttpClient implements HttpClient {
return callBackend(target, request, context);
}
- CacheEntry entry = getCacheEntry(target, request);
+ HttpCacheEntry entry = getCacheEntry(target, request);
if (entry == null) {
cacheMisses.getAndIncrement();
if (log.isDebugEnabled()) {
@@ -352,14 +357,14 @@ public class CachingHttpClient implements HttpClient {
return responseGenerator.generateResponse(entry);
}
- if (entry.isRevalidatable()) {
+ if (validityPolicy.isRevalidatable(entry)) {
log.debug("Revalidating the cache entry");
try {
return revalidateCacheEntry(target, request, context, entry);
} catch (IOException ioex) {
- if (entry.mustRevalidate()
- || (isSharedCache() && entry.proxyRevalidate())) {
+ if (validityPolicy.mustRevalidate(entry)
+ || (isSharedCache() && validityPolicy.proxyRevalidate(entry))) {
return new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_GATEWAY_TIMEOUT, "Gateway Timeout");
} else {
HttpResponse response = responseGenerator.generateResponse(entry);
@@ -386,17 +391,18 @@ public class CachingHttpClient implements HttpClient {
return new Date();
}
- CacheEntry getCacheEntry(HttpHost target, HttpRequest request) {
+ HttpCacheEntry getCacheEntry(HttpHost target, HttpRequest request) {
String uri = uriExtractor.getURI(target, request);
- CacheEntry entry = null;
+ HttpCacheEntry entry = null;
try {
entry = responseCache.getEntry(uri);
} catch (HttpCacheOperationException ex) {
log.debug("Was unable to get an entry from the cache based on the uri provided", ex);
}
- if (entry == null || !entry.hasVariants())
+ if (entry == null || !entry.hasVariants()) {
return entry;
+ }
String variantUri = uriExtractor.getVariantURI(target, request, entry);
try {
@@ -445,7 +451,7 @@ public class CachingHttpClient implements HttpClient {
HttpHost target,
HttpRequest request,
HttpContext context,
- CacheEntry cacheEntry) throws IOException, ProtocolException {
+ HttpCacheEntry cacheEntry) throws IOException, ProtocolException {
HttpRequest conditionalRequest = conditionalRequestBuilder.buildConditionalRequest(request, cacheEntry);
Date requestDate = getCurrentDate();
@@ -456,7 +462,7 @@ public class CachingHttpClient implements HttpClient {
int statusCode = backendResponse.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
cacheUpdates.getAndIncrement();
- CacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry(cacheEntry, requestDate, responseDate, backendResponse);
+ HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry(cacheEntry, requestDate, responseDate, backendResponse);
storeInCache(target, request, updatedEntry);
return responseGenerator.generateResponse(updatedEntry);
}
@@ -465,7 +471,7 @@ public class CachingHttpClient implements HttpClient {
backendResponse);
}
- void storeInCache(HttpHost target, HttpRequest request, CacheEntry entry) {
+ void storeInCache(HttpHost target, HttpRequest request, HttpCacheEntry entry) {
if (entry.hasVariants()) {
storeVariantEntry(target, request, entry);
} else {
@@ -473,7 +479,7 @@ public class CachingHttpClient implements HttpClient {
}
}
- void storeNonVariantEntry(HttpHost target, HttpRequest req, CacheEntry entry) {
+ void storeNonVariantEntry(HttpHost target, HttpRequest req, HttpCacheEntry entry) {
String uri = uriExtractor.getURI(target, req);
try {
responseCache.putEntry(uri, entry);
@@ -485,7 +491,7 @@ public class CachingHttpClient implements HttpClient {
void storeVariantEntry(
final HttpHost target,
final HttpRequest req,
- final CacheEntry entry) {
+ final HttpCacheEntry entry) {
final String variantURI = uriExtractor.getVariantURI(target, req, entry);
try {
responseCache.putEntry(variantURI, entry);
@@ -493,9 +499,9 @@ public class CachingHttpClient implements HttpClient {
log.debug("Was unable to PUT a variant entry into the cache based on the uri provided", e);
}
- HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() {
+ HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() {
- public CacheEntry update(CacheEntry existing) throws HttpCacheOperationException {
+ public HttpCacheEntry update(HttpCacheEntry existing) throws HttpCacheOperationException {
return doGetUpdatedParentEntry(existing, entry, variantURI);
}
@@ -508,13 +514,13 @@ public class CachingHttpClient implements HttpClient {
}
}
- CacheEntry doGetUpdatedParentEntry(
- CacheEntry existing,
- CacheEntry entry, String variantURI) throws HttpCacheOperationException {
+ HttpCacheEntry doGetUpdatedParentEntry(
+ HttpCacheEntry existing,
+ HttpCacheEntry entry, String variantURI) throws HttpCacheOperationException {
if (existing != null) {
- return existing.copyWithVariant(variantURI);
+ return HttpCacheEntry.copyWithVariant(existing, variantURI);
} else {
- return entry.copyWithVariant(variantURI);
+ return HttpCacheEntry.copyWithVariant(entry, variantURI);
}
}
@@ -570,7 +576,7 @@ public class CachingHttpClient implements HttpClient {
responseBytes);
int correctedStatus = corrected.getStatusLine().getStatusCode();
if (HttpStatus.SC_BAD_GATEWAY != correctedStatus) {
- CacheEntry entry = cacheEntryGenerator
+ HttpCacheEntry entry = cacheEntryGenerator
.generateEntry(requestDate, responseDate, corrected,
responseBytes);
storeInCache(target, request, entry);
diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java
index f93c22321..6bf9245cf 100644
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java
+++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ConditionalRequestBuilder.java
@@ -31,6 +31,8 @@ import org.apache.http.HeaderElement;
import org.apache.http.HttpRequest;
import org.apache.http.ProtocolException;
import org.apache.http.annotation.Immutable;
+import org.apache.http.client.cache.HeaderConstants;
+import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.impl.client.RequestWrapper;
/**
@@ -40,7 +42,7 @@ import org.apache.http.impl.client.RequestWrapper;
class ConditionalRequestBuilder {
/**
- * When a {@link CacheEntry} is stale but 'might' be used as a response
+ * When a {@link HttpCacheEntry} is stale but 'might' be used as a response
* to an {@link HttpRequest} we will attempt to revalidate the entry with
* the origin. Build the origin {@link HttpRequest} here and return it.
*
@@ -49,7 +51,7 @@ class ConditionalRequestBuilder {
* @return the wrapped request
* @throws ProtocolException when I am unable to build a new origin request.
*/
- public HttpRequest buildConditionalRequest(HttpRequest request, CacheEntry cacheEntry)
+ public HttpRequest buildConditionalRequest(HttpRequest request, HttpCacheEntry cacheEntry)
throws ProtocolException {
RequestWrapper wrapperRequest = new RequestWrapper(request);
wrapperRequest.resetHeaders();
diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java
index 24c8299e4..eede354af 100644
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java
+++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/RequestProtocolCompliance.java
@@ -39,6 +39,7 @@ import org.apache.http.HttpVersion;
import org.apache.http.ProtocolException;
import org.apache.http.ProtocolVersion;
import org.apache.http.annotation.Immutable;
+import org.apache.http.client.cache.HeaderConstants;
import org.apache.http.entity.AbstractHttpEntity;
import org.apache.http.impl.client.RequestWrapper;
import org.apache.http.message.BasicHeader;
diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java
index 0adb61446..2d7a53688 100644
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java
+++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseCachingPolicy.java
@@ -36,6 +36,7 @@ import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.HttpVersion;
import org.apache.http.annotation.Immutable;
+import org.apache.http.client.cache.HeaderConstants;
import org.apache.http.impl.cookie.DateParseException;
import org.apache.http.impl.cookie.DateUtils;
import org.apache.http.protocol.HTTP;
diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProtocolCompliance.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProtocolCompliance.java
index cca08213a..526e45277 100644
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProtocolCompliance.java
+++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/ResponseProtocolCompliance.java
@@ -36,6 +36,7 @@ import org.apache.http.HttpVersion;
import org.apache.http.ProtocolVersion;
import org.apache.http.annotation.Immutable;
import org.apache.http.client.ClientProtocolException;
+import org.apache.http.client.cache.HeaderConstants;
import org.apache.http.impl.client.RequestWrapper;
import org.apache.http.impl.cookie.DateUtils;
import org.apache.http.protocol.HTTP;
diff --git a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/URIExtractor.java b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/URIExtractor.java
index 8ea0541b8..5a715fa8e 100644
--- a/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/URIExtractor.java
+++ b/httpclient-cache/src/main/java/org/apache/http/impl/client/cache/URIExtractor.java
@@ -37,6 +37,8 @@ import org.apache.http.HeaderElement;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.annotation.Immutable;
+import org.apache.http.client.cache.HeaderConstants;
+import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.protocol.HTTP;
/**
@@ -84,7 +86,7 @@ class URIExtractor {
* @param entry the parent entry used to track the varients
* @return String the extracted variant URI
*/
- public String getVariantURI(HttpHost host, HttpRequest req, CacheEntry entry) {
+ public String getVariantURI(HttpHost host, HttpRequest req, HttpCacheEntry entry) {
Header[] varyHdrs = entry.getHeaders(HeaderConstants.VARY);
if (varyHdrs == null || varyHdrs.length == 0) {
return getURI(host, req);
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
new file mode 100644
index 000000000..747f494ab
--- /dev/null
+++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/CacheEntry.java
@@ -0,0 +1,84 @@
+/*
+ * ====================================================================
+ * 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 org.apache.http.Header;
+import org.apache.http.HttpEntity;
+import org.apache.http.StatusLine;
+import org.apache.http.client.cache.HttpCacheEntry;
+import org.apache.http.entity.BasicHttpEntity;
+import org.apache.http.entity.ByteArrayEntity;
+
+public class CacheEntry extends HttpCacheEntry {
+
+ private static final long serialVersionUID = 7964121802841871079L;
+
+ public static final long MAX_AGE = CacheValidityPolicy.MAX_AGE;
+
+ public CacheEntry(
+ Date requestDate,
+ Date responseDate,
+ StatusLine statusLine,
+ Header[] responseHeaders,
+ HttpEntity body) {
+ super(requestDate, responseDate, statusLine, responseHeaders, body, null);
+ }
+
+ public CacheEntry(
+ Date requestDate,
+ Date responseDate) {
+ super(requestDate, responseDate, new OKStatus(), new Header[] {}, new BasicHttpEntity(), null);
+ }
+
+ public CacheEntry(
+ Date requestDate,
+ Date responseDate,
+ Header[] headers) {
+ super(requestDate, responseDate, new OKStatus(), headers, new BasicHttpEntity(), null);
+ }
+
+ public CacheEntry(Header[] headers) {
+ super(new Date(), new Date(), new OKStatus(), headers, new BasicHttpEntity(), null);
+ }
+
+ public CacheEntry(
+ Header[] headers,
+ byte[] content) {
+ super(new Date(), new Date(), new OKStatus(), headers, new ByteArrayEntity(content), null);
+ }
+
+ public CacheEntry() {
+ this(new Date(), new Date());
+ }
+
+ public CacheEntry(byte[] content) {
+ super(new Date(), new Date(), new OKStatus(), new Header[] {}, new ByteArrayEntity(content), null);
+ }
+
+}
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 653fae3c7..7b2ce3b0e 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
@@ -62,13 +62,12 @@ public class DoNotTestProtocolRequirements {
private HttpHost host;
private HttpEntity mockEntity;
private HttpClient mockBackend;
- private HttpCache mockCache;
+ private HttpCache mockCache;
private HttpRequest request;
private HttpResponse originResponse;
private CachingHttpClient impl;
- @SuppressWarnings("unchecked")
@Before
public void setUp() {
host = new HttpHost("foo.example.com");
@@ -77,7 +76,7 @@ public class DoNotTestProtocolRequirements {
originResponse = make200Response();
- HttpCache cache = new BasicHttpCache(MAX_ENTRIES);
+ HttpCache cache = new BasicHttpCache(MAX_ENTRIES);
mockBackend = EasyMock.createMock(HttpClient.class);
mockEntity = EasyMock.createMock(HttpEntity.class);
mockCache = EasyMock.createMock(HttpCache.class);
diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/OKStatus.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/OKStatus.java
new file mode 100644
index 000000000..eeebb295a
--- /dev/null
+++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/OKStatus.java
@@ -0,0 +1,39 @@
+/*
+ * ====================================================================
+ * 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 org.apache.http.HttpStatus;
+import org.apache.http.HttpVersion;
+import org.apache.http.message.BasicStatusLine;
+
+public class OKStatus extends BasicStatusLine {
+
+ public OKStatus() {
+ super(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
+ }
+
+}
\ No newline at end of file
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 1a90c3e43..2b3acb144 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
@@ -26,38 +26,29 @@
*/
package org.apache.http.impl.client.cache;
-import java.util.Date;
import java.util.Set;
import org.apache.http.Header;
-import org.apache.http.ProtocolVersion;
-import org.apache.http.entity.ByteArrayEntity;
-import org.apache.http.impl.cookie.DateUtils;
+import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.message.BasicHeader;
import org.junit.Assert;
import org.junit.Test;
public class TestCacheEntry {
- private static final ProtocolVersion HTTP_1_1 = new ProtocolVersion("HTTP",1,1);
-
@Test
public void testGetHeadersReturnsCorrectHeaders() {
Header[] headers = new Header[] { new BasicHeader("foo", "fooValue"),
new BasicHeader("bar", "barValue1"), new BasicHeader("bar", "barValue2") };
- CacheEntry entry = getEntry(headers);
+ CacheEntry entry = new CacheEntry(headers);
Assert.assertEquals(2, entry.getHeaders("bar").length);
}
- private CacheEntry getEntry(Header[] headers) {
- return getEntry(new Date(), new Date(), headers);
- }
-
@Test
public void testGetFirstHeaderReturnsCorrectHeader() {
Header[] headers = new Header[] { new BasicHeader("foo", "fooValue"),
new BasicHeader("bar", "barValue1"), new BasicHeader("bar", "barValue2") };
- CacheEntry entry = getEntry(headers);
+ CacheEntry entry = new CacheEntry(headers);
Assert.assertEquals("barValue1", entry.getFirstHeader("bar").getValue());
}
@@ -67,8 +58,7 @@ public class TestCacheEntry {
Header[] headers = new Header[] { new BasicHeader("foo", "fooValue"),
new BasicHeader("bar", "barValue1"), new BasicHeader("bar", "barValue2") };
-
- CacheEntry entry = getEntry(headers);
+ CacheEntry entry = new CacheEntry(headers);
Assert.assertEquals(0, entry.getHeaders("baz").length);
}
@@ -77,334 +67,23 @@ public class TestCacheEntry {
public void testGetFirstHeaderReturnsNullIfNoneMatch() {
Header[] headers = new Header[] { new BasicHeader("foo", "fooValue"),
new BasicHeader("bar", "barValue1"), new BasicHeader("bar", "barValue2") };
- CacheEntry entry = getEntry(headers);
-
+ CacheEntry entry = new CacheEntry(headers);
Assert.assertEquals(null, entry.getFirstHeader("quux"));
}
- @Test
- public void testApparentAgeIsMaxIntIfDateHeaderNotPresent() {
- Header[] headers = new Header[0];
- CacheEntry entry = getEntry(headers);
- Assert.assertEquals(2147483648L, entry.getApparentAgeSecs());
- }
-
- @Test
- public void testApparentAgeIsResponseReceivedTimeLessDateHeader() {
- Date now = new Date();
- Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
- Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
-
- Header[] headers = new Header[] { new BasicHeader("Date", DateUtils
- .formatDate(tenSecondsAgo)) };
-
-
-
- CacheEntry entry = getEntry(now, sixSecondsAgo, headers);
-
- Assert.assertEquals(4, entry.getApparentAgeSecs());
- }
-
- private CacheEntry getEntry(Date requestDate, Date responseDate, Header[] headers) {
- return new CacheEntry(requestDate, responseDate, HTTP_1_1, headers,
- new ByteArrayEntity(new byte[] {}), 200, "OK");
- }
-
- @Test
- public void testNegativeApparentAgeIsBroughtUpToZero() {
- Date now = new Date();
- Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
- Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
-
- Header[] headers = new Header[] { new BasicHeader("Date", DateUtils
- .formatDate(sixSecondsAgo)) };
-
- CacheEntry entry = getEntry(now,tenSecondsAgo,headers);
- Assert.assertEquals(0, entry.getApparentAgeSecs());
- }
-
- @Test
- public void testCorrectedReceivedAgeIsAgeHeaderIfLarger() {
- Header[] headers = new Header[] { new BasicHeader("Age", "10"), };
- CacheEntry entry = new CacheEntry(new Date(), new Date(), HTTP_1_1,
- headers, new ByteArrayEntity(new byte[] {}), 200, "OK") {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- protected long getApparentAgeSecs() {
- return 6;
- }
- };
-
-
- Assert.assertEquals(10, entry.getCorrectedReceivedAgeSecs());
- }
-
- @Test
- public void testCorrectedReceivedAgeIsApparentAgeIfLarger() {
- Header[] headers = new Header[] { new BasicHeader("Age", "6"), };
- CacheEntry entry = new CacheEntry(new Date(), new Date(), HTTP_1_1,
- headers, new ByteArrayEntity(new byte[] {}), 200 ,"OK") {
- private static final long serialVersionUID = 1L;
-
- @Override
- protected long getApparentAgeSecs() {
- return 10;
- }
- };
-
- Assert.assertEquals(10, entry.getCorrectedReceivedAgeSecs());
- }
-
- @Test
- public void testResponseDelayIsDifferenceBetweenResponseAndRequestTimes() {
- Date now = new Date();
- Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
- Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
-
- Header[] headers = new Header[]{};
-
- CacheEntry entry = new CacheEntry(tenSecondsAgo, sixSecondsAgo,
- new ProtocolVersion("HTTP",1,1), headers, new ByteArrayEntity(new byte[] {}),
- 200, "OK");
-
-
- Assert.assertEquals(4, entry.getResponseDelaySecs());
- }
-
- @Test
- public void testCorrectedInitialAgeIsCorrectedReceivedAgePlusResponseDelay() {
- CacheEntry entry = new CacheEntry(new Date(), new Date(), HTTP_1_1, new Header[] {},
- new ByteArrayEntity(new byte[] {}), 200, "OK") {
- private static final long serialVersionUID = 1L;
-
- @Override
- protected long getCorrectedReceivedAgeSecs() {
- return 7;
- }
-
- @Override
- protected long getResponseDelaySecs() {
- return 13;
- }
- };
- Assert.assertEquals(20, entry.getCorrectedInitialAgeSecs());
- }
-
- @Test
- public void testResidentTimeSecondsIsTimeSinceResponseTime() {
- final Date now = new Date();
- Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
-
- CacheEntry entry = new CacheEntry(new Date(), sixSecondsAgo, HTTP_1_1, new Header[]{},
- new ByteArrayEntity(new byte[] {}), 200, "OK") {
- private static final long serialVersionUID = 1L;
-
- @Override
- protected Date getCurrentDate() {
- return now;
- }
- };
-
- Assert.assertEquals(6, entry.getResidentTimeSecs());
- }
-
- @Test
- public void testCurrentAgeIsCorrectedInitialAgePlusResidentTime() {
- CacheEntry entry = new CacheEntry(new Date(), new Date(), HTTP_1_1, new Header[]{},
- new ByteArrayEntity(new byte[] {}), 200, "OK") {
- private static final long serialVersionUID = 1L;
-
- @Override
- protected long getCorrectedInitialAgeSecs() {
- return 11;
- }
-
- @Override
- protected long getResidentTimeSecs() {
- return 17;
- }
- };
- Assert.assertEquals(28, entry.getCurrentAgeSecs());
- }
-
- @Test
- public void testFreshnessLifetimeIsSMaxAgeIfPresent() {
- Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10") };
- CacheEntry entry = getEntry(headers);
- Assert.assertEquals(10, entry.getFreshnessLifetimeSecs());
- }
-
- @Test
- public void testFreshnessLifetimeIsMaxAgeIfPresent() {
- Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10") };
- CacheEntry entry = getEntry(headers);
- Assert.assertEquals(10, entry.getFreshnessLifetimeSecs());
- }
-
- @Test
- public void testFreshnessLifetimeIsMostRestrictiveOfMaxAgeAndSMaxAge() {
- Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10"),
- new BasicHeader("Cache-Control", "s-maxage=20") };
- CacheEntry entry = getEntry(headers);
- Assert.assertEquals(10, entry.getFreshnessLifetimeSecs());
-
- headers = new Header[] { new BasicHeader("Cache-Control", "max-age=20"),
- new BasicHeader("Cache-Control", "s-maxage=10") };
- entry = getEntry(headers);
- Assert.assertEquals(10, entry.getFreshnessLifetimeSecs());
- }
-
- @Test
- public void testFreshnessLifetimeIsMaxAgeEvenIfExpiresIsPresent() {
- Date now = new Date();
- Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
- Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
- Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10"),
- new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
- new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
-
- CacheEntry entry = getEntry(headers);
- Assert.assertEquals(10, entry.getFreshnessLifetimeSecs());
- }
-
- @Test
- public void testFreshnessLifetimeIsSMaxAgeEvenIfExpiresIsPresent() {
- Date now = new Date();
- Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
- Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
- Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10"),
- new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
- new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
-
- CacheEntry entry = getEntry(headers);
- Assert.assertEquals(10, entry.getFreshnessLifetimeSecs());
- }
-
- @Test
- public void testFreshnessLifetimeIsFromExpiresHeaderIfNoMaxAge() {
- Date now = new Date();
- Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
- Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
- Header[] headers = new Header[] {
- new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
- new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
-
- CacheEntry entry = getEntry(headers);
- Assert.assertEquals(4, entry.getFreshnessLifetimeSecs());
- }
-
- @Test
- public void testResponseIsFreshIfFreshnessLifetimeExceedsCurrentAge() {
- CacheEntry entry = new CacheEntry(new Date(), new Date(), HTTP_1_1, new Header[]{},
- new ByteArrayEntity(new byte[] {}), 200, "OK") {
- private static final long serialVersionUID = 1L;
-
- @Override
- public long getCurrentAgeSecs() {
- return 6;
- }
-
- @Override
- public long getFreshnessLifetimeSecs() {
- return 10;
- }
- };
-
- Assert.assertTrue(entry.isResponseFresh());
- }
-
- @Test
- public void testResponseIsNotFreshIfFreshnessLifetimeEqualsCurrentAge() {
- CacheEntry entry = new CacheEntry(new Date(), new Date(), HTTP_1_1, new Header[]{},
- new ByteArrayEntity(new byte[] {}), 200, "OK") {
-
- private static final long serialVersionUID = 1L;
-
- @Override
- public long getCurrentAgeSecs() {
- return 6;
- }
-
- @Override
- public long getFreshnessLifetimeSecs() {
- return 6;
- }
- };
-
- Assert.assertFalse(entry.isResponseFresh());
- }
-
- @Test
- public void testResponseIsNotFreshIfCurrentAgeExceedsFreshnessLifetime() {
- CacheEntry entry = new CacheEntry(new Date(), new Date(), HTTP_1_1, new Header[] {},
- new ByteArrayEntity(new byte[] {}), 200, "OK") {
- private static final long serialVersionUID = 1L;
-
- @Override
- public long getCurrentAgeSecs() {
- return 10;
- }
-
- @Override
- public long getFreshnessLifetimeSecs() {
- return 6;
- }
- };
-
- Assert.assertFalse(entry.isResponseFresh());
- }
-
- @Test
- public void testCacheEntryIsRevalidatableIfHeadersIncludeETag() {
-
- Header[] headers = {
- new BasicHeader("Expires", DateUtils.formatDate(new Date())),
- new BasicHeader("ETag", "somevalue")};
-
- CacheEntry entry = getEntry(headers);
-
- Assert.assertTrue(entry.isRevalidatable());
- }
-
- @Test
- public void testCacheEntryIsRevalidatableIfHeadersIncludeLastModifiedDate() {
-
- Header[] headers = {
- new BasicHeader("Expires", DateUtils.formatDate(new Date())),
- new BasicHeader("Last-Modified", DateUtils.formatDate(new Date())) };
-
- CacheEntry entry = getEntry(headers);
- Assert.assertTrue(entry.isRevalidatable());
- }
-
- @Test
- public void testCacheEntryIsNotRevalidatableIfNoAppropriateHeaders() {
-
- Header[] headers = {
- new BasicHeader("Expires", DateUtils.formatDate(new Date())),
- new BasicHeader("Cache-Control", "public") };
-
- CacheEntry entry = getEntry(headers);
- Assert.assertFalse(entry.isRevalidatable());
- }
-
-
-
@Test
public void testCacheEntryWithNoVaryHeaderDoesNotHaveVariants() {
Header[] headers = new Header[0];
- CacheEntry entry = getEntry(headers);
+ CacheEntry entry = new CacheEntry(headers);
Assert.assertFalse(entry.hasVariants());
}
@Test
public void testCacheEntryWithOneVaryHeaderHasVariants() {
Header[] headers = { new BasicHeader("Vary", "User-Agent") };
- CacheEntry entry = getEntry(headers);
+ CacheEntry entry = new CacheEntry(headers);
Assert.assertTrue(entry.hasVariants());
}
@@ -412,14 +91,14 @@ public class TestCacheEntry {
public void testCacheEntryWithMultipleVaryHeadersHasVariants() {
Header[] headers = { new BasicHeader("Vary", "User-Agent"),
new BasicHeader("Vary", "Accept-Encoding") };
- CacheEntry entry = getEntry(headers);
+ CacheEntry entry = new CacheEntry(headers);
Assert.assertTrue(entry.hasVariants());
}
@Test
public void testCacheEntryWithVaryStarHasVariants(){
Header[] headers = { new BasicHeader("Vary", "*") };
- CacheEntry entry = getEntry(headers);
+ CacheEntry entry = new CacheEntry(headers);
Assert.assertTrue(entry.hasVariants());
}
@@ -427,10 +106,10 @@ public class TestCacheEntry {
public void testCacheEntryCanStoreMultipleVariantUris() {
Header[] headers = new Header[]{};
- CacheEntry entry = getEntry(headers);
+ CacheEntry entry = new CacheEntry(headers);
- CacheEntry addedOne = entry.copyWithVariant("foo");
- CacheEntry addedTwo = addedOne.copyWithVariant("bar");
+ HttpCacheEntry addedOne = HttpCacheEntry.copyWithVariant(entry, "foo");
+ HttpCacheEntry addedTwo = HttpCacheEntry.copyWithVariant(addedOne, "bar");
Set variants = addedTwo.getVariantURIs();
@@ -438,99 +117,4 @@ public class TestCacheEntry {
Assert.assertTrue(variants.contains("bar"));
}
- @Test
- public void testMalformedDateHeaderIsIgnored() {
-
- Header[] headers = new Header[] { new BasicHeader("Date", "asdf") };
- CacheEntry entry = getEntry(headers);
-
- Date d = entry.getDateValue();
-
- Assert.assertNull(d);
- }
-
- @Test
- public void testMalformedContentLengthReturnsNegativeOne() {
-
- Header[] headers = new Header[] { new BasicHeader("Content-Length", "asdf") };
- CacheEntry entry = getEntry(headers);
-
- long length = entry.getContentLengthValue();
-
- Assert.assertEquals(-1, length);
- }
-
- @Test
- public void testNegativeAgeHeaderValueReturnsMaxAge() {
-
- Header[] headers = new Header[] { new BasicHeader("Age", "-100") };
- CacheEntry entry = getEntry(headers);
-
- long length = entry.getAgeValue();
-
- Assert.assertEquals(CacheEntry.MAX_AGE, length);
- }
-
- @Test
- public void testMalformedAgeHeaderValueReturnsMaxAge() {
-
- Header[] headers = new Header[] { new BasicHeader("Age", "asdf") };
- CacheEntry entry = getEntry(headers);
-
- long length = entry.getAgeValue();
-
- Assert.assertEquals(CacheEntry.MAX_AGE, length);
- }
-
- @Test
- public void testMalformedCacheControlMaxAgeHeaderReturnsZero() {
-
- Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=asdf") };
- CacheEntry entry = getEntry(headers);
-
- long maxage = entry.getMaxAge();
-
- Assert.assertEquals(0, maxage);
- }
-
- @Test
- public void testMalformedExpirationDateReturnsNull() {
- Header[] headers = new Header[] { new BasicHeader("Expires", "asdf") };
- CacheEntry entry = getEntry(headers);
-
- Date expirationDate = entry.getExpirationDate();
-
- Assert.assertNull(expirationDate);
- }
-
- @Test
- public void testMustRevalidateIsFalseIfDirectiveNotPresent() {
- Header[] headers = new Header[] { new BasicHeader("Cache-Control","public") };
- CacheEntry entry = getEntry(headers);
- Assert.assertFalse(entry.mustRevalidate());
- }
-
- @Test
- public void testMustRevalidateIsTrueWhenDirectiveIsPresent() {
- Header[] headers = new Header[] { new BasicHeader("Cache-Control","public, must-revalidate") };
- CacheEntry entry = getEntry(headers);
- Assert.assertTrue(entry.mustRevalidate());
- }
-
- @Test
- public void testProxyRevalidateIsFalseIfDirectiveNotPresent() {
- Header[] headers = new Header[] { new BasicHeader("Cache-Control","public") };
- CacheEntry entry = getEntry(headers);
- Assert.assertFalse(entry.proxyRevalidate());
- }
-
- @Test
- public void testProxyRevalidateIsTrueWhenDirectiveIsPresent() {
- Header[] headers = new Header[] { new BasicHeader("Cache-Control","public, proxy-revalidate") };
- CacheEntry entry = getEntry(headers);
- Assert.assertTrue(entry.proxyRevalidate());
- }
-
-
-
}
diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryGenerator.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryGenerator.java
index 7901b9edf..d43081831 100644
--- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryGenerator.java
+++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryGenerator.java
@@ -32,6 +32,7 @@ import org.apache.http.HttpEntity;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
import org.apache.http.ProtocolVersion;
+import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.message.BasicHttpResponse;
import org.junit.Assert;
@@ -51,7 +52,7 @@ public class TestCacheEntryGenerator {
response.setHeader("fooHeader", "fooHeaderValue");
- CacheEntry entry = gen.generateEntry(new Date(), new Date(), response, new byte[] {});
+ HttpCacheEntry entry = gen.generateEntry(new Date(), new Date(), response, new byte[] {});
Assert.assertEquals("HTTP", entry.getProtocolVersion().getProtocol());
Assert.assertEquals(1, entry.getProtocolVersion().getMajor());
diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java
index 84f7ccead..11ff35704 100644
--- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java
+++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheEntryUpdater.java
@@ -29,13 +29,13 @@ package org.apache.http.impl.client.cache;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
import org.apache.http.HttpStatus;
+import org.apache.http.HttpVersion;
import org.apache.http.ProtocolVersion;
-import org.apache.http.entity.ByteArrayEntity;
+import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.impl.cookie.DateUtils;
import org.apache.http.message.BasicHeader;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicStatusLine;
-import org.easymock.classextension.EasyMock;
import org.junit.Assert;
import org.junit.Before;
import org.junit.Test;
@@ -48,59 +48,28 @@ import static junit.framework.Assert.assertNotSame;
public class TestCacheEntryUpdater {
-
- private static final ProtocolVersion HTTP_1_1 = new ProtocolVersion("HTTP", 1, 1);
-
-
- private HttpResponse mockResponse;
- private CacheEntry mockCacheEntry;
private Date requestDate;
private Date responseDate;
- private boolean implMocked = false;
private CacheEntryUpdater impl;
@Before
public void setUp() throws Exception {
- mockResponse = EasyMock.createMock(HttpResponse.class);
- mockCacheEntry = EasyMock.createMock(CacheEntry.class);
-
requestDate = new Date(System.currentTimeMillis() - 1000);
responseDate = new Date();
impl = new CacheEntryUpdater();
}
- private void replayMocks() {
- EasyMock.replay(mockResponse);
- EasyMock.replay(mockCacheEntry);
- if (implMocked) {
- EasyMock.replay(impl);
- }
- }
-
- private void verifyMocks() {
- EasyMock.verify(mockResponse);
- EasyMock.verify(mockCacheEntry);
- if (implMocked) {
- EasyMock.verify(impl);
- }
- }
-
@Test
public void testUpdateCacheEntryReturnsDifferentEntryInstance() throws IOException {
- CacheEntry entry = getEntry(new Header[]{});
- BasicHttpResponse response = new BasicHttpResponse(HTTP_1_1, 200, "OK");
+ CacheEntry entry = new CacheEntry();
+ BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
- replayMocks();
-
- CacheEntry newEntry = impl.updateCacheEntry(entry, requestDate, responseDate, response);
-
- verifyMocks();
+ HttpCacheEntry newEntry = impl.updateCacheEntry(entry, requestDate, responseDate, response);
assertNotSame(newEntry, entry);
-
}
@Test
@@ -110,13 +79,13 @@ public class TestCacheEntryUpdater {
new BasicHeader("Date", DateUtils.formatDate(responseDate)),
new BasicHeader("ETag", "\"etag\"")};
- CacheEntry cacheEntry = getEntry(headers);
+ CacheEntry cacheEntry = new CacheEntry(headers);
HttpResponse response = new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion(
"http", 1, 1), HttpStatus.SC_NOT_MODIFIED, ""));
response.setHeaders(new Header[]{});
- CacheEntry updatedEntry = impl.updateCacheEntry(cacheEntry, new Date(), new Date(), response);
+ HttpCacheEntry updatedEntry = impl.updateCacheEntry(cacheEntry, new Date(), new Date(), response);
Assert.assertEquals(2, updatedEntry.getAllHeaders().length);
@@ -133,7 +102,7 @@ public class TestCacheEntryUpdater {
new BasicHeader("Cache-Control", "private"), new BasicHeader("ETag", "\"etag\""),
new BasicHeader("Last-Modified", DateUtils.formatDate(requestDate)),
new BasicHeader("Cache-Control", "max-age=0"),};
- CacheEntry cacheEntry = getEntry(headers);
+ CacheEntry cacheEntry = new CacheEntry(headers);
HttpResponse response = new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion(
"http", 1, 1), HttpStatus.SC_NOT_MODIFIED, ""));
@@ -141,7 +110,7 @@ public class TestCacheEntryUpdater {
new BasicHeader("Last-Modified", DateUtils.formatDate(responseDate)),
new BasicHeader("Cache-Control", "public"),});
- CacheEntry updatedEntry = impl.updateCacheEntry(cacheEntry, new Date(), new Date(), response);
+ HttpCacheEntry updatedEntry = impl.updateCacheEntry(cacheEntry, new Date(), new Date(), response);
Assert.assertEquals(4, updatedEntry.getAllHeaders().length);
@@ -160,14 +129,14 @@ public class TestCacheEntryUpdater {
new BasicHeader("Date", DateUtils.formatDate(requestDate)),
new BasicHeader("ETag", "\"etag\"")};
- CacheEntry cacheEntry = getEntry(headers);
+ CacheEntry cacheEntry = new CacheEntry(headers);
HttpResponse response = new BasicHttpResponse(new BasicStatusLine(new ProtocolVersion(
"http", 1, 1), HttpStatus.SC_NOT_MODIFIED, ""));
response.setHeaders(new Header[]{
new BasicHeader("Last-Modified", DateUtils.formatDate(responseDate)),
new BasicHeader("Cache-Control", "public"),});
- CacheEntry updatedEntry = impl.updateCacheEntry(cacheEntry, new Date(), new Date(), response);
+ HttpCacheEntry updatedEntry = impl.updateCacheEntry(cacheEntry, new Date(), new Date(), response);
Assert.assertEquals(4, updatedEntry.getAllHeaders().length);
@@ -191,23 +160,17 @@ public class TestCacheEntryUpdater {
Date twoSecondsAgo = new Date(now.getTime() - 2000L);
Date oneSecondAgo = new Date(now.getTime() - 1000L);
- Header[] headers = new Header[]{};
+ CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo);
- CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, HTTP_1_1, headers,
- new ByteArrayEntity(new byte[] {}), 200, "OK");
+ HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
- HttpResponse response = new BasicHttpResponse(HTTP_1_1, 200, "OK");
-
- CacheEntry updated = impl.updateCacheEntry(entry, twoSecondsAgo, oneSecondAgo, response);
+ HttpCacheEntry updated = impl.updateCacheEntry(entry, twoSecondsAgo, oneSecondAgo, response);
assertEquals(twoSecondsAgo, updated.getRequestDate());
assertEquals(oneSecondAgo, updated.getResponseDate());
}
-
- // UTILITY
-
private void headersContain(Header[] headers, String name, String value) {
for (Header header : headers) {
if (header.getName().equals(name)) {
@@ -219,13 +182,4 @@ public class TestCacheEntryUpdater {
Assert.fail("Header [" + name + ": " + value + "] not found in headers.");
}
-
- private CacheEntry getEntry(Header[] headers) {
- return getEntry(new Date(), new Date(), headers);
- }
-
- private CacheEntry getEntry(Date requestDate, Date responseDate, Header[] headers) {
- return new CacheEntry(requestDate, responseDate, HTTP_1_1, headers,
- new ByteArrayEntity(new byte[] {}), 200, "OK");
- }
}
diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java
index 23b95eea6..445f61513 100644
--- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java
+++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheInvalidator.java
@@ -46,14 +46,11 @@ public class TestCacheInvalidator {
private static final ProtocolVersion HTTP_1_1 = new ProtocolVersion("HTTP", 1, 1);
private CacheInvalidator impl;
- private HttpCache mockCache;
+ private HttpCache mockCache;
private HttpHost host;
private URIExtractor extractor;
private CacheEntry mockEntry;
- private boolean mockedImpl;
-
- @SuppressWarnings("unchecked")
@Before
public void setUp() {
host = new HttpHost("foo.example.com");
@@ -67,17 +64,11 @@ public class TestCacheInvalidator {
private void replayMocks() {
EasyMock.replay(mockCache);
EasyMock.replay(mockEntry);
-
- if (mockedImpl)
- EasyMock.replay(impl);
}
private void verifyMocks() {
EasyMock.verify(mockCache);
EasyMock.verify(mockEntry);
-
- if (mockedImpl)
- EasyMock.verify(impl);
}
// Tests
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
new file mode 100644
index 000000000..638927ab7
--- /dev/null
+++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCacheValidityPolicy.java
@@ -0,0 +1,453 @@
+/*
+ * ====================================================================
+ * 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 org.apache.http.Header;
+import org.apache.http.client.cache.HttpCacheEntry;
+import org.apache.http.impl.cookie.DateUtils;
+import org.apache.http.message.BasicHeader;
+import org.junit.Assert;
+import org.junit.Test;
+
+public class TestCacheValidityPolicy {
+
+ @Test
+ public void testApparentAgeIsMaxIntIfDateHeaderNotPresent() {
+ CacheEntry entry = new CacheEntry();
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ Assert.assertEquals(2147483648L, impl.getApparentAgeSecs(entry));
+ }
+
+ @Test
+ public void testApparentAgeIsResponseReceivedTimeLessDateHeader() {
+ Date now = new Date();
+ Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
+ Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
+
+ Header[] headers = new Header[] { new BasicHeader("Date", DateUtils
+ .formatDate(tenSecondsAgo)) };
+
+ CacheEntry entry = new CacheEntry(now, sixSecondsAgo, headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+
+ Assert.assertEquals(4, impl.getApparentAgeSecs(entry));
+ }
+
+ @Test
+ public void testNegativeApparentAgeIsBroughtUpToZero() {
+ Date now = new Date();
+ Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
+ Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
+
+ Header[] headers = new Header[] { new BasicHeader("Date", DateUtils
+ .formatDate(sixSecondsAgo)) };
+
+ CacheEntry entry = new CacheEntry(now,tenSecondsAgo,headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ Assert.assertEquals(0, impl.getApparentAgeSecs(entry));
+ }
+
+ @Test
+ public void testCorrectedReceivedAgeIsAgeHeaderIfLarger() {
+ Header[] headers = new Header[] { new BasicHeader("Age", "10"), };
+ CacheEntry entry = new CacheEntry(headers);
+
+ CacheValidityPolicy impl = new CacheValidityPolicy() {
+
+ @Override
+ protected long getApparentAgeSecs(HttpCacheEntry entry) {
+ return 6;
+ }
+
+ };
+
+ Assert.assertEquals(10, impl.getCorrectedReceivedAgeSecs(entry));
+ }
+
+ @Test
+ public void testCorrectedReceivedAgeIsApparentAgeIfLarger() {
+ Header[] headers = new Header[] { new BasicHeader("Age", "6"), };
+ CacheEntry entry = new CacheEntry(headers);
+
+ CacheValidityPolicy impl = new CacheValidityPolicy() {
+
+ @Override
+ protected long getApparentAgeSecs(HttpCacheEntry entry) {
+ return 10;
+ }
+
+ };
+
+ Assert.assertEquals(10, impl.getCorrectedReceivedAgeSecs(entry));
+ }
+
+ @Test
+ public void testResponseDelayIsDifferenceBetweenResponseAndRequestTimes() {
+ Date now = new Date();
+ Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
+ Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
+
+ CacheEntry entry = new CacheEntry(tenSecondsAgo, sixSecondsAgo);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+
+ Assert.assertEquals(4, impl.getResponseDelaySecs(entry));
+ }
+
+ @Test
+ public void testCorrectedInitialAgeIsCorrectedReceivedAgePlusResponseDelay() {
+ CacheEntry entry = new CacheEntry();
+ CacheValidityPolicy impl = new CacheValidityPolicy() {
+
+ @Override
+ protected long getCorrectedReceivedAgeSecs(HttpCacheEntry entry) {
+ return 7;
+ }
+
+ @Override
+ protected long getResponseDelaySecs(HttpCacheEntry entry) {
+ return 13;
+ }
+
+ };
+ Assert.assertEquals(20, impl.getCorrectedInitialAgeSecs(entry));
+ }
+
+ @Test
+ public void testResidentTimeSecondsIsTimeSinceResponseTime() {
+ final Date now = new Date();
+ final Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
+
+ CacheEntry entry = new CacheEntry(now, sixSecondsAgo);
+
+ CacheValidityPolicy impl = new CacheValidityPolicy() {
+
+ @Override
+ protected Date getCurrentDate() {
+ return now;
+ }
+
+ };
+
+ Assert.assertEquals(6, impl.getResidentTimeSecs(entry));
+ }
+
+ @Test
+ public void testCurrentAgeIsCorrectedInitialAgePlusResidentTime() {
+ CacheEntry entry = new CacheEntry();
+ CacheValidityPolicy impl = new CacheValidityPolicy() {
+
+ @Override
+ protected long getCorrectedInitialAgeSecs(HttpCacheEntry entry) {
+ return 11;
+ }
+
+ @Override
+ protected long getResidentTimeSecs(HttpCacheEntry entry) {
+ return 17;
+ }
+ };
+ Assert.assertEquals(28, impl.getCurrentAgeSecs(entry));
+ }
+
+ @Test
+ public void testFreshnessLifetimeIsSMaxAgeIfPresent() {
+ Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10") };
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
+ }
+
+ @Test
+ public void testFreshnessLifetimeIsMaxAgeIfPresent() {
+ Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10") };
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
+ }
+
+ @Test
+ public void testFreshnessLifetimeIsMostRestrictiveOfMaxAgeAndSMaxAge() {
+ Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10"),
+ new BasicHeader("Cache-Control", "s-maxage=20") };
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
+
+ headers = new Header[] { new BasicHeader("Cache-Control", "max-age=20"),
+ new BasicHeader("Cache-Control", "s-maxage=10") };
+ entry = new CacheEntry(headers);
+ Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
+ }
+
+ @Test
+ public void testFreshnessLifetimeIsMaxAgeEvenIfExpiresIsPresent() {
+ Date now = new Date();
+ Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
+ Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
+ Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=10"),
+ new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
+ new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
+
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
+ }
+
+ @Test
+ public void testFreshnessLifetimeIsSMaxAgeEvenIfExpiresIsPresent() {
+ Date now = new Date();
+ Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
+ Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
+ Header[] headers = new Header[] { new BasicHeader("Cache-Control", "s-maxage=10"),
+ new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
+ new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
+
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ Assert.assertEquals(10, impl.getFreshnessLifetimeSecs(entry));
+ }
+
+ @Test
+ public void testFreshnessLifetimeIsFromExpiresHeaderIfNoMaxAge() {
+ Date now = new Date();
+ Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
+ Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
+ Header[] headers = new Header[] {
+ new BasicHeader("Date", DateUtils.formatDate(tenSecondsAgo)),
+ new BasicHeader("Expires", DateUtils.formatDate(sixSecondsAgo)) };
+
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ Assert.assertEquals(4, impl.getFreshnessLifetimeSecs(entry));
+ }
+
+ @Test
+ public void testResponseIsFreshIfFreshnessLifetimeExceedsCurrentAge() {
+ CacheEntry entry = new CacheEntry();
+ CacheValidityPolicy impl = new CacheValidityPolicy() {
+
+ @Override
+ public long getCurrentAgeSecs(HttpCacheEntry entry) {
+ return 6;
+ }
+
+ @Override
+ public long getFreshnessLifetimeSecs(HttpCacheEntry entry) {
+ return 10;
+ }
+ };
+
+ Assert.assertTrue(impl.isResponseFresh(entry));
+ }
+
+ @Test
+ public void testResponseIsNotFreshIfFreshnessLifetimeEqualsCurrentAge() {
+ CacheEntry entry = new CacheEntry();
+ CacheValidityPolicy impl = new CacheValidityPolicy() {
+
+ @Override
+ public long getCurrentAgeSecs(HttpCacheEntry entry) {
+ return 6;
+ }
+
+ @Override
+ public long getFreshnessLifetimeSecs(HttpCacheEntry entry) {
+ return 6;
+ }
+ };
+
+ Assert.assertFalse(impl.isResponseFresh(entry));
+ }
+
+ @Test
+ public void testResponseIsNotFreshIfCurrentAgeExceedsFreshnessLifetime() {
+ CacheEntry entry = new CacheEntry();
+ CacheValidityPolicy impl = new CacheValidityPolicy() {
+
+ @Override
+ public long getCurrentAgeSecs(HttpCacheEntry entry) {
+ return 10;
+ }
+
+ @Override
+ public long getFreshnessLifetimeSecs(HttpCacheEntry entry) {
+ return 6;
+ }
+ };
+
+ Assert.assertFalse(impl.isResponseFresh(entry));
+ }
+
+ @Test
+ public void testCacheEntryIsRevalidatableIfHeadersIncludeETag() {
+
+ Header[] headers = {
+ new BasicHeader("Expires", DateUtils.formatDate(new Date())),
+ new BasicHeader("ETag", "somevalue")};
+
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+
+ Assert.assertTrue(impl.isRevalidatable(entry));
+ }
+
+ @Test
+ public void testCacheEntryIsRevalidatableIfHeadersIncludeLastModifiedDate() {
+
+ Header[] headers = {
+ new BasicHeader("Expires", DateUtils.formatDate(new Date())),
+ new BasicHeader("Last-Modified", DateUtils.formatDate(new Date())) };
+
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+
+ Assert.assertTrue(impl.isRevalidatable(entry));
+ }
+
+ @Test
+ public void testCacheEntryIsNotRevalidatableIfNoAppropriateHeaders() {
+
+ Header[] headers = {
+ new BasicHeader("Expires", DateUtils.formatDate(new Date())),
+ new BasicHeader("Cache-Control", "public") };
+
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+
+ Assert.assertFalse(impl.isRevalidatable(entry));
+ }
+
+ @Test
+ public void testMalformedDateHeaderIsIgnored() {
+
+ Header[] headers = new Header[] { new BasicHeader("Date", "asdf") };
+ CacheEntry entry = new CacheEntry(headers);
+
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ Date d = impl.getDateValue(entry);
+
+ Assert.assertNull(d);
+ }
+
+ @Test
+ public void testMalformedContentLengthReturnsNegativeOne() {
+
+ Header[] headers = new Header[] { new BasicHeader("Content-Length", "asdf") };
+ CacheEntry entry = new CacheEntry(headers);
+
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ long length = impl.getContentLengthValue(entry);
+
+ Assert.assertEquals(-1, length);
+ }
+
+ @Test
+ public void testNegativeAgeHeaderValueReturnsMaxAge() {
+
+ Header[] headers = new Header[] { new BasicHeader("Age", "-100") };
+ CacheEntry entry = new CacheEntry(headers);
+
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ long length = impl.getAgeValue(entry);
+
+ Assert.assertEquals(CacheEntry.MAX_AGE, length);
+ }
+
+ @Test
+ public void testMalformedAgeHeaderValueReturnsMaxAge() {
+
+ Header[] headers = new Header[] { new BasicHeader("Age", "asdf") };
+ CacheEntry entry = new CacheEntry(headers);
+
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ long length = impl.getAgeValue(entry);
+
+ Assert.assertEquals(CacheEntry.MAX_AGE, length);
+ }
+
+ @Test
+ public void testMalformedCacheControlMaxAgeHeaderReturnsZero() {
+
+ Header[] headers = new Header[] { new BasicHeader("Cache-Control", "max-age=asdf") };
+ CacheEntry entry = new CacheEntry(headers);
+
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ long maxage = impl.getMaxAge(entry);
+
+ Assert.assertEquals(0, maxage);
+ }
+
+ @Test
+ public void testMalformedExpirationDateReturnsNull() {
+ Header[] headers = new Header[] { new BasicHeader("Expires", "asdf") };
+ CacheEntry entry = new CacheEntry(headers);
+
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+ Date expirationDate = impl.getExpirationDate(entry);
+
+ Assert.assertNull(expirationDate);
+ }
+
+ @Test
+ public void testMustRevalidateIsFalseIfDirectiveNotPresent() {
+ Header[] headers = new Header[] { new BasicHeader("Cache-Control","public") };
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+
+ Assert.assertFalse(impl.mustRevalidate(entry));
+ }
+
+ @Test
+ public void testMustRevalidateIsTrueWhenDirectiveIsPresent() {
+ Header[] headers = new Header[] { new BasicHeader("Cache-Control","public, must-revalidate") };
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+
+ Assert.assertTrue(impl.mustRevalidate(entry));
+ }
+
+ @Test
+ public void testProxyRevalidateIsFalseIfDirectiveNotPresent() {
+ Header[] headers = new Header[] { new BasicHeader("Cache-Control","public") };
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+
+ Assert.assertFalse(impl.proxyRevalidate(entry));
+ }
+
+ @Test
+ public void testProxyRevalidateIsTrueWhenDirectiveIsPresent() {
+ Header[] headers = new Header[] { new BasicHeader("Cache-Control","public, proxy-revalidate") };
+ CacheEntry entry = new CacheEntry(headers);
+ CacheValidityPolicy impl = new CacheValidityPolicy();
+
+ Assert.assertTrue(impl.proxyRevalidate(entry));
+ }
+
+}
diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachedHttpResponseGenerator.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachedHttpResponseGenerator.java
index 5fc1790f4..d0e48c684 100644
--- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachedHttpResponseGenerator.java
+++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachedHttpResponseGenerator.java
@@ -30,26 +30,45 @@ import java.util.Date;
import org.apache.http.Header;
import org.apache.http.HttpResponse;
-import org.apache.http.ProtocolVersion;
-import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.impl.cookie.DateUtils;
import org.apache.http.message.BasicHeader;
+import org.easymock.classextension.EasyMock;
import org.junit.Assert;
+import org.junit.Before;
import org.junit.Test;
public class TestCachedHttpResponseGenerator {
+ private CacheEntry entry;
+ private CacheValidityPolicy mockValidityPolicy;
+ private CachedHttpResponseGenerator impl;
+
+ @Before
+ public void setUp() {
+ Date now = new Date();
+ Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
+ Date eightSecondsAgo = new Date(now.getTime() - 8 * 1000L);
+ Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
+ Date tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
+ Header[] hdrs = { new BasicHeader("Date", DateUtils.formatDate(eightSecondsAgo)),
+ new BasicHeader("Expires", DateUtils.formatDate(tenSecondsFromNow)),
+ new BasicHeader("Content-Length", "150") };
+
+ entry = new CacheEntry(tenSecondsAgo, sixSecondsAgo, hdrs);
+ mockValidityPolicy = EasyMock.createMock(CacheValidityPolicy.class);
+ impl = new CachedHttpResponseGenerator(mockValidityPolicy);
+ }
+
+ public void replayMocks() {
+ EasyMock.replay(mockValidityPolicy);
+ }
+
@Test
public void testResponseHasContentLength() {
-
- Header[] hdrs = new Header[] {};
byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
- CacheEntry entry = new CacheEntry(
- new Date(), new Date(), new ProtocolVersion("HTTP", 1, 1), hdrs,
- new ByteArrayEntity(buf), 200, "OK");
+ CacheEntry entry = new CacheEntry(buf);
- CachedHttpResponseGenerator gen = new CachedHttpResponseGenerator();
- HttpResponse response = gen.generateResponse(entry);
+ HttpResponse response = impl.generateResponse(entry);
Header length = response.getFirstHeader("Content-Length");
Assert.assertNotNull("Content-Length Header is missing", length);
@@ -63,13 +82,9 @@ public class TestCachedHttpResponseGenerator {
Header[] hdrs = new Header[] { new BasicHeader("Transfer-Encoding", "chunked") };
byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
- CacheEntry entry = new CacheEntry(
- new Date(), new Date(), new ProtocolVersion("HTTP", 1, 1), hdrs,
- new ByteArrayEntity(buf), 200, "OK");
+ CacheEntry entry = new CacheEntry(hdrs, buf);
-
- CachedHttpResponseGenerator gen = new CachedHttpResponseGenerator();
- HttpResponse response = gen.generateResponse(entry);
+ HttpResponse response = impl.generateResponse(entry);
Header length = response.getFirstHeader("Content-Length");
@@ -78,10 +93,7 @@ public class TestCachedHttpResponseGenerator {
@Test
public void testResponseMatchesCacheEntry() {
- CacheEntry entry = buildEntry();
-
- CachedHttpResponseGenerator gen = new CachedHttpResponseGenerator();
- HttpResponse response = gen.generateResponse(entry);
+ HttpResponse response = impl.generateResponse(entry);
Assert.assertTrue(response.containsHeader("Content-Length"));
@@ -92,36 +104,29 @@ public class TestCachedHttpResponseGenerator {
@Test
public void testResponseStatusCodeMatchesCacheEntry() {
- CacheEntry entry = buildEntry();
-
- CachedHttpResponseGenerator gen = new CachedHttpResponseGenerator();
- HttpResponse response = gen.generateResponse(entry);
+ HttpResponse response = impl.generateResponse(entry);
Assert.assertEquals(entry.getStatusCode(), response.getStatusLine().getStatusCode());
}
@Test
public void testAgeHeaderIsPopulatedWithCurrentAgeOfCacheEntryIfNonZero() {
- final long currAge = 10L;
+ currentAge(10L);
+ replayMocks();
- CacheEntry entry = buildEntryWithCurrentAge(currAge);
-
- CachedHttpResponseGenerator gen = new CachedHttpResponseGenerator();
- HttpResponse response = gen.generateResponse(entry);
+ HttpResponse response = impl.generateResponse(entry);
Header ageHdr = response.getFirstHeader("Age");
Assert.assertNotNull(ageHdr);
- Assert.assertEquals(currAge, Long.parseLong(ageHdr.getValue()));
+ Assert.assertEquals(10L, Long.parseLong(ageHdr.getValue()));
}
@Test
public void testAgeHeaderIsNotPopulatedIfCurrentAgeOfCacheEntryIsZero() {
- final long currAge = 0L;
+ currentAge(0L);
+ replayMocks();
- CacheEntry entry = buildEntryWithCurrentAge(currAge);
-
- CachedHttpResponseGenerator gen = new CachedHttpResponseGenerator();
- HttpResponse response = gen.generateResponse(entry);
+ HttpResponse response = impl.generateResponse(entry);
Header ageHdr = response.getFirstHeader("Age");
Assert.assertNull(ageHdr);
@@ -129,53 +134,19 @@ public class TestCachedHttpResponseGenerator {
@Test
public void testAgeHeaderIsPopulatedWithMaxAgeIfCurrentAgeTooBig() {
+ currentAge(CacheEntry.MAX_AGE + 1L);
+ replayMocks();
- CacheEntry entry = buildEntryWithCurrentAge(CacheEntry.MAX_AGE + 1L);
-
- CachedHttpResponseGenerator gen = new CachedHttpResponseGenerator();
- HttpResponse response = gen.generateResponse(entry);
+ HttpResponse response = impl.generateResponse(entry);
Header ageHdr = response.getFirstHeader("Age");
Assert.assertNotNull(ageHdr);
Assert.assertEquals(CacheEntry.MAX_AGE, Long.parseLong(ageHdr.getValue()));
}
- private CacheEntry buildEntry() {
- Date now = new Date();
- Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
- Date eightSecondsAgo = new Date(now.getTime() - 8 * 1000L);
- Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
- Date tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
- Header[] hdrs = { new BasicHeader("Date", DateUtils.formatDate(eightSecondsAgo)),
- new BasicHeader("Expires", DateUtils.formatDate(tenSecondsFromNow)),
- new BasicHeader("Content-Length", "150") };
-
- return new CacheEntry(tenSecondsAgo, sixSecondsAgo, new ProtocolVersion("HTTP", 1, 1),
- hdrs, new ByteArrayEntity(new byte[] {}), 200, "OK");
+ private void currentAge(long sec) {
+ EasyMock.expect(
+ mockValidityPolicy.getCurrentAgeSecs(entry)).andReturn(sec);
}
-
- private CacheEntry buildEntryWithCurrentAge(final long currAge){
- Date now = new Date();
- Date sixSecondsAgo = new Date(now.getTime() - 6 * 1000L);
- Date eightSecondsAgo = new Date(now.getTime() - 8 * 1000L);
- Date tenSecondsAgo = new Date(now.getTime() - 10 * 1000L);
- Date tenSecondsFromNow = new Date(now.getTime() + 10 * 1000L);
- Header[] hdrs = { new BasicHeader("Date", DateUtils.formatDate(eightSecondsAgo)),
- new BasicHeader("Expires", DateUtils.formatDate(tenSecondsFromNow)),
- new BasicHeader("Content-Length", "150") };
-
-
- return new CacheEntry(tenSecondsAgo, sixSecondsAgo, new ProtocolVersion("HTTP", 1, 1),
- hdrs, new ByteArrayEntity(new byte[] {}), 200, "OK"){
-
- private static final long serialVersionUID = 1L;
-
- @Override
- public long getCurrentAgeSecs() {
- return currAge;
- }
-
- };
- }
}
diff --git a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachedResponseSuitabilityChecker.java b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachedResponseSuitabilityChecker.java
index 4da6df57a..f2c13e652 100644
--- a/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachedResponseSuitabilityChecker.java
+++ b/httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestCachedResponseSuitabilityChecker.java
@@ -26,7 +26,6 @@
*/
package org.apache.http.impl.client.cache;
-import org.apache.http.Header;
import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.message.BasicHeader;
@@ -38,28 +37,28 @@ import org.junit.Test;
public class TestCachedResponseSuitabilityChecker {
- private CachedResponseSuitabilityChecker impl;
private HttpHost host;
private HttpRequest request;
- private CacheEntry mockEntry;
- private HttpRequest mockRequest;
+ private CacheEntry entry;
+ private CacheValidityPolicy mockValidityPolicy;
+ private CachedResponseSuitabilityChecker impl;
@Before
public void setUp() {
host = new HttpHost("foo.example.com");
request = new BasicHttpRequest("GET", "/foo");
- mockEntry = EasyMock.createMock(CacheEntry.class);
- mockRequest = EasyMock.createMock(HttpRequest.class);
+ mockValidityPolicy = EasyMock.createMock(CacheValidityPolicy.class);
+ entry = new CacheEntry();
- impl = new CachedResponseSuitabilityChecker();
+ impl = new CachedResponseSuitabilityChecker(mockValidityPolicy);
}
public void replayMocks() {
- EasyMock.replay(mockEntry, mockRequest);
+ EasyMock.replay(mockValidityPolicy);
}
public void verifyMocks() {
- EasyMock.verify(mockEntry, mockRequest);
+ EasyMock.verify(mockValidityPolicy);
}
@Test
@@ -68,7 +67,7 @@ public class TestCachedResponseSuitabilityChecker {
contentLengthMatchesActualLength(false);
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, request, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
@@ -82,7 +81,7 @@ public class TestCachedResponseSuitabilityChecker {
modifiedSince(false, request);
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, request, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
@@ -97,7 +96,7 @@ public class TestCachedResponseSuitabilityChecker {
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, request, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
@@ -109,7 +108,7 @@ public class TestCachedResponseSuitabilityChecker {
responseIsFresh(false);
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, request, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
@@ -125,7 +124,7 @@ public class TestCachedResponseSuitabilityChecker {
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, request, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
Assert.assertFalse(result);
}
@@ -136,11 +135,11 @@ public class TestCachedResponseSuitabilityChecker {
responseIsFresh(true);
contentLengthMatchesActualLength(true);
modifiedSince(false, request);
+ currentAge(20L);
- org.easymock.EasyMock.expect(mockEntry.getCurrentAgeSecs()).andReturn(20L);
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, request, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
Assert.assertFalse(result);
}
@@ -151,11 +150,11 @@ public class TestCachedResponseSuitabilityChecker {
responseIsFresh(true);
contentLengthMatchesActualLength(true);
modifiedSince(false, request);
+ currentAge(5L);
- org.easymock.EasyMock.expect(mockEntry.getCurrentAgeSecs()).andReturn(5L);
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, request, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
Assert.assertTrue(result);
}
@@ -166,11 +165,11 @@ public class TestCachedResponseSuitabilityChecker {
responseIsFresh(true);
contentLengthMatchesActualLength(true);
modifiedSince(false, request);
+ freshnessLifetime(15L);
- org.easymock.EasyMock.expect(mockEntry.getFreshnessLifetimeSecs()).andReturn(15L);
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, request, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
Assert.assertTrue(result);
}
@@ -181,11 +180,11 @@ public class TestCachedResponseSuitabilityChecker {
responseIsFresh(true);
contentLengthMatchesActualLength(true);
modifiedSince(false, request);
+ freshnessLifetime(5L);
- org.easymock.EasyMock.expect(mockEntry.getFreshnessLifetimeSecs()).andReturn(5L);
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, request, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
Assert.assertFalse(result);
}
@@ -199,23 +198,21 @@ public class TestCachedResponseSuitabilityChecker {
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, request, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
Assert.assertFalse(result);
}
@Test
public void testMalformedCacheControlMaxAgeRequestHeaderCausesUnsuitableEntry() {
-
- Header[] hdrs = new Header[] { new BasicHeader("Cache-Control", "max-age=foo") };
+ request.addHeader(new BasicHeader("Cache-Control", "max-age=foo"));
responseIsFresh(true);
contentLengthMatchesActualLength(true);
- modifiedSince(false, mockRequest);
+ modifiedSince(false, request);
- org.easymock.EasyMock.expect(mockRequest.getHeaders("Cache-Control")).andReturn(hdrs);
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, mockRequest, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
@@ -224,32 +221,43 @@ public class TestCachedResponseSuitabilityChecker {
@Test
public void testMalformedCacheControlMinFreshRequestHeaderCausesUnsuitableEntry() {
+ request.addHeader(new BasicHeader("Cache-Control", "min-fresh=foo"));
- Header[] hdrs = new Header[] { new BasicHeader("Cache-Control", "min-fresh=foo") };
responseIsFresh(true);
contentLengthMatchesActualLength(true);
- modifiedSince(false, mockRequest);
+ modifiedSince(false, request);
- org.easymock.EasyMock.expect(mockRequest.getHeaders("Cache-Control")).andReturn(hdrs);
replayMocks();
- boolean result = impl.canCachedResponseBeUsed(host, mockRequest, mockEntry);
+ boolean result = impl.canCachedResponseBeUsed(host, request, entry);
verifyMocks();
Assert.assertFalse(result);
}
+ private void currentAge(long sec) {
+ EasyMock.expect(
+ mockValidityPolicy.getCurrentAgeSecs(entry)).andReturn(sec);
+ }
+
+ private void freshnessLifetime(long sec) {
+ EasyMock.expect(
+ mockValidityPolicy.getFreshnessLifetimeSecs(entry)).andReturn(sec);
+ }
+
private void responseIsFresh(boolean fresh) {
- org.easymock.EasyMock.expect(mockEntry.isResponseFresh()).andReturn(fresh);
+ EasyMock.expect(
+ mockValidityPolicy.isResponseFresh(entry)).andReturn(fresh);
}
private void modifiedSince(boolean modified, HttpRequest request) {
- org.easymock.EasyMock.expect(mockEntry.modifiedSince(request)).andReturn(modified);
+ EasyMock.expect(
+ mockValidityPolicy.modifiedSince(entry, request)).andReturn(modified);
}
private void contentLengthMatchesActualLength(boolean b) {
- org.easymock.EasyMock.expect(mockEntry.contentLengthHeaderMatchesActualLength()).andReturn(
- b);
+ EasyMock.expect(
+ mockValidityPolicy.contentLengthHeaderMatchesActualLength(entry)).andReturn(b);
}
}
\ No newline at end of file
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 c446b8969..5df149a5a 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
@@ -50,6 +50,7 @@ import org.apache.http.client.ClientProtocolException;
import org.apache.http.client.HttpClient;
import org.apache.http.client.ResponseHandler;
import org.apache.http.client.cache.HttpCache;
+import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.methods.HttpGet;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
@@ -89,11 +90,13 @@ public class TestCachingHttpClient {
private static final String GET_RESPONSE_READER = "getResponseReader";
private CachingHttpClient impl;
+ private boolean mockedImpl;
private CacheInvalidator mockInvalidator;
+ private CacheValidityPolicy mockValidityPolicy;
private CacheableRequestPolicy mockRequestPolicy;
private HttpClient mockBackend;
- private HttpCache mockCache;
+ private HttpCache mockCache;
private CachedResponseSuitabilityChecker mockSuitabilityChecker;
private ResponseCachingPolicy mockResponsePolicy;
private HttpRequest mockRequest;
@@ -123,8 +126,6 @@ public class TestCachingHttpClient {
private Date requestDate;
private Date responseDate;
- private boolean mockedImpl;
-
private CacheEntryUpdater mockCacheEntryUpdater;
private ResponseProtocolCompliance mockResponseProtocolCompliance;
private RequestProtocolCompliance mockRequestProtocolCompliance;
@@ -136,6 +137,7 @@ public class TestCachingHttpClient {
mockInvalidator = EasyMock.createMock(CacheInvalidator.class);
mockRequestPolicy = EasyMock.createMock(CacheableRequestPolicy.class);
+ mockValidityPolicy = EasyMock.createMock(CacheValidityPolicy.class);
mockBackend = EasyMock.createMock(HttpClient.class);
mockCache = EasyMock.createMock(HttpCache.class);
mockSuitabilityChecker = EasyMock.createMock(CachedResponseSuitabilityChecker.class);
@@ -168,7 +170,7 @@ public class TestCachingHttpClient {
requestDate = new Date(System.currentTimeMillis() - 1000);
responseDate = new Date();
host = new HttpHost("foo.example.com");
- impl = new CachingHttpClient(mockBackend, mockResponsePolicy, mockEntryGenerator,
+ impl = new CachingHttpClient(mockBackend, mockValidityPolicy, mockResponsePolicy, mockEntryGenerator,
mockExtractor, mockCache, mockResponseGenerator, mockInvalidator,
mockRequestPolicy, mockSuitabilityChecker, mockConditionalRequestBuilder,
mockCacheEntryUpdater, mockResponseProtocolCompliance,
@@ -179,6 +181,7 @@ public class TestCachingHttpClient {
EasyMock.replay(mockInvalidator);
EasyMock.replay(mockRequestPolicy);
+ EasyMock.replay(mockValidityPolicy);
EasyMock.replay(mockSuitabilityChecker);
EasyMock.replay(mockResponsePolicy);
EasyMock.replay(mockCacheEntry);
@@ -204,7 +207,6 @@ public class TestCachingHttpClient {
EasyMock.replay(mockReconstructedResponse);
EasyMock.replay(mockResponseProtocolCompliance);
EasyMock.replay(mockRequestProtocolCompliance);
-
if (mockedImpl) {
EasyMock.replay(impl);
}
@@ -213,6 +215,7 @@ public class TestCachingHttpClient {
private void verifyMocks() {
EasyMock.verify(mockInvalidator);
EasyMock.verify(mockRequestPolicy);
+ EasyMock.verify(mockValidityPolicy);
EasyMock.verify(mockSuitabilityChecker);
EasyMock.verify(mockResponsePolicy);
EasyMock.verify(mockCacheEntry);
@@ -238,7 +241,6 @@ public class TestCachingHttpClient {
EasyMock.verify(mockReconstructedResponse);
EasyMock.verify(mockResponseProtocolCompliance);
EasyMock.verify(mockRequestProtocolCompliance);
-
if (mockedImpl) {
EasyMock.verify(impl);
}
@@ -288,7 +290,7 @@ public class TestCachingHttpClient {
}
private void requestInspectsRequestLine() {
- org.easymock.EasyMock.expect(mockRequest.getRequestLine()).andReturn(mockRequestLine);
+ EasyMock.expect(mockRequest.getRequestLine()).andReturn(mockRequestLine);
}
private void requestIsFatallyNonCompliant(RequestProtocolError error) {
@@ -296,7 +298,7 @@ public class TestCachingHttpClient {
if (error != null) {
errors.add(error);
}
- org.easymock.EasyMock.expect(
+ EasyMock.expect(
mockRequestProtocolCompliance.requestIsFatallyNonCompliant(mockRequest)).andReturn(
errors);
}
@@ -320,12 +322,12 @@ public class TestCachingHttpClient {
final String variantURI = "variantURI";
- final CacheEntry entry = new CacheEntry(new Date(), new Date(), HTTP_1_1,
- new Header[] {}, new ByteArrayEntity(new byte[] {}), 200, "OK");
+ final CacheEntry entry = new CacheEntry(new Date(), new Date(), new OKStatus(),
+ new Header[] {}, new ByteArrayEntity(new byte[] {}));
replayMocks();
- CacheEntry updatedEntry = impl.doGetUpdatedParentEntry(null, entry, variantURI);
+ HttpCacheEntry updatedEntry = impl.doGetUpdatedParentEntry(null, entry, variantURI);
verifyMocks();
@@ -518,7 +520,7 @@ public class TestCachingHttpClient {
gotCacheMiss(theURI);
replayMocks();
- CacheEntry result = impl.getCacheEntry(host, mockRequest);
+ HttpCacheEntry result = impl.getCacheEntry(host, mockRequest);
verifyMocks();
Assert.assertNull(result);
}
@@ -532,7 +534,7 @@ public class TestCachingHttpClient {
cacheEntryHasVariants(false);
replayMocks();
- CacheEntry result = impl.getCacheEntry(host, mockRequest);
+ HttpCacheEntry result = impl.getCacheEntry(host, mockRequest);
verifyMocks();
Assert.assertSame(mockCacheEntry, result);
}
@@ -549,7 +551,7 @@ public class TestCachingHttpClient {
gotCacheMiss(variantURI);
replayMocks();
- CacheEntry result = impl.getCacheEntry(host, mockRequest);
+ HttpCacheEntry result = impl.getCacheEntry(host, mockRequest);
verifyMocks();
Assert.assertNull(result);
}
@@ -566,7 +568,7 @@ public class TestCachingHttpClient {
gotCacheHit(variantURI, mockVariantCacheEntry);
replayMocks();
- CacheEntry result = impl.getCacheEntry(host, mockRequest);
+ HttpCacheEntry result = impl.getCacheEntry(host, mockRequest);
verifyMocks();
Assert.assertSame(mockVariantCacheEntry, result);
}
@@ -624,7 +626,7 @@ public class TestCachingHttpClient {
final HttpHost theHost = host;
final HttpRequest theRequest = mockRequest;
final HttpResponse theResponse = mockBackendResponse;
- impl = new CachingHttpClient(mockBackend, mockResponsePolicy, mockEntryGenerator,
+ impl = new CachingHttpClient(mockBackend, mockValidityPolicy, mockResponsePolicy, mockEntryGenerator,
mockExtractor, mockCache, mockResponseGenerator, mockInvalidator,
mockRequestPolicy, mockSuitabilityChecker, mockConditionalRequestBuilder,
mockCacheEntryUpdater, mockResponseProtocolCompliance,
@@ -656,7 +658,7 @@ public class TestCachingHttpClient {
final HttpResponse theResponse = mockBackendResponse;
final ResponseHandler