From 5715851ff1027be8623c9a12eb0805fc24a843a6 Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Wed, 19 Feb 2014 19:59:44 +0100 Subject: [PATCH] modify cache api to match the one from shiro --- .../src/main/java/sonia/scm/cache/Cache.java | 45 ++++++----- .../main/java/sonia/scm/cache/MapCache.java | 68 +++++++++++++---- .../java/sonia/scm/cache/MapCacheManager.java | 11 +-- .../main/java/sonia/scm/cache/GuavaCache.java | 75 +++++++++++++++---- .../sonia/scm/cache/GuavaCacheManager.java | 4 +- .../java/sonia/scm/cache/CacheTestBase.java | 49 +++++++++++- 6 files changed, 197 insertions(+), 55 deletions(-) diff --git a/scm-core/src/main/java/sonia/scm/cache/Cache.java b/scm-core/src/main/java/sonia/scm/cache/Cache.java index dd064691c6..1a5b380695 100644 --- a/scm-core/src/main/java/sonia/scm/cache/Cache.java +++ b/scm-core/src/main/java/sonia/scm/cache/Cache.java @@ -43,8 +43,8 @@ import com.google.common.base.Predicate; * * @author Sebastian Sdorra * - * @param - The type of the keys for the cache - * @param - The type of cache elements + * @param type of the keys for the cache + * @param type of cached elements */ public interface Cache { @@ -59,7 +59,7 @@ public interface Cache * Returns true if this cache contains an element with the specified key. * * - * @param key - The key of the cached element + * @param key key of the cached element * * @return true if this cache contains an element with the specified key */ @@ -69,33 +69,43 @@ public interface Cache * Put a new element to this cache. * * - * @param key - The key of the element to cache - * @param value - The element that should be cached + * @param key key of the element to cache + * @param value element that should be cached + * + * @return previous cached value or null */ - public void put(K key, V value); + public V put(K key, V value); /** - * Remove the element with the specified key from this cache. The method - * returns true if the operation was successful. + * Remove the element with the specified key from this cache. Return previous + * cached value. * + * @param key key of the cached element * - * @param key - The key of the cached element - * - * @return true if the operation was successful + * @return previous cached value or null */ - public boolean remove(K key); + public V remove(K key); /** * Remove all elements with matching {@link Predicate} from this cache. - * The method returns true if the operation was successful. + * The method returns all previous cached values. * * @since 1.9 * - * @param predicate - predicate to match cache keys + * @param predicate predicate to match cache keys * - * @return true if the operation was successful + * @return all previous cached values */ - public boolean removeAll(Predicate predicate); + public Iterable removeAll(Predicate predicate); + + /** + * Returns the number of entries in the cache. + * + * @return number of entries in the cache + * + * @since 2.0.0 + */ + public int size(); //~--- get methods ---------------------------------------------------------- @@ -103,8 +113,7 @@ public interface Cache * Returns the element with the specified key. * Returns null if the cache contains no element with the specified key. * - * - * @param key - The key of the cached element + * @param key key of the cached element * * @return The cached element with the specified key or null */ diff --git a/scm-test/src/main/java/sonia/scm/cache/MapCache.java b/scm-test/src/main/java/sonia/scm/cache/MapCache.java index 98819fdc6a..a3b0f4cd2d 100644 --- a/scm-test/src/main/java/sonia/scm/cache/MapCache.java +++ b/scm-test/src/main/java/sonia/scm/cache/MapCache.java @@ -37,10 +37,14 @@ package sonia.scm.cache; import com.google.common.base.Predicate; import com.google.common.collect.Maps; +import com.google.common.collect.Sets; //~--- JDK imports ------------------------------------------------------------ +import java.util.Collection; +import java.util.Collections; import java.util.Map; +import java.util.Set; /** * @@ -50,7 +54,8 @@ import java.util.Map; * @param * @param */ -public class MapCache implements Cache +public class MapCache + implements Cache, org.apache.shiro.cache.Cache { /** @@ -81,13 +86,27 @@ public class MapCache implements Cache * Method description * * - * @param key - * @param value + * @return */ @Override - public void put(K key, V value) + public Set keys() { - map.put(key, value); + return Collections.unmodifiableSet(map.keySet()); + } + + /** + * Method description + * + * + * @param key + * @param value + * + * @return + */ + @Override + public V put(K key, V value) + { + return map.put(key, value); } /** @@ -99,9 +118,9 @@ public class MapCache implements Cache * @return */ @Override - public boolean remove(K key) + public V remove(K key) { - return map.remove(key) != null; + return map.remove(key); } /** @@ -113,22 +132,43 @@ public class MapCache implements Cache * @return */ @Override - public boolean removeAll(Predicate filter) + public Iterable removeAll(Predicate filter) { - boolean result = false; + Set values = Sets.newHashSet(); for (K key : map.keySet()) { if (filter.apply(key)) { - if (remove(key)) - { - result = true; - } + values.add(remove(key)); } } - return result; + return values; + } + + /** + * Method description + * + * + * @return + */ + @Override + public int size() + { + return map.size(); + } + + /** + * Method description + * + * + * @return + */ + @Override + public Collection values() + { + return Collections.unmodifiableCollection(map.values()); } //~--- get methods ---------------------------------------------------------- diff --git a/scm-test/src/main/java/sonia/scm/cache/MapCacheManager.java b/scm-test/src/main/java/sonia/scm/cache/MapCacheManager.java index 8aa5f6f8b9..3fa19565d3 100644 --- a/scm-test/src/main/java/sonia/scm/cache/MapCacheManager.java +++ b/scm-test/src/main/java/sonia/scm/cache/MapCacheManager.java @@ -30,6 +30,7 @@ */ + package sonia.scm.cache; //~--- non-JDK imports -------------------------------------------------------- @@ -47,7 +48,8 @@ import java.util.Map; * @author Sebastian Sdorra * @since 1.17 */ -public class MapCacheManager implements CacheManager +public class MapCacheManager + implements CacheManager, org.apache.shiro.cache.CacheManager { /** @@ -76,9 +78,9 @@ public class MapCacheManager implements CacheManager * @return */ @Override - public Cache getCache(String name) + public synchronized MapCache getCache(String name) { - Cache cache = cacheMap.get(name); + MapCache cache = cacheMap.get(name); if (cache == null) { @@ -89,10 +91,9 @@ public class MapCacheManager implements CacheManager return cache; } - //~--- fields --------------------------------------------------------------- /** Field description */ @SuppressWarnings("unchecked") - private final Map cacheMap = Maps.newHashMap(); + private final Map cacheMap = Maps.newHashMap(); } diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java index c3108ab406..be735a7ba4 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCache.java @@ -30,6 +30,7 @@ */ + package sonia.scm.cache; //~--- non-JDK imports -------------------------------------------------------- @@ -43,6 +44,8 @@ import org.slf4j.LoggerFactory; //~--- JDK imports ------------------------------------------------------------ +import java.util.Collection; +import java.util.Map.Entry; import java.util.Set; /** @@ -52,7 +55,8 @@ import java.util.Set; * @param * @param */ -public class GuavaCache implements Cache +public class GuavaCache + implements Cache, org.apache.shiro.cache.Cache { /** @@ -144,13 +148,31 @@ public class GuavaCache implements Cache * Method description * * - * @param key - * @param value + * @return */ @Override - public void put(K key, V value) + public Set keys() { + return cache.asMap().keySet(); + } + + /** + * Method description + * + * + * @param key + * @param value + * + * @return + */ + @Override + public V put(K key, V value) + { + V previous = cache.getIfPresent(key); + cache.put(key, copyStrategy.copyOnWrite(value)); + + return previous; } /** @@ -162,11 +184,13 @@ public class GuavaCache implements Cache * @return */ @Override - public boolean remove(K key) + public V remove(K key) { + V value = cache.getIfPresent(key); + cache.invalidate(key); - return true; + return value; } /** @@ -178,27 +202,50 @@ public class GuavaCache implements Cache * @return */ @Override - public boolean removeAll(Predicate filter) + public Iterable removeAll(Predicate filter) { + Set removedValues = Sets.newHashSet(); Set keysToRemove = Sets.newHashSet(); - for (K key : cache.asMap().keySet()) + for (Entry e : cache.asMap().entrySet()) { - if (filter.apply(key)) + if (filter.apply(e.getKey())) { - keysToRemove.add(key); + keysToRemove.add(e.getKey()); + removedValues.add(e.getValue()); } } - boolean result = false; - if (!keysToRemove.isEmpty()) { cache.invalidateAll(keysToRemove); - result = true; } - return result; + return removedValues; + } + + /** + * Method description + * + * + * @return + */ + @Override + public int size() + { + return (int) cache.size(); + } + + /** + * Method description + * + * + * @return + */ + @Override + public Collection values() + { + return cache.asMap().values(); } //~--- get methods ---------------------------------------------------------- diff --git a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java index 1c75ea0830..c46adb9fd3 100644 --- a/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java +++ b/scm-webapp/src/main/java/sonia/scm/cache/GuavaCacheManager.java @@ -30,6 +30,7 @@ */ + package sonia.scm.cache; //~--- non-JDK imports -------------------------------------------------------- @@ -52,7 +53,8 @@ import java.util.Map; * @author Sebastian Sdorra */ @Singleton -public class GuavaCacheManager implements CacheManager +public class GuavaCacheManager + implements CacheManager, org.apache.shiro.cache.CacheManager { /** diff --git a/scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java b/scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java index 13b893cb57..90136e9e5b 100644 --- a/scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java +++ b/scm-webapp/src/test/java/sonia/scm/cache/CacheTestBase.java @@ -30,17 +30,21 @@ */ + package sonia.scm.cache; //~--- non-JDK imports -------------------------------------------------------- import com.google.common.base.Predicate; + import org.junit.After; import org.junit.Before; import org.junit.Test; import sonia.scm.util.IOUtil; +import static org.hamcrest.Matchers.*; + import static org.junit.Assert.*; /** @@ -107,6 +111,21 @@ public abstract class CacheTestBase assertFalse(cache.contains("test-2")); } + /** + * Method description + * + */ + @Test + public void testOverride() + { + cache.put("test", "test123"); + + String previous = cache.put("test", "test456"); + + assertEquals("test123", previous); + assertEquals("test456", cache.get("test")); + } + /** * Method description * @@ -127,7 +146,10 @@ public abstract class CacheTestBase { cache.put("test", "test123"); assertEquals("test123", cache.get("test")); - cache.remove("test"); + + String previous = cache.remove("test"); + + assertEquals("test123", previous); assertNull(cache.get("test")); } @@ -139,10 +161,11 @@ public abstract class CacheTestBase public void testRemoveAll() { cache.put("test-1", "test123"); - cache.put("test-2", "test123"); + cache.put("test-2", "test456"); cache.put("a-1", "test123"); cache.put("a-2", "test123"); - cache.removeAll(new Predicate() + + Iterable previous = cache.removeAll(new Predicate() { @Override public boolean apply(String item) @@ -150,12 +173,32 @@ public abstract class CacheTestBase return item.startsWith("test"); } }); + + assertThat(previous, containsInAnyOrder("test123", "test456")); assertNull(cache.get("test-1")); assertNull(cache.get("test-2")); assertNotNull(cache.get("a-1")); assertNotNull(cache.get("a-2")); } + /** + * Method description + * + */ + @Test + public void testSize() + { + assertEquals(0, cache.size()); + cache.put("test", "test123"); + assertEquals(1, cache.size()); + cache.put("test-1", "test123"); + assertEquals(2, cache.size()); + cache.remove("test"); + assertEquals(1, cache.size()); + cache.clear(); + assertEquals(0, cache.size()); + } + //~--- fields --------------------------------------------------------------- /** Field description */