modify cache api to match the one from shiro

This commit is contained in:
Sebastian Sdorra
2014-02-19 19:59:44 +01:00
parent ffc12f2fa1
commit 5715851ff1
6 changed files with 197 additions and 55 deletions

View File

@@ -43,8 +43,8 @@ import com.google.common.base.Predicate;
* *
* @author Sebastian Sdorra * @author Sebastian Sdorra
* *
* @param <K> - The type of the keys for the cache * @param <K> type of the keys for the cache
* @param <V> - The type of cache elements * @param <V> type of cached elements
*/ */
public interface Cache<K, V> public interface Cache<K, V>
{ {
@@ -59,7 +59,7 @@ public interface Cache<K, V>
* Returns true if this cache contains an element with the specified key. * 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 * @return true if this cache contains an element with the specified key
*/ */
@@ -69,33 +69,43 @@ public interface Cache<K, V>
* Put a new element to this cache. * Put a new element to this cache.
* *
* *
* @param key - The key of the element to cache * @param key key of the element to cache
* @param value - The element that should be cached * @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 * Remove the element with the specified key from this cache. Return previous
* returns true if the operation was successful. * cached value.
* *
* @param key key of the cached element
* *
* @param key - The key of the cached element * @return previous cached value or null
*
* @return true if the operation was successful
*/ */
public boolean remove(K key); public V remove(K key);
/** /**
* Remove all elements with matching {@link Predicate} from this cache. * 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 * @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<K> predicate); public Iterable<V> removeAll(Predicate<K> 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 ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------
@@ -103,8 +113,7 @@ public interface Cache<K, V>
* Returns the element with the specified key. * Returns the element with the specified key.
* Returns null if the cache contains no element with the specified key. * Returns null if the cache contains no element with the specified key.
* *
* * @param key key of the cached element
* @param key - The key of the cached element
* *
* @return The cached element with the specified key or null * @return The cached element with the specified key or null
*/ */

View File

@@ -37,10 +37,14 @@ package sonia.scm.cache;
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.collect.Maps; import com.google.common.collect.Maps;
import com.google.common.collect.Sets;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.util.Collection;
import java.util.Collections;
import java.util.Map; import java.util.Map;
import java.util.Set;
/** /**
* *
@@ -50,7 +54,8 @@ import java.util.Map;
* @param <K> * @param <K>
* @param <V> * @param <V>
*/ */
public class MapCache<K, V> implements Cache<K, V> public class MapCache<K, V>
implements Cache<K, V>, org.apache.shiro.cache.Cache<K, V>
{ {
/** /**
@@ -81,13 +86,27 @@ public class MapCache<K, V> implements Cache<K, V>
* Method description * Method description
* *
* *
* @param key * @return
* @param value
*/ */
@Override @Override
public void put(K key, V value) public Set<K> 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<K, V> implements Cache<K, V>
* @return * @return
*/ */
@Override @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<K, V> implements Cache<K, V>
* @return * @return
*/ */
@Override @Override
public boolean removeAll(Predicate<K> filter) public Iterable<V> removeAll(Predicate<K> filter)
{ {
boolean result = false; Set<V> values = Sets.newHashSet();
for (K key : map.keySet()) for (K key : map.keySet())
{ {
if (filter.apply(key)) if (filter.apply(key))
{ {
if (remove(key)) values.add(remove(key));
{
result = true;
}
} }
} }
return result; return values;
}
/**
* Method description
*
*
* @return
*/
@Override
public int size()
{
return map.size();
}
/**
* Method description
*
*
* @return
*/
@Override
public Collection<V> values()
{
return Collections.unmodifiableCollection(map.values());
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------

View File

@@ -30,6 +30,7 @@
*/ */
package sonia.scm.cache; package sonia.scm.cache;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
@@ -47,7 +48,8 @@ import java.util.Map;
* @author Sebastian Sdorra * @author Sebastian Sdorra
* @since 1.17 * @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 * @return
*/ */
@Override @Override
public <K, V> Cache<K, V> getCache(String name) public synchronized <K, V> MapCache<K, V> getCache(String name)
{ {
Cache<K, V> cache = cacheMap.get(name); MapCache<K, V> cache = cacheMap.get(name);
if (cache == null) if (cache == null)
{ {
@@ -89,10 +91,9 @@ public class MapCacheManager implements CacheManager
return cache; return cache;
} }
//~--- fields --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** Field description */ /** Field description */
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private final Map<String, Cache> cacheMap = Maps.newHashMap(); private final Map<String, MapCache> cacheMap = Maps.newHashMap();
} }

View File

@@ -30,6 +30,7 @@
*/ */
package sonia.scm.cache; package sonia.scm.cache;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
@@ -43,6 +44,8 @@ import org.slf4j.LoggerFactory;
//~--- JDK imports ------------------------------------------------------------ //~--- JDK imports ------------------------------------------------------------
import java.util.Collection;
import java.util.Map.Entry;
import java.util.Set; import java.util.Set;
/** /**
@@ -52,7 +55,8 @@ import java.util.Set;
* @param <K> * @param <K>
* @param <V> * @param <V>
*/ */
public class GuavaCache<K, V> implements Cache<K, V> public class GuavaCache<K, V>
implements Cache<K, V>, org.apache.shiro.cache.Cache<K, V>
{ {
/** /**
@@ -144,13 +148,31 @@ public class GuavaCache<K, V> implements Cache<K, V>
* Method description * Method description
* *
* *
* @param key * @return
* @param value
*/ */
@Override @Override
public void put(K key, V value) public Set<K> 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)); cache.put(key, copyStrategy.copyOnWrite(value));
return previous;
} }
/** /**
@@ -162,11 +184,13 @@ public class GuavaCache<K, V> implements Cache<K, V>
* @return * @return
*/ */
@Override @Override
public boolean remove(K key) public V remove(K key)
{ {
V value = cache.getIfPresent(key);
cache.invalidate(key); cache.invalidate(key);
return true; return value;
} }
/** /**
@@ -178,27 +202,50 @@ public class GuavaCache<K, V> implements Cache<K, V>
* @return * @return
*/ */
@Override @Override
public boolean removeAll(Predicate<K> filter) public Iterable<V> removeAll(Predicate<K> filter)
{ {
Set<V> removedValues = Sets.newHashSet();
Set<K> keysToRemove = Sets.newHashSet(); Set<K> keysToRemove = Sets.newHashSet();
for (K key : cache.asMap().keySet()) for (Entry<K, V> 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()) if (!keysToRemove.isEmpty())
{ {
cache.invalidateAll(keysToRemove); 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<V> values()
{
return cache.asMap().values();
} }
//~--- get methods ---------------------------------------------------------- //~--- get methods ----------------------------------------------------------

View File

@@ -30,6 +30,7 @@
*/ */
package sonia.scm.cache; package sonia.scm.cache;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
@@ -52,7 +53,8 @@ import java.util.Map;
* @author Sebastian Sdorra * @author Sebastian Sdorra
*/ */
@Singleton @Singleton
public class GuavaCacheManager implements CacheManager public class GuavaCacheManager
implements CacheManager, org.apache.shiro.cache.CacheManager
{ {
/** /**

View File

@@ -30,17 +30,21 @@
*/ */
package sonia.scm.cache; package sonia.scm.cache;
//~--- non-JDK imports -------------------------------------------------------- //~--- non-JDK imports --------------------------------------------------------
import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import org.junit.After; import org.junit.After;
import org.junit.Before; import org.junit.Before;
import org.junit.Test; import org.junit.Test;
import sonia.scm.util.IOUtil; import sonia.scm.util.IOUtil;
import static org.hamcrest.Matchers.*;
import static org.junit.Assert.*; import static org.junit.Assert.*;
/** /**
@@ -107,6 +111,21 @@ public abstract class CacheTestBase
assertFalse(cache.contains("test-2")); 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 * Method description
* *
@@ -127,7 +146,10 @@ public abstract class CacheTestBase
{ {
cache.put("test", "test123"); cache.put("test", "test123");
assertEquals("test123", cache.get("test")); assertEquals("test123", cache.get("test"));
cache.remove("test");
String previous = cache.remove("test");
assertEquals("test123", previous);
assertNull(cache.get("test")); assertNull(cache.get("test"));
} }
@@ -139,10 +161,11 @@ public abstract class CacheTestBase
public void testRemoveAll() public void testRemoveAll()
{ {
cache.put("test-1", "test123"); cache.put("test-1", "test123");
cache.put("test-2", "test123"); cache.put("test-2", "test456");
cache.put("a-1", "test123"); cache.put("a-1", "test123");
cache.put("a-2", "test123"); cache.put("a-2", "test123");
cache.removeAll(new Predicate<String>()
Iterable<String> previous = cache.removeAll(new Predicate<String>()
{ {
@Override @Override
public boolean apply(String item) public boolean apply(String item)
@@ -150,12 +173,32 @@ public abstract class CacheTestBase
return item.startsWith("test"); return item.startsWith("test");
} }
}); });
assertThat(previous, containsInAnyOrder("test123", "test456"));
assertNull(cache.get("test-1")); assertNull(cache.get("test-1"));
assertNull(cache.get("test-2")); assertNull(cache.get("test-2"));
assertNotNull(cache.get("a-1")); assertNotNull(cache.get("a-1"));
assertNotNull(cache.get("a-2")); 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 --------------------------------------------------------------- //~--- fields ---------------------------------------------------------------
/** Field description */ /** Field description */