HTTPCLIENT-979: cache entry resource management extracted from CachingHttpClient
Contributed by Jonathan Moore <jonathan_moore at comcast.com> git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@986864 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
parent
5c33d5cfd9
commit
83c2c00109
|
@ -27,19 +27,34 @@
|
|||
package org.apache.http.client.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.Date;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public interface HttpCache {
|
||||
|
||||
void putEntry(String key, HttpCacheEntry entry) throws IOException;
|
||||
void flushCacheEntriesFor(HttpHost host, HttpRequest request)
|
||||
throws IOException;
|
||||
|
||||
HttpCacheEntry getEntry(String key) throws IOException;
|
||||
void flushInvalidatedCacheEntriesFor(HttpHost host, HttpRequest request)
|
||||
throws IOException;
|
||||
|
||||
void removeEntry(String key) throws IOException;
|
||||
HttpCacheEntry getCacheEntry(HttpHost host, HttpRequest request)
|
||||
throws IOException;
|
||||
|
||||
void updateEntry(
|
||||
String key, HttpCacheUpdateCallback callback) throws IOException;
|
||||
HttpResponse cacheAndReturnResponse(
|
||||
HttpHost host, HttpRequest request, HttpResponse originResponse,
|
||||
Date requestSent, Date responseReceived)
|
||||
throws IOException;
|
||||
|
||||
HttpResponse updateCacheEntry(
|
||||
HttpHost target, HttpRequest request, HttpCacheEntry stale, HttpResponse originResponse,
|
||||
Date requestSent, Date responseReceived)
|
||||
throws IOException;
|
||||
|
||||
}
|
||||
|
|
45
httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheStorage.java
vendored
Normal file
45
httpclient-cache/src/main/java/org/apache/http/client/cache/HttpCacheStorage.java
vendored
Normal file
|
@ -0,0 +1,45 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.http.client.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
/**
|
||||
* @since 4.1
|
||||
*/
|
||||
public interface HttpCacheStorage {
|
||||
|
||||
void putEntry(String key, HttpCacheEntry entry) throws IOException;
|
||||
|
||||
HttpCacheEntry getEntry(String key) throws IOException;
|
||||
|
||||
void removeEntry(String key) throws IOException;
|
||||
|
||||
void updateEntry(
|
||||
String key, HttpCacheUpdateCallback callback) throws IOException;
|
||||
|
||||
}
|
|
@ -1,93 +1,204 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.http.annotation.ThreadSafe;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.HttpVersion;
|
||||
import org.apache.http.client.cache.HttpCache;
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
import org.apache.http.client.cache.HttpCacheStorage;
|
||||
import org.apache.http.client.cache.HttpCacheUpdateCallback;
|
||||
import org.apache.http.client.cache.Resource;
|
||||
import org.apache.http.client.cache.ResourceFactory;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.message.BasicHttpResponse;
|
||||
|
||||
/**
|
||||
* Basic {@link HttpCache} implementation backed by an instance of {@link LinkedHashMap}.
|
||||
* This cache does NOT deallocate resources associated with the cache entries. It is intended
|
||||
* for use with {@link MemCacheEntry} and similar.
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class BasicHttpCache implements HttpCache {
|
||||
|
||||
private final CacheMap entries;
|
||||
private final URIExtractor uriExtractor;
|
||||
private final ResourceFactory resourceFactory;
|
||||
private final int maxObjectSizeBytes;
|
||||
private final CacheEntryUpdater cacheEntryUpdater;
|
||||
private final CachedHttpResponseGenerator responseGenerator;
|
||||
private final CacheInvalidator cacheInvalidator;
|
||||
private final HttpCacheStorage storage;
|
||||
|
||||
public BasicHttpCache(int maxEntries) {
|
||||
this.entries = new CacheMap(maxEntries);
|
||||
public BasicHttpCache(ResourceFactory resourceFactory, HttpCacheStorage storage, CacheConfig config) {
|
||||
this.resourceFactory = resourceFactory;
|
||||
this.uriExtractor = new URIExtractor();
|
||||
this.cacheEntryUpdater = new CacheEntryUpdater(resourceFactory);
|
||||
this.maxObjectSizeBytes = config.getMaxObjectSizeBytes();
|
||||
this.responseGenerator = new CachedHttpResponseGenerator();
|
||||
this.storage = storage;
|
||||
this.cacheInvalidator = new CacheInvalidator(this.uriExtractor, this.storage);
|
||||
}
|
||||
|
||||
/**
|
||||
* Places a HttpCacheEntry in the cache
|
||||
*
|
||||
* @param url
|
||||
* Url to use as the cache key
|
||||
* @param entry
|
||||
* HttpCacheEntry to place in the cache
|
||||
*/
|
||||
public synchronized void putEntry(String url, HttpCacheEntry entry) throws IOException {
|
||||
entries.put(url, entry);
|
||||
public BasicHttpCache(CacheConfig config) {
|
||||
this(new HeapResourceFactory(), new BasicHttpCacheStorage(config), config);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an entry from the cache, if it exists
|
||||
*
|
||||
* @param url
|
||||
* Url that is the cache key
|
||||
* @return HttpCacheEntry if one exists, or null for cache miss
|
||||
*/
|
||||
public synchronized HttpCacheEntry getEntry(String url) throws IOException {
|
||||
return entries.get(url);
|
||||
public BasicHttpCache() {
|
||||
this(new CacheConfig());
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a HttpCacheEntry from the cache
|
||||
*
|
||||
* @param url
|
||||
* Url that is the cache key
|
||||
*/
|
||||
public synchronized void removeEntry(String url) throws IOException {
|
||||
entries.remove(url);
|
||||
public void flushCacheEntriesFor(HttpHost host, HttpRequest request)
|
||||
throws IOException {
|
||||
String uri = uriExtractor.getURI(host, request);
|
||||
storage.removeEntry(uri);
|
||||
}
|
||||
|
||||
public synchronized void updateEntry(
|
||||
String url,
|
||||
HttpCacheUpdateCallback callback) throws IOException {
|
||||
HttpCacheEntry existingEntry = entries.get(url);
|
||||
entries.put(url, callback.update(existingEntry));
|
||||
void storeInCache(
|
||||
HttpHost target, HttpRequest request, HttpCacheEntry entry) throws IOException {
|
||||
if (entry.hasVariants()) {
|
||||
storeVariantEntry(target, request, entry);
|
||||
} else {
|
||||
storeNonVariantEntry(target, request, entry);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
void storeNonVariantEntry(
|
||||
HttpHost target, HttpRequest req, HttpCacheEntry entry) throws IOException {
|
||||
String uri = uriExtractor.getURI(target, req);
|
||||
storage.putEntry(uri, entry);
|
||||
}
|
||||
|
||||
void storeVariantEntry(
|
||||
final HttpHost target,
|
||||
final HttpRequest req,
|
||||
final HttpCacheEntry entry) throws IOException {
|
||||
final String parentURI = uriExtractor.getURI(target, req);
|
||||
final String variantURI = uriExtractor.getVariantURI(target, req, entry);
|
||||
storage.putEntry(variantURI, entry);
|
||||
|
||||
HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() {
|
||||
|
||||
public HttpCacheEntry update(HttpCacheEntry existing) throws IOException {
|
||||
return doGetUpdatedParentEntry(
|
||||
req.getRequestLine().getUri(), existing, entry, variantURI);
|
||||
}
|
||||
|
||||
};
|
||||
storage.updateEntry(parentURI, callback);
|
||||
}
|
||||
|
||||
|
||||
boolean isIncompleteResponse(HttpResponse resp, Resource resource) {
|
||||
int status = resp.getStatusLine().getStatusCode();
|
||||
if (status != HttpStatus.SC_OK
|
||||
&& status != HttpStatus.SC_PARTIAL_CONTENT) {
|
||||
return false;
|
||||
}
|
||||
Header hdr = resp.getFirstHeader("Content-Length");
|
||||
if (hdr == null) return false;
|
||||
int contentLength;
|
||||
try {
|
||||
contentLength = Integer.parseInt(hdr.getValue());
|
||||
} catch (NumberFormatException nfe) {
|
||||
return false;
|
||||
}
|
||||
return (resource.length() < contentLength);
|
||||
}
|
||||
|
||||
HttpResponse generateIncompleteResponseError(HttpResponse response,
|
||||
Resource resource) {
|
||||
int contentLength = Integer.parseInt(response.getFirstHeader("Content-Length").getValue());
|
||||
HttpResponse error =
|
||||
new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_GATEWAY, "Bad Gateway");
|
||||
error.setHeader("Content-Type","text/plain;charset=UTF-8");
|
||||
String msg = String.format("Received incomplete response " +
|
||||
"with Content-Length %d but actual body length %d",
|
||||
contentLength, resource.length());
|
||||
byte[] msgBytes = msg.getBytes();
|
||||
error.setHeader("Content-Length", Integer.toString(msgBytes.length));
|
||||
error.setEntity(new ByteArrayEntity(msgBytes));
|
||||
return error;
|
||||
}
|
||||
|
||||
HttpCacheEntry doGetUpdatedParentEntry(
|
||||
final String requestId,
|
||||
final HttpCacheEntry existing,
|
||||
final HttpCacheEntry entry,
|
||||
final String variantURI) throws IOException {
|
||||
HttpCacheEntry src = existing;
|
||||
if (src == null) {
|
||||
src = entry;
|
||||
}
|
||||
Set<String> variants = new HashSet<String>(src.getVariantURIs());
|
||||
variants.add(variantURI);
|
||||
Resource resource = resourceFactory.copy(requestId, src.getResource());
|
||||
return new HttpCacheEntry(
|
||||
src.getRequestDate(),
|
||||
src.getResponseDate(),
|
||||
src.getStatusLine(),
|
||||
src.getAllHeaders(),
|
||||
resource,
|
||||
variants);
|
||||
}
|
||||
|
||||
public HttpResponse updateCacheEntry(HttpHost target, HttpRequest request,
|
||||
HttpCacheEntry stale, HttpResponse originResponse,
|
||||
Date requestSent, Date responseReceived) throws IOException {
|
||||
HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry(
|
||||
request.getRequestLine().getUri(),
|
||||
stale,
|
||||
requestSent,
|
||||
responseReceived,
|
||||
originResponse);
|
||||
storeInCache(target, request, updatedEntry);
|
||||
return responseGenerator.generateResponse(updatedEntry);
|
||||
}
|
||||
|
||||
public HttpResponse cacheAndReturnResponse(HttpHost host, HttpRequest request,
|
||||
HttpResponse originResponse, Date requestSent, Date responseReceived)
|
||||
throws IOException {
|
||||
|
||||
SizeLimitedResponseReader responseReader = getResponseReader(request, originResponse);
|
||||
responseReader.readResponse();
|
||||
|
||||
if (responseReader.isLimitReached()) {
|
||||
return responseReader.getReconstructedResponse();
|
||||
}
|
||||
|
||||
Resource resource = responseReader.getResource();
|
||||
if (isIncompleteResponse(originResponse, resource)) {
|
||||
return generateIncompleteResponseError(originResponse, resource);
|
||||
}
|
||||
|
||||
HttpCacheEntry entry = new HttpCacheEntry(
|
||||
requestSent,
|
||||
responseReceived,
|
||||
originResponse.getStatusLine(),
|
||||
originResponse.getAllHeaders(),
|
||||
resource,
|
||||
null);
|
||||
storeInCache(host, request, entry);
|
||||
return responseGenerator.generateResponse(entry);
|
||||
}
|
||||
|
||||
SizeLimitedResponseReader getResponseReader(HttpRequest request, HttpResponse backEndResponse) {
|
||||
return new SizeLimitedResponseReader(
|
||||
resourceFactory, maxObjectSizeBytes, request, backEndResponse);
|
||||
}
|
||||
|
||||
public HttpCacheEntry getCacheEntry(HttpHost host, HttpRequest request) throws IOException {
|
||||
HttpCacheEntry root = storage.getEntry(uriExtractor.getURI(host, request));
|
||||
if (root == null) return null;
|
||||
if (!root.hasVariants()) return root;
|
||||
HttpCacheEntry variant = storage.getEntry(uriExtractor.getVariantURI(host, request, root));
|
||||
return variant;
|
||||
}
|
||||
|
||||
public void flushInvalidatedCacheEntriesFor(HttpHost host,
|
||||
HttpRequest request) throws IOException {
|
||||
cacheInvalidator.flushInvalidatedCacheEntries(host, request);
|
||||
|
||||
}
|
||||
|
||||
}
|
94
httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheStorage.java
vendored
Normal file
94
httpclient-cache/src/main/java/org/apache/http/impl/client/cache/BasicHttpCacheStorage.java
vendored
Normal file
|
@ -0,0 +1,94 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.LinkedHashMap;
|
||||
|
||||
import org.apache.http.annotation.ThreadSafe;
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
import org.apache.http.client.cache.HttpCacheStorage;
|
||||
import org.apache.http.client.cache.HttpCacheUpdateCallback;
|
||||
|
||||
/**
|
||||
* Basic {@link HttpCacheStorage} implementation backed by an instance of {@link LinkedHashMap}.
|
||||
* This cache does NOT deallocate resources associated with the cache entries. It is intended
|
||||
* for use with {@link MemCacheEntry} and similar.
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class BasicHttpCacheStorage implements HttpCacheStorage {
|
||||
|
||||
private final CacheMap entries;
|
||||
|
||||
public BasicHttpCacheStorage(CacheConfig config) {
|
||||
super();
|
||||
this.entries = new CacheMap(config.getMaxCacheEntries());
|
||||
}
|
||||
|
||||
/**
|
||||
* Places a HttpCacheEntry in the cache
|
||||
*
|
||||
* @param url
|
||||
* Url to use as the cache key
|
||||
* @param entry
|
||||
* HttpCacheEntry to place in the cache
|
||||
*/
|
||||
public synchronized void putEntry(String url, HttpCacheEntry entry) throws IOException {
|
||||
entries.put(url, entry);
|
||||
}
|
||||
|
||||
/**
|
||||
* Gets an entry from the cache, if it exists
|
||||
*
|
||||
* @param url
|
||||
* Url that is the cache key
|
||||
* @return HttpCacheEntry if one exists, or null for cache miss
|
||||
*/
|
||||
public synchronized HttpCacheEntry getEntry(String url) throws IOException {
|
||||
return entries.get(url);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a HttpCacheEntry from the cache
|
||||
*
|
||||
* @param url
|
||||
* Url that is the cache key
|
||||
*/
|
||||
public synchronized void removeEntry(String url) throws IOException {
|
||||
entries.remove(url);
|
||||
}
|
||||
|
||||
public synchronized void updateEntry(
|
||||
String url,
|
||||
HttpCacheUpdateCallback callback) throws IOException {
|
||||
HttpCacheEntry existingEntry = entries.get(url);
|
||||
entries.put(url, callback.update(existingEntry));
|
||||
}
|
||||
|
||||
}
|
|
@ -37,7 +37,14 @@ public class CacheConfig {
|
|||
*/
|
||||
public final static int DEFAULT_MAX_OBJECT_SIZE_BYTES = 8192;
|
||||
|
||||
/** Default setting for the maximum number of cache entries
|
||||
* that will be retained.
|
||||
*/
|
||||
public final static int DEFAULT_MAX_CACHE_ENTRIES = 1000;
|
||||
|
||||
private int maxObjectSizeBytes = DEFAULT_MAX_OBJECT_SIZE_BYTES;
|
||||
private int maxCacheEntries = DEFAULT_MAX_CACHE_ENTRIES;
|
||||
|
||||
private boolean isSharedCache = true;
|
||||
|
||||
/**
|
||||
|
@ -74,4 +81,19 @@ public class CacheConfig {
|
|||
this.isSharedCache = isSharedCache;
|
||||
}
|
||||
|
||||
/**
|
||||
* Returns the maximum number of cache entries the cache will retain.
|
||||
* @return int
|
||||
*/
|
||||
public int getMaxCacheEntries() {
|
||||
return maxCacheEntries;
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the maximum number of cache entries the cache will retain.
|
||||
* @param maxCacheEntries int
|
||||
*/
|
||||
public void setMaxCacheEntries(int maxCacheEntries) {
|
||||
this.maxCacheEntries = maxCacheEntries;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -40,6 +40,7 @@ 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.HttpCacheStorage;
|
||||
|
||||
/**
|
||||
* Given a particular HttpRequest, flush any cache entries that this request
|
||||
|
@ -50,7 +51,7 @@ import org.apache.http.client.cache.HttpCacheEntry;
|
|||
@ThreadSafe // so long as the cache implementation is thread-safe
|
||||
class CacheInvalidator {
|
||||
|
||||
private final HttpCache cache;
|
||||
private final HttpCacheStorage storage;
|
||||
private final URIExtractor uriExtractor;
|
||||
|
||||
private final Log log = LogFactory.getLog(getClass());
|
||||
|
@ -60,13 +61,13 @@ class CacheInvalidator {
|
|||
* {@link URIExtractor}.
|
||||
*
|
||||
* @param uriExtractor Provides identifiers for the keys to store cache entries
|
||||
* @param cache the cache to store items away in
|
||||
* @param storage the cache to store items away in
|
||||
*/
|
||||
public CacheInvalidator(
|
||||
final URIExtractor uriExtractor,
|
||||
final HttpCache cache) {
|
||||
final HttpCacheStorage storage) {
|
||||
this.uriExtractor = uriExtractor;
|
||||
this.cache = cache;
|
||||
this.storage = storage;
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -82,15 +83,15 @@ class CacheInvalidator {
|
|||
|
||||
String theUri = uriExtractor.getURI(host, req);
|
||||
|
||||
HttpCacheEntry parent = cache.getEntry(theUri);
|
||||
HttpCacheEntry parent = storage.getEntry(theUri);
|
||||
|
||||
log.debug("parent entry: " + parent);
|
||||
|
||||
if (parent != null) {
|
||||
for (String variantURI : parent.getVariantURIs()) {
|
||||
cache.removeEntry(variantURI);
|
||||
storage.removeEntry(variantURI);
|
||||
}
|
||||
cache.removeEntry(theUri);
|
||||
storage.removeEntry(theUri);
|
||||
}
|
||||
URL reqURL;
|
||||
try {
|
||||
|
@ -115,7 +116,7 @@ class CacheInvalidator {
|
|||
|
||||
protected void flushUriIfSameHost(URL requestURL, URL targetURL) throws IOException {
|
||||
if (targetURL.getAuthority().equalsIgnoreCase(requestURL.getAuthority())) {
|
||||
cache.removeEntry(targetURL.toString());
|
||||
storage.removeEntry(targetURL.toString());
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -29,14 +29,11 @@ package org.apache.http.impl.client.cache;
|
|||
import java.io.IOException;
|
||||
import java.net.URI;
|
||||
import java.util.Date;
|
||||
import java.util.HashSet;
|
||||
import java.util.List;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.atomic.AtomicLong;
|
||||
|
||||
import org.apache.commons.logging.Log;
|
||||
import org.apache.commons.logging.LogFactory;
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
|
@ -52,12 +49,8 @@ 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.HttpCacheUpdateCallback;
|
||||
import org.apache.http.client.cache.Resource;
|
||||
import org.apache.http.client.cache.ResourceFactory;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.impl.client.DefaultHttpClient;
|
||||
import org.apache.http.message.BasicHttpResponse;
|
||||
import org.apache.http.message.BasicStatusLine;
|
||||
|
@ -70,7 +63,6 @@ import org.apache.http.protocol.HttpContext;
|
|||
@ThreadSafe // So long as the responseCache implementation is threadsafe
|
||||
public class CachingHttpClient implements HttpClient {
|
||||
|
||||
private final static int MAX_CACHE_ENTRIES = 1000;
|
||||
private final static boolean SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS = false;
|
||||
|
||||
private final AtomicLong cacheHits = new AtomicLong();
|
||||
|
@ -79,19 +71,14 @@ public class CachingHttpClient implements HttpClient {
|
|||
|
||||
private final HttpClient backend;
|
||||
private final HttpCache responseCache;
|
||||
private final ResourceFactory resourceFactory;
|
||||
private final CacheValidityPolicy validityPolicy;
|
||||
private final ResponseCachingPolicy responseCachingPolicy;
|
||||
private final URIExtractor uriExtractor;
|
||||
private final CachedHttpResponseGenerator responseGenerator;
|
||||
private final CacheInvalidator cacheInvalidator;
|
||||
private final CacheableRequestPolicy cacheableRequestPolicy;
|
||||
private final CachedResponseSuitabilityChecker suitabilityChecker;
|
||||
|
||||
private final ConditionalRequestBuilder conditionalRequestBuilder;
|
||||
|
||||
private final CacheEntryUpdater cacheEntryUpdater;
|
||||
|
||||
private final int maxObjectSizeBytes;
|
||||
private final boolean sharedCache;
|
||||
|
||||
|
@ -103,7 +90,6 @@ public class CachingHttpClient implements HttpClient {
|
|||
public CachingHttpClient(
|
||||
HttpClient client,
|
||||
HttpCache cache,
|
||||
ResourceFactory resourceFactory,
|
||||
CacheConfig config) {
|
||||
super();
|
||||
if (client == null) {
|
||||
|
@ -112,9 +98,6 @@ public class CachingHttpClient implements HttpClient {
|
|||
if (cache == null) {
|
||||
throw new IllegalArgumentException("HttpCache may not be null");
|
||||
}
|
||||
if (resourceFactory == null) {
|
||||
throw new IllegalArgumentException("ResourceFactory may not be null");
|
||||
}
|
||||
if (config == null) {
|
||||
throw new IllegalArgumentException("CacheConfig may not be null");
|
||||
}
|
||||
|
@ -122,16 +105,12 @@ public class CachingHttpClient implements HttpClient {
|
|||
this.sharedCache = config.isSharedCache();
|
||||
this.backend = client;
|
||||
this.responseCache = cache;
|
||||
this.resourceFactory = resourceFactory;
|
||||
this.validityPolicy = new CacheValidityPolicy();
|
||||
this.responseCachingPolicy = new ResponseCachingPolicy(maxObjectSizeBytes, sharedCache);
|
||||
this.responseGenerator = new CachedHttpResponseGenerator(this.validityPolicy);
|
||||
this.uriExtractor = new URIExtractor();
|
||||
this.cacheInvalidator = new CacheInvalidator(this.uriExtractor, this.responseCache);
|
||||
this.cacheableRequestPolicy = new CacheableRequestPolicy();
|
||||
this.suitabilityChecker = new CachedResponseSuitabilityChecker(this.validityPolicy);
|
||||
this.conditionalRequestBuilder = new ConditionalRequestBuilder();
|
||||
this.cacheEntryUpdater = new CacheEntryUpdater(this.resourceFactory);
|
||||
|
||||
this.responseCompliance = new ResponseProtocolCompliance();
|
||||
this.requestCompliance = new RequestProtocolCompliance();
|
||||
|
@ -139,91 +118,73 @@ public class CachingHttpClient implements HttpClient {
|
|||
|
||||
public CachingHttpClient() {
|
||||
this(new DefaultHttpClient(),
|
||||
new BasicHttpCache(MAX_CACHE_ENTRIES),
|
||||
new HeapResourceFactory(),
|
||||
new BasicHttpCache(),
|
||||
new CacheConfig());
|
||||
}
|
||||
|
||||
public CachingHttpClient(CacheConfig config) {
|
||||
this(new DefaultHttpClient(),
|
||||
new BasicHttpCache(MAX_CACHE_ENTRIES),
|
||||
new HeapResourceFactory(),
|
||||
new BasicHttpCache(config),
|
||||
config);
|
||||
}
|
||||
|
||||
public CachingHttpClient(HttpClient client) {
|
||||
this(client,
|
||||
new BasicHttpCache(MAX_CACHE_ENTRIES),
|
||||
new HeapResourceFactory(),
|
||||
new BasicHttpCache(),
|
||||
new CacheConfig());
|
||||
}
|
||||
|
||||
public CachingHttpClient(HttpClient client, CacheConfig config) {
|
||||
this(client,
|
||||
new BasicHttpCache(MAX_CACHE_ENTRIES),
|
||||
new HeapResourceFactory(),
|
||||
new BasicHttpCache(config),
|
||||
config);
|
||||
}
|
||||
|
||||
public CachingHttpClient(
|
||||
HttpCache cache,
|
||||
ResourceFactory resourceFactory) {
|
||||
HttpCache cache) {
|
||||
this(new DefaultHttpClient(),
|
||||
cache,
|
||||
resourceFactory,
|
||||
new CacheConfig());
|
||||
}
|
||||
|
||||
public CachingHttpClient(
|
||||
HttpCache cache,
|
||||
ResourceFactory resourceFactory,
|
||||
CacheConfig config) {
|
||||
this(new DefaultHttpClient(),
|
||||
cache,
|
||||
resourceFactory,
|
||||
config);
|
||||
}
|
||||
|
||||
public CachingHttpClient(
|
||||
HttpClient client,
|
||||
HttpCache cache,
|
||||
ResourceFactory resourceFactory) {
|
||||
HttpCache cache) {
|
||||
this(client,
|
||||
cache,
|
||||
resourceFactory,
|
||||
new CacheConfig());
|
||||
}
|
||||
|
||||
CachingHttpClient(
|
||||
HttpClient backend,
|
||||
ResourceFactory resourceFactory,
|
||||
CacheValidityPolicy validityPolicy,
|
||||
ResponseCachingPolicy responseCachingPolicy,
|
||||
URIExtractor uriExtractor,
|
||||
HttpCache responseCache,
|
||||
CachedHttpResponseGenerator responseGenerator,
|
||||
CacheInvalidator cacheInvalidator,
|
||||
CacheableRequestPolicy cacheableRequestPolicy,
|
||||
CachedResponseSuitabilityChecker suitabilityChecker,
|
||||
ConditionalRequestBuilder conditionalRequestBuilder,
|
||||
CacheEntryUpdater entryUpdater,
|
||||
ResponseProtocolCompliance responseCompliance,
|
||||
RequestProtocolCompliance requestCompliance) {
|
||||
CacheConfig config = new CacheConfig();
|
||||
this.maxObjectSizeBytes = config.getMaxObjectSizeBytes();
|
||||
this.sharedCache = config.isSharedCache();
|
||||
this.backend = backend;
|
||||
this.resourceFactory = resourceFactory;
|
||||
this.validityPolicy = validityPolicy;
|
||||
this.responseCachingPolicy = responseCachingPolicy;
|
||||
this.uriExtractor = uriExtractor;
|
||||
this.responseCache = responseCache;
|
||||
this.responseGenerator = responseGenerator;
|
||||
this.cacheInvalidator = cacheInvalidator;
|
||||
this.cacheableRequestPolicy = cacheableRequestPolicy;
|
||||
this.suitabilityChecker = suitabilityChecker;
|
||||
this.conditionalRequestBuilder = conditionalRequestBuilder;
|
||||
this.cacheEntryUpdater = entryUpdater;
|
||||
this.responseCompliance = responseCompliance;
|
||||
this.requestCompliance = requestCompliance;
|
||||
}
|
||||
|
@ -409,13 +370,13 @@ public class CachingHttpClient implements HttpClient {
|
|||
throw new ClientProtocolException(e);
|
||||
}
|
||||
|
||||
cacheInvalidator.flushInvalidatedCacheEntries(target, request);
|
||||
responseCache.flushInvalidatedCacheEntriesFor(target, request);
|
||||
|
||||
if (!cacheableRequestPolicy.isServableFromCache(request)) {
|
||||
return callBackend(target, request, context);
|
||||
}
|
||||
|
||||
HttpCacheEntry entry = getCacheEntry(target, request);
|
||||
HttpCacheEntry entry = responseCache.getCacheEntry(target, request);
|
||||
if (entry == null) {
|
||||
cacheMisses.getAndIncrement();
|
||||
if (log.isDebugEnabled()) {
|
||||
|
@ -471,18 +432,6 @@ public class CachingHttpClient implements HttpClient {
|
|||
return new Date();
|
||||
}
|
||||
|
||||
HttpCacheEntry getCacheEntry(HttpHost target, HttpRequest request) throws IOException {
|
||||
String uri = uriExtractor.getURI(target, request);
|
||||
HttpCacheEntry entry = responseCache.getEntry(uri);
|
||||
|
||||
if (entry == null || !entry.hasVariants()) {
|
||||
return entry;
|
||||
}
|
||||
|
||||
String variantUri = uriExtractor.getVariantURI(target, request, entry);
|
||||
return responseCache.getEntry(variantUri);
|
||||
}
|
||||
|
||||
boolean clientRequestsOurOptions(HttpRequest request) {
|
||||
RequestLine line = request.getRequestLine();
|
||||
|
||||
|
@ -533,101 +482,14 @@ public class CachingHttpClient implements HttpClient {
|
|||
int statusCode = backendResponse.getStatusLine().getStatusCode();
|
||||
if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
|
||||
cacheUpdates.getAndIncrement();
|
||||
HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry(
|
||||
request.getRequestLine().getUri(),
|
||||
cacheEntry,
|
||||
requestDate,
|
||||
responseDate,
|
||||
backendResponse);
|
||||
storeInCache(target, request, updatedEntry);
|
||||
return responseGenerator.generateResponse(updatedEntry);
|
||||
return responseCache.updateCacheEntry(target, request, cacheEntry,
|
||||
backendResponse, requestDate, responseDate);
|
||||
}
|
||||
|
||||
return handleBackendResponse(target, conditionalRequest, requestDate, responseDate,
|
||||
backendResponse);
|
||||
}
|
||||
|
||||
void storeInCache(
|
||||
HttpHost target, HttpRequest request, HttpCacheEntry entry) throws IOException {
|
||||
if (entry.hasVariants()) {
|
||||
storeVariantEntry(target, request, entry);
|
||||
} else {
|
||||
storeNonVariantEntry(target, request, entry);
|
||||
}
|
||||
}
|
||||
|
||||
void storeNonVariantEntry(
|
||||
HttpHost target, HttpRequest req, HttpCacheEntry entry) throws IOException {
|
||||
String uri = uriExtractor.getURI(target, req);
|
||||
responseCache.putEntry(uri, entry);
|
||||
}
|
||||
|
||||
void storeVariantEntry(
|
||||
final HttpHost target,
|
||||
final HttpRequest req,
|
||||
final HttpCacheEntry entry) throws IOException {
|
||||
final String parentURI = uriExtractor.getURI(target, req);
|
||||
final String variantURI = uriExtractor.getVariantURI(target, req, entry);
|
||||
responseCache.putEntry(variantURI, entry);
|
||||
|
||||
HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() {
|
||||
|
||||
public HttpCacheEntry update(HttpCacheEntry existing) throws IOException {
|
||||
return doGetUpdatedParentEntry(
|
||||
req.getRequestLine().getUri(), existing, entry, variantURI);
|
||||
}
|
||||
|
||||
};
|
||||
responseCache.updateEntry(parentURI, callback);
|
||||
}
|
||||
|
||||
HttpCacheEntry doGetUpdatedParentEntry(
|
||||
final String requestId,
|
||||
final HttpCacheEntry existing,
|
||||
final HttpCacheEntry entry,
|
||||
final String variantURI) throws IOException {
|
||||
HttpCacheEntry src = existing;
|
||||
if (src == null) {
|
||||
src = entry;
|
||||
}
|
||||
Set<String> variants = new HashSet<String>(src.getVariantURIs());
|
||||
variants.add(variantURI);
|
||||
Resource resource = resourceFactory.copy(requestId, src.getResource());
|
||||
return new HttpCacheEntry(
|
||||
src.getRequestDate(),
|
||||
src.getResponseDate(),
|
||||
src.getStatusLine(),
|
||||
src.getAllHeaders(),
|
||||
resource,
|
||||
variants);
|
||||
}
|
||||
|
||||
HttpResponse correctIncompleteResponse(HttpResponse resp, Resource resource) {
|
||||
int status = resp.getStatusLine().getStatusCode();
|
||||
if (status != HttpStatus.SC_OK
|
||||
&& status != HttpStatus.SC_PARTIAL_CONTENT) {
|
||||
return resp;
|
||||
}
|
||||
Header hdr = resp.getFirstHeader("Content-Length");
|
||||
if (hdr == null) return resp;
|
||||
int contentLength;
|
||||
try {
|
||||
contentLength = Integer.parseInt(hdr.getValue());
|
||||
} catch (NumberFormatException nfe) {
|
||||
return resp;
|
||||
}
|
||||
if (resource.length() >= contentLength) return resp;
|
||||
HttpResponse error =
|
||||
new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_BAD_GATEWAY, "Bad Gateway");
|
||||
error.setHeader("Content-Type","text/plain;charset=UTF-8");
|
||||
String msg = String.format("Received incomplete response " +
|
||||
"with Content-Length %d but actual body length %d", contentLength, resource.length());
|
||||
byte[] msgBytes = msg.getBytes();
|
||||
error.setHeader("Content-Length", Integer.toString(msgBytes.length));
|
||||
error.setEntity(new ByteArrayEntity(msgBytes));
|
||||
return error;
|
||||
}
|
||||
|
||||
HttpResponse handleBackendResponse(
|
||||
HttpHost target,
|
||||
HttpRequest request,
|
||||
|
@ -640,40 +502,13 @@ public class CachingHttpClient implements HttpClient {
|
|||
|
||||
boolean cacheable = responseCachingPolicy.isResponseCacheable(request, backendResponse);
|
||||
|
||||
HttpResponse corrected = backendResponse;
|
||||
if (cacheable) {
|
||||
|
||||
SizeLimitedResponseReader responseReader = getResponseReader(request, backendResponse);
|
||||
responseReader.readResponse();
|
||||
|
||||
if (responseReader.isLimitReached()) {
|
||||
return responseReader.getReconstructedResponse();
|
||||
}
|
||||
|
||||
Resource resource = responseReader.getResource();
|
||||
corrected = correctIncompleteResponse(backendResponse, resource);
|
||||
int correctedStatus = corrected.getStatusLine().getStatusCode();
|
||||
if (HttpStatus.SC_BAD_GATEWAY != correctedStatus) {
|
||||
HttpCacheEntry entry = new HttpCacheEntry(
|
||||
requestDate,
|
||||
responseDate,
|
||||
corrected.getStatusLine(),
|
||||
corrected.getAllHeaders(),
|
||||
resource,
|
||||
null);
|
||||
storeInCache(target, request, entry);
|
||||
return responseGenerator.generateResponse(entry);
|
||||
}
|
||||
return responseCache.cacheAndReturnResponse(target, request, backendResponse, requestDate,
|
||||
responseDate);
|
||||
}
|
||||
|
||||
String uri = uriExtractor.getURI(target, request);
|
||||
responseCache.removeEntry(uri);
|
||||
return corrected;
|
||||
}
|
||||
|
||||
SizeLimitedResponseReader getResponseReader(HttpRequest request, HttpResponse backEndResponse) {
|
||||
return new SizeLimitedResponseReader(
|
||||
resourceFactory, maxObjectSizeBytes, request, backEndResponse);
|
||||
responseCache.flushCacheEntriesFor(target, request);
|
||||
return backendResponse;
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -33,13 +33,13 @@ import java.util.HashSet;
|
|||
import java.util.Set;
|
||||
|
||||
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.HttpCacheStorage;
|
||||
import org.apache.http.client.cache.HttpCacheUpdateCallback;
|
||||
import org.apache.http.client.cache.Resource;
|
||||
|
||||
/**
|
||||
* {@link HttpCache} implementation capable of deallocating resources associated with
|
||||
* {@link HttpCacheStorage} implementation capable of deallocating resources associated with
|
||||
* the cache entries. This cache keeps track of cache entries using {@link PhantomReference}
|
||||
* and maintains a collection of all resources that are no longer in use. The cache, however,
|
||||
* does not automatically deallocates associated resources by invoking {@link Resource#dispose()}
|
||||
|
@ -47,13 +47,13 @@ import org.apache.http.client.cache.Resource;
|
|||
* resource deallocation. The cache can be permanently shut down using {@link #shutdown()}
|
||||
* method. All resources associated with the entries used by the cache will be deallocated.
|
||||
*
|
||||
* This {@link HttpCache} implementation is intended for use with {@link FileCacheEntry}
|
||||
* This {@link HttpCacheStorage} implementation is intended for use with {@link FileCacheEntry}
|
||||
* and similar.
|
||||
*
|
||||
* @since 4.1
|
||||
*/
|
||||
@ThreadSafe
|
||||
public class ManagedHttpCache implements HttpCache {
|
||||
public class ManagedHttpCacheStorage implements HttpCacheStorage {
|
||||
|
||||
private final CacheMap entries;
|
||||
private final ReferenceQueue<HttpCacheEntry> morque;
|
||||
|
@ -61,9 +61,9 @@ public class ManagedHttpCache implements HttpCache {
|
|||
|
||||
private volatile boolean shutdown;
|
||||
|
||||
public ManagedHttpCache(int maxEntries) {
|
||||
public ManagedHttpCacheStorage(final CacheConfig config) {
|
||||
super();
|
||||
this.entries = new CacheMap(maxEntries);
|
||||
this.entries = new CacheMap(config.getMaxCacheEntries());
|
||||
this.morque = new ReferenceQueue<HttpCacheEntry>();
|
||||
this.resources = new HashSet<ResourceReference>();
|
||||
}
|
|
@ -32,7 +32,6 @@ import java.io.InputStream;
|
|||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.annotation.NotThreadSafe;
|
||||
import org.apache.http.client.cache.InputLimit;
|
||||
import org.apache.http.client.cache.Resource;
|
||||
|
@ -116,8 +115,7 @@ class SizeLimitedResponseReader {
|
|||
|
||||
HttpResponse getReconstructedResponse() throws IOException {
|
||||
ensureConsumed();
|
||||
HttpResponse reconstructed = new BasicHttpResponse(response.getProtocolVersion(),
|
||||
HttpStatus.SC_OK, "Success");
|
||||
HttpResponse reconstructed = new BasicHttpResponse(response.getStatusLine());
|
||||
reconstructed.setHeaders(response.getAllHeaders());
|
||||
reconstructed.setEntity(new CombinedEntity(resource, instream));
|
||||
return reconstructed;
|
||||
|
|
|
@ -31,15 +31,15 @@ import java.io.IOException;
|
|||
import net.sf.ehcache.Ehcache;
|
||||
import net.sf.ehcache.Element;
|
||||
|
||||
import org.apache.http.client.cache.HttpCache;
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
import org.apache.http.client.cache.HttpCacheStorage;
|
||||
import org.apache.http.client.cache.HttpCacheUpdateCallback;
|
||||
|
||||
public class EhcacheHttpCache implements HttpCache {
|
||||
public class EhcacheHttpCacheStorage implements HttpCacheStorage {
|
||||
|
||||
private final Ehcache cache;
|
||||
|
||||
public EhcacheHttpCache(Ehcache cache) {
|
||||
public EhcacheHttpCacheStorage(Ehcache cache) {
|
||||
this.cache = cache;
|
||||
}
|
||||
|
|
@ -48,12 +48,13 @@ public abstract class AbstractProtocolTest {
|
|||
|
||||
originResponse = make200Response();
|
||||
|
||||
cache = new BasicHttpCache(MAX_ENTRIES);
|
||||
params = new CacheConfig();
|
||||
params.setMaxCacheEntries(MAX_ENTRIES);
|
||||
params.setMaxObjectSizeBytes(MAX_BYTES);
|
||||
cache = new BasicHttpCache(params);
|
||||
mockBackend = EasyMock.createMock(HttpClient.class);
|
||||
mockCache = EasyMock.createMock(HttpCache.class);
|
||||
params = new CacheConfig();
|
||||
params.setMaxObjectSizeBytes(MAX_BYTES);
|
||||
impl = new CachingHttpClient(mockBackend, cache, new HeapResourceFactory(), params);
|
||||
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||
}
|
||||
|
||||
protected void replayMocks() {
|
||||
|
@ -89,18 +90,23 @@ public abstract class AbstractProtocolTest {
|
|||
mockBackend = EasyMock.createMock(HttpClient.class);
|
||||
mockCache = EasyMock.createMock(HttpCache.class);
|
||||
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, new HeapResourceFactory(), params);
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, params);
|
||||
|
||||
EasyMock.expect(mockCache.getEntry((String) EasyMock.anyObject())).andReturn(null)
|
||||
.anyTimes();
|
||||
EasyMock.expect(mockCache.getCacheEntry(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class)))
|
||||
.andReturn(null).anyTimes();
|
||||
mockCache.flushCacheEntriesFor(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class));
|
||||
EasyMock.expectLastCall().anyTimes();
|
||||
|
||||
mockCache.removeEntry(EasyMock.isA(String.class));
|
||||
mockCache.flushCacheEntriesFor(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class));
|
||||
EasyMock.expectLastCall().anyTimes();
|
||||
|
||||
mockCache.flushInvalidatedCacheEntriesFor(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class));
|
||||
EasyMock.expectLastCall().anyTimes();
|
||||
}
|
||||
|
||||
protected void behaveAsNonSharedCache() {
|
||||
params.setSharedCache(false);
|
||||
impl = new CachingHttpClient(mockBackend, cache, new HeapResourceFactory(), params);
|
||||
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||
}
|
||||
|
||||
public AbstractProtocolTest() {
|
||||
|
|
|
@ -27,6 +27,7 @@
|
|||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.util.Date;
|
||||
import java.util.Set;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
|
@ -78,4 +79,8 @@ public class CacheEntry extends HttpCacheEntry {
|
|||
super(new Date(), new Date(), new OKStatus(), new Header[] {}, new HeapResource(content), null);
|
||||
}
|
||||
|
||||
public CacheEntry(Set<String> variants) {
|
||||
super(new Date(), new Date(), new OKStatus(), new Header[] {}, BODY, variants);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -75,14 +75,15 @@ public class DoNotTestProtocolRequirements {
|
|||
request = new BasicHttpRequest("GET", "/foo", HTTP_1_1);
|
||||
|
||||
originResponse = make200Response();
|
||||
CacheConfig params = new CacheConfig();
|
||||
params.setMaxObjectSizeBytes(MAX_BYTES);
|
||||
params.setMaxCacheEntries(MAX_ENTRIES);
|
||||
|
||||
HttpCache cache = new BasicHttpCache(MAX_ENTRIES);
|
||||
HttpCache cache = new BasicHttpCache(params);
|
||||
mockBackend = EasyMock.createMock(HttpClient.class);
|
||||
mockEntity = EasyMock.createMock(HttpEntity.class);
|
||||
mockCache = EasyMock.createMock(HttpCache.class);
|
||||
CacheConfig params = new CacheConfig();
|
||||
params.setMaxObjectSizeBytes(MAX_BYTES);
|
||||
impl = new CachingHttpClient(mockBackend, cache, new HeapResourceFactory(), params);
|
||||
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||
}
|
||||
|
||||
private HttpResponse make200Response() {
|
||||
|
|
|
@ -195,9 +195,13 @@ public class HttpTestUtils {
|
|||
*/
|
||||
public static boolean semanticallyTransparent(HttpResponse r1, HttpResponse r2)
|
||||
throws Exception {
|
||||
return (equivalent(r1.getEntity(), r2.getEntity())
|
||||
&& semanticallyTransparent(r1.getStatusLine(), r2.getStatusLine()) && isEndToEndHeaderSubset(
|
||||
r1, r2));
|
||||
final boolean entitiesEquivalent = equivalent(r1.getEntity(), r2.getEntity());
|
||||
if (!entitiesEquivalent) return false;
|
||||
final boolean statusLinesEquivalent = semanticallyTransparent(r1.getStatusLine(), r2.getStatusLine());
|
||||
if (!statusLinesEquivalent) return false;
|
||||
final boolean e2eHeadersEquivalentSubset = isEndToEndHeaderSubset(
|
||||
r1, r2);
|
||||
return e2eHeadersEquivalentSubset;
|
||||
}
|
||||
|
||||
/* Assert.asserts that two requests are morally equivalent. */
|
||||
|
|
64
httpclient-cache/src/test/java/org/apache/http/impl/client/cache/SimpleHttpCacheStorage.java
vendored
Normal file
64
httpclient-cache/src/test/java/org/apache/http/impl/client/cache/SimpleHttpCacheStorage.java
vendored
Normal file
|
@ -0,0 +1,64 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.util.HashMap;
|
||||
import java.util.Map;
|
||||
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
import org.apache.http.client.cache.HttpCacheStorage;
|
||||
import org.apache.http.client.cache.HttpCacheUpdateCallback;
|
||||
|
||||
class SimpleHttpCacheStorage implements HttpCacheStorage {
|
||||
|
||||
public final Map<String,HttpCacheEntry> map;
|
||||
|
||||
public SimpleHttpCacheStorage() {
|
||||
map = new HashMap<String,HttpCacheEntry>();
|
||||
}
|
||||
|
||||
public void putEntry(String key, HttpCacheEntry entry) throws IOException {
|
||||
map.put(key, entry);
|
||||
}
|
||||
|
||||
public HttpCacheEntry getEntry(String key) throws IOException {
|
||||
return map.get(key);
|
||||
}
|
||||
|
||||
public void removeEntry(String key) throws IOException {
|
||||
map.remove(key);
|
||||
}
|
||||
|
||||
public void updateEntry(String key, HttpCacheUpdateCallback callback)
|
||||
throws IOException {
|
||||
HttpCacheEntry v1 = map.get(key);
|
||||
HttpCacheEntry v2 = callback.update(v1);
|
||||
map.put(key,v2);
|
||||
}
|
||||
|
||||
}
|
335
httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestBasicHttpCache.java
vendored
Normal file
335
httpclient-cache/src/test/java/org/apache/http/impl/client/cache/TestBasicHttpCache.java
vendored
Normal file
|
@ -0,0 +1,335 @@
|
|||
/*
|
||||
* ====================================================================
|
||||
* 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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import static org.junit.Assert.assertEquals;
|
||||
import static org.junit.Assert.assertFalse;
|
||||
import static org.junit.Assert.assertNotNull;
|
||||
import static org.junit.Assert.assertNull;
|
||||
import static org.junit.Assert.assertSame;
|
||||
import static org.junit.Assert.assertTrue;
|
||||
|
||||
import java.io.InputStream;
|
||||
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.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.HttpVersion;
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
import org.apache.http.client.cache.Resource;
|
||||
import org.apache.http.client.methods.HttpDelete;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.impl.cookie.DateUtils;
|
||||
import org.apache.http.message.BasicHttpResponse;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestBasicHttpCache {
|
||||
|
||||
private BasicHttpCache impl;
|
||||
private SimpleHttpCacheStorage backing;
|
||||
|
||||
@Before
|
||||
public void setUp() throws Exception {
|
||||
backing = new SimpleHttpCacheStorage();
|
||||
impl = new BasicHttpCache(new HeapResourceFactory(), backing, new CacheConfig());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCanFlushCacheEntriesAtUri() throws Exception {
|
||||
HttpHost host = new HttpHost("foo.example.com");
|
||||
HttpRequest req = new HttpDelete("/bar");
|
||||
final String key = (new URIExtractor()).getURI(host, req);
|
||||
HttpCacheEntry entry = new CacheEntry();
|
||||
|
||||
backing.map.put(key, entry);
|
||||
|
||||
impl.flushCacheEntriesFor(host, req);
|
||||
|
||||
assertNull(backing.map.get(key));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecognizesComplete200Response()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","128");
|
||||
Resource resource = new HeapResource(bytes);
|
||||
|
||||
assertFalse(impl.isIncompleteResponse(resp, resource));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecognizesComplete206Response()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
Resource resource = new HeapResource(bytes);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","128");
|
||||
resp.setHeader("Content-Range","bytes 0-127/255");
|
||||
|
||||
assertFalse(impl.isIncompleteResponse(resp, resource));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRecognizesIncomplete200Response()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
Resource resource = new HeapResource(bytes);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","256");
|
||||
|
||||
assertTrue(impl.isIncompleteResponse(resp, resource));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIgnoresIncompleteNon200Or206Responses()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_FORBIDDEN, "Forbidden");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
Resource resource = new HeapResource(bytes);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","256");
|
||||
|
||||
assertFalse(impl.isIncompleteResponse(resp, resource));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResponsesWithoutExplicitContentLengthAreComplete()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
Resource resource = new HeapResource(bytes);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
|
||||
assertFalse(impl.isIncompleteResponse(resp, resource));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testResponsesWithUnparseableContentLengthHeaderAreComplete()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
Resource resource = new HeapResource(bytes);
|
||||
resp.setHeader("Content-Length","foo");
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
|
||||
assertFalse(impl.isIncompleteResponse(resp, resource));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncompleteResponseErrorProvidesPlainTextErrorMessage()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
Resource resource = new HeapResource(bytes);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","256");
|
||||
|
||||
HttpResponse result = impl.generateIncompleteResponseError(resp, resource);
|
||||
Header ctype = result.getFirstHeader("Content-Type");
|
||||
assertEquals("text/plain;charset=UTF-8", ctype.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIncompleteResponseErrorProvidesNonEmptyErrorMessage()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
Resource resource = new HeapResource(bytes);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","256");
|
||||
|
||||
HttpResponse result = impl.generateIncompleteResponseError(resp, resource);
|
||||
int clen = Integer.parseInt(result.getFirstHeader("Content-Length").getValue());
|
||||
assertTrue(clen > 0);
|
||||
HttpEntity body = result.getEntity();
|
||||
if (body.getContentLength() < 0) {
|
||||
InputStream is = body.getContent();
|
||||
int bytes_read = 0;
|
||||
while((is.read()) != -1) {
|
||||
bytes_read++;
|
||||
}
|
||||
is.close();
|
||||
assertEquals(clen, bytes_read);
|
||||
} else {
|
||||
assertTrue(body.getContentLength() == clen);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheUpdateAddsVariantURIToParentEntry() throws Exception {
|
||||
final String parentKey = "parentKey";
|
||||
final String variantKey = "variantKey";
|
||||
final String existingVariantKey = "existingVariantKey";
|
||||
final Set<String> existingVariants = new HashSet<String>();
|
||||
existingVariants.add(existingVariantKey);
|
||||
final CacheEntry parent = new CacheEntry(existingVariants);
|
||||
final CacheEntry variant = new CacheEntry();
|
||||
|
||||
HttpCacheEntry result = impl.doGetUpdatedParentEntry(parentKey, parent, variant, variantKey);
|
||||
assertEquals(2, result.getVariantURIs().size());
|
||||
assertTrue(result.getVariantURIs().contains(existingVariantKey));
|
||||
assertTrue(result.getVariantURIs().contains(variantKey));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoreInCachePutsNonVariantEntryInPlace() throws Exception {
|
||||
CacheEntry entry = new CacheEntry();
|
||||
assertFalse(entry.hasVariants());
|
||||
HttpHost host = new HttpHost("foo.example.com");
|
||||
HttpRequest req = new HttpGet("http://foo.example.com/bar");
|
||||
String key = (new URIExtractor()).getURI(host, req);
|
||||
|
||||
impl.storeInCache(host, req, entry);
|
||||
assertSame(entry, backing.map.get(key));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTooLargeResponsesAreNotCached() throws Exception {
|
||||
HttpHost host = new HttpHost("foo.example.com");
|
||||
HttpRequest request = new HttpGet("http://foo.example.com/bar");
|
||||
|
||||
Date now = new Date();
|
||||
Date requestSent = new Date(now.getTime() - 3 * 1000L);
|
||||
Date responseGenerated = new Date(now.getTime() - 2 * 1000L);
|
||||
Date responseReceived = new Date(now.getTime() - 1 * 1000L);
|
||||
|
||||
HttpResponse originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
originResponse.setEntity(HttpTestUtils.makeBody(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES + 1));
|
||||
originResponse.setHeader("Cache-Control","public, max-age=3600");
|
||||
originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated));
|
||||
originResponse.setHeader("ETag", "\"etag\"");
|
||||
|
||||
HttpResponse result = impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived);
|
||||
assertEquals(0, backing.map.size());
|
||||
assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result));
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testSmallEnoughResponsesAreCached() throws Exception {
|
||||
HttpHost host = new HttpHost("foo.example.com");
|
||||
HttpRequest request = new HttpGet("http://foo.example.com/bar");
|
||||
|
||||
Date now = new Date();
|
||||
Date requestSent = new Date(now.getTime() - 3 * 1000L);
|
||||
Date responseGenerated = new Date(now.getTime() - 2 * 1000L);
|
||||
Date responseReceived = new Date(now.getTime() - 1 * 1000L);
|
||||
|
||||
HttpResponse originResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
originResponse.setEntity(HttpTestUtils.makeBody(CacheConfig.DEFAULT_MAX_OBJECT_SIZE_BYTES - 1));
|
||||
originResponse.setHeader("Cache-Control","public, max-age=3600");
|
||||
originResponse.setHeader("Date", DateUtils.formatDate(responseGenerated));
|
||||
originResponse.setHeader("ETag", "\"etag\"");
|
||||
|
||||
HttpResponse result = impl.cacheAndReturnResponse(host, request, originResponse, requestSent, responseReceived);
|
||||
assertEquals(1, backing.map.size());
|
||||
assertTrue(backing.map.containsKey((new URIExtractor()).getURI(host, request)));
|
||||
assertTrue(HttpTestUtils.semanticallyTransparent(originResponse, result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCacheEntryReturnsNullOnCacheMiss() throws Exception {
|
||||
HttpHost host = new HttpHost("foo.example.com");
|
||||
HttpRequest request = new HttpGet("http://foo.example.com/bar");
|
||||
HttpCacheEntry result = impl.getCacheEntry(host, request);
|
||||
Assert.assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCacheEntryFetchesFromCacheOnCacheHitIfNoVariants() throws Exception {
|
||||
CacheEntry entry = new CacheEntry();
|
||||
assertFalse(entry.hasVariants());
|
||||
HttpHost host = new HttpHost("foo.example.com");
|
||||
HttpRequest request = new HttpGet("http://foo.example.com/bar");
|
||||
|
||||
String key = (new URIExtractor()).getURI(host, request);
|
||||
|
||||
backing.map.put(key,entry);
|
||||
|
||||
HttpCacheEntry result = impl.getCacheEntry(host, request);
|
||||
Assert.assertSame(entry, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCacheEntryReturnsNullIfNoVariantInCache() throws Exception {
|
||||
HttpHost host = new HttpHost("foo.example.com");
|
||||
HttpRequest request = new HttpGet("http://foo.example.com/bar");
|
||||
|
||||
HttpRequest origRequest = new HttpGet("http://foo.example.com/bar");
|
||||
origRequest.setHeader("Accept-Encoding","gzip");
|
||||
|
||||
HttpResponse origResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
origResponse.setEntity(HttpTestUtils.makeBody(128));
|
||||
origResponse.setHeader("Date", DateUtils.formatDate(new Date()));
|
||||
origResponse.setHeader("Cache-Control", "max-age=3600, public");
|
||||
origResponse.setHeader("ETag", "\"etag\"");
|
||||
origResponse.setHeader("Vary", "Accept-Encoding");
|
||||
origResponse.setHeader("Content-Encoding","gzip");
|
||||
|
||||
impl.cacheAndReturnResponse(host, origRequest, origResponse, new Date(), new Date());
|
||||
HttpCacheEntry result = impl.getCacheEntry(host, request);
|
||||
assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCacheEntryReturnsVariantIfPresentInCache() throws Exception {
|
||||
HttpHost host = new HttpHost("foo.example.com");
|
||||
HttpRequest request = new HttpGet("http://foo.example.com/bar");
|
||||
request.setHeader("Accept-Encoding","gzip");
|
||||
|
||||
HttpRequest origRequest = new HttpGet("http://foo.example.com/bar");
|
||||
origRequest.setHeader("Accept-Encoding","gzip");
|
||||
|
||||
HttpResponse origResponse = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
origResponse.setEntity(HttpTestUtils.makeBody(128));
|
||||
origResponse.setHeader("Date", DateUtils.formatDate(new Date()));
|
||||
origResponse.setHeader("Cache-Control", "max-age=3600, public");
|
||||
origResponse.setHeader("ETag", "\"etag\"");
|
||||
origResponse.setHeader("Vary", "Accept-Encoding");
|
||||
origResponse.setHeader("Content-Encoding","gzip");
|
||||
|
||||
impl.cacheAndReturnResponse(host, origRequest, origResponse, new Date(), new Date());
|
||||
HttpCacheEntry result = impl.getCacheEntry(host, request);
|
||||
assertNotNull(result);
|
||||
}
|
||||
|
||||
|
||||
}
|
|
@ -34,7 +34,7 @@ import org.apache.http.HttpEntityEnclosingRequest;
|
|||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.client.cache.HttpCache;
|
||||
import org.apache.http.client.cache.HttpCacheStorage;
|
||||
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.easymock.classextension.EasyMock;
|
||||
|
@ -46,7 +46,7 @@ public class TestCacheInvalidator {
|
|||
private static final ProtocolVersion HTTP_1_1 = new ProtocolVersion("HTTP", 1, 1);
|
||||
|
||||
private CacheInvalidator impl;
|
||||
private HttpCache mockCache;
|
||||
private HttpCacheStorage mockStorage;
|
||||
private HttpHost host;
|
||||
private URIExtractor extractor;
|
||||
private CacheEntry mockEntry;
|
||||
|
@ -54,20 +54,20 @@ public class TestCacheInvalidator {
|
|||
@Before
|
||||
public void setUp() {
|
||||
host = new HttpHost("foo.example.com");
|
||||
mockCache = EasyMock.createMock(HttpCache.class);
|
||||
mockStorage = EasyMock.createMock(HttpCacheStorage.class);
|
||||
extractor = new URIExtractor();
|
||||
mockEntry = EasyMock.createMock(CacheEntry.class);
|
||||
|
||||
impl = new CacheInvalidator(extractor, mockCache);
|
||||
impl = new CacheInvalidator(extractor, mockStorage);
|
||||
}
|
||||
|
||||
private void replayMocks() {
|
||||
EasyMock.replay(mockCache);
|
||||
EasyMock.replay(mockStorage);
|
||||
EasyMock.replay(mockEntry);
|
||||
}
|
||||
|
||||
private void verifyMocks() {
|
||||
EasyMock.verify(mockCache);
|
||||
EasyMock.verify(mockStorage);
|
||||
EasyMock.verify(mockEntry);
|
||||
}
|
||||
|
||||
|
@ -283,16 +283,16 @@ public class TestCacheInvalidator {
|
|||
}
|
||||
|
||||
private void cacheReturnsEntryForUri(String theUri) throws IOException {
|
||||
org.easymock.EasyMock.expect(mockCache.getEntry(theUri)).andReturn(mockEntry);
|
||||
org.easymock.EasyMock.expect(mockStorage.getEntry(theUri)).andReturn(mockEntry);
|
||||
}
|
||||
|
||||
private void cacheReturnsExceptionForUri(String theUri) throws IOException {
|
||||
org.easymock.EasyMock.expect(mockCache.getEntry(theUri)).andThrow(
|
||||
org.easymock.EasyMock.expect(mockStorage.getEntry(theUri)).andThrow(
|
||||
new IOException("TOTAL FAIL"));
|
||||
}
|
||||
|
||||
private void entryIsRemoved(String theUri) throws IOException {
|
||||
mockCache.removeEntry(theUri);
|
||||
mockStorage.removeEntry(theUri);
|
||||
}
|
||||
|
||||
}
|
|
@ -27,14 +27,11 @@
|
|||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.net.URI;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
|
@ -47,13 +44,9 @@ 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.cache.Resource;
|
||||
import org.apache.http.client.cache.ResourceFactory;
|
||||
import org.apache.http.client.methods.HttpUriRequest;
|
||||
import org.apache.http.conn.ClientConnectionManager;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.apache.http.message.BasicHttpResponse;
|
||||
import org.apache.http.params.BasicHttpParams;
|
||||
import org.apache.http.params.HttpParams;
|
||||
import org.apache.http.protocol.BasicHttpContext;
|
||||
|
@ -73,17 +66,9 @@ public class TestCachingHttpClient {
|
|||
|
||||
private static final String REVALIDATE_CACHE_ENTRY = "revalidateCacheEntry";
|
||||
|
||||
private static final String GET_CACHE_ENTRY = "getCacheEntry";
|
||||
|
||||
private static final String STORE_IN_CACHE = "storeInCache";
|
||||
|
||||
private static final String GET_RESPONSE_READER = "getResponseReader";
|
||||
|
||||
private CachingHttpClient impl;
|
||||
private boolean mockedImpl;
|
||||
|
||||
private ResourceFactory mockResourceFactory;
|
||||
private CacheInvalidator mockInvalidator;
|
||||
private CacheValidityPolicy mockValidityPolicy;
|
||||
private CacheableRequestPolicy mockRequestPolicy;
|
||||
private HttpClient mockBackend;
|
||||
|
@ -92,20 +77,14 @@ public class TestCachingHttpClient {
|
|||
private ResponseCachingPolicy mockResponsePolicy;
|
||||
private HttpResponse mockBackendResponse;
|
||||
private CacheEntry mockCacheEntry;
|
||||
private CacheEntry mockVariantCacheEntry;
|
||||
private CacheEntry mockUpdatedCacheEntry;
|
||||
private URIExtractor mockExtractor;
|
||||
private CachedHttpResponseGenerator mockResponseGenerator;
|
||||
private SizeLimitedResponseReader mockResponseReader;
|
||||
private ClientConnectionManager mockConnectionManager;
|
||||
private ResponseHandler<Object> mockHandler;
|
||||
private HttpUriRequest mockUriRequest;
|
||||
private HttpResponse mockCachedResponse;
|
||||
private HttpResponse mockReconstructedResponse;
|
||||
private ConditionalRequestBuilder mockConditionalRequestBuilder;
|
||||
private HttpRequest mockConditionalRequest;
|
||||
private StatusLine mockStatusLine;
|
||||
private CacheEntryUpdater mockCacheEntryUpdater;
|
||||
private ResponseProtocolCompliance mockResponseProtocolCompliance;
|
||||
private RequestProtocolCompliance mockRequestProtocolCompliance;
|
||||
|
||||
|
@ -119,8 +98,6 @@ public class TestCachingHttpClient {
|
|||
@SuppressWarnings("unchecked")
|
||||
@Before
|
||||
public void setUp() {
|
||||
mockResourceFactory = EasyMock.createMock(ResourceFactory.class);
|
||||
mockInvalidator = EasyMock.createMock(CacheInvalidator.class);
|
||||
mockRequestPolicy = EasyMock.createMock(CacheableRequestPolicy.class);
|
||||
mockValidityPolicy = EasyMock.createMock(CacheValidityPolicy.class);
|
||||
mockBackend = EasyMock.createMock(HttpClient.class);
|
||||
|
@ -132,17 +109,11 @@ public class TestCachingHttpClient {
|
|||
mockBackendResponse = EasyMock.createMock(HttpResponse.class);
|
||||
mockUriRequest = EasyMock.createMock(HttpUriRequest.class);
|
||||
mockCacheEntry = EasyMock.createMock(CacheEntry.class);
|
||||
mockUpdatedCacheEntry = EasyMock.createMock(CacheEntry.class);
|
||||
mockVariantCacheEntry = EasyMock.createMock(CacheEntry.class);
|
||||
mockExtractor = EasyMock.createMock(URIExtractor.class);
|
||||
mockResponseGenerator = EasyMock.createMock(CachedHttpResponseGenerator.class);
|
||||
mockCachedResponse = EasyMock.createMock(HttpResponse.class);
|
||||
mockConditionalRequestBuilder = EasyMock.createMock(ConditionalRequestBuilder.class);
|
||||
mockConditionalRequest = EasyMock.createMock(HttpRequest.class);
|
||||
mockStatusLine = EasyMock.createMock(StatusLine.class);
|
||||
mockCacheEntryUpdater = EasyMock.createMock(CacheEntryUpdater.class);
|
||||
mockResponseReader = EasyMock.createMock(SizeLimitedResponseReader.class);
|
||||
mockReconstructedResponse = EasyMock.createMock(HttpResponse.class);
|
||||
mockResponseProtocolCompliance = EasyMock.createMock(ResponseProtocolCompliance.class);
|
||||
mockRequestProtocolCompliance = EasyMock.createMock(RequestProtocolCompliance.class);
|
||||
|
||||
|
@ -154,32 +125,24 @@ public class TestCachingHttpClient {
|
|||
params = new BasicHttpParams();
|
||||
impl = new CachingHttpClient(
|
||||
mockBackend,
|
||||
mockResourceFactory,
|
||||
mockValidityPolicy,
|
||||
mockResponsePolicy,
|
||||
mockExtractor,
|
||||
mockCache,
|
||||
mockResponseGenerator,
|
||||
mockInvalidator,
|
||||
mockRequestPolicy,
|
||||
mockSuitabilityChecker,
|
||||
mockConditionalRequestBuilder,
|
||||
mockCacheEntryUpdater,
|
||||
mockResponseProtocolCompliance,
|
||||
mockRequestProtocolCompliance);
|
||||
}
|
||||
|
||||
private void replayMocks() {
|
||||
EasyMock.replay(mockResourceFactory);
|
||||
EasyMock.replay(mockInvalidator);
|
||||
EasyMock.replay(mockRequestPolicy);
|
||||
EasyMock.replay(mockValidityPolicy);
|
||||
EasyMock.replay(mockSuitabilityChecker);
|
||||
EasyMock.replay(mockResponsePolicy);
|
||||
EasyMock.replay(mockCacheEntry);
|
||||
EasyMock.replay(mockVariantCacheEntry);
|
||||
EasyMock.replay(mockResponseGenerator);
|
||||
EasyMock.replay(mockExtractor);
|
||||
EasyMock.replay(mockBackend);
|
||||
EasyMock.replay(mockCache);
|
||||
EasyMock.replay(mockConnectionManager);
|
||||
|
@ -190,9 +153,6 @@ public class TestCachingHttpClient {
|
|||
EasyMock.replay(mockConditionalRequestBuilder);
|
||||
EasyMock.replay(mockConditionalRequest);
|
||||
EasyMock.replay(mockStatusLine);
|
||||
EasyMock.replay(mockCacheEntryUpdater);
|
||||
EasyMock.replay(mockResponseReader);
|
||||
EasyMock.replay(mockReconstructedResponse);
|
||||
EasyMock.replay(mockResponseProtocolCompliance);
|
||||
EasyMock.replay(mockRequestProtocolCompliance);
|
||||
if (mockedImpl) {
|
||||
|
@ -201,16 +161,12 @@ public class TestCachingHttpClient {
|
|||
}
|
||||
|
||||
private void verifyMocks() {
|
||||
EasyMock.verify(mockResourceFactory);
|
||||
EasyMock.verify(mockInvalidator);
|
||||
EasyMock.verify(mockRequestPolicy);
|
||||
EasyMock.verify(mockValidityPolicy);
|
||||
EasyMock.verify(mockSuitabilityChecker);
|
||||
EasyMock.verify(mockResponsePolicy);
|
||||
EasyMock.verify(mockCacheEntry);
|
||||
EasyMock.verify(mockVariantCacheEntry);
|
||||
EasyMock.verify(mockResponseGenerator);
|
||||
EasyMock.verify(mockExtractor);
|
||||
EasyMock.verify(mockBackend);
|
||||
EasyMock.verify(mockCache);
|
||||
EasyMock.verify(mockConnectionManager);
|
||||
|
@ -221,9 +177,6 @@ public class TestCachingHttpClient {
|
|||
EasyMock.verify(mockConditionalRequestBuilder);
|
||||
EasyMock.verify(mockConditionalRequest);
|
||||
EasyMock.verify(mockStatusLine);
|
||||
EasyMock.verify(mockCacheEntryUpdater);
|
||||
EasyMock.verify(mockResponseReader);
|
||||
EasyMock.verify(mockReconstructedResponse);
|
||||
EasyMock.verify(mockResponseProtocolCompliance);
|
||||
EasyMock.verify(mockRequestProtocolCompliance);
|
||||
if (mockedImpl) {
|
||||
|
@ -233,20 +186,12 @@ public class TestCachingHttpClient {
|
|||
|
||||
@Test
|
||||
public void testCacheableResponsesGoIntoCache() throws Exception {
|
||||
mockImplMethods(STORE_IN_CACHE, GET_RESPONSE_READER);
|
||||
responsePolicyAllowsCaching(true);
|
||||
|
||||
responseProtocolValidationIsCalled();
|
||||
|
||||
getMockResponseReader();
|
||||
responseRead();
|
||||
responseLimitReached(false);
|
||||
responseGetResource();
|
||||
storeInCacheWasCalled();
|
||||
responseIsGeneratedFromCache();
|
||||
responseStatusLineIsInspectable();
|
||||
responseGetHeaders();
|
||||
responseDoesNotHaveExplicitContentLength();
|
||||
EasyMock.expect(mockCache.cacheAndReturnResponse(host, request, mockBackendResponse, requestDate, responseDate))
|
||||
.andReturn(mockCachedResponse);
|
||||
|
||||
replayMocks();
|
||||
HttpResponse result = impl.handleBackendResponse(host, request, requestDate,
|
||||
|
@ -283,37 +228,13 @@ public class TestCachingHttpClient {
|
|||
errors);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testStoreInCachePutsNonVariantEntryInPlace() throws Exception {
|
||||
|
||||
final String theURI = "theURI";
|
||||
|
||||
cacheEntryHasVariants(false);
|
||||
extractTheURI(theURI);
|
||||
putInCache(theURI);
|
||||
|
||||
replayMocks();
|
||||
impl.storeInCache(host, request, mockCacheEntry);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheUpdateAddsVariantURIToParentEntry() throws Exception {
|
||||
final String variantURI = "variantURI";
|
||||
final CacheEntry entry = new CacheEntry();
|
||||
copyResource();
|
||||
replayMocks();
|
||||
impl.doGetUpdatedParentEntry("/stuff", null, entry, variantURI);
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
|
||||
@Test
|
||||
public void testCacheMissCausesBackendRequest() throws Exception {
|
||||
mockImplMethods(GET_CACHE_ENTRY, CALL_BACKEND);
|
||||
mockImplMethods(CALL_BACKEND);
|
||||
cacheInvalidatorWasCalled();
|
||||
requestPolicyAllowsCaching(true);
|
||||
getCacheEntryReturns(null);
|
||||
|
||||
requestProtocolValidationIsCalled();
|
||||
requestIsFatallyNonCompliant(null);
|
||||
|
||||
|
@ -331,7 +252,7 @@ public class TestCachingHttpClient {
|
|||
|
||||
@Test
|
||||
public void testUnsuitableUnvalidatableCacheEntryCausesBackendRequest() throws Exception {
|
||||
mockImplMethods(GET_CACHE_ENTRY, CALL_BACKEND);
|
||||
mockImplMethods(CALL_BACKEND);
|
||||
cacheInvalidatorWasCalled();
|
||||
requestPolicyAllowsCaching(true);
|
||||
requestProtocolValidationIsCalled();
|
||||
|
@ -354,7 +275,7 @@ public class TestCachingHttpClient {
|
|||
|
||||
@Test
|
||||
public void testUnsuitableValidatableCacheEntryCausesRevalidation() throws Exception {
|
||||
mockImplMethods(GET_CACHE_ENTRY, REVALIDATE_CACHE_ENTRY);
|
||||
mockImplMethods(REVALIDATE_CACHE_ENTRY);
|
||||
cacheInvalidatorWasCalled();
|
||||
requestPolicyAllowsCaching(true);
|
||||
requestProtocolValidationIsCalled();
|
||||
|
@ -384,11 +305,9 @@ public class TestCachingHttpClient {
|
|||
backendCallWasMadeWithRequest(mockConditionalRequest);
|
||||
getCurrentDateReturns(responseDate);
|
||||
backendResponseCodeIs(HttpStatus.SC_OK);
|
||||
cacheEntryUpdaterCalled();
|
||||
cacheEntryHasVariants(false, mockUpdatedCacheEntry);
|
||||
extractTheURI("http://foo.example.com");
|
||||
putInCache("http://foo.example.com", mockUpdatedCacheEntry);
|
||||
responseIsGeneratedFromCache(mockUpdatedCacheEntry);
|
||||
EasyMock.expect(mockCache.updateCacheEntry(host, request,
|
||||
mockCacheEntry, mockBackendResponse, requestDate, responseDate))
|
||||
.andReturn(mockCachedResponse);
|
||||
|
||||
replayMocks();
|
||||
|
||||
|
@ -406,17 +325,15 @@ public class TestCachingHttpClient {
|
|||
@Test
|
||||
public void testRevalidationUpdatesCacheEntryAndPutsItToCacheWhen304ReturningCachedResponse()
|
||||
throws Exception {
|
||||
mockImplMethods(GET_CURRENT_DATE, STORE_IN_CACHE);
|
||||
mockImplMethods(GET_CURRENT_DATE);
|
||||
conditionalRequestBuilderCalled();
|
||||
getCurrentDateReturns(requestDate);
|
||||
backendCallWasMadeWithRequest(mockConditionalRequest);
|
||||
getCurrentDateReturns(responseDate);
|
||||
backendResponseCodeIs(HttpStatus.SC_NOT_MODIFIED);
|
||||
|
||||
cacheEntryUpdaterCalled();
|
||||
storeInCacheWasCalled(mockUpdatedCacheEntry);
|
||||
|
||||
responseIsGeneratedFromCache(mockUpdatedCacheEntry);
|
||||
EasyMock.expect(mockCache.updateCacheEntry(host, request,
|
||||
mockCacheEntry, mockBackendResponse, requestDate, responseDate))
|
||||
.andReturn(mockCachedResponse);
|
||||
|
||||
replayMocks();
|
||||
|
||||
|
@ -432,7 +349,6 @@ public class TestCachingHttpClient {
|
|||
|
||||
@Test
|
||||
public void testSuitableCacheEntryDoesNotCauseBackendRequest() throws Exception {
|
||||
mockImplMethods(GET_CACHE_ENTRY);
|
||||
cacheInvalidatorWasCalled();
|
||||
requestPolicyAllowsCaching(true);
|
||||
requestProtocolValidationIsCalled();
|
||||
|
@ -465,13 +381,11 @@ public class TestCachingHttpClient {
|
|||
|
||||
@Test
|
||||
public void testNonCacheableResponseIsNotCachedAndIsReturnedAsIs() throws Exception {
|
||||
final String theURI = "theURI";
|
||||
Date currentDate = new Date();
|
||||
responsePolicyAllowsCaching(false);
|
||||
responseProtocolValidationIsCalled();
|
||||
|
||||
extractTheURI(theURI);
|
||||
removeFromCache(theURI);
|
||||
flushCache();
|
||||
|
||||
replayMocks();
|
||||
HttpResponse result = impl.handleBackendResponse(host, request, currentDate,
|
||||
|
@ -481,115 +395,6 @@ public class TestCachingHttpClient {
|
|||
Assert.assertSame(mockBackendResponse, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCacheEntryReturnsNullOnCacheMiss() throws Exception {
|
||||
|
||||
final String theURI = "theURI";
|
||||
extractTheURI(theURI);
|
||||
gotCacheMiss(theURI);
|
||||
|
||||
replayMocks();
|
||||
HttpCacheEntry result = impl.getCacheEntry(host, request);
|
||||
verifyMocks();
|
||||
Assert.assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCacheEntryFetchesFromCacheOnCacheHitIfNoVariants() throws Exception {
|
||||
|
||||
final String theURI = "theURI";
|
||||
extractTheURI(theURI);
|
||||
gotCacheHit(theURI);
|
||||
cacheEntryHasVariants(false);
|
||||
|
||||
replayMocks();
|
||||
HttpCacheEntry result = impl.getCacheEntry(host, request);
|
||||
verifyMocks();
|
||||
Assert.assertSame(mockCacheEntry, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCacheEntryReturnsNullIfNoVariantInCache() throws Exception {
|
||||
|
||||
final String theURI = "theURI";
|
||||
final String variantURI = "variantURI";
|
||||
extractTheURI(theURI);
|
||||
gotCacheHit(theURI);
|
||||
cacheEntryHasVariants(true);
|
||||
extractVariantURI(variantURI);
|
||||
gotCacheMiss(variantURI);
|
||||
|
||||
replayMocks();
|
||||
HttpCacheEntry result = impl.getCacheEntry(host, request);
|
||||
verifyMocks();
|
||||
Assert.assertNull(result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testGetCacheEntryReturnsVariantIfPresentInCache() throws Exception {
|
||||
|
||||
final String theURI = "theURI";
|
||||
final String variantURI = "variantURI";
|
||||
extractTheURI(theURI);
|
||||
gotCacheHit(theURI, mockCacheEntry);
|
||||
cacheEntryHasVariants(true);
|
||||
extractVariantURI(variantURI);
|
||||
gotCacheHit(variantURI, mockVariantCacheEntry);
|
||||
|
||||
replayMocks();
|
||||
HttpCacheEntry result = impl.getCacheEntry(host, request);
|
||||
verifyMocks();
|
||||
Assert.assertSame(mockVariantCacheEntry, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testTooLargeResponsesAreNotCached() throws Exception {
|
||||
mockImplMethods(GET_CURRENT_DATE, GET_RESPONSE_READER, STORE_IN_CACHE);
|
||||
getCurrentDateReturns(requestDate);
|
||||
backendCallWasMadeWithRequest(request);
|
||||
responseProtocolValidationIsCalled();
|
||||
|
||||
getCurrentDateReturns(responseDate);
|
||||
responsePolicyAllowsCaching(true);
|
||||
getMockResponseReader();
|
||||
responseRead();
|
||||
responseLimitReached(true);
|
||||
responseGetReconstructed();
|
||||
|
||||
replayMocks();
|
||||
|
||||
impl.callBackend(host, request, context);
|
||||
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmallEnoughResponsesAreCached() throws Exception {
|
||||
requestDate = new Date();
|
||||
responseDate = new Date();
|
||||
mockImplMethods(GET_CURRENT_DATE, GET_RESPONSE_READER, STORE_IN_CACHE);
|
||||
getCurrentDateReturns(requestDate);
|
||||
responseProtocolValidationIsCalled();
|
||||
|
||||
backendCallWasMadeWithRequest(request);
|
||||
getCurrentDateReturns(responseDate);
|
||||
responsePolicyAllowsCaching(true);
|
||||
getMockResponseReader();
|
||||
responseRead();
|
||||
responseLimitReached(false);
|
||||
responseGetResource();
|
||||
storeInCacheWasCalled();
|
||||
responseIsGeneratedFromCache();
|
||||
responseStatusLineIsInspectable();
|
||||
responseGetHeaders();
|
||||
responseDoesNotHaveExplicitContentLength();
|
||||
|
||||
replayMocks();
|
||||
|
||||
impl.callBackend(host, request, context);
|
||||
|
||||
verifyMocks();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCallsSelfForExecuteOnHostRequestWithNullContext() throws Exception {
|
||||
|
@ -599,17 +404,13 @@ public class TestCachingHttpClient {
|
|||
final HttpResponse theResponse = mockBackendResponse;
|
||||
impl = new CachingHttpClient(
|
||||
mockBackend,
|
||||
mockResourceFactory,
|
||||
mockValidityPolicy,
|
||||
mockResponsePolicy,
|
||||
mockExtractor,
|
||||
mockCache,
|
||||
mockResponseGenerator,
|
||||
mockInvalidator,
|
||||
mockRequestPolicy,
|
||||
mockSuitabilityChecker,
|
||||
mockConditionalRequestBuilder,
|
||||
mockCacheEntryUpdater,
|
||||
mockResponseProtocolCompliance,
|
||||
mockRequestProtocolCompliance) {
|
||||
@Override
|
||||
|
@ -641,17 +442,13 @@ public class TestCachingHttpClient {
|
|||
final Object value = new Object();
|
||||
impl = new CachingHttpClient(
|
||||
mockBackend,
|
||||
mockResourceFactory,
|
||||
mockValidityPolicy,
|
||||
mockResponsePolicy,
|
||||
mockExtractor,
|
||||
mockCache,
|
||||
mockResponseGenerator,
|
||||
mockInvalidator,
|
||||
mockRequestPolicy,
|
||||
mockSuitabilityChecker,
|
||||
mockConditionalRequestBuilder,
|
||||
mockCacheEntryUpdater,
|
||||
mockResponseProtocolCompliance,
|
||||
mockRequestProtocolCompliance) {
|
||||
@Override
|
||||
|
@ -691,17 +488,13 @@ public class TestCachingHttpClient {
|
|||
final HttpContext theContext = context;
|
||||
impl = new CachingHttpClient(
|
||||
mockBackend,
|
||||
mockResourceFactory,
|
||||
mockValidityPolicy,
|
||||
mockResponsePolicy,
|
||||
mockExtractor,
|
||||
mockCache,
|
||||
mockResponseGenerator,
|
||||
mockInvalidator,
|
||||
mockRequestPolicy,
|
||||
mockSuitabilityChecker,
|
||||
mockConditionalRequestBuilder,
|
||||
mockCacheEntryUpdater,
|
||||
mockResponseProtocolCompliance,
|
||||
mockRequestProtocolCompliance) {
|
||||
@Override
|
||||
|
@ -733,17 +526,13 @@ public class TestCachingHttpClient {
|
|||
final HttpResponse theResponse = mockBackendResponse;
|
||||
impl = new CachingHttpClient(
|
||||
mockBackend,
|
||||
mockResourceFactory,
|
||||
mockValidityPolicy,
|
||||
mockResponsePolicy,
|
||||
mockExtractor,
|
||||
mockCache,
|
||||
mockResponseGenerator,
|
||||
mockInvalidator,
|
||||
mockRequestPolicy,
|
||||
mockSuitabilityChecker,
|
||||
mockConditionalRequestBuilder,
|
||||
mockCacheEntryUpdater,
|
||||
mockResponseProtocolCompliance,
|
||||
mockRequestProtocolCompliance) {
|
||||
@Override
|
||||
|
@ -773,17 +562,13 @@ public class TestCachingHttpClient {
|
|||
final HttpResponse theResponse = mockBackendResponse;
|
||||
impl = new CachingHttpClient(
|
||||
mockBackend,
|
||||
mockResourceFactory,
|
||||
mockValidityPolicy,
|
||||
mockResponsePolicy,
|
||||
mockExtractor,
|
||||
mockCache,
|
||||
mockResponseGenerator,
|
||||
mockInvalidator,
|
||||
mockRequestPolicy,
|
||||
mockSuitabilityChecker,
|
||||
mockConditionalRequestBuilder,
|
||||
mockCacheEntryUpdater,
|
||||
mockResponseProtocolCompliance,
|
||||
mockRequestProtocolCompliance) {
|
||||
@Override
|
||||
|
@ -816,17 +601,13 @@ public class TestCachingHttpClient {
|
|||
final Object theValue = new Object();
|
||||
impl = new CachingHttpClient(
|
||||
mockBackend,
|
||||
mockResourceFactory,
|
||||
mockValidityPolicy,
|
||||
mockResponsePolicy,
|
||||
mockExtractor,
|
||||
mockCache,
|
||||
mockResponseGenerator,
|
||||
mockInvalidator,
|
||||
mockRequestPolicy,
|
||||
mockSuitabilityChecker,
|
||||
mockConditionalRequestBuilder,
|
||||
mockCacheEntryUpdater,
|
||||
mockResponseProtocolCompliance,
|
||||
mockRequestProtocolCompliance) {
|
||||
@Override
|
||||
|
@ -861,17 +642,13 @@ public class TestCachingHttpClient {
|
|||
final Object theValue = new Object();
|
||||
impl = new CachingHttpClient(
|
||||
mockBackend,
|
||||
mockResourceFactory,
|
||||
mockValidityPolicy,
|
||||
mockResponsePolicy,
|
||||
mockExtractor,
|
||||
mockCache,
|
||||
mockResponseGenerator,
|
||||
mockInvalidator,
|
||||
mockRequestPolicy,
|
||||
mockSuitabilityChecker,
|
||||
mockConditionalRequestBuilder,
|
||||
mockCacheEntryUpdater,
|
||||
mockResponseProtocolCompliance,
|
||||
mockRequestProtocolCompliance) {
|
||||
@Override
|
||||
|
@ -916,17 +693,13 @@ public class TestCachingHttpClient {
|
|||
@Test
|
||||
public void testResponseIsGeneratedWhenCacheEntryIsUsable() throws Exception {
|
||||
|
||||
final String theURI = "http://foo";
|
||||
|
||||
requestIsFatallyNonCompliant(null);
|
||||
requestProtocolValidationIsCalled();
|
||||
cacheInvalidatorWasCalled();
|
||||
requestPolicyAllowsCaching(true);
|
||||
cacheEntrySuitable(true);
|
||||
extractTheURI(theURI);
|
||||
gotCacheHit(theURI);
|
||||
getCacheEntryReturns(mockCacheEntry);
|
||||
responseIsGeneratedFromCache();
|
||||
cacheEntryHasVariants(false);
|
||||
|
||||
replayMocks();
|
||||
impl.execute(host, request, context);
|
||||
|
@ -953,123 +726,17 @@ public class TestCachingHttpClient {
|
|||
Assert.assertTrue(gotException);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectIncompleteResponseDoesNotCorrectComplete200Response()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","128");
|
||||
|
||||
HttpResponse result = impl.correctIncompleteResponse(resp, new HeapResource(bytes));
|
||||
Assert.assertTrue(HttpTestUtils.semanticallyTransparent(resp, result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectIncompleteResponseDoesNotCorrectComplete206Response()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_PARTIAL_CONTENT, "Partial Content");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","128");
|
||||
resp.setHeader("Content-Range","bytes 0-127/255");
|
||||
|
||||
HttpResponse result = impl.correctIncompleteResponse(resp, new HeapResource(bytes));
|
||||
Assert.assertTrue(HttpTestUtils.semanticallyTransparent(resp, result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectIncompleteResponseGenerates502ForIncomplete200Response()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","256");
|
||||
|
||||
HttpResponse result = impl.correctIncompleteResponse(resp, new HeapResource(bytes));
|
||||
Assert.assertTrue(HttpStatus.SC_BAD_GATEWAY == result.getStatusLine().getStatusCode());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectIncompleteResponseDoesNotCorrectIncompleteNon200Or206Responses()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_FORBIDDEN, "Forbidden");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","256");
|
||||
|
||||
HttpResponse result = impl.correctIncompleteResponse(resp, new HeapResource(bytes));
|
||||
Assert.assertTrue(HttpTestUtils.semanticallyTransparent(resp, result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectIncompleteResponseDoesNotCorrectResponsesWithoutExplicitContentLength()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
|
||||
HttpResponse result = impl.correctIncompleteResponse(resp, new HeapResource(bytes));
|
||||
Assert.assertTrue(HttpTestUtils.semanticallyTransparent(resp, result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectIncompleteResponseDoesNotCorrectResponsesWithUnparseableContentLengthHeader()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
resp.setHeader("Content-Length","foo");
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
|
||||
HttpResponse result = impl.correctIncompleteResponse(resp, new HeapResource(bytes));
|
||||
Assert.assertTrue(HttpTestUtils.semanticallyTransparent(resp, result));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectIncompleteResponseProvidesPlainTextErrorMessage()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","256");
|
||||
|
||||
HttpResponse result = impl.correctIncompleteResponse(resp, new HeapResource(bytes));
|
||||
Header ctype = result.getFirstHeader("Content-Type");
|
||||
Assert.assertEquals("text/plain;charset=UTF-8", ctype.getValue());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCorrectIncompleteResponseProvidesNonEmptyErrorMessage()
|
||||
throws Exception {
|
||||
HttpResponse resp = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
byte[] bytes = HttpTestUtils.getRandomBytes(128);
|
||||
resp.setEntity(new ByteArrayEntity(bytes));
|
||||
resp.setHeader("Content-Length","256");
|
||||
|
||||
HttpResponse result = impl.correctIncompleteResponse(resp, new HeapResource(bytes));
|
||||
int clen = Integer.parseInt(result.getFirstHeader("Content-Length").getValue());
|
||||
Assert.assertTrue(clen > 0);
|
||||
HttpEntity body = result.getEntity();
|
||||
if (body.getContentLength() < 0) {
|
||||
InputStream is = body.getContent();
|
||||
int bytes_read = 0;
|
||||
while((is.read()) != -1) {
|
||||
bytes_read++;
|
||||
}
|
||||
is.close();
|
||||
Assert.assertEquals(clen, bytes_read);
|
||||
} else {
|
||||
Assert.assertTrue(body.getContentLength() == clen);
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testIsSharedCache() {
|
||||
Assert.assertTrue(impl.isSharedCache());
|
||||
}
|
||||
|
||||
private void getCacheEntryReturns(HttpCacheEntry result) throws IOException {
|
||||
EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(result);
|
||||
}
|
||||
|
||||
private void cacheInvalidatorWasCalled() throws IOException {
|
||||
mockInvalidator.flushInvalidatedCacheEntries(
|
||||
mockCache.flushInvalidatedCacheEntriesFor(
|
||||
EasyMock.<HttpHost>anyObject(),
|
||||
EasyMock.<HttpRequest>anyObject());
|
||||
}
|
||||
|
@ -1096,22 +763,6 @@ public class TestCachingHttpClient {
|
|||
EasyMock.<HttpCacheEntry>anyObject())).andReturn(b);
|
||||
}
|
||||
|
||||
private void cacheEntryUpdaterCalled() throws IOException {
|
||||
EasyMock.expect(
|
||||
mockCacheEntryUpdater.updateCacheEntry(
|
||||
EasyMock.<String>anyObject(),
|
||||
EasyMock.<HttpCacheEntry>anyObject(),
|
||||
EasyMock.<Date>anyObject(),
|
||||
EasyMock.<Date>anyObject(),
|
||||
EasyMock.<HttpResponse>anyObject())).andReturn(mockUpdatedCacheEntry);
|
||||
}
|
||||
|
||||
private void getCacheEntryReturns(CacheEntry entry) throws IOException {
|
||||
EasyMock.expect(impl.getCacheEntry(
|
||||
EasyMock.<HttpHost>anyObject(),
|
||||
EasyMock.<HttpRequest>anyObject())).andReturn(entry);
|
||||
}
|
||||
|
||||
private void backendResponseCodeIs(int code) {
|
||||
EasyMock.expect(mockBackendResponse.getStatusLine()).andReturn(mockStatusLine);
|
||||
EasyMock.expect(mockStatusLine.getStatusCode()).andReturn(code);
|
||||
|
@ -1128,42 +779,11 @@ public class TestCachingHttpClient {
|
|||
EasyMock.expect(impl.getCurrentDate()).andReturn(date);
|
||||
}
|
||||
|
||||
private void getMockResponseReader() {
|
||||
EasyMock.expect(impl.getResponseReader(
|
||||
EasyMock.<HttpRequest>anyObject(),
|
||||
EasyMock.<HttpResponse>anyObject())).andReturn(mockResponseReader);
|
||||
}
|
||||
|
||||
private void removeFromCache(String theURI) throws Exception {
|
||||
mockCache.removeEntry(theURI);
|
||||
}
|
||||
|
||||
private void requestPolicyAllowsCaching(boolean allow) {
|
||||
EasyMock.expect(mockRequestPolicy.isServableFromCache(
|
||||
EasyMock.<HttpRequest>anyObject())).andReturn(allow);
|
||||
}
|
||||
|
||||
private void responseDoesNotHaveExplicitContentLength() {
|
||||
EasyMock.expect(mockBackendResponse.getFirstHeader("Content-Length"))
|
||||
.andReturn(null).anyTimes();
|
||||
}
|
||||
|
||||
private void responseRead() throws Exception {
|
||||
mockResponseReader.readResponse();
|
||||
}
|
||||
|
||||
private void responseLimitReached(boolean limitReached) throws Exception {
|
||||
EasyMock.expect(mockResponseReader.isLimitReached()).andReturn(limitReached);
|
||||
}
|
||||
|
||||
private void responseGetResource() throws Exception {
|
||||
EasyMock.expect(mockResponseReader.getResource()).andReturn(new HeapResource(new byte[] {} ));
|
||||
}
|
||||
|
||||
private void responseGetReconstructed() throws Exception {
|
||||
EasyMock.expect(mockResponseReader.getReconstructedResponse()).andReturn(mockReconstructedResponse);
|
||||
}
|
||||
|
||||
private void backendCallWasMadeWithRequest(HttpRequest request) throws IOException {
|
||||
EasyMock.expect(mockBackend.execute(
|
||||
EasyMock.<HttpHost>anyObject(),
|
||||
|
@ -1178,10 +798,6 @@ public class TestCachingHttpClient {
|
|||
EasyMock.<HttpResponse>anyObject())).andReturn(allow);
|
||||
}
|
||||
|
||||
private void gotCacheMiss(String theURI) throws Exception {
|
||||
EasyMock.expect(mockCache.getEntry(theURI)).andReturn(null);
|
||||
}
|
||||
|
||||
private void cacheEntrySuitable(boolean suitable) {
|
||||
EasyMock.expect(
|
||||
mockSuitabilityChecker.canCachedResponseBeUsed(
|
||||
|
@ -1190,68 +806,13 @@ public class TestCachingHttpClient {
|
|||
EasyMock.<HttpCacheEntry>anyObject())).andReturn(suitable);
|
||||
}
|
||||
|
||||
private void gotCacheHit(String theURI) throws Exception {
|
||||
EasyMock.expect(mockCache.getEntry(theURI)).andReturn(mockCacheEntry);
|
||||
}
|
||||
|
||||
private void gotCacheHit(String theURI, CacheEntry entry) throws Exception {
|
||||
EasyMock.expect(mockCache.getEntry(theURI)).andReturn(entry);
|
||||
}
|
||||
|
||||
private void cacheEntryHasVariants(boolean b) {
|
||||
EasyMock.expect(mockCacheEntry.hasVariants()).andReturn(b);
|
||||
}
|
||||
|
||||
private void cacheEntryHasVariants(boolean b, CacheEntry entry) {
|
||||
EasyMock.expect(entry.hasVariants()).andReturn(b);
|
||||
}
|
||||
|
||||
private void responseIsGeneratedFromCache() {
|
||||
EasyMock.expect(mockResponseGenerator.generateResponse(
|
||||
EasyMock.<HttpCacheEntry>anyObject())).andReturn(mockCachedResponse);
|
||||
}
|
||||
|
||||
private void responseStatusLineIsInspectable() {
|
||||
EasyMock.expect(mockBackendResponse.getStatusLine()).andReturn(new OKStatus()).anyTimes();
|
||||
}
|
||||
|
||||
private void responseGetHeaders() {
|
||||
EasyMock.expect(mockBackendResponse.getAllHeaders()).andReturn(new Header[] {}).anyTimes();
|
||||
}
|
||||
|
||||
private void responseIsGeneratedFromCache(CacheEntry entry) {
|
||||
EasyMock.expect(mockResponseGenerator.generateResponse(entry))
|
||||
.andReturn(mockCachedResponse);
|
||||
}
|
||||
|
||||
private void extractTheURI(String theURI) {
|
||||
EasyMock.expect(mockExtractor.getURI(host, request)).andReturn(theURI);
|
||||
}
|
||||
|
||||
private void extractVariantURI(String variantURI) {
|
||||
extractVariantURI(variantURI,mockCacheEntry);
|
||||
}
|
||||
|
||||
private void extractVariantURI(String variantURI, CacheEntry entry){
|
||||
EasyMock.expect(mockExtractor.getVariantURI(
|
||||
EasyMock.<HttpHost>anyObject(),
|
||||
EasyMock.<HttpRequest>anyObject(),
|
||||
EasyMock.same(entry))).andReturn(variantURI);
|
||||
}
|
||||
|
||||
private void putInCache(String theURI) throws Exception {
|
||||
mockCache.putEntry(theURI, mockCacheEntry);
|
||||
}
|
||||
|
||||
private void putInCache(String theURI, CacheEntry entry) throws Exception {
|
||||
mockCache.putEntry(theURI, entry);
|
||||
}
|
||||
|
||||
private void copyResource() throws IOException {
|
||||
EasyMock.expect(
|
||||
mockResourceFactory.copy(
|
||||
EasyMock.<String>anyObject(),
|
||||
EasyMock.<Resource>anyObject())).andReturn(new HeapResource(new byte[] {}));
|
||||
private void flushCache() throws IOException {
|
||||
mockCache.flushCacheEntriesFor(host, request);
|
||||
}
|
||||
|
||||
private void handleBackendResponseReturnsResponse(HttpRequest request, HttpResponse response)
|
||||
|
@ -1265,20 +826,6 @@ public class TestCachingHttpClient {
|
|||
EasyMock.<HttpResponse>anyObject())).andReturn(response);
|
||||
}
|
||||
|
||||
private void storeInCacheWasCalled() throws IOException {
|
||||
impl.storeInCache(
|
||||
EasyMock.<HttpHost>anyObject(),
|
||||
EasyMock.<HttpRequest>anyObject(),
|
||||
EasyMock.<HttpCacheEntry>anyObject());
|
||||
}
|
||||
|
||||
private void storeInCacheWasCalled(CacheEntry entry) throws IOException {
|
||||
impl.storeInCache(
|
||||
EasyMock.<HttpHost>anyObject(),
|
||||
EasyMock.<HttpRequest>anyObject(),
|
||||
EasyMock.same(entry));
|
||||
}
|
||||
|
||||
private void responseProtocolValidationIsCalled() throws ClientProtocolException {
|
||||
mockResponseProtocolCompliance.ensureProtocolCompliance(
|
||||
EasyMock.<HttpRequest>anyObject(),
|
||||
|
@ -1301,17 +848,13 @@ public class TestCachingHttpClient {
|
|||
mockedImpl = true;
|
||||
impl = EasyMock.createMockBuilder(CachingHttpClient.class).withConstructor(
|
||||
mockBackend,
|
||||
mockResourceFactory,
|
||||
mockValidityPolicy,
|
||||
mockResponsePolicy,
|
||||
mockExtractor,
|
||||
mockCache,
|
||||
mockResponseGenerator,
|
||||
mockInvalidator,
|
||||
mockRequestPolicy,
|
||||
mockSuitabilityChecker,
|
||||
mockConditionalRequestBuilder,
|
||||
mockCacheEntryUpdater,
|
||||
mockResponseProtocolCompliance,
|
||||
mockRequestProtocolCompliance).addMockedMethods(methods).createMock();
|
||||
}
|
||||
|
|
|
@ -93,14 +93,16 @@ public class TestProtocolDeviations {
|
|||
|
||||
originResponse = make200Response();
|
||||
|
||||
HttpCache cache = new BasicHttpCache(MAX_ENTRIES);
|
||||
CacheConfig params = new CacheConfig();
|
||||
params.setMaxObjectSizeBytes(MAX_BYTES);
|
||||
params.setMaxCacheEntries(MAX_ENTRIES);
|
||||
|
||||
HttpCache cache = new BasicHttpCache(params);
|
||||
mockBackend = EasyMock.createMock(HttpClient.class);
|
||||
mockEntity = EasyMock.createMock(HttpEntity.class);
|
||||
mockCache = EasyMock.createMock(HttpCache.class);
|
||||
|
||||
CacheConfig params = new CacheConfig();
|
||||
params.setMaxObjectSizeBytes(MAX_BYTES);
|
||||
impl = new CachingHttpClient(mockBackend, cache, new HeapResourceFactory(), params);
|
||||
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||
}
|
||||
|
||||
private HttpResponse make200Response() {
|
||||
|
|
|
@ -42,7 +42,6 @@ import org.apache.http.HttpStatus;
|
|||
import org.apache.http.HttpVersion;
|
||||
import org.apache.http.ProtocolVersion;
|
||||
import org.apache.http.client.ClientProtocolException;
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
import org.apache.http.entity.BasicHttpEntity;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.impl.client.RequestWrapper;
|
||||
|
@ -2220,9 +2219,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
|||
|
||||
CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes);
|
||||
|
||||
mockCache.putEntry(EasyMock.eq("http://foo.example.com/thing"), EasyMock.isA(HttpCacheEntry.class));
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, params);
|
||||
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, new HeapResourceFactory(), params);
|
||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||
|
||||
HttpRequest validate = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||
validate.setHeader("If-None-Match", "\"etag\"");
|
||||
|
@ -2232,17 +2231,23 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
|||
notModified.setHeader("Date", DateUtils.formatDate(now));
|
||||
notModified.setHeader("ETag", "\"etag\"");
|
||||
|
||||
EasyMock.expect(mockCache.getEntry("http://foo.example.com/thing")).andReturn(entry);
|
||||
HttpResponse reconstructed = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
|
||||
mockCache.flushInvalidatedCacheEntriesFor(host, request);
|
||||
EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry);
|
||||
EasyMock.expect(
|
||||
mockBackend.execute(EasyMock.eq(host), eqRequest(validate), (HttpContext) EasyMock
|
||||
.isNull())).andReturn(notModified);
|
||||
EasyMock.expect(mockCache.updateCacheEntry(EasyMock.same(host), EasyMock.same(request),
|
||||
EasyMock.same(entry), EasyMock.same(notModified), EasyMock.isA(Date.class),
|
||||
EasyMock.isA(Date.class)))
|
||||
.andReturn(reconstructed);
|
||||
|
||||
replayMocks();
|
||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||
HttpResponse result = impl.execute(host, request);
|
||||
verifyMocks();
|
||||
|
||||
Assert.assertEquals(200, result.getStatusLine().getStatusCode());
|
||||
Assert.assertSame(reconstructed, result);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
@ -2264,12 +2269,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
|||
|
||||
CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes);
|
||||
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, new HeapResourceFactory(), params);
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, params);
|
||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||
|
||||
EasyMock.expect(mockCache.getEntry("http://foo.example.com/thing")).andReturn(entry);
|
||||
mockCache.flushInvalidatedCacheEntriesFor(host, request);
|
||||
EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry);
|
||||
|
||||
replayMocks();
|
||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||
HttpResponse result = impl.execute(host, request);
|
||||
verifyMocks();
|
||||
|
||||
|
@ -2305,16 +2311,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
|||
|
||||
CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes);
|
||||
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, new HeapResourceFactory(), params);
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, params);
|
||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||
|
||||
EasyMock.expect(mockCache.getEntry("http://foo.example.com/thing")).andReturn(entry);
|
||||
mockCache.flushInvalidatedCacheEntriesFor(host, request);
|
||||
EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry);
|
||||
EasyMock.expect(
|
||||
mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class),
|
||||
(HttpContext) EasyMock.isNull())).andThrow(
|
||||
new IOException("can't talk to origin!")).anyTimes();
|
||||
|
||||
replayMocks();
|
||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||
|
||||
HttpResponse result = impl.execute(host, request);
|
||||
|
||||
|
@ -2506,12 +2513,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
|||
|
||||
CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes);
|
||||
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, new HeapResourceFactory(), params);
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, params);
|
||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||
|
||||
EasyMock.expect(mockCache.getEntry("http://foo.example.com/thing")).andReturn(entry);
|
||||
mockCache.flushInvalidatedCacheEntriesFor(host, request);
|
||||
EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry);
|
||||
|
||||
replayMocks();
|
||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||
HttpResponse result = impl.execute(host, request);
|
||||
verifyMocks();
|
||||
|
||||
|
@ -2550,7 +2558,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
|||
|
||||
CacheEntry entry = new CacheEntry(requestTime, responseTime, hdrs, bytes);
|
||||
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, new HeapResourceFactory(), params);
|
||||
impl = new CachingHttpClient(mockBackend, mockCache, params);
|
||||
|
||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||
|
||||
HttpResponse validated = make200Response();
|
||||
validated.setHeader("Cache-Control", "public");
|
||||
|
@ -2558,18 +2568,20 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
|||
validated.setHeader("Content-Length", "128");
|
||||
validated.setEntity(new ByteArrayEntity(bytes));
|
||||
|
||||
HttpResponse reconstructed = make200Response();
|
||||
|
||||
Capture<HttpRequest> cap = new Capture<HttpRequest>();
|
||||
|
||||
EasyMock.expect(mockCache.getEntry("http://foo.example.com/thing")).andReturn(entry);
|
||||
|
||||
mockCache.putEntry(EasyMock.isA(String.class), EasyMock.isA(HttpCacheEntry.class));
|
||||
|
||||
mockCache.flushInvalidatedCacheEntriesFor(host, request);
|
||||
EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry);
|
||||
EasyMock.expect(
|
||||
mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.capture(cap),
|
||||
(HttpContext) EasyMock.isNull())).andReturn(validated).times(0, 1);
|
||||
EasyMock.expect(mockCache.updateCacheEntry(EasyMock.same(host), EasyMock.same(request), EasyMock.same(entry),
|
||||
EasyMock.same(validated), EasyMock.isA(Date.class), EasyMock.isA(Date.class)))
|
||||
.andReturn(reconstructed).times(0, 1);
|
||||
|
||||
replayMocks();
|
||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||
HttpResponse result = impl.execute(host, request);
|
||||
verifyMocks();
|
||||
|
||||
|
|
|
@ -1,171 +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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.http.client.cache.HttpCacheEntry;
|
||||
import org.apache.http.client.cache.HttpCacheUpdateCallback;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
||||
public class TestResponseCache {
|
||||
|
||||
private BasicHttpCache cache;
|
||||
private HttpCacheEntry entry;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
cache = new BasicHttpCache(5);
|
||||
entry = new CacheEntry();
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testEntryRemainsInCacheWhenPutThere() throws Exception {
|
||||
cache.putEntry("foo", entry);
|
||||
|
||||
HttpCacheEntry cachedEntry = cache.getEntry("foo");
|
||||
|
||||
Assert.assertSame(entry, cachedEntry);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testRemovedEntriesDoNotExistAnymore() throws Exception {
|
||||
cache.putEntry("foo", entry);
|
||||
|
||||
cache.removeEntry("foo");
|
||||
|
||||
HttpCacheEntry nullEntry = cache.getEntry("foo");
|
||||
|
||||
Assert.assertNull(nullEntry);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheHoldsNoMoreThanSpecifiedMaxEntries() throws Exception {
|
||||
BasicHttpCache cache = new BasicHttpCache(1);
|
||||
|
||||
HttpCacheEntry entry1 = new CacheEntry();
|
||||
cache.putEntry("foo", entry1);
|
||||
|
||||
HttpCacheEntry entry2 = new CacheEntry();
|
||||
cache.putEntry("bar", entry2);
|
||||
|
||||
HttpCacheEntry entry3 = new CacheEntry();
|
||||
cache.putEntry("baz", entry3);
|
||||
|
||||
HttpCacheEntry e1 = cache.getEntry("foo");
|
||||
Assert.assertNull("Got foo entry when we should not", e1);
|
||||
|
||||
HttpCacheEntry e2 = cache.getEntry("bar");
|
||||
Assert.assertNull("Got bar entry when we should not", e2);
|
||||
|
||||
HttpCacheEntry e3 = cache.getEntry("baz");
|
||||
Assert.assertNotNull("Did not get baz entry, but should have", e3);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testSmallCacheKeepsMostRecentlyUsedEntry() throws Exception {
|
||||
|
||||
final int max_size = 3;
|
||||
BasicHttpCache cache = new BasicHttpCache(max_size);
|
||||
|
||||
// fill the cache with entries
|
||||
for (int i = 0; i < max_size; i++) {
|
||||
HttpCacheEntry entry = new CacheEntry();
|
||||
cache.putEntry("entry" + i, entry);
|
||||
}
|
||||
|
||||
// read the eldest entry to make it the MRU entry
|
||||
cache.getEntry("entry0");
|
||||
|
||||
// add another entry, which kicks out the eldest (should be the 2nd one
|
||||
// created), and becomes the new MRU entry
|
||||
HttpCacheEntry newMru = new CacheEntry();
|
||||
cache.putEntry("newMru", newMru);
|
||||
|
||||
// get the original second eldest
|
||||
HttpCacheEntry gone = cache.getEntry("entry1");
|
||||
Assert.assertNull("entry1 should be gone", gone);
|
||||
|
||||
HttpCacheEntry latest = cache.getEntry("newMru");
|
||||
Assert.assertNotNull("latest entry should still be there", latest);
|
||||
|
||||
HttpCacheEntry originalEldest = cache.getEntry("entry0");
|
||||
Assert.assertNotNull("original eldest entry should still be there", originalEldest);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testZeroMaxSizeCacheDoesNotStoreAnything() throws Exception {
|
||||
BasicHttpCache cache = new BasicHttpCache(0);
|
||||
|
||||
HttpCacheEntry entry = new CacheEntry();
|
||||
cache.putEntry("foo", entry);
|
||||
|
||||
HttpCacheEntry gone = cache.getEntry("foo");
|
||||
|
||||
Assert.assertNull("This cache should not have anything in it!", gone);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testCacheEntryCallbackUpdatesCacheEntry() throws Exception {
|
||||
|
||||
final byte[] expectedArray = new byte[] { 1, 2, 3, 4, 5 };
|
||||
|
||||
HttpCacheEntry entry = new CacheEntry();
|
||||
|
||||
cache.putEntry("foo", entry);
|
||||
|
||||
cache.updateEntry("foo", new HttpCacheUpdateCallback() {
|
||||
|
||||
public HttpCacheEntry update(HttpCacheEntry existing) {
|
||||
HttpCacheEntry updated = new HttpCacheEntry(
|
||||
existing.getRequestDate(),
|
||||
existing.getRequestDate(),
|
||||
existing.getStatusLine(),
|
||||
existing.getAllHeaders(),
|
||||
new HeapResource(expectedArray),
|
||||
null);
|
||||
return updated;
|
||||
}
|
||||
});
|
||||
|
||||
HttpCacheEntry afterUpdate = cache.getEntry("foo");
|
||||
|
||||
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
|
||||
InputStream instream = afterUpdate.getResource().getInputStream();
|
||||
byte[] buf = new byte[2048];
|
||||
int len;
|
||||
while ((len = instream.read(buf)) != -1) {
|
||||
outstream.write(buf, 0, len);
|
||||
}
|
||||
byte[] bytes = outstream.toByteArray();
|
||||
Assert.assertArrayEquals(expectedArray, bytes);
|
||||
}
|
||||
|
||||
}
|
|
@ -26,18 +26,14 @@
|
|||
*/
|
||||
package org.apache.http.impl.client.cache;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
|
||||
import org.apache.http.Header;
|
||||
import org.apache.http.HttpEntity;
|
||||
import org.apache.http.HttpRequest;
|
||||
import org.apache.http.HttpResponse;
|
||||
import org.apache.http.HttpStatus;
|
||||
import org.apache.http.HttpVersion;
|
||||
import org.apache.http.message.BasicRequestLine;
|
||||
import org.apache.http.client.methods.HttpGet;
|
||||
import org.apache.http.entity.ByteArrayEntity;
|
||||
import org.apache.http.message.BasicHttpResponse;
|
||||
import org.apache.http.util.EntityUtils;
|
||||
import org.easymock.classextension.EasyMock;
|
||||
import org.junit.Assert;
|
||||
import org.junit.Before;
|
||||
import org.junit.Test;
|
||||
|
@ -46,56 +42,44 @@ public class TestSizeLimitedResponseReader {
|
|||
|
||||
private static final long MAX_SIZE = 4;
|
||||
|
||||
private HttpRequest request;
|
||||
private SizeLimitedResponseReader impl;
|
||||
private HttpRequest mockRequest;
|
||||
private HttpResponse mockResponse;
|
||||
private HttpEntity mockEntity;
|
||||
|
||||
private boolean mockedImpl;
|
||||
|
||||
@Before
|
||||
public void setUp() {
|
||||
mockRequest = EasyMock.createMock(HttpRequest.class);
|
||||
mockResponse = EasyMock.createMock(HttpResponse.class);
|
||||
mockEntity = EasyMock.createMock(HttpEntity.class);
|
||||
request = new HttpGet("http://foo.example.com/bar");
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testLargeResponseIsTooLarge() throws Exception {
|
||||
byte[] buf = new byte[] { 1, 2, 3, 4, 5};
|
||||
requestReturnsRequestLine();
|
||||
responseReturnsProtocolVersion();
|
||||
responseReturnsHeaders();
|
||||
responseReturnsContent(new ByteArrayInputStream(buf));
|
||||
initReader();
|
||||
replayMocks();
|
||||
byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
|
||||
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
response.setEntity(new ByteArrayEntity(buf));
|
||||
|
||||
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
|
||||
|
||||
impl.readResponse();
|
||||
boolean tooLarge = impl.isLimitReached();
|
||||
HttpResponse response = impl.getReconstructedResponse();
|
||||
byte[] result = EntityUtils.toByteArray(response.getEntity());
|
||||
HttpResponse result = impl.getReconstructedResponse();
|
||||
byte[] body = EntityUtils.toByteArray(result.getEntity());
|
||||
|
||||
verifyMocks();
|
||||
Assert.assertTrue(tooLarge);
|
||||
Assert.assertArrayEquals(buf, result);
|
||||
Assert.assertArrayEquals(buf, body);
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testExactSizeResponseIsNotTooLarge() throws Exception {
|
||||
byte[] buf = new byte[] { 1, 2, 3, 4 };
|
||||
requestReturnsRequestLine();
|
||||
responseReturnsProtocolVersion();
|
||||
responseReturnsHeaders();
|
||||
responseReturnsContent(new ByteArrayInputStream(buf));
|
||||
initReader();
|
||||
replayMocks();
|
||||
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
response.setEntity(new ByteArrayEntity(buf));
|
||||
|
||||
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
|
||||
|
||||
impl.readResponse();
|
||||
boolean tooLarge = impl.isLimitReached();
|
||||
HttpResponse response = impl.getReconstructedResponse();
|
||||
byte[] result = EntityUtils.toByteArray(response.getEntity());
|
||||
HttpResponse reconstructed = impl.getReconstructedResponse();
|
||||
byte[] result = EntityUtils.toByteArray(reconstructed.getEntity());
|
||||
|
||||
verifyMocks();
|
||||
Assert.assertFalse(tooLarge);
|
||||
Assert.assertArrayEquals(buf, result);
|
||||
}
|
||||
|
@ -103,18 +87,15 @@ public class TestSizeLimitedResponseReader {
|
|||
@Test
|
||||
public void testSmallResponseIsNotTooLarge() throws Exception {
|
||||
byte[] buf = new byte[] { 1, 2, 3 };
|
||||
requestReturnsRequestLine();
|
||||
responseReturnsProtocolVersion();
|
||||
responseReturnsHeaders();
|
||||
responseReturnsContent(new ByteArrayInputStream(buf));
|
||||
initReader();
|
||||
replayMocks();
|
||||
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
response.setEntity(new ByteArrayEntity(buf));
|
||||
|
||||
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
|
||||
|
||||
impl.readResponse();
|
||||
boolean tooLarge = impl.isLimitReached();
|
||||
HttpResponse response = impl.getReconstructedResponse();
|
||||
byte[] result = EntityUtils.toByteArray(response.getEntity());
|
||||
verifyMocks();
|
||||
HttpResponse reconstructed = impl.getReconstructedResponse();
|
||||
byte[] result = EntityUtils.toByteArray(reconstructed.getEntity());
|
||||
|
||||
Assert.assertFalse(tooLarge);
|
||||
Assert.assertArrayEquals(buf, result);
|
||||
|
@ -122,56 +103,14 @@ public class TestSizeLimitedResponseReader {
|
|||
|
||||
@Test
|
||||
public void testResponseWithNoEntityIsNotTooLarge() throws Exception {
|
||||
responseHasNullEntity();
|
||||
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||
|
||||
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
|
||||
|
||||
initReader();
|
||||
replayMocks();
|
||||
impl.readResponse();
|
||||
boolean tooLarge = impl.isLimitReached();
|
||||
verifyMocks();
|
||||
|
||||
Assert.assertFalse(tooLarge);
|
||||
}
|
||||
|
||||
private void responseReturnsContent(InputStream buffer) throws IOException {
|
||||
EasyMock.expect(mockResponse.getEntity()).andReturn(mockEntity);
|
||||
EasyMock.expect(mockEntity.getContent()).andReturn(buffer);
|
||||
}
|
||||
|
||||
private void requestReturnsRequestLine() {
|
||||
EasyMock.expect(mockRequest.getRequestLine()).andReturn(
|
||||
new BasicRequestLine("GET", "/", HttpVersion.HTTP_1_1));
|
||||
}
|
||||
|
||||
private void responseReturnsProtocolVersion() {
|
||||
EasyMock.expect(mockResponse.getProtocolVersion()).andReturn(HttpVersion.HTTP_1_1);
|
||||
}
|
||||
|
||||
private void responseReturnsHeaders() {
|
||||
EasyMock.expect(mockResponse.getAllHeaders()).andReturn(new Header[] {});
|
||||
}
|
||||
|
||||
private void responseHasNullEntity() {
|
||||
EasyMock.expect(mockResponse.getEntity()).andReturn(null);
|
||||
}
|
||||
|
||||
private void verifyMocks() {
|
||||
EasyMock.verify(mockRequest, mockResponse, mockEntity);
|
||||
if (mockedImpl) {
|
||||
EasyMock.verify(impl);
|
||||
}
|
||||
}
|
||||
|
||||
private void replayMocks() {
|
||||
EasyMock.replay(mockRequest, mockResponse, mockEntity);
|
||||
if (mockedImpl) {
|
||||
EasyMock.replay(impl);
|
||||
}
|
||||
}
|
||||
|
||||
private void initReader() {
|
||||
impl = new SizeLimitedResponseReader(
|
||||
new HeapResourceFactory(), MAX_SIZE, mockRequest, mockResponse);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
|
@ -40,11 +40,11 @@ import org.junit.Test;
|
|||
public class TestEhcacheHttpCache extends TestCase {
|
||||
|
||||
private Ehcache mockCache;
|
||||
private EhcacheHttpCache impl;
|
||||
private EhcacheHttpCacheStorage impl;
|
||||
|
||||
public void setUp() {
|
||||
mockCache = EasyMock.createMock(Ehcache.class);
|
||||
impl = new EhcacheHttpCache(mockCache);
|
||||
impl = new EhcacheHttpCacheStorage(mockCache);
|
||||
}
|
||||
|
||||
@Test
|
||||
|
|
|
@ -1,99 +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
|
||||
* <http://www.apache.org/>.
|
||||
*
|
||||
*/
|
||||
package org.apache.http.impl.client.cache.ehcache;
|
||||
|
||||
import net.sf.ehcache.CacheManager;
|
||||
import net.sf.ehcache.config.CacheConfiguration;
|
||||
import net.sf.ehcache.config.Configuration;
|
||||
import net.sf.ehcache.store.MemoryStoreEvictionPolicy;
|
||||
|
||||
import org.apache.http.HttpHost;
|
||||
import org.apache.http.HttpVersion;
|
||||
import org.apache.http.client.HttpClient;
|
||||
import org.apache.http.client.cache.HttpCache;
|
||||
import org.apache.http.impl.client.cache.CacheConfig;
|
||||
import org.apache.http.impl.client.cache.CachingHttpClient;
|
||||
import org.apache.http.impl.client.cache.HeapResourceFactory;
|
||||
import org.apache.http.impl.client.cache.HttpTestUtils;
|
||||
import org.apache.http.impl.client.cache.TestProtocolRequirements;
|
||||
import org.apache.http.message.BasicHttpRequest;
|
||||
import org.easymock.classextension.EasyMock;
|
||||
import org.junit.After;
|
||||
import org.junit.AfterClass;
|
||||
import org.junit.Before;
|
||||
import org.junit.BeforeClass;
|
||||
|
||||
public class TestEhcacheProtcolRequirements extends TestProtocolRequirements{
|
||||
|
||||
private final String TEST_EHCACHE_NAME = "TestEhcacheProtocolRequirements-cache";
|
||||
|
||||
private static CacheManager CACHE_MANAGER;
|
||||
|
||||
@BeforeClass
|
||||
public static void setUpGlobal() {
|
||||
Configuration config = new Configuration();
|
||||
config.addDefaultCache(
|
||||
new CacheConfiguration("default", Integer.MAX_VALUE)
|
||||
.memoryStoreEvictionPolicy(MemoryStoreEvictionPolicy.LFU)
|
||||
.overflowToDisk(false));
|
||||
CACHE_MANAGER = CacheManager.create(config);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Before
|
||||
public void setUp() {
|
||||
host = new HttpHost("foo.example.com");
|
||||
|
||||
body = HttpTestUtils.makeBody(entityLength);
|
||||
|
||||
request = new BasicHttpRequest("GET", "/foo", HttpVersion.HTTP_1_1);
|
||||
|
||||
originResponse = make200Response();
|
||||
|
||||
if (CACHE_MANAGER.cacheExists(TEST_EHCACHE_NAME)){
|
||||
CACHE_MANAGER.removeCache(TEST_EHCACHE_NAME);
|
||||
}
|
||||
CACHE_MANAGER.addCache(TEST_EHCACHE_NAME);
|
||||
cache = new EhcacheHttpCache(CACHE_MANAGER.getCache(TEST_EHCACHE_NAME));
|
||||
mockBackend = EasyMock.createMock(HttpClient.class);
|
||||
mockCache = EasyMock.createMock(HttpCache.class);
|
||||
params = new CacheConfig();
|
||||
params.setMaxObjectSizeBytes(MAX_BYTES);
|
||||
impl = new CachingHttpClient(mockBackend, cache, new HeapResourceFactory(), params);
|
||||
}
|
||||
|
||||
@After
|
||||
public void tearDown(){
|
||||
CACHE_MANAGER.removeCache(TEST_EHCACHE_NAME);
|
||||
}
|
||||
|
||||
@AfterClass
|
||||
public static void tearDownGlobal(){
|
||||
CACHE_MANAGER.shutdown();
|
||||
}
|
||||
|
||||
}
|
Loading…
Reference in New Issue