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 @@ + + + + + + + + + + + + + + + + + + +