diff --git a/scm-webapp/pom.xml b/scm-webapp/pom.xml
index 205b98edf0..51b18334b2 100644
--- a/scm-webapp/pom.xml
+++ b/scm-webapp/pom.xml
@@ -85,6 +85,12 @@
${guice.version}
+
+ org.slf4j
+ slf4j-jdk14
+ 1.6.1
+
+
net.sf.ehcache
ehcache-core
diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java
index 75beaa632f..b7b884875b 100644
--- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java
+++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java
@@ -10,9 +10,13 @@ package sonia.scm;
//~--- non-JDK imports --------------------------------------------------------
import com.google.inject.multibindings.Multibinder;
+import com.google.inject.name.Names;
import com.google.inject.servlet.ServletModule;
import sonia.scm.api.rest.UriExtensionsConfig;
+import sonia.scm.cache.CacheManager;
+import sonia.scm.cache.CacheRepositoryManagerDecorator;
+import sonia.scm.cache.EhCacheManager;
import sonia.scm.plugin.SCMPluginManager;
import sonia.scm.plugin.ScriptResourceServlet;
import sonia.scm.repository.BasicRepositoryManager;
@@ -118,8 +122,11 @@ public class ScmServletModule extends ServletModule
repositoryHandlerBinder.addBinding().to(handler);
}
+ bind(CacheManager.class).to(EhCacheManager.class);
bind(Authenticator.class).to(DemoAuthenticator.class);
- bind(RepositoryManager.class).to(BasicRepositoryManager.class);
+ bind(RepositoryManager.class).annotatedWith(Undecorated.class).to(
+ BasicRepositoryManager.class);
+ bind(RepositoryManager.class).to(CacheRepositoryManagerDecorator.class);
bind(ScmWebPluginContext.class).toInstance(webPluginContext);
/*
diff --git a/scm-webapp/src/main/java/sonia/scm/Undecorated.java b/scm-webapp/src/main/java/sonia/scm/Undecorated.java
new file mode 100644
index 0000000000..f6b51ec32a
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/Undecorated.java
@@ -0,0 +1,28 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.BindingAnnotation;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@BindingAnnotation
+@Target({ ElementType.FIELD, ElementType.METHOD, ElementType.PARAMETER })
+@Retention(RetentionPolicy.RUNTIME)
+public @interface Undecorated {}
diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheManager.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheManager.java
new file mode 100644
index 0000000000..6e645f6dcb
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheManager.java
@@ -0,0 +1,46 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm.cache;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public interface CacheManager
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ * @param value
+ * @param name
+ * @param
+ * @param
+ *
+ * @return
+ */
+ public ExtendedCache getExtendedCache(Class key,
+ Class value, String name);
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ * @param value
+ * @param name
+ * @param
+ * @param
+ *
+ * @return
+ */
+ public SimpleCache getSimpleCache(Class key, Class value,
+ String name);
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/cache/CacheRepositoryManagerDecorator.java b/scm-webapp/src/main/java/sonia/scm/cache/CacheRepositoryManagerDecorator.java
new file mode 100644
index 0000000000..d7b8592855
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/cache/CacheRepositoryManagerDecorator.java
@@ -0,0 +1,217 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm.cache;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Inject;
+import com.google.inject.name.Named;
+
+import sonia.scm.repository.AbstractRepositoryManagerDecorator;
+import sonia.scm.repository.Repository;
+import sonia.scm.repository.RepositoryException;
+import sonia.scm.repository.RepositoryManager;
+import sonia.scm.util.AssertUtil;
+import sonia.scm.util.Util;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.io.IOException;
+
+import java.util.Collection;
+import sonia.scm.Undecorated;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+public class CacheRepositoryManagerDecorator
+ extends AbstractRepositoryManagerDecorator
+{
+
+ /** Field description */
+ public static final String CACHE_KEY_ALL = "__all";
+
+ /** Field description */
+ public static final String CACHE_REPOSITORY = "sonia.cache.repository";
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param manager
+ * @param cacheManager
+ */
+ @Inject
+ public CacheRepositoryManagerDecorator(
+ @Undecorated RepositoryManager manager,
+ CacheManager cacheManager)
+ {
+ super(manager);
+ cache = cacheManager.getExtendedCache(String.class, Repository.class,
+ CACHE_REPOSITORY);
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public void create(Repository repository)
+ throws RepositoryException, IOException
+ {
+ orginal.create(repository);
+ putToCache(repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public void delete(Repository repository)
+ throws RepositoryException, IOException
+ {
+ orginal.delete(repository);
+ removeFromCache(repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public void modify(Repository repository)
+ throws RepositoryException, IOException
+ {
+ cache.remove(repository.getId());
+ orginal.modify(repository);
+ putToCache(repository);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ *
+ * @throws IOException
+ * @throws RepositoryException
+ */
+ @Override
+ public void refresh(Repository repository)
+ throws RepositoryException, IOException
+ {
+ orginal.refresh(repository);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param id
+ *
+ * @return
+ */
+ @Override
+ public Repository get(String id)
+ {
+ AssertUtil.assertIsNotEmpty(id);
+
+ Repository repository = cache.get(id);
+
+ if (repository == null)
+ {
+ repository = orginal.get(id);
+
+ if (repository != null)
+ {
+ putToCache(repository);
+ }
+ }
+
+ return repository;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @return
+ */
+ @Override
+ public Collection getAll()
+ {
+ Collection repositories = cache.getCollection(CACHE_KEY_ALL);
+
+ if (repositories == null)
+ {
+ repositories = orginal.getAll();
+ cache.putCollection(CACHE_KEY_ALL, repositories);
+ }
+
+ return repositories;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ */
+ private void putToCache(Repository repository)
+ {
+ String id = repository.getId();
+
+ if (Util.isNotEmpty(id))
+ {
+ cache.put(id, repository);
+ cache.removeCollection(CACHE_KEY_ALL);
+ }
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param repository
+ */
+ private void removeFromCache(Repository repository)
+ {
+ cache.remove(repository.getId());
+ cache.removeCollection(CACHE_KEY_ALL);
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private ExtendedCache cache;
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/cache/EhCache.java b/scm-webapp/src/main/java/sonia/scm/cache/EhCache.java
new file mode 100644
index 0000000000..2d358bd2fe
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/cache/EhCache.java
@@ -0,0 +1,156 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm.cache;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import net.sf.ehcache.Cache;
+import net.sf.ehcache.Element;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.Collection;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ *
+ * @param
+ * @param
+ */
+public class EhCache implements ExtendedCache
+{
+
+ /**
+ * Constructs ...
+ *
+ *
+ * @param cache
+ */
+ public EhCache(Cache cache)
+ {
+ this.cache = cache;
+ }
+
+ //~--- methods --------------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ */
+ @Override
+ public void clear()
+ {
+ cache.removeAll();
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ * @param value
+ */
+ @Override
+ public void put(K key, V value)
+ {
+ cache.put(new Element(key, value));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ * @param value
+ */
+ @Override
+ public void putCollection(K key, Collection value)
+ {
+ cache.put(new Element(key, value));
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ *
+ * @return
+ */
+ @Override
+ public boolean remove(K key)
+ {
+ return cache.remove(key);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ *
+ * @return
+ */
+ @Override
+ public boolean removeCollection(K key)
+ {
+ return cache.remove(key);
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ *
+ * @return
+ */
+ @Override
+ public V get(K key)
+ {
+ V value = null;
+ Element el = cache.get(key);
+
+ if (el != null)
+ {
+ value = (V) el.getObjectValue();
+ }
+
+ return value;
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ *
+ * @return
+ */
+ @Override
+ public Collection getCollection(K key)
+ {
+ Collection value = null;
+ Element el = cache.get(key);
+
+ if (el != null)
+ {
+ value = (Collection) el.getObjectValue();
+ }
+
+ return value;
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private Cache cache;
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/cache/EhCacheManager.java b/scm-webapp/src/main/java/sonia/scm/cache/EhCacheManager.java
new file mode 100644
index 0000000000..7e41a1c84f
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/cache/EhCacheManager.java
@@ -0,0 +1,99 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm.cache;
+
+//~--- non-JDK imports --------------------------------------------------------
+
+import com.google.inject.Singleton;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ */
+@Singleton
+public class EhCacheManager implements CacheManager
+{
+
+ /** Field description */
+ public static final String CONFIG = "/config/ehcache.xml";
+
+ //~--- constructors ---------------------------------------------------------
+
+ /**
+ * Constructs ...
+ *
+ */
+ public EhCacheManager()
+ {
+ cacheManager =
+ new net.sf.ehcache.CacheManager(EhCacheManager.class.getResource(CONFIG));
+ }
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ * @param value
+ * @param name
+ * @param
+ * @param
+ *
+ * @return
+ */
+ @Override
+ public ExtendedCache getExtendedCache(Class key,
+ Class value, String name)
+ {
+ return getCache(key, value, name);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ * @param value
+ * @param name
+ * @param
+ * @param
+ *
+ * @return
+ */
+ @Override
+ public SimpleCache getSimpleCache(Class key, Class value,
+ String name)
+ {
+ return getCache(key, value, name);
+ }
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ * @param value
+ * @param name
+ * @param
+ * @param
+ *
+ * @return
+ */
+ private EhCache getCache(Class key, Class value,
+ String name)
+ {
+ return new EhCache(cacheManager.getCache(name));
+ }
+
+ //~--- fields ---------------------------------------------------------------
+
+ /** Field description */
+ private net.sf.ehcache.CacheManager cacheManager;
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/cache/ExtendedCache.java b/scm-webapp/src/main/java/sonia/scm/cache/ExtendedCache.java
new file mode 100644
index 0000000000..ef59daf956
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/cache/ExtendedCache.java
@@ -0,0 +1,54 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm.cache;
+
+//~--- JDK imports ------------------------------------------------------------
+
+import java.util.Collection;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ *
+ * @param
+ * @param
+ */
+public interface ExtendedCache extends SimpleCache
+{
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ * @param value
+ */
+ public void putCollection(K key, Collection value);
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ *
+ * @return
+ */
+ public boolean removeCollection(K key);
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ *
+ * @return
+ */
+ public Collection getCollection(K key);
+}
diff --git a/scm-webapp/src/main/java/sonia/scm/cache/SimpleCache.java b/scm-webapp/src/main/java/sonia/scm/cache/SimpleCache.java
new file mode 100644
index 0000000000..f23e330fd4
--- /dev/null
+++ b/scm-webapp/src/main/java/sonia/scm/cache/SimpleCache.java
@@ -0,0 +1,56 @@
+/*
+ * To change this template, choose Tools | Templates
+ * and open the template in the editor.
+ */
+
+
+
+package sonia.scm.cache;
+
+/**
+ *
+ * @author Sebastian Sdorra
+ *
+ * @param
+ * @param
+ */
+public interface SimpleCache
+{
+
+ /**
+ * Method description
+ *
+ */
+ public void clear();
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ * @param value
+ */
+ public void put(K key, V value);
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ *
+ * @return
+ */
+ public boolean remove(K key);
+
+ //~--- get methods ----------------------------------------------------------
+
+ /**
+ * Method description
+ *
+ *
+ * @param key
+ *
+ * @return
+ */
+ public V get(K key);
+}
diff --git a/scm-webapp/src/main/resources/config/ehcache.xml b/scm-webapp/src/main/resources/config/ehcache.xml
new file mode 100644
index 0000000000..4cd9d35c07
--- /dev/null
+++ b/scm-webapp/src/main/resources/config/ehcache.xml
@@ -0,0 +1,79 @@
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+