HTTP cache entry implementation backed by a temporary file

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@982219 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2010-08-04 11:34:48 +00:00
parent 7c8a1fdf5b
commit d6a0b4d1a1
13 changed files with 406 additions and 113 deletions

View File

@ -40,6 +40,7 @@ import org.apache.http.StatusLine;
public interface HttpCacheEntryFactory {
HttpCacheEntry generate(
String requestId,
Date requestDate,
Date responseDate,
StatusLine statusLine,
@ -47,6 +48,7 @@ public interface HttpCacheEntryFactory {
byte[] body) throws IOException;
HttpCacheEntry copyVariant(
String requestId,
HttpCacheEntry entry,
String variantURI) throws IOException;

View File

@ -0,0 +1,79 @@
/*
* ====================================================================
* 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.net.InetAddress;
import java.net.UnknownHostException;
import java.security.NoSuchAlgorithmException;
import java.security.SecureRandom;
import java.util.Formatter;
import java.util.Locale;
import org.apache.http.annotation.Immutable;
/**
* Should produce reasonably unique tokens.
*/
@Immutable
class BasicIdGenerator {
private final String hostname;
private final SecureRandom rnd;
private long count;
public BasicIdGenerator() {
super();
String hostname;
try {
hostname = InetAddress.getLocalHost().getHostName();
} catch (UnknownHostException ex) {
hostname = "localhost";
}
this.hostname = hostname;
try {
this.rnd = SecureRandom.getInstance("SHA1PRNG");
} catch (NoSuchAlgorithmException ex) {
throw new Error(ex);
}
this.rnd.setSeed(System.currentTimeMillis());
}
public synchronized String generate() {
this.count++;
int rndnum = this.rnd.nextInt();
StringBuilder buffer = new StringBuilder();
buffer.append(System.currentTimeMillis());
buffer.append('.');
Formatter formatter = new Formatter(buffer, Locale.US);
formatter.format("%1$016x-%2$08x", this.count, rndnum);
buffer.append('.');
buffer.append(this.hostname);
return buffer.toString();
}
}

View File

@ -78,10 +78,10 @@ class CacheEntity implements HttpEntity, Serializable {
throw new IllegalArgumentException("Output stream may not be null");
}
InputStream instream = this.cacheEntry.getBody();
byte[] buf = new byte[2048];
int len;
while ((len = instream.read(buf)) != -1) {
outstream.write(buf, 0, len);
try {
IOUtils.copy(instream, outstream);
} finally {
instream.close();
}
}

View File

@ -69,6 +69,7 @@ class CacheEntryUpdater {
/**
* Update the entry with the new information from the response.
*
* @param request id
* @param entry The cache Entry to be updated
* @param requestDate When the request was performed
* @param responseDate When the response was gotten
@ -77,6 +78,7 @@ class CacheEntryUpdater {
* @throws java.io.IOException if something bad happens while trying to read the body from the original entry
*/
public HttpCacheEntry updateCacheEntry(
String requestId,
HttpCacheEntry entry,
Date requestDate,
Date responseDate,
@ -91,6 +93,7 @@ class CacheEntryUpdater {
outstream.write(buf, 0, len);
}
HttpCacheEntry updated = cacheEntryFactory.generate(
requestId,
requestDate,
responseDate,
entry.getStatusLine(),

View File

@ -524,7 +524,12 @@ public class CachingHttpClient implements HttpClient {
int statusCode = backendResponse.getStatusLine().getStatusCode();
if (statusCode == HttpStatus.SC_NOT_MODIFIED || statusCode == HttpStatus.SC_OK) {
cacheUpdates.getAndIncrement();
HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry(cacheEntry, requestDate, responseDate, backendResponse);
HttpCacheEntry updatedEntry = cacheEntryUpdater.updateCacheEntry(
request.getRequestLine().getUri(),
cacheEntry,
requestDate,
responseDate,
backendResponse);
storeInCache(target, request, updatedEntry);
return responseGenerator.generateResponse(updatedEntry);
}
@ -552,27 +557,30 @@ public class CachingHttpClient implements HttpClient {
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(existing, entry, variantURI);
return doGetUpdatedParentEntry(
req.getRequestLine().getUri(), existing, entry, variantURI);
}
};
String parentURI = uriExtractor.getURI(target, req);
responseCache.updateEntry(parentURI, callback);
}
HttpCacheEntry doGetUpdatedParentEntry(
HttpCacheEntry existing,
HttpCacheEntry entry, String variantURI) throws IOException {
final String requestId,
final HttpCacheEntry existing,
final HttpCacheEntry entry,
final String variantURI) throws IOException {
if (existing != null) {
return cacheEntryFactory.copyVariant(existing, variantURI);
return cacheEntryFactory.copyVariant(requestId, existing, variantURI);
} else {
return cacheEntryFactory.copyVariant(entry, variantURI);
return cacheEntryFactory.copyVariant(requestId, entry, variantURI);
}
}
@ -629,6 +637,7 @@ public class CachingHttpClient implements HttpClient {
int correctedStatus = corrected.getStatusLine().getStatusCode();
if (HttpStatus.SC_BAD_GATEWAY != correctedStatus) {
HttpCacheEntry entry = cacheEntryFactory.generate(
request.getRequestLine().getUri(),
requestDate,
responseDate,
corrected.getStatusLine(),

View File

@ -62,6 +62,10 @@ class FileCacheEntry extends HttpCacheEntry {
this.resource = new FileResource(file);
}
File getRawBody() {
return this.file;
}
@Override
public long getBodyLength() {
return this.file.length();

View File

@ -0,0 +1,105 @@
/*
* ====================================================================
* 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.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
import org.apache.http.Header;
import org.apache.http.StatusLine;
import org.apache.http.annotation.Immutable;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheEntryFactory;
/**
* Generates {@link HttpCacheEntry} instances whose body is stored in a temporary file.
*
* @since 4.1
*/
@Immutable
public class FileCacheEntryFactory implements HttpCacheEntryFactory {
private final File cacheDir;
private final BasicIdGenerator idgen;
public FileCacheEntryFactory(final File cacheDir) {
super();
this.cacheDir = cacheDir;
this.idgen = new BasicIdGenerator();
}
public HttpCacheEntry generate(
final String requestId,
final Date requestDate,
final Date responseDate,
final StatusLine statusLine,
final Header[] headers,
byte[] body) throws IOException {
String uid = this.idgen.generate();
File file = new File(this.cacheDir, uid + "." + requestId);
return new FileCacheEntry(
requestDate,
responseDate,
statusLine,
headers,
file,
null);
}
public HttpCacheEntry copyVariant(
final String requestId,
final HttpCacheEntry entry,
final String variantURI) throws IOException {
String uid = this.idgen.generate();
File file = new File(this.cacheDir, uid + "-" + requestId);
Set<String> variants = new HashSet<String>(entry.getVariantURIs());
variants.add(variantURI);
if (entry instanceof FileCacheEntry) {
File src = ((FileCacheEntry) entry).getRawBody();
IOUtils.copyFile(src, file);
} else {
FileOutputStream out = new FileOutputStream(file);
IOUtils.copyAndClose(entry.getBody(), out);
}
return new FileCacheEntry(
entry.getRequestDate(),
entry.getResponseDate(),
entry.getStatusLine(),
entry.getAllHeaders(),
file,
variants);
}
}

View File

@ -0,0 +1,96 @@
/*
* ====================================================================
* 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.Closeable;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import org.apache.http.annotation.Immutable;
@Immutable
class IOUtils {
static void copy(final InputStream in, final OutputStream out) throws IOException {
byte[] buf = new byte[2048];
int len;
while ((len = in.read(buf)) != -1) {
out.write(buf, 0, len);
}
}
static void closeSilently(final Closeable closable) {
try {
closable.close();
} catch (IOException ignore) {
}
}
static void copyAndClose(final InputStream in, final OutputStream out) throws IOException {
try {
copy(in, out);
in.close();
out.close();
} catch (IOException ex) {
closeSilently(in);
closeSilently(out);
// Propagate the original exception
throw ex;
}
}
static void copyFile(final File in, final File out) throws IOException {
RandomAccessFile f1 = new RandomAccessFile(in, "r");
RandomAccessFile f2 = new RandomAccessFile(out, "w");
try {
FileChannel c1 = f1.getChannel();
FileChannel c2 = f2.getChannel();
try {
c1.transferTo(0, f1.length(), c2);
c1.close();
c2.close();
} catch (IOException ex) {
closeSilently(c1);
closeSilently(c2);
// Propagate the original exception
throw ex;
}
f1.close();
f2.close();
} catch (IOException ex) {
closeSilently(f1);
closeSilently(f2);
// Propagate the original exception
throw ex;
}
}
}

View File

@ -59,6 +59,10 @@ class MemCacheEntry extends HttpCacheEntry {
this.body = body;
}
byte[] getRawBody() {
return this.body;
}
@Override
public long getBodyLength() {
return this.body.length;

View File

@ -28,7 +28,6 @@ package org.apache.http.impl.client.cache;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Date;
import java.util.HashSet;
import java.util.Set;
@ -41,18 +40,18 @@ import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheEntryFactory;
/**
* Generates {@link MemCacheEntry}s.
* Generates {@link HttpCacheEntry} instances stored entirely in memory.
*
* @since 4.1
*/
@Immutable
class MemCacheEntryFactory implements HttpCacheEntryFactory {
public class MemCacheEntryFactory implements HttpCacheEntryFactory {
public HttpCacheEntry generateEntry(
Date requestDate,
Date responseDate,
HttpResponse response,
byte[] body) {
final Date requestDate,
final Date responseDate,
final HttpResponse response,
final byte[] body) {
return new MemCacheEntry(requestDate,
responseDate,
response.getStatusLine(),
@ -62,6 +61,7 @@ class MemCacheEntryFactory implements HttpCacheEntryFactory {
}
public HttpCacheEntry generate(
final String requestId,
final Date requestDate,
final Date responseDate,
final StatusLine statusLine,
@ -76,23 +76,28 @@ class MemCacheEntryFactory implements HttpCacheEntryFactory {
}
public HttpCacheEntry copyVariant(
final HttpCacheEntry entry, final String variantURI) throws IOException {
final String requestId,
final HttpCacheEntry entry,
final String variantURI) throws IOException {
byte[] body;
if (entry instanceof MemCacheEntry) {
body = ((MemCacheEntry) entry).getRawBody();
} else {
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
IOUtils.copyAndClose(entry.getBody(), outstream);
body = outstream.toByteArray();
}
Set<String> variants = new HashSet<String>(entry.getVariantURIs());
variants.add(variantURI);
ByteArrayOutputStream outstream = new ByteArrayOutputStream();
InputStream instream = entry.getBody();
byte[] buf = new byte[2048];
int len;
while ((len = instream.read(buf)) != -1) {
outstream.write(buf, 0, len);
}
return new MemCacheEntry(
entry.getRequestDate(),
entry.getResponseDate(),
entry.getStatusLine(),
entry.getAllHeaders(),
outstream.toByteArray(),
body,
variants);
}
}
}

View File

@ -110,8 +110,8 @@ public class TestCacheEntry {
MemCacheEntryFactory entryGenerator = new MemCacheEntryFactory();
HttpCacheEntry addedOne = entryGenerator.copyVariant(entry, "foo");
HttpCacheEntry addedTwo = entryGenerator.copyVariant(addedOne, "bar");
HttpCacheEntry addedOne = entryGenerator.copyVariant(null, entry, "foo");
HttpCacheEntry addedTwo = entryGenerator.copyVariant(null, addedOne, "bar");
Set<String> variants = addedTwo.getVariantURIs();

View File

@ -67,7 +67,7 @@ public class TestCacheEntryUpdater {
CacheEntry entry = new CacheEntry();
BasicHttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
HttpCacheEntry newEntry = impl.updateCacheEntry(entry, requestDate, responseDate, response);
HttpCacheEntry newEntry = impl.updateCacheEntry(null, entry, requestDate, responseDate, response);
assertNotSame(newEntry, entry);
}
@ -85,7 +85,7 @@ public class TestCacheEntryUpdater {
"http", 1, 1), HttpStatus.SC_NOT_MODIFIED, ""));
response.setHeaders(new Header[]{});
HttpCacheEntry updatedEntry = impl.updateCacheEntry(cacheEntry, new Date(), new Date(), response);
HttpCacheEntry updatedEntry = impl.updateCacheEntry(null, cacheEntry, new Date(), new Date(), response);
Assert.assertEquals(2, updatedEntry.getAllHeaders().length);
@ -110,7 +110,7 @@ public class TestCacheEntryUpdater {
new BasicHeader("Last-Modified", DateUtils.formatDate(responseDate)),
new BasicHeader("Cache-Control", "public"),});
HttpCacheEntry updatedEntry = impl.updateCacheEntry(cacheEntry, new Date(), new Date(), response);
HttpCacheEntry updatedEntry = impl.updateCacheEntry(null, cacheEntry, new Date(), new Date(), response);
Assert.assertEquals(4, updatedEntry.getAllHeaders().length);
@ -136,7 +136,7 @@ public class TestCacheEntryUpdater {
new BasicHeader("Last-Modified", DateUtils.formatDate(responseDate)),
new BasicHeader("Cache-Control", "public"),});
HttpCacheEntry updatedEntry = impl.updateCacheEntry(cacheEntry, new Date(), new Date(), response);
HttpCacheEntry updatedEntry = impl.updateCacheEntry(null, cacheEntry, new Date(), new Date(), response);
Assert.assertEquals(4, updatedEntry.getAllHeaders().length);
@ -164,7 +164,7 @@ public class TestCacheEntryUpdater {
HttpResponse response = new BasicHttpResponse(HttpVersion.HTTP_1_1, 200, "OK");
HttpCacheEntry updated = impl.updateCacheEntry(entry, twoSecondsAgo, oneSecondAgo, response);
HttpCacheEntry updated = impl.updateCacheEntry(null, entry, twoSecondsAgo, oneSecondAgo, response);
assertEquals(twoSecondsAgo, updated.getRequestDate());
assertEquals(oneSecondAgo, updated.getResponseDate());

View File

@ -52,7 +52,9 @@ import org.apache.http.client.cache.HttpCacheEntryFactory;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
import org.apache.http.entity.ByteArrayEntity;
import org.apache.http.message.BasicHttpRequest;
import org.apache.http.message.BasicHttpResponse;
import org.apache.http.message.BasicRequestLine;
import org.apache.http.message.BasicStatusLine;
import org.apache.http.params.HttpParams;
import org.apache.http.protocol.HttpContext;
@ -78,6 +80,7 @@ public class TestCachingHttpClient {
private static final String GET_RESPONSE_READER = "getResponseReader";
private static final StatusLine SC_OK = new BasicStatusLine(HttpVersion.HTTP_1_1, 200, "OK");
private static final RequestLine GET_STUFF = new BasicRequestLine("GET", "/stuff", HttpVersion.HTTP_1_1);
private static final Header[] HEADERS = new Header[] {};
private CachingHttpClient impl;
@ -90,7 +93,6 @@ public class TestCachingHttpClient {
private HttpCache mockCache;
private CachedResponseSuitabilityChecker mockSuitabilityChecker;
private ResponseCachingPolicy mockResponsePolicy;
private HttpRequest mockRequest;
private HttpResponse mockBackendResponse;
private CacheEntry mockCacheEntry;
private CacheEntry mockVariantCacheEntry;
@ -98,9 +100,7 @@ public class TestCachingHttpClient {
private URIExtractor mockExtractor;
private HttpCacheEntryFactory mockEntryGenerator;
private CachedHttpResponseGenerator mockResponseGenerator;
private SizeLimitedResponseReader mockResponseReader;
private HttpHost host;
private ClientConnectionManager mockConnectionManager;
private HttpContext mockContext;
private ResponseHandler<Object> mockHandler;
@ -108,19 +108,17 @@ public class TestCachingHttpClient {
private HttpUriRequest mockUriRequest;
private HttpResponse mockCachedResponse;
private HttpResponse mockReconstructedResponse;
private ConditionalRequestBuilder mockConditionalRequestBuilder;
private HttpRequest mockConditionalRequest;
private StatusLine mockStatusLine;
private Date requestDate;
private Date responseDate;
private CacheEntryUpdater mockCacheEntryUpdater;
private ResponseProtocolCompliance mockResponseProtocolCompliance;
private RequestProtocolCompliance mockRequestProtocolCompliance;
private RequestLine mockRequestLine;
private Date requestDate;
private Date responseDate;
private HttpHost host;
private HttpRequest request;
@SuppressWarnings("unchecked")
@Before
@ -137,7 +135,6 @@ public class TestCachingHttpClient {
mockContext = EasyMock.createMock(HttpContext.class);
mockHandler = EasyMock.createMock(ResponseHandler.class);
mockParams = EasyMock.createMock(HttpParams.class);
mockRequest = EasyMock.createMock(HttpRequest.class);
mockBackendResponse = EasyMock.createMock(HttpResponse.class);
mockUriRequest = EasyMock.createMock(HttpUriRequest.class);
mockCacheEntry = EasyMock.createMock(CacheEntry.class);
@ -155,12 +152,11 @@ public class TestCachingHttpClient {
mockReconstructedResponse = EasyMock.createMock(HttpResponse.class);
mockResponseProtocolCompliance = EasyMock.createMock(ResponseProtocolCompliance.class);
mockRequestProtocolCompliance = EasyMock.createMock(RequestProtocolCompliance.class);
mockRequestLine = EasyMock.createMock(RequestLine.class);
requestDate = new Date(System.currentTimeMillis() - 1000);
responseDate = new Date();
host = new HttpHost("foo.example.com");
request = new BasicHttpRequest(GET_STUFF);
impl = new CachingHttpClient(mockBackend, mockValidityPolicy, mockResponsePolicy, mockEntryGenerator,
mockExtractor, mockCache, mockResponseGenerator, mockInvalidator,
mockRequestPolicy, mockSuitabilityChecker, mockConditionalRequestBuilder,
@ -186,7 +182,6 @@ public class TestCachingHttpClient {
EasyMock.replay(mockContext);
EasyMock.replay(mockHandler);
EasyMock.replay(mockParams);
EasyMock.replay(mockRequest);
EasyMock.replay(mockBackendResponse);
EasyMock.replay(mockUriRequest);
EasyMock.replay(mockCachedResponse);
@ -220,7 +215,6 @@ public class TestCachingHttpClient {
EasyMock.verify(mockContext);
EasyMock.verify(mockHandler);
EasyMock.verify(mockParams);
EasyMock.verify(mockRequest);
EasyMock.verify(mockBackendResponse);
EasyMock.verify(mockUriRequest);
EasyMock.verify(mockCachedResponse);
@ -256,7 +250,7 @@ public class TestCachingHttpClient {
responseDoesNotHaveExplicitContentLength();
replayMocks();
HttpResponse result = impl.handleBackendResponse(host, mockRequest, requestDate,
HttpResponse result = impl.handleBackendResponse(host, request, requestDate,
responseDate, mockBackendResponse);
verifyMocks();
@ -272,26 +266,21 @@ public class TestCachingHttpClient {
callBackendReturnsResponse(mockBackendResponse);
requestProtocolValidationIsCalled();
requestIsFatallyNonCompliant(null);
requestInspectsRequestLine();
replayMocks();
HttpResponse result = impl.execute(host, mockRequest, mockContext);
HttpResponse result = impl.execute(host, request, mockContext);
verifyMocks();
Assert.assertSame(mockBackendResponse, result);
}
private void requestInspectsRequestLine() {
EasyMock.expect(mockRequest.getRequestLine()).andReturn(mockRequestLine);
}
private void requestIsFatallyNonCompliant(RequestProtocolError error) {
List<RequestProtocolError> errors = new ArrayList<RequestProtocolError>();
if (error != null) {
errors.add(error);
}
EasyMock.expect(
mockRequestProtocolCompliance.requestIsFatallyNonCompliant(mockRequest)).andReturn(
mockRequestProtocolCompliance.requestIsFatallyNonCompliant(request)).andReturn(
errors);
}
@ -305,7 +294,7 @@ public class TestCachingHttpClient {
putInCache(theURI);
replayMocks();
impl.storeInCache(host, mockRequest, mockCacheEntry);
impl.storeInCache(host, request, mockCacheEntry);
verifyMocks();
}
@ -315,7 +304,7 @@ public class TestCachingHttpClient {
final CacheEntry entry = new CacheEntry();
copyCacheEntry(entry, variantURI);
replayMocks();
impl.doGetUpdatedParentEntry(null, entry, variantURI);
impl.doGetUpdatedParentEntry(GET_STUFF.getUri(), null, entry, variantURI);
verifyMocks();
}
@ -328,12 +317,11 @@ public class TestCachingHttpClient {
getCacheEntryReturns(null);
requestProtocolValidationIsCalled();
requestIsFatallyNonCompliant(null);
requestInspectsRequestLine();
callBackendReturnsResponse(mockBackendResponse);
replayMocks();
HttpResponse result = impl.execute(host, mockRequest, mockContext);
HttpResponse result = impl.execute(host, request, mockContext);
verifyMocks();
Assert.assertSame(mockBackendResponse, result);
@ -349,7 +337,6 @@ public class TestCachingHttpClient {
requestPolicyAllowsCaching(true);
requestProtocolValidationIsCalled();
requestIsFatallyNonCompliant(null);
requestInspectsRequestLine();
getCacheEntryReturns(mockCacheEntry);
cacheEntrySuitable(false);
@ -357,7 +344,7 @@ public class TestCachingHttpClient {
callBackendReturnsResponse(mockBackendResponse);
replayMocks();
HttpResponse result = impl.execute(host, mockRequest, mockContext);
HttpResponse result = impl.execute(host, request, mockContext);
verifyMocks();
Assert.assertSame(mockBackendResponse, result);
@ -373,7 +360,6 @@ public class TestCachingHttpClient {
requestPolicyAllowsCaching(true);
requestProtocolValidationIsCalled();
requestIsFatallyNonCompliant(null);
requestInspectsRequestLine();
getCacheEntryReturns(mockCacheEntry);
cacheEntrySuitable(false);
@ -381,7 +367,7 @@ public class TestCachingHttpClient {
revalidateCacheEntryReturns(mockBackendResponse);
replayMocks();
HttpResponse result = impl.execute(host, mockRequest, mockContext);
HttpResponse result = impl.execute(host, request, mockContext);
verifyMocks();
Assert.assertSame(mockBackendResponse, result);
@ -407,7 +393,7 @@ public class TestCachingHttpClient {
replayMocks();
HttpResponse result = impl.revalidateCacheEntry(host, mockRequest, mockContext,
HttpResponse result = impl.revalidateCacheEntry(host, request, mockContext,
mockCacheEntry);
verifyMocks();
@ -435,7 +421,7 @@ public class TestCachingHttpClient {
replayMocks();
HttpResponse result = impl.revalidateCacheEntry(host, mockRequest, mockContext, mockCacheEntry);
HttpResponse result = impl.revalidateCacheEntry(host, request, mockContext, mockCacheEntry);
verifyMocks();
@ -455,10 +441,9 @@ public class TestCachingHttpClient {
cacheEntrySuitable(true);
responseIsGeneratedFromCache();
requestIsFatallyNonCompliant(null);
requestInspectsRequestLine();
replayMocks();
HttpResponse result = impl.execute(host, mockRequest, mockContext);
HttpResponse result = impl.execute(host, request, mockContext);
verifyMocks();
Assert.assertSame(mockCachedResponse, result);
@ -468,13 +453,13 @@ public class TestCachingHttpClient {
public void testCallBackendMakesBackEndRequestAndHandlesResponse() throws Exception {
mockImplMethods(GET_CURRENT_DATE, HANDLE_BACKEND_RESPONSE);
getCurrentDateReturns(requestDate);
backendCallWasMadeWithRequest(mockRequest);
backendCallWasMadeWithRequest(request);
getCurrentDateReturns(responseDate);
handleBackendResponseReturnsResponse(mockRequest, mockBackendResponse);
handleBackendResponseReturnsResponse(request, mockBackendResponse);
replayMocks();
impl.callBackend(host, mockRequest, mockContext);
impl.callBackend(host, request, mockContext);
verifyMocks();
}
@ -490,7 +475,7 @@ public class TestCachingHttpClient {
removeFromCache(theURI);
replayMocks();
HttpResponse result = impl.handleBackendResponse(host, mockRequest, currentDate,
HttpResponse result = impl.handleBackendResponse(host, request, currentDate,
currentDate, mockBackendResponse);
verifyMocks();
@ -505,7 +490,7 @@ public class TestCachingHttpClient {
gotCacheMiss(theURI);
replayMocks();
HttpCacheEntry result = impl.getCacheEntry(host, mockRequest);
HttpCacheEntry result = impl.getCacheEntry(host, request);
verifyMocks();
Assert.assertNull(result);
}
@ -519,7 +504,7 @@ public class TestCachingHttpClient {
cacheEntryHasVariants(false);
replayMocks();
HttpCacheEntry result = impl.getCacheEntry(host, mockRequest);
HttpCacheEntry result = impl.getCacheEntry(host, request);
verifyMocks();
Assert.assertSame(mockCacheEntry, result);
}
@ -536,7 +521,7 @@ public class TestCachingHttpClient {
gotCacheMiss(variantURI);
replayMocks();
HttpCacheEntry result = impl.getCacheEntry(host, mockRequest);
HttpCacheEntry result = impl.getCacheEntry(host, request);
verifyMocks();
Assert.assertNull(result);
}
@ -553,7 +538,7 @@ public class TestCachingHttpClient {
gotCacheHit(variantURI, mockVariantCacheEntry);
replayMocks();
HttpCacheEntry result = impl.getCacheEntry(host, mockRequest);
HttpCacheEntry result = impl.getCacheEntry(host, request);
verifyMocks();
Assert.assertSame(mockVariantCacheEntry, result);
}
@ -562,7 +547,7 @@ public class TestCachingHttpClient {
public void testTooLargeResponsesAreNotCached() throws Exception {
mockImplMethods(GET_CURRENT_DATE, GET_RESPONSE_READER, STORE_IN_CACHE);
getCurrentDateReturns(requestDate);
backendCallWasMadeWithRequest(mockRequest);
backendCallWasMadeWithRequest(request);
responseProtocolValidationIsCalled();
getCurrentDateReturns(responseDate);
@ -573,7 +558,7 @@ public class TestCachingHttpClient {
replayMocks();
impl.callBackend(host, mockRequest, mockContext);
impl.callBackend(host, request, mockContext);
verifyMocks();
}
@ -586,7 +571,7 @@ public class TestCachingHttpClient {
getCurrentDateReturns(requestDate);
responseProtocolValidationIsCalled();
backendCallWasMadeWithRequest(mockRequest);
backendCallWasMadeWithRequest(request);
getCurrentDateReturns(responseDate);
responsePolicyAllowsCaching(true);
getMockResponseReader();
@ -601,7 +586,7 @@ public class TestCachingHttpClient {
replayMocks();
impl.callBackend(host, mockRequest, mockContext);
impl.callBackend(host, request, mockContext);
verifyMocks();
}
@ -610,7 +595,7 @@ public class TestCachingHttpClient {
public void testCallsSelfForExecuteOnHostRequestWithNullContext() throws Exception {
final Counter c = new Counter();
final HttpHost theHost = host;
final HttpRequest theRequest = mockRequest;
final HttpRequest theRequest = request;
final HttpResponse theResponse = mockBackendResponse;
impl = new CachingHttpClient(mockBackend, mockValidityPolicy, mockResponsePolicy, mockEntryGenerator,
mockExtractor, mockCache, mockResponseGenerator, mockInvalidator,
@ -628,7 +613,7 @@ public class TestCachingHttpClient {
};
replayMocks();
HttpResponse result = impl.execute(host, mockRequest);
HttpResponse result = impl.execute(host, request);
verifyMocks();
Assert.assertSame(mockBackendResponse, result);
Assert.assertEquals(1, c.getCount());
@ -640,7 +625,7 @@ public class TestCachingHttpClient {
final Counter c = new Counter();
final HttpHost theHost = host;
final HttpRequest theRequest = mockRequest;
final HttpRequest theRequest = request;
final HttpResponse theResponse = mockBackendResponse;
final ResponseHandler<Object> theHandler = mockHandler;
final Object value = new Object();
@ -669,7 +654,7 @@ public class TestCachingHttpClient {
value);
replayMocks();
Object result = impl.execute(host, mockRequest, mockHandler);
Object result = impl.execute(host, request, mockHandler);
verifyMocks();
Assert.assertSame(value, result);
@ -681,7 +666,7 @@ public class TestCachingHttpClient {
final Counter c = new Counter();
final HttpHost theHost = host;
final HttpRequest theRequest = mockRequest;
final HttpRequest theRequest = request;
final HttpResponse theResponse = mockBackendResponse;
final HttpContext theContext = mockContext;
impl = new CachingHttpClient(mockBackend, mockValidityPolicy, mockResponsePolicy, mockEntryGenerator,
@ -705,7 +690,7 @@ public class TestCachingHttpClient {
theObject);
replayMocks();
Object result = impl.execute(host, mockRequest, mockHandler, mockContext);
Object result = impl.execute(host, request, mockHandler, mockContext);
verifyMocks();
Assert.assertEquals(1, c.getCount());
Assert.assertSame(theObject, result);
@ -864,7 +849,6 @@ public class TestCachingHttpClient {
final String theURI = "http://foo";
requestIsFatallyNonCompliant(null);
requestInspectsRequestLine();
requestProtocolValidationIsCalled();
cacheInvalidatorWasCalled();
requestPolicyAllowsCaching(true);
@ -875,7 +859,7 @@ public class TestCachingHttpClient {
cacheEntryHasVariants(false);
replayMocks();
impl.execute(host, mockRequest, mockContext);
impl.execute(host, request, mockContext);
verifyMocks();
}
@ -884,14 +868,13 @@ public class TestCachingHttpClient {
ProtocolException expected = new ProtocolException("ouch");
requestInspectsRequestLine();
requestIsFatallyNonCompliant(null);
requestCannotBeMadeCompliantThrows(expected);
boolean gotException = false;
replayMocks();
try {
impl.execute(host, mockRequest, mockContext);
impl.execute(host, request, mockContext);
} catch (ClientProtocolException ex) {
Assert.assertTrue(ex.getCause().getMessage().equals(expected.getMessage()));
gotException = true;
@ -1016,18 +999,18 @@ public class TestCachingHttpClient {
}
private void cacheInvalidatorWasCalled() throws IOException {
mockInvalidator.flushInvalidatedCacheEntries(host, mockRequest);
mockInvalidator.flushInvalidatedCacheEntries(host, request);
}
private void callBackendReturnsResponse(HttpResponse response) throws IOException {
EasyMock.expect(impl.callBackend(host, mockRequest, mockContext)).andReturn(
EasyMock.expect(impl.callBackend(host, request, mockContext)).andReturn(
response);
}
private void revalidateCacheEntryReturns(HttpResponse response) throws IOException,
ProtocolException {
EasyMock.expect(
impl.revalidateCacheEntry(host, mockRequest, mockContext, mockCacheEntry))
impl.revalidateCacheEntry(host, request, mockContext, mockCacheEntry))
.andReturn(response);
}
@ -1037,12 +1020,13 @@ public class TestCachingHttpClient {
private void cacheEntryUpdaterCalled() throws IOException {
EasyMock.expect(
mockCacheEntryUpdater.updateCacheEntry(mockCacheEntry, requestDate, responseDate,
mockBackendResponse)).andReturn(mockUpdatedCacheEntry);
mockCacheEntryUpdater.updateCacheEntry(
request.getRequestLine().getUri(),
mockCacheEntry, requestDate, responseDate, mockBackendResponse)).andReturn(mockUpdatedCacheEntry);
}
private void getCacheEntryReturns(CacheEntry entry) throws IOException {
EasyMock.expect(impl.getCacheEntry(host, mockRequest)).andReturn(entry);
EasyMock.expect(impl.getCacheEntry(host, request)).andReturn(entry);
}
private void backendResponseCodeIs(int code) {
@ -1052,7 +1036,7 @@ public class TestCachingHttpClient {
private void conditionalRequestBuilderCalled() throws ProtocolException {
EasyMock.expect(
mockConditionalRequestBuilder.buildConditionalRequest(mockRequest, mockCacheEntry))
mockConditionalRequestBuilder.buildConditionalRequest(request, mockCacheEntry))
.andReturn(mockConditionalRequest);
}
@ -1070,7 +1054,7 @@ public class TestCachingHttpClient {
}
private void requestPolicyAllowsCaching(boolean allow) {
EasyMock.expect(mockRequestPolicy.isServableFromCache(mockRequest)).andReturn(
EasyMock.expect(mockRequestPolicy.isServableFromCache(request)).andReturn(
allow);
}
@ -1101,7 +1085,7 @@ public class TestCachingHttpClient {
private void responsePolicyAllowsCaching(boolean allow) {
EasyMock.expect(
mockResponsePolicy.isResponseCacheable(mockRequest, mockBackendResponse))
mockResponsePolicy.isResponseCacheable(request, mockBackendResponse))
.andReturn(allow);
}
@ -1111,7 +1095,7 @@ public class TestCachingHttpClient {
private void cacheEntrySuitable(boolean suitable) {
EasyMock.expect(
mockSuitabilityChecker.canCachedResponseBeUsed(host, mockRequest, mockCacheEntry))
mockSuitabilityChecker.canCachedResponseBeUsed(host, request, mockCacheEntry))
.andReturn(suitable);
}
@ -1150,7 +1134,7 @@ public class TestCachingHttpClient {
}
private void extractTheURI(String theURI) {
EasyMock.expect(mockExtractor.getURI(host, mockRequest)).andReturn(theURI);
EasyMock.expect(mockExtractor.getURI(host, request)).andReturn(theURI);
}
private void extractVariantURI(String variantURI) {
@ -1159,7 +1143,7 @@ public class TestCachingHttpClient {
private void extractVariantURI(String variantURI, CacheEntry entry){
EasyMock
.expect(mockExtractor.getVariantURI(host, mockRequest, entry)).andReturn(
.expect(mockExtractor.getVariantURI(host, request, entry)).andReturn(
variantURI);
}
@ -1173,13 +1157,15 @@ public class TestCachingHttpClient {
private void generateCacheEntry(Date requestDate, Date responseDate, byte[] bytes) throws IOException {
EasyMock.expect(
mockEntryGenerator.generate(requestDate, responseDate, SC_OK, HEADERS,
bytes)).andReturn(mockCacheEntry);
mockEntryGenerator.generate(
request.getRequestLine().getUri(),
requestDate, responseDate, SC_OK, HEADERS, bytes)).andReturn(mockCacheEntry);
}
private void copyCacheEntry(CacheEntry entry, String variantURI) throws IOException {
EasyMock.expect(
mockEntryGenerator.copyVariant(entry, variantURI)).andReturn(entry);
mockEntryGenerator.copyVariant(
request.getRequestLine().getUri(), entry, variantURI)).andReturn(entry);
}
private void handleBackendResponseReturnsResponse(HttpRequest request, HttpResponse response)
@ -1190,26 +1176,26 @@ public class TestCachingHttpClient {
}
private void storeInCacheWasCalled() throws IOException {
impl.storeInCache(host, mockRequest, mockCacheEntry);
impl.storeInCache(host, request, mockCacheEntry);
}
private void storeInCacheWasCalled(CacheEntry entry) throws IOException {
impl.storeInCache(host, mockRequest, entry);
impl.storeInCache(host, request, entry);
}
private void responseProtocolValidationIsCalled() throws ClientProtocolException {
mockResponseProtocolCompliance.ensureProtocolCompliance(mockRequest, mockBackendResponse);
mockResponseProtocolCompliance.ensureProtocolCompliance(request, mockBackendResponse);
}
private void requestProtocolValidationIsCalled() throws Exception {
EasyMock.expect(
mockRequestProtocolCompliance.makeRequestCompliant(mockRequest)).andReturn(
mockRequest);
mockRequestProtocolCompliance.makeRequestCompliant(request)).andReturn(
request);
}
private void requestCannotBeMadeCompliantThrows(ProtocolException exception) throws Exception {
EasyMock.expect(
mockRequestProtocolCompliance.makeRequestCompliant(mockRequest))
mockRequestProtocolCompliance.makeRequestCompliant(request))
.andThrow(exception);
}