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;
|
package org.apache.http.client.cache;
|
||||||
|
|
||||||
import java.io.IOException;
|
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
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
public interface HttpCache {
|
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(
|
HttpResponse cacheAndReturnResponse(
|
||||||
String key, HttpCacheUpdateCallback callback) throws IOException;
|
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;
|
package org.apache.http.impl.client.cache;
|
||||||
|
|
||||||
import java.io.IOException;
|
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.HttpCache;
|
||||||
import org.apache.http.client.cache.HttpCacheEntry;
|
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.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 {
|
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) {
|
public BasicHttpCache(ResourceFactory resourceFactory, HttpCacheStorage storage, CacheConfig config) {
|
||||||
this.entries = new CacheMap(maxEntries);
|
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
public BasicHttpCache(CacheConfig config) {
|
||||||
* Places a HttpCacheEntry in the cache
|
this(new HeapResourceFactory(), new BasicHttpCacheStorage(config), config);
|
||||||
*
|
|
||||||
* @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() {
|
||||||
* Gets an entry from the cache, if it exists
|
this(new CacheConfig());
|
||||||
*
|
|
||||||
* @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 void flushCacheEntriesFor(HttpHost host, HttpRequest request)
|
||||||
* Removes a HttpCacheEntry from the cache
|
throws IOException {
|
||||||
*
|
String uri = uriExtractor.getURI(host, request);
|
||||||
* @param url
|
storage.removeEntry(uri);
|
||||||
* Url that is the cache key
|
|
||||||
*/
|
|
||||||
public synchronized void removeEntry(String url) throws IOException {
|
|
||||||
entries.remove(url);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public synchronized void updateEntry(
|
void storeInCache(
|
||||||
String url,
|
HttpHost target, HttpRequest request, HttpCacheEntry entry) throws IOException {
|
||||||
HttpCacheUpdateCallback callback) throws IOException {
|
if (entry.hasVariants()) {
|
||||||
HttpCacheEntry existingEntry = entries.get(url);
|
storeVariantEntry(target, request, entry);
|
||||||
entries.put(url, callback.update(existingEntry));
|
} 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;
|
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 maxObjectSizeBytes = DEFAULT_MAX_OBJECT_SIZE_BYTES;
|
||||||
|
private int maxCacheEntries = DEFAULT_MAX_CACHE_ENTRIES;
|
||||||
|
|
||||||
private boolean isSharedCache = true;
|
private boolean isSharedCache = true;
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -74,4 +81,19 @@ public class CacheConfig {
|
||||||
this.isSharedCache = isSharedCache;
|
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.HeaderConstants;
|
||||||
import org.apache.http.client.cache.HttpCache;
|
import org.apache.http.client.cache.HttpCache;
|
||||||
import org.apache.http.client.cache.HttpCacheEntry;
|
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
|
* 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
|
@ThreadSafe // so long as the cache implementation is thread-safe
|
||||||
class CacheInvalidator {
|
class CacheInvalidator {
|
||||||
|
|
||||||
private final HttpCache cache;
|
private final HttpCacheStorage storage;
|
||||||
private final URIExtractor uriExtractor;
|
private final URIExtractor uriExtractor;
|
||||||
|
|
||||||
private final Log log = LogFactory.getLog(getClass());
|
private final Log log = LogFactory.getLog(getClass());
|
||||||
|
@ -60,13 +61,13 @@ class CacheInvalidator {
|
||||||
* {@link URIExtractor}.
|
* {@link URIExtractor}.
|
||||||
*
|
*
|
||||||
* @param uriExtractor Provides identifiers for the keys to store cache entries
|
* @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(
|
public CacheInvalidator(
|
||||||
final URIExtractor uriExtractor,
|
final URIExtractor uriExtractor,
|
||||||
final HttpCache cache) {
|
final HttpCacheStorage storage) {
|
||||||
this.uriExtractor = uriExtractor;
|
this.uriExtractor = uriExtractor;
|
||||||
this.cache = cache;
|
this.storage = storage;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -82,15 +83,15 @@ class CacheInvalidator {
|
||||||
|
|
||||||
String theUri = uriExtractor.getURI(host, req);
|
String theUri = uriExtractor.getURI(host, req);
|
||||||
|
|
||||||
HttpCacheEntry parent = cache.getEntry(theUri);
|
HttpCacheEntry parent = storage.getEntry(theUri);
|
||||||
|
|
||||||
log.debug("parent entry: " + parent);
|
log.debug("parent entry: " + parent);
|
||||||
|
|
||||||
if (parent != null) {
|
if (parent != null) {
|
||||||
for (String variantURI : parent.getVariantURIs()) {
|
for (String variantURI : parent.getVariantURIs()) {
|
||||||
cache.removeEntry(variantURI);
|
storage.removeEntry(variantURI);
|
||||||
}
|
}
|
||||||
cache.removeEntry(theUri);
|
storage.removeEntry(theUri);
|
||||||
}
|
}
|
||||||
URL reqURL;
|
URL reqURL;
|
||||||
try {
|
try {
|
||||||
|
@ -115,7 +116,7 @@ class CacheInvalidator {
|
||||||
|
|
||||||
protected void flushUriIfSameHost(URL requestURL, URL targetURL) throws IOException {
|
protected void flushUriIfSameHost(URL requestURL, URL targetURL) throws IOException {
|
||||||
if (targetURL.getAuthority().equalsIgnoreCase(requestURL.getAuthority())) {
|
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.io.IOException;
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.HashSet;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
import java.util.Set;
|
|
||||||
import java.util.concurrent.atomic.AtomicLong;
|
import java.util.concurrent.atomic.AtomicLong;
|
||||||
|
|
||||||
import org.apache.commons.logging.Log;
|
import org.apache.commons.logging.Log;
|
||||||
import org.apache.commons.logging.LogFactory;
|
import org.apache.commons.logging.LogFactory;
|
||||||
import org.apache.http.Header;
|
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.HttpResponse;
|
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.HeaderConstants;
|
||||||
import org.apache.http.client.cache.HttpCache;
|
import org.apache.http.client.cache.HttpCache;
|
||||||
import org.apache.http.client.cache.HttpCacheEntry;
|
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.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.conn.ClientConnectionManager;
|
import org.apache.http.conn.ClientConnectionManager;
|
||||||
import org.apache.http.entity.ByteArrayEntity;
|
|
||||||
import org.apache.http.impl.client.DefaultHttpClient;
|
import org.apache.http.impl.client.DefaultHttpClient;
|
||||||
import org.apache.http.message.BasicHttpResponse;
|
import org.apache.http.message.BasicHttpResponse;
|
||||||
import org.apache.http.message.BasicStatusLine;
|
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
|
@ThreadSafe // So long as the responseCache implementation is threadsafe
|
||||||
public class CachingHttpClient implements HttpClient {
|
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 static boolean SUPPORTS_RANGE_AND_CONTENT_RANGE_HEADERS = false;
|
||||||
|
|
||||||
private final AtomicLong cacheHits = new AtomicLong();
|
private final AtomicLong cacheHits = new AtomicLong();
|
||||||
|
@ -79,19 +71,14 @@ public class CachingHttpClient implements HttpClient {
|
||||||
|
|
||||||
private final HttpClient backend;
|
private final HttpClient backend;
|
||||||
private final HttpCache responseCache;
|
private final HttpCache responseCache;
|
||||||
private final ResourceFactory resourceFactory;
|
|
||||||
private final CacheValidityPolicy validityPolicy;
|
private final CacheValidityPolicy validityPolicy;
|
||||||
private final ResponseCachingPolicy responseCachingPolicy;
|
private final ResponseCachingPolicy responseCachingPolicy;
|
||||||
private final URIExtractor uriExtractor;
|
|
||||||
private final CachedHttpResponseGenerator responseGenerator;
|
private final CachedHttpResponseGenerator responseGenerator;
|
||||||
private final CacheInvalidator cacheInvalidator;
|
|
||||||
private final CacheableRequestPolicy cacheableRequestPolicy;
|
private final CacheableRequestPolicy cacheableRequestPolicy;
|
||||||
private final CachedResponseSuitabilityChecker suitabilityChecker;
|
private final CachedResponseSuitabilityChecker suitabilityChecker;
|
||||||
|
|
||||||
private final ConditionalRequestBuilder conditionalRequestBuilder;
|
private final ConditionalRequestBuilder conditionalRequestBuilder;
|
||||||
|
|
||||||
private final CacheEntryUpdater cacheEntryUpdater;
|
|
||||||
|
|
||||||
private final int maxObjectSizeBytes;
|
private final int maxObjectSizeBytes;
|
||||||
private final boolean sharedCache;
|
private final boolean sharedCache;
|
||||||
|
|
||||||
|
@ -103,7 +90,6 @@ public class CachingHttpClient implements HttpClient {
|
||||||
public CachingHttpClient(
|
public CachingHttpClient(
|
||||||
HttpClient client,
|
HttpClient client,
|
||||||
HttpCache cache,
|
HttpCache cache,
|
||||||
ResourceFactory resourceFactory,
|
|
||||||
CacheConfig config) {
|
CacheConfig config) {
|
||||||
super();
|
super();
|
||||||
if (client == null) {
|
if (client == null) {
|
||||||
|
@ -112,9 +98,6 @@ public class CachingHttpClient implements HttpClient {
|
||||||
if (cache == null) {
|
if (cache == null) {
|
||||||
throw new IllegalArgumentException("HttpCache may not be null");
|
throw new IllegalArgumentException("HttpCache may not be null");
|
||||||
}
|
}
|
||||||
if (resourceFactory == null) {
|
|
||||||
throw new IllegalArgumentException("ResourceFactory may not be null");
|
|
||||||
}
|
|
||||||
if (config == null) {
|
if (config == null) {
|
||||||
throw new IllegalArgumentException("CacheConfig may not be null");
|
throw new IllegalArgumentException("CacheConfig may not be null");
|
||||||
}
|
}
|
||||||
|
@ -122,16 +105,12 @@ public class CachingHttpClient implements HttpClient {
|
||||||
this.sharedCache = config.isSharedCache();
|
this.sharedCache = config.isSharedCache();
|
||||||
this.backend = client;
|
this.backend = client;
|
||||||
this.responseCache = cache;
|
this.responseCache = cache;
|
||||||
this.resourceFactory = resourceFactory;
|
|
||||||
this.validityPolicy = new CacheValidityPolicy();
|
this.validityPolicy = new CacheValidityPolicy();
|
||||||
this.responseCachingPolicy = new ResponseCachingPolicy(maxObjectSizeBytes, sharedCache);
|
this.responseCachingPolicy = new ResponseCachingPolicy(maxObjectSizeBytes, sharedCache);
|
||||||
this.responseGenerator = new CachedHttpResponseGenerator(this.validityPolicy);
|
this.responseGenerator = new CachedHttpResponseGenerator(this.validityPolicy);
|
||||||
this.uriExtractor = new URIExtractor();
|
|
||||||
this.cacheInvalidator = new CacheInvalidator(this.uriExtractor, this.responseCache);
|
|
||||||
this.cacheableRequestPolicy = new CacheableRequestPolicy();
|
this.cacheableRequestPolicy = new CacheableRequestPolicy();
|
||||||
this.suitabilityChecker = new CachedResponseSuitabilityChecker(this.validityPolicy);
|
this.suitabilityChecker = new CachedResponseSuitabilityChecker(this.validityPolicy);
|
||||||
this.conditionalRequestBuilder = new ConditionalRequestBuilder();
|
this.conditionalRequestBuilder = new ConditionalRequestBuilder();
|
||||||
this.cacheEntryUpdater = new CacheEntryUpdater(this.resourceFactory);
|
|
||||||
|
|
||||||
this.responseCompliance = new ResponseProtocolCompliance();
|
this.responseCompliance = new ResponseProtocolCompliance();
|
||||||
this.requestCompliance = new RequestProtocolCompliance();
|
this.requestCompliance = new RequestProtocolCompliance();
|
||||||
|
@ -139,91 +118,73 @@ public class CachingHttpClient implements HttpClient {
|
||||||
|
|
||||||
public CachingHttpClient() {
|
public CachingHttpClient() {
|
||||||
this(new DefaultHttpClient(),
|
this(new DefaultHttpClient(),
|
||||||
new BasicHttpCache(MAX_CACHE_ENTRIES),
|
new BasicHttpCache(),
|
||||||
new HeapResourceFactory(),
|
|
||||||
new CacheConfig());
|
new CacheConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachingHttpClient(CacheConfig config) {
|
public CachingHttpClient(CacheConfig config) {
|
||||||
this(new DefaultHttpClient(),
|
this(new DefaultHttpClient(),
|
||||||
new BasicHttpCache(MAX_CACHE_ENTRIES),
|
new BasicHttpCache(config),
|
||||||
new HeapResourceFactory(),
|
|
||||||
config);
|
config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachingHttpClient(HttpClient client) {
|
public CachingHttpClient(HttpClient client) {
|
||||||
this(client,
|
this(client,
|
||||||
new BasicHttpCache(MAX_CACHE_ENTRIES),
|
new BasicHttpCache(),
|
||||||
new HeapResourceFactory(),
|
|
||||||
new CacheConfig());
|
new CacheConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachingHttpClient(HttpClient client, CacheConfig config) {
|
public CachingHttpClient(HttpClient client, CacheConfig config) {
|
||||||
this(client,
|
this(client,
|
||||||
new BasicHttpCache(MAX_CACHE_ENTRIES),
|
new BasicHttpCache(config),
|
||||||
new HeapResourceFactory(),
|
|
||||||
config);
|
config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachingHttpClient(
|
public CachingHttpClient(
|
||||||
HttpCache cache,
|
HttpCache cache) {
|
||||||
ResourceFactory resourceFactory) {
|
|
||||||
this(new DefaultHttpClient(),
|
this(new DefaultHttpClient(),
|
||||||
cache,
|
cache,
|
||||||
resourceFactory,
|
|
||||||
new CacheConfig());
|
new CacheConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachingHttpClient(
|
public CachingHttpClient(
|
||||||
HttpCache cache,
|
HttpCache cache,
|
||||||
ResourceFactory resourceFactory,
|
|
||||||
CacheConfig config) {
|
CacheConfig config) {
|
||||||
this(new DefaultHttpClient(),
|
this(new DefaultHttpClient(),
|
||||||
cache,
|
cache,
|
||||||
resourceFactory,
|
|
||||||
config);
|
config);
|
||||||
}
|
}
|
||||||
|
|
||||||
public CachingHttpClient(
|
public CachingHttpClient(
|
||||||
HttpClient client,
|
HttpClient client,
|
||||||
HttpCache cache,
|
HttpCache cache) {
|
||||||
ResourceFactory resourceFactory) {
|
|
||||||
this(client,
|
this(client,
|
||||||
cache,
|
cache,
|
||||||
resourceFactory,
|
|
||||||
new CacheConfig());
|
new CacheConfig());
|
||||||
}
|
}
|
||||||
|
|
||||||
CachingHttpClient(
|
CachingHttpClient(
|
||||||
HttpClient backend,
|
HttpClient backend,
|
||||||
ResourceFactory resourceFactory,
|
|
||||||
CacheValidityPolicy validityPolicy,
|
CacheValidityPolicy validityPolicy,
|
||||||
ResponseCachingPolicy responseCachingPolicy,
|
ResponseCachingPolicy responseCachingPolicy,
|
||||||
URIExtractor uriExtractor,
|
|
||||||
HttpCache responseCache,
|
HttpCache responseCache,
|
||||||
CachedHttpResponseGenerator responseGenerator,
|
CachedHttpResponseGenerator responseGenerator,
|
||||||
CacheInvalidator cacheInvalidator,
|
|
||||||
CacheableRequestPolicy cacheableRequestPolicy,
|
CacheableRequestPolicy cacheableRequestPolicy,
|
||||||
CachedResponseSuitabilityChecker suitabilityChecker,
|
CachedResponseSuitabilityChecker suitabilityChecker,
|
||||||
ConditionalRequestBuilder conditionalRequestBuilder,
|
ConditionalRequestBuilder conditionalRequestBuilder,
|
||||||
CacheEntryUpdater entryUpdater,
|
|
||||||
ResponseProtocolCompliance responseCompliance,
|
ResponseProtocolCompliance responseCompliance,
|
||||||
RequestProtocolCompliance requestCompliance) {
|
RequestProtocolCompliance requestCompliance) {
|
||||||
CacheConfig config = new CacheConfig();
|
CacheConfig config = new CacheConfig();
|
||||||
this.maxObjectSizeBytes = config.getMaxObjectSizeBytes();
|
this.maxObjectSizeBytes = config.getMaxObjectSizeBytes();
|
||||||
this.sharedCache = config.isSharedCache();
|
this.sharedCache = config.isSharedCache();
|
||||||
this.backend = backend;
|
this.backend = backend;
|
||||||
this.resourceFactory = resourceFactory;
|
|
||||||
this.validityPolicy = validityPolicy;
|
this.validityPolicy = validityPolicy;
|
||||||
this.responseCachingPolicy = responseCachingPolicy;
|
this.responseCachingPolicy = responseCachingPolicy;
|
||||||
this.uriExtractor = uriExtractor;
|
|
||||||
this.responseCache = responseCache;
|
this.responseCache = responseCache;
|
||||||
this.responseGenerator = responseGenerator;
|
this.responseGenerator = responseGenerator;
|
||||||
this.cacheInvalidator = cacheInvalidator;
|
|
||||||
this.cacheableRequestPolicy = cacheableRequestPolicy;
|
this.cacheableRequestPolicy = cacheableRequestPolicy;
|
||||||
this.suitabilityChecker = suitabilityChecker;
|
this.suitabilityChecker = suitabilityChecker;
|
||||||
this.conditionalRequestBuilder = conditionalRequestBuilder;
|
this.conditionalRequestBuilder = conditionalRequestBuilder;
|
||||||
this.cacheEntryUpdater = entryUpdater;
|
|
||||||
this.responseCompliance = responseCompliance;
|
this.responseCompliance = responseCompliance;
|
||||||
this.requestCompliance = requestCompliance;
|
this.requestCompliance = requestCompliance;
|
||||||
}
|
}
|
||||||
|
@ -409,13 +370,13 @@ public class CachingHttpClient implements HttpClient {
|
||||||
throw new ClientProtocolException(e);
|
throw new ClientProtocolException(e);
|
||||||
}
|
}
|
||||||
|
|
||||||
cacheInvalidator.flushInvalidatedCacheEntries(target, request);
|
responseCache.flushInvalidatedCacheEntriesFor(target, request);
|
||||||
|
|
||||||
if (!cacheableRequestPolicy.isServableFromCache(request)) {
|
if (!cacheableRequestPolicy.isServableFromCache(request)) {
|
||||||
return callBackend(target, request, context);
|
return callBackend(target, request, context);
|
||||||
}
|
}
|
||||||
|
|
||||||
HttpCacheEntry entry = getCacheEntry(target, request);
|
HttpCacheEntry entry = responseCache.getCacheEntry(target, request);
|
||||||
if (entry == null) {
|
if (entry == null) {
|
||||||
cacheMisses.getAndIncrement();
|
cacheMisses.getAndIncrement();
|
||||||
if (log.isDebugEnabled()) {
|
if (log.isDebugEnabled()) {
|
||||||
|
@ -471,18 +432,6 @@ public class CachingHttpClient implements HttpClient {
|
||||||
return new Date();
|
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) {
|
boolean clientRequestsOurOptions(HttpRequest request) {
|
||||||
RequestLine line = request.getRequestLine();
|
RequestLine line = request.getRequestLine();
|
||||||
|
|
||||||
|
@ -533,101 +482,14 @@ public class CachingHttpClient implements HttpClient {
|
||||||
int statusCode = backendResponse.getStatusLine().getStatusCode();
|
int statusCode = backendResponse.getStatusLine().getStatusCode();
|
||||||
if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
|
if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
|
||||||
cacheUpdates.getAndIncrement();
|
cacheUpdates.getAndIncrement();
|
||||||
HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry(
|
return responseCache.updateCacheEntry(target, request, cacheEntry,
|
||||||
request.getRequestLine().getUri(),
|
backendResponse, requestDate, responseDate);
|
||||||
cacheEntry,
|
|
||||||
requestDate,
|
|
||||||
responseDate,
|
|
||||||
backendResponse);
|
|
||||||
storeInCache(target, request, updatedEntry);
|
|
||||||
return responseGenerator.generateResponse(updatedEntry);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return handleBackendResponse(target, conditionalRequest, requestDate, responseDate,
|
return handleBackendResponse(target, conditionalRequest, requestDate, responseDate,
|
||||||
backendResponse);
|
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(
|
HttpResponse handleBackendResponse(
|
||||||
HttpHost target,
|
HttpHost target,
|
||||||
HttpRequest request,
|
HttpRequest request,
|
||||||
|
@ -640,40 +502,13 @@ public class CachingHttpClient implements HttpClient {
|
||||||
|
|
||||||
boolean cacheable = responseCachingPolicy.isResponseCacheable(request, backendResponse);
|
boolean cacheable = responseCachingPolicy.isResponseCacheable(request, backendResponse);
|
||||||
|
|
||||||
HttpResponse corrected = backendResponse;
|
|
||||||
if (cacheable) {
|
if (cacheable) {
|
||||||
|
return responseCache.cacheAndReturnResponse(target, request, backendResponse, requestDate,
|
||||||
SizeLimitedResponseReader responseReader = getResponseReader(request, backendResponse);
|
responseDate);
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
String uri = uriExtractor.getURI(target, request);
|
responseCache.flushCacheEntriesFor(target, request);
|
||||||
responseCache.removeEntry(uri);
|
return backendResponse;
|
||||||
return corrected;
|
|
||||||
}
|
|
||||||
|
|
||||||
SizeLimitedResponseReader getResponseReader(HttpRequest request, HttpResponse backEndResponse) {
|
|
||||||
return new SizeLimitedResponseReader(
|
|
||||||
resourceFactory, maxObjectSizeBytes, request, backEndResponse);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
|
@ -33,13 +33,13 @@ import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.http.annotation.ThreadSafe;
|
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.HttpCacheEntry;
|
||||||
|
import org.apache.http.client.cache.HttpCacheStorage;
|
||||||
import org.apache.http.client.cache.HttpCacheUpdateCallback;
|
import org.apache.http.client.cache.HttpCacheUpdateCallback;
|
||||||
import org.apache.http.client.cache.Resource;
|
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}
|
* 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,
|
* 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()}
|
* 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()}
|
* 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.
|
* 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.
|
* and similar.
|
||||||
*
|
*
|
||||||
* @since 4.1
|
* @since 4.1
|
||||||
*/
|
*/
|
||||||
@ThreadSafe
|
@ThreadSafe
|
||||||
public class ManagedHttpCache implements HttpCache {
|
public class ManagedHttpCacheStorage implements HttpCacheStorage {
|
||||||
|
|
||||||
private final CacheMap entries;
|
private final CacheMap entries;
|
||||||
private final ReferenceQueue<HttpCacheEntry> morque;
|
private final ReferenceQueue<HttpCacheEntry> morque;
|
||||||
|
@ -61,9 +61,9 @@ public class ManagedHttpCache implements HttpCache {
|
||||||
|
|
||||||
private volatile boolean shutdown;
|
private volatile boolean shutdown;
|
||||||
|
|
||||||
public ManagedHttpCache(int maxEntries) {
|
public ManagedHttpCacheStorage(final CacheConfig config) {
|
||||||
super();
|
super();
|
||||||
this.entries = new CacheMap(maxEntries);
|
this.entries = new CacheMap(config.getMaxCacheEntries());
|
||||||
this.morque = new ReferenceQueue<HttpCacheEntry>();
|
this.morque = new ReferenceQueue<HttpCacheEntry>();
|
||||||
this.resources = new HashSet<ResourceReference>();
|
this.resources = new HashSet<ResourceReference>();
|
||||||
}
|
}
|
|
@ -32,7 +32,6 @@ import java.io.InputStream;
|
||||||
import org.apache.http.HttpEntity;
|
import org.apache.http.HttpEntity;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
import org.apache.http.HttpStatus;
|
|
||||||
import org.apache.http.annotation.NotThreadSafe;
|
import org.apache.http.annotation.NotThreadSafe;
|
||||||
import org.apache.http.client.cache.InputLimit;
|
import org.apache.http.client.cache.InputLimit;
|
||||||
import org.apache.http.client.cache.Resource;
|
import org.apache.http.client.cache.Resource;
|
||||||
|
@ -116,8 +115,7 @@ class SizeLimitedResponseReader {
|
||||||
|
|
||||||
HttpResponse getReconstructedResponse() throws IOException {
|
HttpResponse getReconstructedResponse() throws IOException {
|
||||||
ensureConsumed();
|
ensureConsumed();
|
||||||
HttpResponse reconstructed = new BasicHttpResponse(response.getProtocolVersion(),
|
HttpResponse reconstructed = new BasicHttpResponse(response.getStatusLine());
|
||||||
HttpStatus.SC_OK, "Success");
|
|
||||||
reconstructed.setHeaders(response.getAllHeaders());
|
reconstructed.setHeaders(response.getAllHeaders());
|
||||||
reconstructed.setEntity(new CombinedEntity(resource, instream));
|
reconstructed.setEntity(new CombinedEntity(resource, instream));
|
||||||
return reconstructed;
|
return reconstructed;
|
||||||
|
|
|
@ -31,15 +31,15 @@ import java.io.IOException;
|
||||||
import net.sf.ehcache.Ehcache;
|
import net.sf.ehcache.Ehcache;
|
||||||
import net.sf.ehcache.Element;
|
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.HttpCacheEntry;
|
||||||
|
import org.apache.http.client.cache.HttpCacheStorage;
|
||||||
import org.apache.http.client.cache.HttpCacheUpdateCallback;
|
import org.apache.http.client.cache.HttpCacheUpdateCallback;
|
||||||
|
|
||||||
public class EhcacheHttpCache implements HttpCache {
|
public class EhcacheHttpCacheStorage implements HttpCacheStorage {
|
||||||
|
|
||||||
private final Ehcache cache;
|
private final Ehcache cache;
|
||||||
|
|
||||||
public EhcacheHttpCache(Ehcache cache) {
|
public EhcacheHttpCacheStorage(Ehcache cache) {
|
||||||
this.cache = cache;
|
this.cache = cache;
|
||||||
}
|
}
|
||||||
|
|
|
@ -48,12 +48,13 @@ public abstract class AbstractProtocolTest {
|
||||||
|
|
||||||
originResponse = make200Response();
|
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);
|
mockBackend = EasyMock.createMock(HttpClient.class);
|
||||||
mockCache = EasyMock.createMock(HttpCache.class);
|
mockCache = EasyMock.createMock(HttpCache.class);
|
||||||
params = new CacheConfig();
|
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||||
params.setMaxObjectSizeBytes(MAX_BYTES);
|
|
||||||
impl = new CachingHttpClient(mockBackend, cache, new HeapResourceFactory(), params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void replayMocks() {
|
protected void replayMocks() {
|
||||||
|
@ -89,18 +90,23 @@ public abstract class AbstractProtocolTest {
|
||||||
mockBackend = EasyMock.createMock(HttpClient.class);
|
mockBackend = EasyMock.createMock(HttpClient.class);
|
||||||
mockCache = EasyMock.createMock(HttpCache.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)
|
EasyMock.expect(mockCache.getCacheEntry(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class)))
|
||||||
.anyTimes();
|
.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();
|
EasyMock.expectLastCall().anyTimes();
|
||||||
}
|
}
|
||||||
|
|
||||||
protected void behaveAsNonSharedCache() {
|
protected void behaveAsNonSharedCache() {
|
||||||
params.setSharedCache(false);
|
params.setSharedCache(false);
|
||||||
impl = new CachingHttpClient(mockBackend, cache, new HeapResourceFactory(), params);
|
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||||
}
|
}
|
||||||
|
|
||||||
public AbstractProtocolTest() {
|
public AbstractProtocolTest() {
|
||||||
|
|
|
@ -27,6 +27,7 @@
|
||||||
package org.apache.http.impl.client.cache;
|
package org.apache.http.impl.client.cache;
|
||||||
|
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
|
import java.util.Set;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
import org.apache.http.Header;
|
||||||
import org.apache.http.client.cache.HttpCacheEntry;
|
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);
|
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);
|
request = new BasicHttpRequest("GET", "/foo", HTTP_1_1);
|
||||||
|
|
||||||
originResponse = make200Response();
|
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);
|
mockBackend = EasyMock.createMock(HttpClient.class);
|
||||||
mockEntity = EasyMock.createMock(HttpEntity.class);
|
mockEntity = EasyMock.createMock(HttpEntity.class);
|
||||||
mockCache = EasyMock.createMock(HttpCache.class);
|
mockCache = EasyMock.createMock(HttpCache.class);
|
||||||
CacheConfig params = new CacheConfig();
|
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||||
params.setMaxObjectSizeBytes(MAX_BYTES);
|
|
||||||
impl = new CachingHttpClient(mockBackend, cache, new HeapResourceFactory(), params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpResponse make200Response() {
|
private HttpResponse make200Response() {
|
||||||
|
|
|
@ -195,9 +195,13 @@ public class HttpTestUtils {
|
||||||
*/
|
*/
|
||||||
public static boolean semanticallyTransparent(HttpResponse r1, HttpResponse r2)
|
public static boolean semanticallyTransparent(HttpResponse r1, HttpResponse r2)
|
||||||
throws Exception {
|
throws Exception {
|
||||||
return (equivalent(r1.getEntity(), r2.getEntity())
|
final boolean entitiesEquivalent = equivalent(r1.getEntity(), r2.getEntity());
|
||||||
&& semanticallyTransparent(r1.getStatusLine(), r2.getStatusLine()) && isEndToEndHeaderSubset(
|
if (!entitiesEquivalent) return false;
|
||||||
r1, r2));
|
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. */
|
/* 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.HttpHost;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.ProtocolVersion;
|
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.BasicHttpEntityEnclosingRequest;
|
||||||
import org.apache.http.message.BasicHttpRequest;
|
import org.apache.http.message.BasicHttpRequest;
|
||||||
import org.easymock.classextension.EasyMock;
|
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 static final ProtocolVersion HTTP_1_1 = new ProtocolVersion("HTTP", 1, 1);
|
||||||
|
|
||||||
private CacheInvalidator impl;
|
private CacheInvalidator impl;
|
||||||
private HttpCache mockCache;
|
private HttpCacheStorage mockStorage;
|
||||||
private HttpHost host;
|
private HttpHost host;
|
||||||
private URIExtractor extractor;
|
private URIExtractor extractor;
|
||||||
private CacheEntry mockEntry;
|
private CacheEntry mockEntry;
|
||||||
|
@ -54,20 +54,20 @@ public class TestCacheInvalidator {
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
host = new HttpHost("foo.example.com");
|
host = new HttpHost("foo.example.com");
|
||||||
mockCache = EasyMock.createMock(HttpCache.class);
|
mockStorage = EasyMock.createMock(HttpCacheStorage.class);
|
||||||
extractor = new URIExtractor();
|
extractor = new URIExtractor();
|
||||||
mockEntry = EasyMock.createMock(CacheEntry.class);
|
mockEntry = EasyMock.createMock(CacheEntry.class);
|
||||||
|
|
||||||
impl = new CacheInvalidator(extractor, mockCache);
|
impl = new CacheInvalidator(extractor, mockStorage);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replayMocks() {
|
private void replayMocks() {
|
||||||
EasyMock.replay(mockCache);
|
EasyMock.replay(mockStorage);
|
||||||
EasyMock.replay(mockEntry);
|
EasyMock.replay(mockEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyMocks() {
|
private void verifyMocks() {
|
||||||
EasyMock.verify(mockCache);
|
EasyMock.verify(mockStorage);
|
||||||
EasyMock.verify(mockEntry);
|
EasyMock.verify(mockEntry);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -283,16 +283,16 @@ public class TestCacheInvalidator {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void cacheReturnsEntryForUri(String theUri) throws IOException {
|
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 {
|
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"));
|
new IOException("TOTAL FAIL"));
|
||||||
}
|
}
|
||||||
|
|
||||||
private void entryIsRemoved(String theUri) throws IOException {
|
private void entryIsRemoved(String theUri) throws IOException {
|
||||||
mockCache.removeEntry(theUri);
|
mockStorage.removeEntry(theUri);
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
|
@ -27,14 +27,11 @@
|
||||||
package org.apache.http.impl.client.cache;
|
package org.apache.http.impl.client.cache;
|
||||||
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
|
||||||
import java.net.URI;
|
import java.net.URI;
|
||||||
import java.util.ArrayList;
|
import java.util.ArrayList;
|
||||||
import java.util.Date;
|
import java.util.Date;
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
|
||||||
import org.apache.http.Header;
|
|
||||||
import org.apache.http.HttpEntity;
|
|
||||||
import org.apache.http.HttpHost;
|
import org.apache.http.HttpHost;
|
||||||
import org.apache.http.HttpRequest;
|
import org.apache.http.HttpRequest;
|
||||||
import org.apache.http.HttpResponse;
|
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.ResponseHandler;
|
||||||
import org.apache.http.client.cache.HttpCache;
|
import org.apache.http.client.cache.HttpCache;
|
||||||
import org.apache.http.client.cache.HttpCacheEntry;
|
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.client.methods.HttpUriRequest;
|
||||||
import org.apache.http.conn.ClientConnectionManager;
|
import org.apache.http.conn.ClientConnectionManager;
|
||||||
import org.apache.http.entity.ByteArrayEntity;
|
|
||||||
import org.apache.http.message.BasicHttpRequest;
|
import org.apache.http.message.BasicHttpRequest;
|
||||||
import org.apache.http.message.BasicHttpResponse;
|
|
||||||
import org.apache.http.params.BasicHttpParams;
|
import org.apache.http.params.BasicHttpParams;
|
||||||
import org.apache.http.params.HttpParams;
|
import org.apache.http.params.HttpParams;
|
||||||
import org.apache.http.protocol.BasicHttpContext;
|
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 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 CachingHttpClient impl;
|
||||||
private boolean mockedImpl;
|
private boolean mockedImpl;
|
||||||
|
|
||||||
private ResourceFactory mockResourceFactory;
|
|
||||||
private CacheInvalidator mockInvalidator;
|
|
||||||
private CacheValidityPolicy mockValidityPolicy;
|
private CacheValidityPolicy mockValidityPolicy;
|
||||||
private CacheableRequestPolicy mockRequestPolicy;
|
private CacheableRequestPolicy mockRequestPolicy;
|
||||||
private HttpClient mockBackend;
|
private HttpClient mockBackend;
|
||||||
|
@ -92,20 +77,14 @@ public class TestCachingHttpClient {
|
||||||
private ResponseCachingPolicy mockResponsePolicy;
|
private ResponseCachingPolicy mockResponsePolicy;
|
||||||
private HttpResponse mockBackendResponse;
|
private HttpResponse mockBackendResponse;
|
||||||
private CacheEntry mockCacheEntry;
|
private CacheEntry mockCacheEntry;
|
||||||
private CacheEntry mockVariantCacheEntry;
|
|
||||||
private CacheEntry mockUpdatedCacheEntry;
|
|
||||||
private URIExtractor mockExtractor;
|
|
||||||
private CachedHttpResponseGenerator mockResponseGenerator;
|
private CachedHttpResponseGenerator mockResponseGenerator;
|
||||||
private SizeLimitedResponseReader mockResponseReader;
|
|
||||||
private ClientConnectionManager mockConnectionManager;
|
private ClientConnectionManager mockConnectionManager;
|
||||||
private ResponseHandler<Object> mockHandler;
|
private ResponseHandler<Object> mockHandler;
|
||||||
private HttpUriRequest mockUriRequest;
|
private HttpUriRequest mockUriRequest;
|
||||||
private HttpResponse mockCachedResponse;
|
private HttpResponse mockCachedResponse;
|
||||||
private HttpResponse mockReconstructedResponse;
|
|
||||||
private ConditionalRequestBuilder mockConditionalRequestBuilder;
|
private ConditionalRequestBuilder mockConditionalRequestBuilder;
|
||||||
private HttpRequest mockConditionalRequest;
|
private HttpRequest mockConditionalRequest;
|
||||||
private StatusLine mockStatusLine;
|
private StatusLine mockStatusLine;
|
||||||
private CacheEntryUpdater mockCacheEntryUpdater;
|
|
||||||
private ResponseProtocolCompliance mockResponseProtocolCompliance;
|
private ResponseProtocolCompliance mockResponseProtocolCompliance;
|
||||||
private RequestProtocolCompliance mockRequestProtocolCompliance;
|
private RequestProtocolCompliance mockRequestProtocolCompliance;
|
||||||
|
|
||||||
|
@ -119,8 +98,6 @@ public class TestCachingHttpClient {
|
||||||
@SuppressWarnings("unchecked")
|
@SuppressWarnings("unchecked")
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mockResourceFactory = EasyMock.createMock(ResourceFactory.class);
|
|
||||||
mockInvalidator = EasyMock.createMock(CacheInvalidator.class);
|
|
||||||
mockRequestPolicy = EasyMock.createMock(CacheableRequestPolicy.class);
|
mockRequestPolicy = EasyMock.createMock(CacheableRequestPolicy.class);
|
||||||
mockValidityPolicy = EasyMock.createMock(CacheValidityPolicy.class);
|
mockValidityPolicy = EasyMock.createMock(CacheValidityPolicy.class);
|
||||||
mockBackend = EasyMock.createMock(HttpClient.class);
|
mockBackend = EasyMock.createMock(HttpClient.class);
|
||||||
|
@ -132,17 +109,11 @@ public class TestCachingHttpClient {
|
||||||
mockBackendResponse = EasyMock.createMock(HttpResponse.class);
|
mockBackendResponse = EasyMock.createMock(HttpResponse.class);
|
||||||
mockUriRequest = EasyMock.createMock(HttpUriRequest.class);
|
mockUriRequest = EasyMock.createMock(HttpUriRequest.class);
|
||||||
mockCacheEntry = EasyMock.createMock(CacheEntry.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);
|
mockResponseGenerator = EasyMock.createMock(CachedHttpResponseGenerator.class);
|
||||||
mockCachedResponse = EasyMock.createMock(HttpResponse.class);
|
mockCachedResponse = EasyMock.createMock(HttpResponse.class);
|
||||||
mockConditionalRequestBuilder = EasyMock.createMock(ConditionalRequestBuilder.class);
|
mockConditionalRequestBuilder = EasyMock.createMock(ConditionalRequestBuilder.class);
|
||||||
mockConditionalRequest = EasyMock.createMock(HttpRequest.class);
|
mockConditionalRequest = EasyMock.createMock(HttpRequest.class);
|
||||||
mockStatusLine = EasyMock.createMock(StatusLine.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);
|
mockResponseProtocolCompliance = EasyMock.createMock(ResponseProtocolCompliance.class);
|
||||||
mockRequestProtocolCompliance = EasyMock.createMock(RequestProtocolCompliance.class);
|
mockRequestProtocolCompliance = EasyMock.createMock(RequestProtocolCompliance.class);
|
||||||
|
|
||||||
|
@ -154,32 +125,24 @@ public class TestCachingHttpClient {
|
||||||
params = new BasicHttpParams();
|
params = new BasicHttpParams();
|
||||||
impl = new CachingHttpClient(
|
impl = new CachingHttpClient(
|
||||||
mockBackend,
|
mockBackend,
|
||||||
mockResourceFactory,
|
|
||||||
mockValidityPolicy,
|
mockValidityPolicy,
|
||||||
mockResponsePolicy,
|
mockResponsePolicy,
|
||||||
mockExtractor,
|
|
||||||
mockCache,
|
mockCache,
|
||||||
mockResponseGenerator,
|
mockResponseGenerator,
|
||||||
mockInvalidator,
|
|
||||||
mockRequestPolicy,
|
mockRequestPolicy,
|
||||||
mockSuitabilityChecker,
|
mockSuitabilityChecker,
|
||||||
mockConditionalRequestBuilder,
|
mockConditionalRequestBuilder,
|
||||||
mockCacheEntryUpdater,
|
|
||||||
mockResponseProtocolCompliance,
|
mockResponseProtocolCompliance,
|
||||||
mockRequestProtocolCompliance);
|
mockRequestProtocolCompliance);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void replayMocks() {
|
private void replayMocks() {
|
||||||
EasyMock.replay(mockResourceFactory);
|
|
||||||
EasyMock.replay(mockInvalidator);
|
|
||||||
EasyMock.replay(mockRequestPolicy);
|
EasyMock.replay(mockRequestPolicy);
|
||||||
EasyMock.replay(mockValidityPolicy);
|
EasyMock.replay(mockValidityPolicy);
|
||||||
EasyMock.replay(mockSuitabilityChecker);
|
EasyMock.replay(mockSuitabilityChecker);
|
||||||
EasyMock.replay(mockResponsePolicy);
|
EasyMock.replay(mockResponsePolicy);
|
||||||
EasyMock.replay(mockCacheEntry);
|
EasyMock.replay(mockCacheEntry);
|
||||||
EasyMock.replay(mockVariantCacheEntry);
|
|
||||||
EasyMock.replay(mockResponseGenerator);
|
EasyMock.replay(mockResponseGenerator);
|
||||||
EasyMock.replay(mockExtractor);
|
|
||||||
EasyMock.replay(mockBackend);
|
EasyMock.replay(mockBackend);
|
||||||
EasyMock.replay(mockCache);
|
EasyMock.replay(mockCache);
|
||||||
EasyMock.replay(mockConnectionManager);
|
EasyMock.replay(mockConnectionManager);
|
||||||
|
@ -190,9 +153,6 @@ public class TestCachingHttpClient {
|
||||||
EasyMock.replay(mockConditionalRequestBuilder);
|
EasyMock.replay(mockConditionalRequestBuilder);
|
||||||
EasyMock.replay(mockConditionalRequest);
|
EasyMock.replay(mockConditionalRequest);
|
||||||
EasyMock.replay(mockStatusLine);
|
EasyMock.replay(mockStatusLine);
|
||||||
EasyMock.replay(mockCacheEntryUpdater);
|
|
||||||
EasyMock.replay(mockResponseReader);
|
|
||||||
EasyMock.replay(mockReconstructedResponse);
|
|
||||||
EasyMock.replay(mockResponseProtocolCompliance);
|
EasyMock.replay(mockResponseProtocolCompliance);
|
||||||
EasyMock.replay(mockRequestProtocolCompliance);
|
EasyMock.replay(mockRequestProtocolCompliance);
|
||||||
if (mockedImpl) {
|
if (mockedImpl) {
|
||||||
|
@ -201,16 +161,12 @@ public class TestCachingHttpClient {
|
||||||
}
|
}
|
||||||
|
|
||||||
private void verifyMocks() {
|
private void verifyMocks() {
|
||||||
EasyMock.verify(mockResourceFactory);
|
|
||||||
EasyMock.verify(mockInvalidator);
|
|
||||||
EasyMock.verify(mockRequestPolicy);
|
EasyMock.verify(mockRequestPolicy);
|
||||||
EasyMock.verify(mockValidityPolicy);
|
EasyMock.verify(mockValidityPolicy);
|
||||||
EasyMock.verify(mockSuitabilityChecker);
|
EasyMock.verify(mockSuitabilityChecker);
|
||||||
EasyMock.verify(mockResponsePolicy);
|
EasyMock.verify(mockResponsePolicy);
|
||||||
EasyMock.verify(mockCacheEntry);
|
EasyMock.verify(mockCacheEntry);
|
||||||
EasyMock.verify(mockVariantCacheEntry);
|
|
||||||
EasyMock.verify(mockResponseGenerator);
|
EasyMock.verify(mockResponseGenerator);
|
||||||
EasyMock.verify(mockExtractor);
|
|
||||||
EasyMock.verify(mockBackend);
|
EasyMock.verify(mockBackend);
|
||||||
EasyMock.verify(mockCache);
|
EasyMock.verify(mockCache);
|
||||||
EasyMock.verify(mockConnectionManager);
|
EasyMock.verify(mockConnectionManager);
|
||||||
|
@ -221,9 +177,6 @@ public class TestCachingHttpClient {
|
||||||
EasyMock.verify(mockConditionalRequestBuilder);
|
EasyMock.verify(mockConditionalRequestBuilder);
|
||||||
EasyMock.verify(mockConditionalRequest);
|
EasyMock.verify(mockConditionalRequest);
|
||||||
EasyMock.verify(mockStatusLine);
|
EasyMock.verify(mockStatusLine);
|
||||||
EasyMock.verify(mockCacheEntryUpdater);
|
|
||||||
EasyMock.verify(mockResponseReader);
|
|
||||||
EasyMock.verify(mockReconstructedResponse);
|
|
||||||
EasyMock.verify(mockResponseProtocolCompliance);
|
EasyMock.verify(mockResponseProtocolCompliance);
|
||||||
EasyMock.verify(mockRequestProtocolCompliance);
|
EasyMock.verify(mockRequestProtocolCompliance);
|
||||||
if (mockedImpl) {
|
if (mockedImpl) {
|
||||||
|
@ -233,20 +186,12 @@ public class TestCachingHttpClient {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testCacheableResponsesGoIntoCache() throws Exception {
|
public void testCacheableResponsesGoIntoCache() throws Exception {
|
||||||
mockImplMethods(STORE_IN_CACHE, GET_RESPONSE_READER);
|
|
||||||
responsePolicyAllowsCaching(true);
|
responsePolicyAllowsCaching(true);
|
||||||
|
|
||||||
responseProtocolValidationIsCalled();
|
responseProtocolValidationIsCalled();
|
||||||
|
|
||||||
getMockResponseReader();
|
EasyMock.expect(mockCache.cacheAndReturnResponse(host, request, mockBackendResponse, requestDate, responseDate))
|
||||||
responseRead();
|
.andReturn(mockCachedResponse);
|
||||||
responseLimitReached(false);
|
|
||||||
responseGetResource();
|
|
||||||
storeInCacheWasCalled();
|
|
||||||
responseIsGeneratedFromCache();
|
|
||||||
responseStatusLineIsInspectable();
|
|
||||||
responseGetHeaders();
|
|
||||||
responseDoesNotHaveExplicitContentLength();
|
|
||||||
|
|
||||||
replayMocks();
|
replayMocks();
|
||||||
HttpResponse result = impl.handleBackendResponse(host, request, requestDate,
|
HttpResponse result = impl.handleBackendResponse(host, request, requestDate,
|
||||||
|
@ -283,37 +228,13 @@ public class TestCachingHttpClient {
|
||||||
errors);
|
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
|
@Test
|
||||||
public void testCacheMissCausesBackendRequest() throws Exception {
|
public void testCacheMissCausesBackendRequest() throws Exception {
|
||||||
mockImplMethods(GET_CACHE_ENTRY, CALL_BACKEND);
|
mockImplMethods(CALL_BACKEND);
|
||||||
cacheInvalidatorWasCalled();
|
cacheInvalidatorWasCalled();
|
||||||
requestPolicyAllowsCaching(true);
|
requestPolicyAllowsCaching(true);
|
||||||
getCacheEntryReturns(null);
|
getCacheEntryReturns(null);
|
||||||
|
|
||||||
requestProtocolValidationIsCalled();
|
requestProtocolValidationIsCalled();
|
||||||
requestIsFatallyNonCompliant(null);
|
requestIsFatallyNonCompliant(null);
|
||||||
|
|
||||||
|
@ -331,7 +252,7 @@ public class TestCachingHttpClient {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnsuitableUnvalidatableCacheEntryCausesBackendRequest() throws Exception {
|
public void testUnsuitableUnvalidatableCacheEntryCausesBackendRequest() throws Exception {
|
||||||
mockImplMethods(GET_CACHE_ENTRY, CALL_BACKEND);
|
mockImplMethods(CALL_BACKEND);
|
||||||
cacheInvalidatorWasCalled();
|
cacheInvalidatorWasCalled();
|
||||||
requestPolicyAllowsCaching(true);
|
requestPolicyAllowsCaching(true);
|
||||||
requestProtocolValidationIsCalled();
|
requestProtocolValidationIsCalled();
|
||||||
|
@ -354,7 +275,7 @@ public class TestCachingHttpClient {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testUnsuitableValidatableCacheEntryCausesRevalidation() throws Exception {
|
public void testUnsuitableValidatableCacheEntryCausesRevalidation() throws Exception {
|
||||||
mockImplMethods(GET_CACHE_ENTRY, REVALIDATE_CACHE_ENTRY);
|
mockImplMethods(REVALIDATE_CACHE_ENTRY);
|
||||||
cacheInvalidatorWasCalled();
|
cacheInvalidatorWasCalled();
|
||||||
requestPolicyAllowsCaching(true);
|
requestPolicyAllowsCaching(true);
|
||||||
requestProtocolValidationIsCalled();
|
requestProtocolValidationIsCalled();
|
||||||
|
@ -384,11 +305,9 @@ public class TestCachingHttpClient {
|
||||||
backendCallWasMadeWithRequest(mockConditionalRequest);
|
backendCallWasMadeWithRequest(mockConditionalRequest);
|
||||||
getCurrentDateReturns(responseDate);
|
getCurrentDateReturns(responseDate);
|
||||||
backendResponseCodeIs(HttpStatus.SC_OK);
|
backendResponseCodeIs(HttpStatus.SC_OK);
|
||||||
cacheEntryUpdaterCalled();
|
EasyMock.expect(mockCache.updateCacheEntry(host, request,
|
||||||
cacheEntryHasVariants(false, mockUpdatedCacheEntry);
|
mockCacheEntry, mockBackendResponse, requestDate, responseDate))
|
||||||
extractTheURI("http://foo.example.com");
|
.andReturn(mockCachedResponse);
|
||||||
putInCache("http://foo.example.com", mockUpdatedCacheEntry);
|
|
||||||
responseIsGeneratedFromCache(mockUpdatedCacheEntry);
|
|
||||||
|
|
||||||
replayMocks();
|
replayMocks();
|
||||||
|
|
||||||
|
@ -406,17 +325,15 @@ public class TestCachingHttpClient {
|
||||||
@Test
|
@Test
|
||||||
public void testRevalidationUpdatesCacheEntryAndPutsItToCacheWhen304ReturningCachedResponse()
|
public void testRevalidationUpdatesCacheEntryAndPutsItToCacheWhen304ReturningCachedResponse()
|
||||||
throws Exception {
|
throws Exception {
|
||||||
mockImplMethods(GET_CURRENT_DATE, STORE_IN_CACHE);
|
mockImplMethods(GET_CURRENT_DATE);
|
||||||
conditionalRequestBuilderCalled();
|
conditionalRequestBuilderCalled();
|
||||||
getCurrentDateReturns(requestDate);
|
getCurrentDateReturns(requestDate);
|
||||||
backendCallWasMadeWithRequest(mockConditionalRequest);
|
backendCallWasMadeWithRequest(mockConditionalRequest);
|
||||||
getCurrentDateReturns(responseDate);
|
getCurrentDateReturns(responseDate);
|
||||||
backendResponseCodeIs(HttpStatus.SC_NOT_MODIFIED);
|
backendResponseCodeIs(HttpStatus.SC_NOT_MODIFIED);
|
||||||
|
EasyMock.expect(mockCache.updateCacheEntry(host, request,
|
||||||
cacheEntryUpdaterCalled();
|
mockCacheEntry, mockBackendResponse, requestDate, responseDate))
|
||||||
storeInCacheWasCalled(mockUpdatedCacheEntry);
|
.andReturn(mockCachedResponse);
|
||||||
|
|
||||||
responseIsGeneratedFromCache(mockUpdatedCacheEntry);
|
|
||||||
|
|
||||||
replayMocks();
|
replayMocks();
|
||||||
|
|
||||||
|
@ -432,7 +349,6 @@ public class TestCachingHttpClient {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testSuitableCacheEntryDoesNotCauseBackendRequest() throws Exception {
|
public void testSuitableCacheEntryDoesNotCauseBackendRequest() throws Exception {
|
||||||
mockImplMethods(GET_CACHE_ENTRY);
|
|
||||||
cacheInvalidatorWasCalled();
|
cacheInvalidatorWasCalled();
|
||||||
requestPolicyAllowsCaching(true);
|
requestPolicyAllowsCaching(true);
|
||||||
requestProtocolValidationIsCalled();
|
requestProtocolValidationIsCalled();
|
||||||
|
@ -465,13 +381,11 @@ public class TestCachingHttpClient {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testNonCacheableResponseIsNotCachedAndIsReturnedAsIs() throws Exception {
|
public void testNonCacheableResponseIsNotCachedAndIsReturnedAsIs() throws Exception {
|
||||||
final String theURI = "theURI";
|
|
||||||
Date currentDate = new Date();
|
Date currentDate = new Date();
|
||||||
responsePolicyAllowsCaching(false);
|
responsePolicyAllowsCaching(false);
|
||||||
responseProtocolValidationIsCalled();
|
responseProtocolValidationIsCalled();
|
||||||
|
|
||||||
extractTheURI(theURI);
|
flushCache();
|
||||||
removeFromCache(theURI);
|
|
||||||
|
|
||||||
replayMocks();
|
replayMocks();
|
||||||
HttpResponse result = impl.handleBackendResponse(host, request, currentDate,
|
HttpResponse result = impl.handleBackendResponse(host, request, currentDate,
|
||||||
|
@ -481,115 +395,6 @@ public class TestCachingHttpClient {
|
||||||
Assert.assertSame(mockBackendResponse, result);
|
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
|
@Test
|
||||||
public void testCallsSelfForExecuteOnHostRequestWithNullContext() throws Exception {
|
public void testCallsSelfForExecuteOnHostRequestWithNullContext() throws Exception {
|
||||||
|
@ -599,17 +404,13 @@ public class TestCachingHttpClient {
|
||||||
final HttpResponse theResponse = mockBackendResponse;
|
final HttpResponse theResponse = mockBackendResponse;
|
||||||
impl = new CachingHttpClient(
|
impl = new CachingHttpClient(
|
||||||
mockBackend,
|
mockBackend,
|
||||||
mockResourceFactory,
|
|
||||||
mockValidityPolicy,
|
mockValidityPolicy,
|
||||||
mockResponsePolicy,
|
mockResponsePolicy,
|
||||||
mockExtractor,
|
|
||||||
mockCache,
|
mockCache,
|
||||||
mockResponseGenerator,
|
mockResponseGenerator,
|
||||||
mockInvalidator,
|
|
||||||
mockRequestPolicy,
|
mockRequestPolicy,
|
||||||
mockSuitabilityChecker,
|
mockSuitabilityChecker,
|
||||||
mockConditionalRequestBuilder,
|
mockConditionalRequestBuilder,
|
||||||
mockCacheEntryUpdater,
|
|
||||||
mockResponseProtocolCompliance,
|
mockResponseProtocolCompliance,
|
||||||
mockRequestProtocolCompliance) {
|
mockRequestProtocolCompliance) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -641,17 +442,13 @@ public class TestCachingHttpClient {
|
||||||
final Object value = new Object();
|
final Object value = new Object();
|
||||||
impl = new CachingHttpClient(
|
impl = new CachingHttpClient(
|
||||||
mockBackend,
|
mockBackend,
|
||||||
mockResourceFactory,
|
|
||||||
mockValidityPolicy,
|
mockValidityPolicy,
|
||||||
mockResponsePolicy,
|
mockResponsePolicy,
|
||||||
mockExtractor,
|
|
||||||
mockCache,
|
mockCache,
|
||||||
mockResponseGenerator,
|
mockResponseGenerator,
|
||||||
mockInvalidator,
|
|
||||||
mockRequestPolicy,
|
mockRequestPolicy,
|
||||||
mockSuitabilityChecker,
|
mockSuitabilityChecker,
|
||||||
mockConditionalRequestBuilder,
|
mockConditionalRequestBuilder,
|
||||||
mockCacheEntryUpdater,
|
|
||||||
mockResponseProtocolCompliance,
|
mockResponseProtocolCompliance,
|
||||||
mockRequestProtocolCompliance) {
|
mockRequestProtocolCompliance) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -691,17 +488,13 @@ public class TestCachingHttpClient {
|
||||||
final HttpContext theContext = context;
|
final HttpContext theContext = context;
|
||||||
impl = new CachingHttpClient(
|
impl = new CachingHttpClient(
|
||||||
mockBackend,
|
mockBackend,
|
||||||
mockResourceFactory,
|
|
||||||
mockValidityPolicy,
|
mockValidityPolicy,
|
||||||
mockResponsePolicy,
|
mockResponsePolicy,
|
||||||
mockExtractor,
|
|
||||||
mockCache,
|
mockCache,
|
||||||
mockResponseGenerator,
|
mockResponseGenerator,
|
||||||
mockInvalidator,
|
|
||||||
mockRequestPolicy,
|
mockRequestPolicy,
|
||||||
mockSuitabilityChecker,
|
mockSuitabilityChecker,
|
||||||
mockConditionalRequestBuilder,
|
mockConditionalRequestBuilder,
|
||||||
mockCacheEntryUpdater,
|
|
||||||
mockResponseProtocolCompliance,
|
mockResponseProtocolCompliance,
|
||||||
mockRequestProtocolCompliance) {
|
mockRequestProtocolCompliance) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -733,17 +526,13 @@ public class TestCachingHttpClient {
|
||||||
final HttpResponse theResponse = mockBackendResponse;
|
final HttpResponse theResponse = mockBackendResponse;
|
||||||
impl = new CachingHttpClient(
|
impl = new CachingHttpClient(
|
||||||
mockBackend,
|
mockBackend,
|
||||||
mockResourceFactory,
|
|
||||||
mockValidityPolicy,
|
mockValidityPolicy,
|
||||||
mockResponsePolicy,
|
mockResponsePolicy,
|
||||||
mockExtractor,
|
|
||||||
mockCache,
|
mockCache,
|
||||||
mockResponseGenerator,
|
mockResponseGenerator,
|
||||||
mockInvalidator,
|
|
||||||
mockRequestPolicy,
|
mockRequestPolicy,
|
||||||
mockSuitabilityChecker,
|
mockSuitabilityChecker,
|
||||||
mockConditionalRequestBuilder,
|
mockConditionalRequestBuilder,
|
||||||
mockCacheEntryUpdater,
|
|
||||||
mockResponseProtocolCompliance,
|
mockResponseProtocolCompliance,
|
||||||
mockRequestProtocolCompliance) {
|
mockRequestProtocolCompliance) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -773,17 +562,13 @@ public class TestCachingHttpClient {
|
||||||
final HttpResponse theResponse = mockBackendResponse;
|
final HttpResponse theResponse = mockBackendResponse;
|
||||||
impl = new CachingHttpClient(
|
impl = new CachingHttpClient(
|
||||||
mockBackend,
|
mockBackend,
|
||||||
mockResourceFactory,
|
|
||||||
mockValidityPolicy,
|
mockValidityPolicy,
|
||||||
mockResponsePolicy,
|
mockResponsePolicy,
|
||||||
mockExtractor,
|
|
||||||
mockCache,
|
mockCache,
|
||||||
mockResponseGenerator,
|
mockResponseGenerator,
|
||||||
mockInvalidator,
|
|
||||||
mockRequestPolicy,
|
mockRequestPolicy,
|
||||||
mockSuitabilityChecker,
|
mockSuitabilityChecker,
|
||||||
mockConditionalRequestBuilder,
|
mockConditionalRequestBuilder,
|
||||||
mockCacheEntryUpdater,
|
|
||||||
mockResponseProtocolCompliance,
|
mockResponseProtocolCompliance,
|
||||||
mockRequestProtocolCompliance) {
|
mockRequestProtocolCompliance) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -816,17 +601,13 @@ public class TestCachingHttpClient {
|
||||||
final Object theValue = new Object();
|
final Object theValue = new Object();
|
||||||
impl = new CachingHttpClient(
|
impl = new CachingHttpClient(
|
||||||
mockBackend,
|
mockBackend,
|
||||||
mockResourceFactory,
|
|
||||||
mockValidityPolicy,
|
mockValidityPolicy,
|
||||||
mockResponsePolicy,
|
mockResponsePolicy,
|
||||||
mockExtractor,
|
|
||||||
mockCache,
|
mockCache,
|
||||||
mockResponseGenerator,
|
mockResponseGenerator,
|
||||||
mockInvalidator,
|
|
||||||
mockRequestPolicy,
|
mockRequestPolicy,
|
||||||
mockSuitabilityChecker,
|
mockSuitabilityChecker,
|
||||||
mockConditionalRequestBuilder,
|
mockConditionalRequestBuilder,
|
||||||
mockCacheEntryUpdater,
|
|
||||||
mockResponseProtocolCompliance,
|
mockResponseProtocolCompliance,
|
||||||
mockRequestProtocolCompliance) {
|
mockRequestProtocolCompliance) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -861,17 +642,13 @@ public class TestCachingHttpClient {
|
||||||
final Object theValue = new Object();
|
final Object theValue = new Object();
|
||||||
impl = new CachingHttpClient(
|
impl = new CachingHttpClient(
|
||||||
mockBackend,
|
mockBackend,
|
||||||
mockResourceFactory,
|
|
||||||
mockValidityPolicy,
|
mockValidityPolicy,
|
||||||
mockResponsePolicy,
|
mockResponsePolicy,
|
||||||
mockExtractor,
|
|
||||||
mockCache,
|
mockCache,
|
||||||
mockResponseGenerator,
|
mockResponseGenerator,
|
||||||
mockInvalidator,
|
|
||||||
mockRequestPolicy,
|
mockRequestPolicy,
|
||||||
mockSuitabilityChecker,
|
mockSuitabilityChecker,
|
||||||
mockConditionalRequestBuilder,
|
mockConditionalRequestBuilder,
|
||||||
mockCacheEntryUpdater,
|
|
||||||
mockResponseProtocolCompliance,
|
mockResponseProtocolCompliance,
|
||||||
mockRequestProtocolCompliance) {
|
mockRequestProtocolCompliance) {
|
||||||
@Override
|
@Override
|
||||||
|
@ -916,17 +693,13 @@ public class TestCachingHttpClient {
|
||||||
@Test
|
@Test
|
||||||
public void testResponseIsGeneratedWhenCacheEntryIsUsable() throws Exception {
|
public void testResponseIsGeneratedWhenCacheEntryIsUsable() throws Exception {
|
||||||
|
|
||||||
final String theURI = "http://foo";
|
|
||||||
|
|
||||||
requestIsFatallyNonCompliant(null);
|
requestIsFatallyNonCompliant(null);
|
||||||
requestProtocolValidationIsCalled();
|
requestProtocolValidationIsCalled();
|
||||||
cacheInvalidatorWasCalled();
|
cacheInvalidatorWasCalled();
|
||||||
requestPolicyAllowsCaching(true);
|
requestPolicyAllowsCaching(true);
|
||||||
cacheEntrySuitable(true);
|
cacheEntrySuitable(true);
|
||||||
extractTheURI(theURI);
|
getCacheEntryReturns(mockCacheEntry);
|
||||||
gotCacheHit(theURI);
|
|
||||||
responseIsGeneratedFromCache();
|
responseIsGeneratedFromCache();
|
||||||
cacheEntryHasVariants(false);
|
|
||||||
|
|
||||||
replayMocks();
|
replayMocks();
|
||||||
impl.execute(host, request, context);
|
impl.execute(host, request, context);
|
||||||
|
@ -953,123 +726,17 @@ public class TestCachingHttpClient {
|
||||||
Assert.assertTrue(gotException);
|
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
|
@Test
|
||||||
public void testIsSharedCache() {
|
public void testIsSharedCache() {
|
||||||
Assert.assertTrue(impl.isSharedCache());
|
Assert.assertTrue(impl.isSharedCache());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
private void getCacheEntryReturns(HttpCacheEntry result) throws IOException {
|
||||||
|
EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(result);
|
||||||
|
}
|
||||||
|
|
||||||
private void cacheInvalidatorWasCalled() throws IOException {
|
private void cacheInvalidatorWasCalled() throws IOException {
|
||||||
mockInvalidator.flushInvalidatedCacheEntries(
|
mockCache.flushInvalidatedCacheEntriesFor(
|
||||||
EasyMock.<HttpHost>anyObject(),
|
EasyMock.<HttpHost>anyObject(),
|
||||||
EasyMock.<HttpRequest>anyObject());
|
EasyMock.<HttpRequest>anyObject());
|
||||||
}
|
}
|
||||||
|
@ -1096,22 +763,6 @@ public class TestCachingHttpClient {
|
||||||
EasyMock.<HttpCacheEntry>anyObject())).andReturn(b);
|
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) {
|
private void backendResponseCodeIs(int code) {
|
||||||
EasyMock.expect(mockBackendResponse.getStatusLine()).andReturn(mockStatusLine);
|
EasyMock.expect(mockBackendResponse.getStatusLine()).andReturn(mockStatusLine);
|
||||||
EasyMock.expect(mockStatusLine.getStatusCode()).andReturn(code);
|
EasyMock.expect(mockStatusLine.getStatusCode()).andReturn(code);
|
||||||
|
@ -1128,42 +779,11 @@ public class TestCachingHttpClient {
|
||||||
EasyMock.expect(impl.getCurrentDate()).andReturn(date);
|
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) {
|
private void requestPolicyAllowsCaching(boolean allow) {
|
||||||
EasyMock.expect(mockRequestPolicy.isServableFromCache(
|
EasyMock.expect(mockRequestPolicy.isServableFromCache(
|
||||||
EasyMock.<HttpRequest>anyObject())).andReturn(allow);
|
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 {
|
private void backendCallWasMadeWithRequest(HttpRequest request) throws IOException {
|
||||||
EasyMock.expect(mockBackend.execute(
|
EasyMock.expect(mockBackend.execute(
|
||||||
EasyMock.<HttpHost>anyObject(),
|
EasyMock.<HttpHost>anyObject(),
|
||||||
|
@ -1178,10 +798,6 @@ public class TestCachingHttpClient {
|
||||||
EasyMock.<HttpResponse>anyObject())).andReturn(allow);
|
EasyMock.<HttpResponse>anyObject())).andReturn(allow);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void gotCacheMiss(String theURI) throws Exception {
|
|
||||||
EasyMock.expect(mockCache.getEntry(theURI)).andReturn(null);
|
|
||||||
}
|
|
||||||
|
|
||||||
private void cacheEntrySuitable(boolean suitable) {
|
private void cacheEntrySuitable(boolean suitable) {
|
||||||
EasyMock.expect(
|
EasyMock.expect(
|
||||||
mockSuitabilityChecker.canCachedResponseBeUsed(
|
mockSuitabilityChecker.canCachedResponseBeUsed(
|
||||||
|
@ -1190,68 +806,13 @@ public class TestCachingHttpClient {
|
||||||
EasyMock.<HttpCacheEntry>anyObject())).andReturn(suitable);
|
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() {
|
private void responseIsGeneratedFromCache() {
|
||||||
EasyMock.expect(mockResponseGenerator.generateResponse(
|
EasyMock.expect(mockResponseGenerator.generateResponse(
|
||||||
EasyMock.<HttpCacheEntry>anyObject())).andReturn(mockCachedResponse);
|
EasyMock.<HttpCacheEntry>anyObject())).andReturn(mockCachedResponse);
|
||||||
}
|
}
|
||||||
|
|
||||||
private void responseStatusLineIsInspectable() {
|
private void flushCache() throws IOException {
|
||||||
EasyMock.expect(mockBackendResponse.getStatusLine()).andReturn(new OKStatus()).anyTimes();
|
mockCache.flushCacheEntriesFor(host, request);
|
||||||
}
|
|
||||||
|
|
||||||
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 handleBackendResponseReturnsResponse(HttpRequest request, HttpResponse response)
|
private void handleBackendResponseReturnsResponse(HttpRequest request, HttpResponse response)
|
||||||
|
@ -1265,20 +826,6 @@ public class TestCachingHttpClient {
|
||||||
EasyMock.<HttpResponse>anyObject())).andReturn(response);
|
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 {
|
private void responseProtocolValidationIsCalled() throws ClientProtocolException {
|
||||||
mockResponseProtocolCompliance.ensureProtocolCompliance(
|
mockResponseProtocolCompliance.ensureProtocolCompliance(
|
||||||
EasyMock.<HttpRequest>anyObject(),
|
EasyMock.<HttpRequest>anyObject(),
|
||||||
|
@ -1301,17 +848,13 @@ public class TestCachingHttpClient {
|
||||||
mockedImpl = true;
|
mockedImpl = true;
|
||||||
impl = EasyMock.createMockBuilder(CachingHttpClient.class).withConstructor(
|
impl = EasyMock.createMockBuilder(CachingHttpClient.class).withConstructor(
|
||||||
mockBackend,
|
mockBackend,
|
||||||
mockResourceFactory,
|
|
||||||
mockValidityPolicy,
|
mockValidityPolicy,
|
||||||
mockResponsePolicy,
|
mockResponsePolicy,
|
||||||
mockExtractor,
|
|
||||||
mockCache,
|
mockCache,
|
||||||
mockResponseGenerator,
|
mockResponseGenerator,
|
||||||
mockInvalidator,
|
|
||||||
mockRequestPolicy,
|
mockRequestPolicy,
|
||||||
mockSuitabilityChecker,
|
mockSuitabilityChecker,
|
||||||
mockConditionalRequestBuilder,
|
mockConditionalRequestBuilder,
|
||||||
mockCacheEntryUpdater,
|
|
||||||
mockResponseProtocolCompliance,
|
mockResponseProtocolCompliance,
|
||||||
mockRequestProtocolCompliance).addMockedMethods(methods).createMock();
|
mockRequestProtocolCompliance).addMockedMethods(methods).createMock();
|
||||||
}
|
}
|
||||||
|
|
|
@ -93,14 +93,16 @@ public class TestProtocolDeviations {
|
||||||
|
|
||||||
originResponse = make200Response();
|
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);
|
mockBackend = EasyMock.createMock(HttpClient.class);
|
||||||
mockEntity = EasyMock.createMock(HttpEntity.class);
|
mockEntity = EasyMock.createMock(HttpEntity.class);
|
||||||
mockCache = EasyMock.createMock(HttpCache.class);
|
mockCache = EasyMock.createMock(HttpCache.class);
|
||||||
|
|
||||||
CacheConfig params = new CacheConfig();
|
impl = new CachingHttpClient(mockBackend, cache, params);
|
||||||
params.setMaxObjectSizeBytes(MAX_BYTES);
|
|
||||||
impl = new CachingHttpClient(mockBackend, cache, new HeapResourceFactory(), params);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpResponse make200Response() {
|
private HttpResponse make200Response() {
|
||||||
|
|
|
@ -42,7 +42,6 @@ import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.HttpVersion;
|
import org.apache.http.HttpVersion;
|
||||||
import org.apache.http.ProtocolVersion;
|
import org.apache.http.ProtocolVersion;
|
||||||
import org.apache.http.client.ClientProtocolException;
|
import org.apache.http.client.ClientProtocolException;
|
||||||
import org.apache.http.client.cache.HttpCacheEntry;
|
|
||||||
import org.apache.http.entity.BasicHttpEntity;
|
import org.apache.http.entity.BasicHttpEntity;
|
||||||
import org.apache.http.entity.ByteArrayEntity;
|
import org.apache.http.entity.ByteArrayEntity;
|
||||||
import org.apache.http.impl.client.RequestWrapper;
|
import org.apache.http.impl.client.RequestWrapper;
|
||||||
|
@ -2220,9 +2219,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
||||||
|
|
||||||
CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes);
|
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);
|
HttpRequest validate = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
||||||
validate.setHeader("If-None-Match", "\"etag\"");
|
validate.setHeader("If-None-Match", "\"etag\"");
|
||||||
|
@ -2232,17 +2231,23 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
||||||
notModified.setHeader("Date", DateUtils.formatDate(now));
|
notModified.setHeader("Date", DateUtils.formatDate(now));
|
||||||
notModified.setHeader("ETag", "\"etag\"");
|
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(
|
EasyMock.expect(
|
||||||
mockBackend.execute(EasyMock.eq(host), eqRequest(validate), (HttpContext) EasyMock
|
mockBackend.execute(EasyMock.eq(host), eqRequest(validate), (HttpContext) EasyMock
|
||||||
.isNull())).andReturn(notModified);
|
.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();
|
replayMocks();
|
||||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
|
||||||
HttpResponse result = impl.execute(host, request);
|
HttpResponse result = impl.execute(host, request);
|
||||||
verifyMocks();
|
verifyMocks();
|
||||||
|
|
||||||
Assert.assertEquals(200, result.getStatusLine().getStatusCode());
|
Assert.assertSame(reconstructed, result);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
|
@ -2264,12 +2269,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
||||||
|
|
||||||
CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes);
|
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();
|
replayMocks();
|
||||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
|
||||||
HttpResponse result = impl.execute(host, request);
|
HttpResponse result = impl.execute(host, request);
|
||||||
verifyMocks();
|
verifyMocks();
|
||||||
|
|
||||||
|
@ -2305,16 +2311,17 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
||||||
|
|
||||||
CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes);
|
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(
|
EasyMock.expect(
|
||||||
mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class),
|
mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.isA(HttpRequest.class),
|
||||||
(HttpContext) EasyMock.isNull())).andThrow(
|
(HttpContext) EasyMock.isNull())).andThrow(
|
||||||
new IOException("can't talk to origin!")).anyTimes();
|
new IOException("can't talk to origin!")).anyTimes();
|
||||||
|
|
||||||
replayMocks();
|
replayMocks();
|
||||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
|
||||||
|
|
||||||
HttpResponse result = impl.execute(host, request);
|
HttpResponse result = impl.execute(host, request);
|
||||||
|
|
||||||
|
@ -2506,12 +2513,13 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
||||||
|
|
||||||
CacheEntry entry = new CacheEntry(tenSecondsAgo, eightSecondsAgo, hdrs, bytes);
|
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();
|
replayMocks();
|
||||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
|
||||||
HttpResponse result = impl.execute(host, request);
|
HttpResponse result = impl.execute(host, request);
|
||||||
verifyMocks();
|
verifyMocks();
|
||||||
|
|
||||||
|
@ -2550,7 +2558,9 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
||||||
|
|
||||||
CacheEntry entry = new CacheEntry(requestTime, responseTime, hdrs, bytes);
|
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();
|
HttpResponse validated = make200Response();
|
||||||
validated.setHeader("Cache-Control", "public");
|
validated.setHeader("Cache-Control", "public");
|
||||||
|
@ -2558,18 +2568,20 @@ public class TestProtocolRequirements extends AbstractProtocolTest {
|
||||||
validated.setHeader("Content-Length", "128");
|
validated.setHeader("Content-Length", "128");
|
||||||
validated.setEntity(new ByteArrayEntity(bytes));
|
validated.setEntity(new ByteArrayEntity(bytes));
|
||||||
|
|
||||||
|
HttpResponse reconstructed = make200Response();
|
||||||
|
|
||||||
Capture<HttpRequest> cap = new Capture<HttpRequest>();
|
Capture<HttpRequest> cap = new Capture<HttpRequest>();
|
||||||
|
|
||||||
EasyMock.expect(mockCache.getEntry("http://foo.example.com/thing")).andReturn(entry);
|
mockCache.flushInvalidatedCacheEntriesFor(host, request);
|
||||||
|
EasyMock.expect(mockCache.getCacheEntry(host, request)).andReturn(entry);
|
||||||
mockCache.putEntry(EasyMock.isA(String.class), EasyMock.isA(HttpCacheEntry.class));
|
|
||||||
|
|
||||||
EasyMock.expect(
|
EasyMock.expect(
|
||||||
mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.capture(cap),
|
mockBackend.execute(EasyMock.isA(HttpHost.class), EasyMock.capture(cap),
|
||||||
(HttpContext) EasyMock.isNull())).andReturn(validated).times(0, 1);
|
(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();
|
replayMocks();
|
||||||
request = new BasicHttpRequest("GET", "/thing", HttpVersion.HTTP_1_1);
|
|
||||||
HttpResponse result = impl.execute(host, request);
|
HttpResponse result = impl.execute(host, request);
|
||||||
verifyMocks();
|
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;
|
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.HttpRequest;
|
||||||
import org.apache.http.HttpResponse;
|
import org.apache.http.HttpResponse;
|
||||||
|
import org.apache.http.HttpStatus;
|
||||||
import org.apache.http.HttpVersion;
|
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.apache.http.util.EntityUtils;
|
||||||
import org.easymock.classextension.EasyMock;
|
|
||||||
import org.junit.Assert;
|
import org.junit.Assert;
|
||||||
import org.junit.Before;
|
import org.junit.Before;
|
||||||
import org.junit.Test;
|
import org.junit.Test;
|
||||||
|
@ -46,56 +42,44 @@ public class TestSizeLimitedResponseReader {
|
||||||
|
|
||||||
private static final long MAX_SIZE = 4;
|
private static final long MAX_SIZE = 4;
|
||||||
|
|
||||||
|
private HttpRequest request;
|
||||||
private SizeLimitedResponseReader impl;
|
private SizeLimitedResponseReader impl;
|
||||||
private HttpRequest mockRequest;
|
|
||||||
private HttpResponse mockResponse;
|
|
||||||
private HttpEntity mockEntity;
|
|
||||||
|
|
||||||
private boolean mockedImpl;
|
|
||||||
|
|
||||||
@Before
|
@Before
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mockRequest = EasyMock.createMock(HttpRequest.class);
|
request = new HttpGet("http://foo.example.com/bar");
|
||||||
mockResponse = EasyMock.createMock(HttpResponse.class);
|
|
||||||
mockEntity = EasyMock.createMock(HttpEntity.class);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testLargeResponseIsTooLarge() throws Exception {
|
public void testLargeResponseIsTooLarge() throws Exception {
|
||||||
byte[] buf = new byte[] { 1, 2, 3, 4, 5};
|
byte[] buf = new byte[] { 1, 2, 3, 4, 5 };
|
||||||
requestReturnsRequestLine();
|
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||||
responseReturnsProtocolVersion();
|
response.setEntity(new ByteArrayEntity(buf));
|
||||||
responseReturnsHeaders();
|
|
||||||
responseReturnsContent(new ByteArrayInputStream(buf));
|
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
|
||||||
initReader();
|
|
||||||
replayMocks();
|
|
||||||
|
|
||||||
impl.readResponse();
|
impl.readResponse();
|
||||||
boolean tooLarge = impl.isLimitReached();
|
boolean tooLarge = impl.isLimitReached();
|
||||||
HttpResponse response = impl.getReconstructedResponse();
|
HttpResponse result = impl.getReconstructedResponse();
|
||||||
byte[] result = EntityUtils.toByteArray(response.getEntity());
|
byte[] body = EntityUtils.toByteArray(result.getEntity());
|
||||||
|
|
||||||
verifyMocks();
|
|
||||||
Assert.assertTrue(tooLarge);
|
Assert.assertTrue(tooLarge);
|
||||||
Assert.assertArrayEquals(buf, result);
|
Assert.assertArrayEquals(buf, body);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testExactSizeResponseIsNotTooLarge() throws Exception {
|
public void testExactSizeResponseIsNotTooLarge() throws Exception {
|
||||||
byte[] buf = new byte[] { 1, 2, 3, 4 };
|
byte[] buf = new byte[] { 1, 2, 3, 4 };
|
||||||
requestReturnsRequestLine();
|
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||||
responseReturnsProtocolVersion();
|
response.setEntity(new ByteArrayEntity(buf));
|
||||||
responseReturnsHeaders();
|
|
||||||
responseReturnsContent(new ByteArrayInputStream(buf));
|
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
|
||||||
initReader();
|
|
||||||
replayMocks();
|
|
||||||
|
|
||||||
impl.readResponse();
|
impl.readResponse();
|
||||||
boolean tooLarge = impl.isLimitReached();
|
boolean tooLarge = impl.isLimitReached();
|
||||||
HttpResponse response = impl.getReconstructedResponse();
|
HttpResponse reconstructed = impl.getReconstructedResponse();
|
||||||
byte[] result = EntityUtils.toByteArray(response.getEntity());
|
byte[] result = EntityUtils.toByteArray(reconstructed.getEntity());
|
||||||
|
|
||||||
verifyMocks();
|
|
||||||
Assert.assertFalse(tooLarge);
|
Assert.assertFalse(tooLarge);
|
||||||
Assert.assertArrayEquals(buf, result);
|
Assert.assertArrayEquals(buf, result);
|
||||||
}
|
}
|
||||||
|
@ -103,18 +87,15 @@ public class TestSizeLimitedResponseReader {
|
||||||
@Test
|
@Test
|
||||||
public void testSmallResponseIsNotTooLarge() throws Exception {
|
public void testSmallResponseIsNotTooLarge() throws Exception {
|
||||||
byte[] buf = new byte[] { 1, 2, 3 };
|
byte[] buf = new byte[] { 1, 2, 3 };
|
||||||
requestReturnsRequestLine();
|
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, HttpStatus.SC_OK, "OK");
|
||||||
responseReturnsProtocolVersion();
|
response.setEntity(new ByteArrayEntity(buf));
|
||||||
responseReturnsHeaders();
|
|
||||||
responseReturnsContent(new ByteArrayInputStream(buf));
|
impl = new SizeLimitedResponseReader(new HeapResourceFactory(), MAX_SIZE, request, response);
|
||||||
initReader();
|
|
||||||
replayMocks();
|
|
||||||
|
|
||||||
impl.readResponse();
|
impl.readResponse();
|
||||||
boolean tooLarge = impl.isLimitReached();
|
boolean tooLarge = impl.isLimitReached();
|
||||||
HttpResponse response = impl.getReconstructedResponse();
|
HttpResponse reconstructed = impl.getReconstructedResponse();
|
||||||
byte[] result = EntityUtils.toByteArray(response.getEntity());
|
byte[] result = EntityUtils.toByteArray(reconstructed.getEntity());
|
||||||
verifyMocks();
|
|
||||||
|
|
||||||
Assert.assertFalse(tooLarge);
|
Assert.assertFalse(tooLarge);
|
||||||
Assert.assertArrayEquals(buf, result);
|
Assert.assertArrayEquals(buf, result);
|
||||||
|
@ -122,56 +103,14 @@ public class TestSizeLimitedResponseReader {
|
||||||
|
|
||||||
@Test
|
@Test
|
||||||
public void testResponseWithNoEntityIsNotTooLarge() throws Exception {
|
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();
|
impl.readResponse();
|
||||||
boolean tooLarge = impl.isLimitReached();
|
boolean tooLarge = impl.isLimitReached();
|
||||||
verifyMocks();
|
|
||||||
|
|
||||||
Assert.assertFalse(tooLarge);
|
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 {
|
public class TestEhcacheHttpCache extends TestCase {
|
||||||
|
|
||||||
private Ehcache mockCache;
|
private Ehcache mockCache;
|
||||||
private EhcacheHttpCache impl;
|
private EhcacheHttpCacheStorage impl;
|
||||||
|
|
||||||
public void setUp() {
|
public void setUp() {
|
||||||
mockCache = EasyMock.createMock(Ehcache.class);
|
mockCache = EasyMock.createMock(Ehcache.class);
|
||||||
impl = new EhcacheHttpCache(mockCache);
|
impl = new EhcacheHttpCacheStorage(mockCache);
|
||||||
}
|
}
|
||||||
|
|
||||||
@Test
|
@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