Refactored exception handling: replaced HttpCacheOperationException with a more generic IOException. This should provide a more natural way of signaling exceptions for file system based caches

git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@979259 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2010-07-26 12:20:02 +00:00
parent c2622c8ca2
commit 7891d8c2d4
9 changed files with 78 additions and 165 deletions

View File

@ -26,18 +26,20 @@
*/
package org.apache.http.client.cache;
import java.io.IOException;
/**
* @since 4.1
*/
public interface HttpCache {
void putEntry(String key, HttpCacheEntry entry) throws HttpCacheOperationException;
void putEntry(String key, HttpCacheEntry entry) throws IOException;
HttpCacheEntry getEntry(String key) throws HttpCacheOperationException;
HttpCacheEntry getEntry(String key) throws IOException;
void removeEntry(String key) throws HttpCacheOperationException;
void removeEntry(String key) throws IOException;
void updateEntry(
String key, HttpCacheUpdateCallback callback) throws HttpCacheOperationException;
String key, HttpCacheUpdateCallback callback) throws IOException;
}

View File

@ -1,56 +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.client.cache;
/**
* Exception to be thrown when an {@link HttpCache} encounters an error performing
* an caching operation.
*
* @since 4.1
*/
public class HttpCacheOperationException extends Exception {
private static final long serialVersionUID = 823573584868632876L;
public HttpCacheOperationException() {
super();
}
public HttpCacheOperationException(String message) {
super(message);
}
public HttpCacheOperationException(String message, Throwable cause) {
super(message, cause);
}
public HttpCacheOperationException(Throwable cause) {
super(cause);
}
}

View File

@ -26,6 +26,8 @@
*/
package org.apache.http.client.cache;
import java.io.IOException;
public interface HttpCacheUpdateCallback {
/**
@ -36,11 +38,9 @@ public interface HttpCacheUpdateCallback {
* <code>null</code> if nonexistent
* @return CacheEntry the cache entry that should replace it, again,
* possible <code>null</code>
* @throws HttpCacheOperationException
* exception containing information about a failure in the cache
*
* @since 4.1
*/
HttpCacheEntry update(HttpCacheEntry existing) throws HttpCacheOperationException;
HttpCacheEntry update(HttpCacheEntry existing) throws IOException;
}

View File

@ -26,13 +26,13 @@
*/
package org.apache.http.impl.client.cache;
import java.io.IOException;
import java.util.LinkedHashMap;
import java.util.Map;
import org.apache.http.annotation.ThreadSafe;
import org.apache.http.client.cache.HttpCache;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheOperationException;
import org.apache.http.client.cache.HttpCacheUpdateCallback;
/**
@ -69,7 +69,7 @@ public class BasicHttpCache implements HttpCache {
* @param entry
* HttpCacheEntry to place in the cache
*/
public synchronized void putEntry(String url, HttpCacheEntry entry) {
public synchronized void putEntry(String url, HttpCacheEntry entry) throws IOException {
baseMap.put(url, entry);
}
@ -80,7 +80,7 @@ public class BasicHttpCache implements HttpCache {
* Url that is the cache key
* @return HttpCacheEntry if one exists, or null for cache miss
*/
public synchronized HttpCacheEntry getEntry(String url) {
public synchronized HttpCacheEntry getEntry(String url) throws IOException {
return baseMap.get(url);
}
@ -90,13 +90,13 @@ public class BasicHttpCache implements HttpCache {
* @param url
* Url that is the cache key
*/
public synchronized void removeEntry(String url) {
public synchronized void removeEntry(String url) throws IOException {
baseMap.remove(url);
}
public synchronized void updateEntry(
String url,
HttpCacheUpdateCallback callback) throws HttpCacheOperationException {
HttpCacheUpdateCallback callback) throws IOException {
HttpCacheEntry existingEntry = baseMap.get(url);
baseMap.put(url, callback.update(existingEntry));
}

View File

@ -26,6 +26,7 @@
*/
package org.apache.http.impl.client.cache;
import java.io.IOException;
import java.net.MalformedURLException;
import java.net.URL;
@ -39,7 +40,6 @@ import org.apache.http.annotation.ThreadSafe;
import org.apache.http.client.cache.HeaderConstants;
import org.apache.http.client.cache.HttpCache;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheOperationException;
/**
* Given a particular HttpRequest, flush any cache entries that this request
@ -76,57 +76,50 @@ class CacheInvalidator {
* @param host The backend host we are talking to
* @param req The HttpRequest to that host
*/
public void flushInvalidatedCacheEntries(HttpHost host, HttpRequest req) {
public void flushInvalidatedCacheEntries(HttpHost host, HttpRequest req) throws IOException {
if (requestShouldNotBeCached(req)) {
log.debug("Request should not be cached");
String theUri = uriExtractor.getURI(host, req);
HttpCacheEntry parent = cache.getEntry(theUri);
log.debug("parent entry: " + parent);
if (parent != null) {
for (String variantURI : parent.getVariantURIs()) {
cache.removeEntry(variantURI);
}
cache.removeEntry(theUri);
}
URL reqURL;
try {
String theUri = uriExtractor.getURI(host, req);
HttpCacheEntry parent = cache.getEntry(theUri);
log.debug("parent entry: " + parent);
if (parent != null) {
for (String variantURI : parent.getVariantURIs()) {
cache.removeEntry(variantURI);
}
cache.removeEntry(theUri);
reqURL = new URL(theUri);
} catch (MalformedURLException mue) {
log.error("Couldn't transform request into valid URL");
return;
}
Header clHdr = req.getFirstHeader("Content-Location");
if (clHdr != null) {
String contentLocation = clHdr.getValue();
if (!flushAbsoluteUriFromSameHost(reqURL, contentLocation)) {
flushRelativeUriFromSameHost(reqURL, contentLocation);
}
URL reqURL;
try {
reqURL = new URL(theUri);
} catch (MalformedURLException mue) {
log.error("Couldn't transform request into valid URL");
return;
}
Header clHdr = req.getFirstHeader("Content-Location");
if (clHdr != null) {
String contentLocation = clHdr.getValue();
if (!flushAbsoluteUriFromSameHost(reqURL, contentLocation)) {
flushRelativeUriFromSameHost(reqURL, contentLocation);
}
}
Header lHdr = req.getFirstHeader("Location");
if (lHdr != null) {
flushAbsoluteUriFromSameHost(reqURL, lHdr.getValue());
}
} catch (HttpCacheOperationException ex) {
log.debug("Was unable to REMOVE an entry from the cache based on the uri provided",
ex);
}
Header lHdr = req.getFirstHeader("Location");
if (lHdr != null) {
flushAbsoluteUriFromSameHost(reqURL, lHdr.getValue());
}
}
}
protected void flushUriIfSameHost(URL requestURL, URL targetURL)
throws HttpCacheOperationException {
protected void flushUriIfSameHost(URL requestURL, URL targetURL) throws IOException {
if (targetURL.getAuthority().equalsIgnoreCase(requestURL.getAuthority())) {
cache.removeEntry(targetURL.toString());
}
}
protected void flushRelativeUriFromSameHost(URL reqURL, String relUri)
throws HttpCacheOperationException {
protected void flushRelativeUriFromSameHost(URL reqURL, String relUri) throws IOException {
URL relURL;
try {
relURL = new URL(reqURL,relUri);
@ -137,8 +130,7 @@ class CacheInvalidator {
flushUriIfSameHost(reqURL, relURL);
}
protected boolean flushAbsoluteUriFromSameHost(URL reqURL, String uri)
throws HttpCacheOperationException {
protected boolean flushAbsoluteUriFromSameHost(URL reqURL, String uri) throws IOException {
URL absURL;
try {
absURL = new URL(uri);

View File

@ -50,7 +50,6 @@ import org.apache.http.client.ResponseHandler;
import org.apache.http.client.cache.HeaderConstants;
import org.apache.http.client.cache.HttpCache;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheOperationException;
import org.apache.http.client.cache.HttpCacheUpdateCallback;
import org.apache.http.client.methods.HttpUriRequest;
import org.apache.http.conn.ClientConnectionManager;
@ -391,25 +390,16 @@ public class CachingHttpClient implements HttpClient {
return new Date();
}
HttpCacheEntry getCacheEntry(HttpHost target, HttpRequest request) {
HttpCacheEntry getCacheEntry(HttpHost target, HttpRequest request) throws IOException {
String uri = uriExtractor.getURI(target, request);
HttpCacheEntry entry = null;
try {
entry = responseCache.getEntry(uri);
} catch (HttpCacheOperationException ex) {
log.debug("Was unable to get an entry from the cache based on the uri provided", ex);
}
HttpCacheEntry entry = responseCache.getEntry(uri);
if (entry == null || !entry.hasVariants()) {
return entry;
}
String variantUri = uriExtractor.getVariantURI(target, request, entry);
try {
return responseCache.getEntry(variantUri);
} catch (HttpCacheOperationException ex) {
return null;
}
return responseCache.getEntry(variantUri);
}
boolean clientRequestsOurOptions(HttpRequest request) {
@ -471,7 +461,8 @@ public class CachingHttpClient implements HttpClient {
backendResponse);
}
void storeInCache(HttpHost target, HttpRequest request, HttpCacheEntry entry) {
void storeInCache(
HttpHost target, HttpRequest request, HttpCacheEntry entry) throws IOException {
if (entry.hasVariants()) {
storeVariantEntry(target, request, entry);
} else {
@ -479,44 +470,33 @@ public class CachingHttpClient implements HttpClient {
}
}
void storeNonVariantEntry(HttpHost target, HttpRequest req, HttpCacheEntry entry) {
void storeNonVariantEntry(
HttpHost target, HttpRequest req, HttpCacheEntry entry) throws IOException {
String uri = uriExtractor.getURI(target, req);
try {
responseCache.putEntry(uri, entry);
} catch (HttpCacheOperationException ex) {
log.debug("Was unable to PUT an entry into the cache based on the uri provided", ex);
}
responseCache.putEntry(uri, entry);
}
void storeVariantEntry(
final HttpHost target,
final HttpRequest req,
final HttpCacheEntry entry) {
final HttpCacheEntry entry) throws IOException {
final String variantURI = uriExtractor.getVariantURI(target, req, entry);
try {
responseCache.putEntry(variantURI, entry);
} catch (HttpCacheOperationException e) {
log.debug("Was unable to PUT a variant entry into the cache based on the uri provided", e);
}
responseCache.putEntry(variantURI, entry);
HttpCacheUpdateCallback callback = new HttpCacheUpdateCallback() {
public HttpCacheEntry update(HttpCacheEntry existing) throws HttpCacheOperationException {
public HttpCacheEntry update(HttpCacheEntry existing) {
return doGetUpdatedParentEntry(existing, entry, variantURI);
}
};
String parentURI = uriExtractor.getURI(target, req);
try {
responseCache.updateEntry(parentURI, callback);
} catch (HttpCacheOperationException e) {
log.debug("Was unable to UPDATE a parent entry for a variant", e);
}
responseCache.updateEntry(parentURI, callback);
}
HttpCacheEntry doGetUpdatedParentEntry(
HttpCacheEntry existing,
HttpCacheEntry entry, String variantURI) throws HttpCacheOperationException {
HttpCacheEntry entry, String variantURI) {
if (existing != null) {
return HttpCacheEntry.copyWithVariant(existing, variantURI);
} else {
@ -585,11 +565,7 @@ public class CachingHttpClient implements HttpClient {
}
String uri = uriExtractor.getURI(target, request);
try {
responseCache.removeEntry(uri);
} catch (HttpCacheOperationException ex) {
log.debug("Was unable to remove an entry from the cache based on the uri provided", ex);
}
responseCache.removeEntry(uri);
return corrected;
}

View File

@ -26,6 +26,7 @@
*/
package org.apache.http.impl.client.cache;
import java.io.IOException;
import java.util.HashSet;
import java.util.Set;
@ -34,7 +35,6 @@ import org.apache.http.HttpHost;
import org.apache.http.HttpRequest;
import org.apache.http.ProtocolVersion;
import org.apache.http.client.cache.HttpCache;
import org.apache.http.client.cache.HttpCacheOperationException;
import org.apache.http.message.BasicHttpEntityEnclosingRequest;
import org.apache.http.message.BasicHttpRequest;
import org.easymock.classextension.EasyMock;
@ -186,7 +186,7 @@ public class TestCacheInvalidator {
}
@Test
public void testDoesNotInvalidateGETRequest() {
public void testDoesNotInvalidateGETRequest() throws Exception {
HttpRequest request = new BasicHttpRequest("GET","/",HTTP_1_1);
replayMocks();
@ -197,7 +197,7 @@ public class TestCacheInvalidator {
}
@Test
public void testDoesNotInvalidateHEADRequest() {
public void testDoesNotInvalidateHEADRequest() throws Exception {
HttpRequest request = new BasicHttpRequest("HEAD","/",HTTP_1_1);
replayMocks();
@ -244,7 +244,7 @@ public class TestCacheInvalidator {
}
@Test
public void testVariantURIsAreFlushedAlso() throws HttpCacheOperationException {
public void testVariantURIsAreFlushedAlso() throws Exception {
HttpRequest request = new BasicHttpRequest("POST","/",HTTP_1_1);
final String theUri = "http://foo.example.com/";
@ -264,7 +264,7 @@ public class TestCacheInvalidator {
verifyMocks();
}
@Test
@Test(expected=IOException.class)
public void testCacheFlushException() throws Exception {
HttpRequest request = new BasicHttpRequest("POST","/",HTTP_1_1);
String theURI = "http://foo.example.com/";
@ -273,7 +273,6 @@ public class TestCacheInvalidator {
replayMocks();
impl.flushInvalidatedCacheEntries(host, request);
verifyMocks();
}
// Expectations
@ -283,16 +282,16 @@ public class TestCacheInvalidator {
org.easymock.EasyMock.expect(mockEntry.getVariantURIs()).andReturn(variantURIs);
}
private void cacheReturnsEntryForUri(String theUri) throws HttpCacheOperationException {
private void cacheReturnsEntryForUri(String theUri) throws IOException {
org.easymock.EasyMock.expect(mockCache.getEntry(theUri)).andReturn(mockEntry);
}
private void cacheReturnsExceptionForUri(String theUri) throws HttpCacheOperationException {
private void cacheReturnsExceptionForUri(String theUri) throws IOException {
org.easymock.EasyMock.expect(mockCache.getEntry(theUri)).andThrow(
new HttpCacheOperationException("TOTAL FAIL"));
new IOException("TOTAL FAIL"));
}
private void entryIsRemoved(String theUri) throws HttpCacheOperationException {
private void entryIsRemoved(String theUri) throws IOException {
mockCache.removeEntry(theUri);
}

View File

@ -1068,7 +1068,7 @@ public class TestCachingHttpClient {
}
private void cacheInvalidatorWasCalled() {
private void cacheInvalidatorWasCalled() throws IOException {
mockInvalidator.flushInvalidatedCacheEntries(host, mockRequest);
}
@ -1094,7 +1094,7 @@ public class TestCachingHttpClient {
mockBackendResponse)).andReturn(mockUpdatedCacheEntry);
}
private void getCacheEntryReturns(CacheEntry entry) {
private void getCacheEntryReturns(CacheEntry entry) throws IOException {
EasyMock.expect(impl.getCacheEntry(host, mockRequest)).andReturn(entry);
}
@ -1235,11 +1235,11 @@ public class TestCachingHttpClient {
mockBackendResponse)).andReturn(response);
}
private void storeInCacheWasCalled() {
private void storeInCacheWasCalled() throws IOException {
impl.storeInCache(host, mockRequest, mockCacheEntry);
}
private void storeInCacheWasCalled(CacheEntry entry) {
private void storeInCacheWasCalled(CacheEntry entry) throws IOException {
impl.storeInCache(host, mockRequest, entry);
}

View File

@ -46,7 +46,7 @@ public class TestResponseCache {
}
@Test
public void testEntryRemainsInCacheWhenPutThere() {
public void testEntryRemainsInCacheWhenPutThere() throws Exception {
cache.putEntry("foo", entry);
HttpCacheEntry cachedEntry = cache.getEntry("foo");
@ -55,7 +55,7 @@ public class TestResponseCache {
}
@Test
public void testRemovedEntriesDoNotExistAnymore() {
public void testRemovedEntriesDoNotExistAnymore() throws Exception {
cache.putEntry("foo", entry);
cache.removeEntry("foo");
@ -66,7 +66,7 @@ public class TestResponseCache {
}
@Test
public void testCacheHoldsNoMoreThanSpecifiedMaxEntries() {
public void testCacheHoldsNoMoreThanSpecifiedMaxEntries() throws Exception {
BasicHttpCache cache = new BasicHttpCache(1);
HttpCacheEntry entry1 = new CacheEntry();
@ -89,7 +89,7 @@ public class TestResponseCache {
}
@Test
public void testSmallCacheKeepsMostRecentlyUsedEntry() {
public void testSmallCacheKeepsMostRecentlyUsedEntry() throws Exception {
final int max_size = 3;
BasicHttpCache cache = new BasicHttpCache(max_size);
@ -120,7 +120,7 @@ public class TestResponseCache {
}
@Test
public void testZeroMaxSizeCacheDoesNotStoreAnything() {
public void testZeroMaxSizeCacheDoesNotStoreAnything() throws Exception {
BasicHttpCache cache = new BasicHttpCache(0);
HttpCacheEntry entry = new CacheEntry();