HTTPCLIENT-978: ehcache based HTTP cache implementation

Contributed by Michajlo Matijkiw <michajlo_matijkiw at comcast.com>


git-svn-id: https://svn.apache.org/repos/asf/httpcomponents/httpclient/trunk@985733 13f79535-47bb-0310-9956-ffa450edef68
This commit is contained in:
Oleg Kalnichevski 2010-08-15 18:51:32 +00:00
parent a840e65989
commit 6956d4ffc8
5 changed files with 284 additions and 2 deletions

View File

@ -38,7 +38,7 @@
HttpComponents HttpClient - Cache HttpComponents HttpClient - Cache
</description> </description>
<url>http://hc.apache.org/httpcomponents-client</url> <url>http://hc.apache.org/httpcomponents-client</url>
<packaging>jar</packaging> <packaging>jar</packaging>
<licenses> <licenses>
<license> <license>
@ -79,6 +79,20 @@
<version>${easymock.version}</version> <version>${easymock.version}</version>
<scope>test</scope> <scope>test</scope>
</dependency> </dependency>
<dependency>
<groupId>net.sf.ehcache</groupId>
<artifactId>ehcache-core</artifactId>
<version>${ehcache.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
<dependency>
<groupId>org.slf4j</groupId>
<artifactId>slf4j-jcl</artifactId>
<version>${slf4j.version}</version>
<scope>compile</scope>
<optional>true</optional>
</dependency>
</dependencies> </dependencies>
<properties> <properties>

View File

@ -0,0 +1,76 @@
/*
* ====================================================================
* 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 java.io.IOException;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import org.apache.http.client.cache.HttpCache;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.client.cache.HttpCacheUpdateCallback;
public class EhcacheHttpCache implements HttpCache {
private Ehcache cache;
public EhcacheHttpCache(Ehcache cache) {
this.cache = cache;
}
public synchronized void putEntry(String key, HttpCacheEntry entry) throws IOException {
cache.put(new Element(key, entry));
}
public synchronized HttpCacheEntry getEntry(String url) {
Element e = cache.get(url);
return (e != null) ? (HttpCacheEntry)e.getValue() : null;
}
public synchronized void removeEntry(String url) {
cache.remove(url);
}
public synchronized void updateEntry(String key, HttpCacheUpdateCallback callback)
throws IOException {
Element e = cache.get(key);
HttpCacheEntry existingEntry = (e != null) ? (HttpCacheEntry)e.getValue() : null;
HttpCacheEntry updatedEntry = callback.update(existingEntry);
if (e == null) {
putEntry(key, updatedEntry);
} else {
// Attempt to do a CAS replace, if we fail throw an IOException for now
// While this operation should work fine within this instance, multiple instances
// could trample each others' data
if (!cache.replace(e, new Element(key, updatedEntry))) {
throw new IOException();
}
}
}
}

View File

@ -0,0 +1,91 @@
/*
* ====================================================================
* 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 java.io.IOException;
import junit.framework.TestCase;
import net.sf.ehcache.Ehcache;
import net.sf.ehcache.Element;
import org.apache.http.client.cache.HttpCacheEntry;
import org.apache.http.impl.client.cache.CacheEntry;
import org.easymock.EasyMock;
import org.junit.Test;
public class TestEhcacheHttpCache extends TestCase {
private Ehcache mockCache;
private EhcacheHttpCache impl;
public void setUp() {
mockCache = EasyMock.createMock(Ehcache.class);
impl = new EhcacheHttpCache(mockCache);
}
@Test
public void testCachePut() throws IOException {
final String key = "foo";
final HttpCacheEntry value = new CacheEntry();
Element e = new Element(key, value);
mockCache.put(e);
EasyMock.replay(mockCache);
impl.putEntry(key, value);
EasyMock.verify(mockCache);
}
@Test
public void testCacheGet() {
final String key = "foo";
final HttpCacheEntry cachedValue = new CacheEntry();
Element element = new Element(key, cachedValue);
EasyMock.expect(mockCache.get(key))
.andReturn(element);
EasyMock.replay(mockCache);
HttpCacheEntry resultingEntry = impl.getEntry(key);
EasyMock.verify(mockCache);
assertSame(cachedValue, resultingEntry);
}
@Test
public void testCacheRemove() {
final String key = "foo";
EasyMock.expect(mockCache.remove(key)).andReturn(true);
EasyMock.replay(mockCache);
impl.removeEntry(key);
EasyMock.verify(mockCache);
}
}

View File

@ -0,0 +1,99 @@
/*
* ====================================================================
* 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();
}
}

View File

@ -1,5 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?> <?xml version="1.0" encoding="UTF-8"?>
<!-- <!--
==================================================================== ====================================================================
Licensed to the Apache Software Foundation (ASF) under one Licensed to the Apache Software Foundation (ASF) under one
or more contributor license agreements. See the NOTICE file or more contributor license agreements. See the NOTICE file
@ -71,6 +71,8 @@
<httpcore.version>4.1-beta1</httpcore.version> <httpcore.version>4.1-beta1</httpcore.version>
<commons-logging.version>1.1.1</commons-logging.version> <commons-logging.version>1.1.1</commons-logging.version>
<commons-codec.version>1.4</commons-codec.version> <commons-codec.version>1.4</commons-codec.version>
<ehcache.version>2.2.0</ehcache.version>
<slf4j.version>1.5.11</slf4j.version>
<junit.version>4.8.1</junit.version> <junit.version>4.8.1</junit.version>
<easymock.version>2.5.2</easymock.version> <easymock.version>2.5.2</easymock.version>
</properties> </properties>