From c022320e0a80e5641bc92fd622664e97da7870cd Mon Sep 17 00:00:00 2001 From: Sebastian Sdorra Date: Mon, 14 Jan 2013 08:41:22 +0100 Subject: [PATCH] synchronize getChangeset method of hook events and call registered pre processors before the changesets are returned to hook --- .../repository/AbstractRepositoryManager.java | 17 ++ .../repository/DefaultRepositoryManager.java | 29 ++- .../SynchronizedRepositoryHookEvent.java | 201 ++++++++++++++++++ .../DefaultRepositoryManagerTest.java | 23 +- 4 files changed, 265 insertions(+), 5 deletions(-) create mode 100644 scm-webapp/src/main/java/sonia/scm/repository/SynchronizedRepositoryHookEvent.java diff --git a/scm-core/src/main/java/sonia/scm/repository/AbstractRepositoryManager.java b/scm-core/src/main/java/sonia/scm/repository/AbstractRepositoryManager.java index f46056da7c..e2955d1e64 100644 --- a/scm-core/src/main/java/sonia/scm/repository/AbstractRepositoryManager.java +++ b/scm-core/src/main/java/sonia/scm/repository/AbstractRepositoryManager.java @@ -177,6 +177,9 @@ public abstract class AbstractRepositoryManager implements RepositoryManager AssertUtil.assertIsNotNull(event.getType()); event.setRepository(repository); + // prepare the event + event = prepareHookEvent(event); + // post wrapped hook to event system ScmEventBus.getInstance().post(WrappedRepositoryHookEvent.wrap(event)); @@ -246,6 +249,20 @@ public abstract class AbstractRepositoryManager implements RepositoryManager ScmEventBus.getInstance().post(new RepositoryEvent(repository, event)); } + /** + * Prepare a hook event before it is fired to the event system of SCM-Manager. + * + * + * @param event hook event + * @since 1.26 + * + * @return + */ + protected RepositoryHookEvent prepareHookEvent(RepositoryHookEvent event) + { + return event; + } + //~--- fields --------------------------------------------------------------- /** repository hooks map */ diff --git a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java index b6835d77c4..5d953ef851 100644 --- a/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java +++ b/scm-webapp/src/main/java/sonia/scm/repository/DefaultRepositoryManager.java @@ -89,14 +89,15 @@ import javax.servlet.http.HttpServletRequest; public class DefaultRepositoryManager extends AbstractRepositoryManager { + /** Field description */ + private static final String THREAD_NAME = "Hook-%s"; + /** Field description */ private static final Logger logger = LoggerFactory.getLogger(DefaultRepositoryManager.class); //~--- constructors --------------------------------------------------------- - private static final String THREAD_NAME = "Hook-%s"; - /** * Constructs ... * @@ -108,19 +109,22 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager * @param handlerSet * @param repositoryListenersProvider * @param repositoryHooksProvider + * @param preProcessorUtil */ @Inject public DefaultRepositoryManager(ScmConfiguration configuration, SCMContextProvider contextProvider, KeyGenerator keyGenerator, RepositoryDAO repositoryDAO, Set handlerSet, Provider> repositoryListenersProvider, - Provider> repositoryHooksProvider) + Provider> repositoryHooksProvider, + PreProcessorUtil preProcessorUtil) { this.configuration = configuration; this.keyGenerator = keyGenerator; this.repositoryDAO = repositoryDAO; this.repositoryListenersProvider = repositoryListenersProvider; this.repositoryHooksProvider = repositoryHooksProvider; + this.preProcessorUtil = preProcessorUtil; //J- ThreadFactory factory = new ThreadFactoryBuilder() @@ -129,7 +133,7 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager Executors.newCachedThreadPool(factory) ); //J+ - + handlerMap = new HashMap(); types = new HashSet(); @@ -838,6 +842,20 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager } } + /** + * Method description + * + * + * @param event + * + * @return + */ + @Override + protected RepositoryHookEvent prepareHookEvent(RepositoryHookEvent event) + { + return SynchronizedRepositoryHookEvent.wrap(event, preProcessorUtil); + } + /** * Method description * @@ -1012,6 +1030,9 @@ public class DefaultRepositoryManager extends AbstractRepositoryManager /** Field description */ private KeyGenerator keyGenerator; + /** Field description */ + private PreProcessorUtil preProcessorUtil; + /** Field description */ private RepositoryDAO repositoryDAO; diff --git a/scm-webapp/src/main/java/sonia/scm/repository/SynchronizedRepositoryHookEvent.java b/scm-webapp/src/main/java/sonia/scm/repository/SynchronizedRepositoryHookEvent.java new file mode 100644 index 0000000000..8bc9c2b210 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/repository/SynchronizedRepositoryHookEvent.java @@ -0,0 +1,201 @@ +/** + * Copyright (c) 2010, Sebastian Sdorra All rights reserved. + * + * Redistribution and use in source and binary forms, with or without + * modification, are permitted provided that the following conditions are met: + * + * 1. Redistributions of source code must retain the above copyright notice, + * this list of conditions and the following disclaimer. 2. Redistributions in + * binary form must reproduce the above copyright notice, this list of + * conditions and the following disclaimer in the documentation and/or other + * materials provided with the distribution. 3. Neither the name of SCM-Manager; + * nor the names of its contributors may be used to endorse or promote products + * derived from this software without specific prior written permission. + * + * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" + * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE + * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE + * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE FOR + * ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL + * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR + * SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER + * CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, + * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE + * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE. + * + * http://bitbucket.org/sdorra/scm-manager + * + */ + + + +package sonia.scm.repository; + +//~--- non-JDK imports -------------------------------------------------------- + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.Collection; + +/** + * + * @author Sebastian Sdorra + */ +public class SynchronizedRepositoryHookEvent implements RepositoryHookEvent +{ + + /** Field description */ + private static final Object LOCK = new Object(); + + /** + * the logger for SynchronizedRepositoryHookEvent + */ + private static final Logger logger = + LoggerFactory.getLogger(SynchronizedRepositoryHookEvent.class); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + * + * @param wrappedEvent + * @param preProcessorUtil + */ + private SynchronizedRepositoryHookEvent(RepositoryHookEvent wrappedEvent, + PreProcessorUtil preProcessorUtil) + { + this.wrappedEvent = wrappedEvent; + this.preProcessorUtil = preProcessorUtil; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param event + * @param preProcessorUtil + * + * @return + */ + public static SynchronizedRepositoryHookEvent wrap(RepositoryHookEvent event, + PreProcessorUtil preProcessorUtil) + { + SynchronizedRepositoryHookEvent syncedEvent; + + if (event instanceof SynchronizedRepositoryHookEvent) + { + syncedEvent = (SynchronizedRepositoryHookEvent) event; + } + else + { + syncedEvent = new SynchronizedRepositoryHookEvent(event, + preProcessorUtil); + } + + return syncedEvent; + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + @Override + public Collection getChangesets() + { + if (changesets == null) + { + synchronized (LOCK) + { + if (changesets == null) + { + changesets = wrappedEvent.getChangesets(); + + if (changesets != null) + { + prepareChangesetsForReturn(); + } + } + } + } + + return changesets; + } + + /** + * Method description + * + * + * @return + */ + @Override + public Repository getRepository() + { + return wrappedEvent.getRepository(); + } + + /** + * Method description + * + * + * @return + */ + @Override + public RepositoryHookType getType() + { + return wrappedEvent.getType(); + } + + //~--- set methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @param repository + */ + @Override + public void setRepository(Repository repository) + { + wrappedEvent.setRepository(repository); + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + */ + private void prepareChangesetsForReturn() + { + Repository repository = getRepository(); + + logger.debug("prepare changesets of repository {} for return to hook", + repository.getName()); + + for (Changeset c : changesets) + { + preProcessorUtil.prepareForReturn(repository, c); + } + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private volatile Collection changesets; + + /** Field description */ + private PreProcessorUtil preProcessorUtil; + + /** Field description */ + private RepositoryHookEvent wrappedEvent; +} diff --git a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java index 984dd8b105..720bd3dd0e 100644 --- a/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java +++ b/scm-webapp/src/test/java/sonia/scm/repository/DefaultRepositoryManagerTest.java @@ -58,6 +58,7 @@ import static org.mockito.Mockito.*; import java.io.IOException; +import java.util.Collections; import java.util.HashSet; import java.util.Set; @@ -157,7 +158,27 @@ public class DefaultRepositoryManagerTest extends RepositoryManagerTestBase return new DefaultRepositoryManager(configuration, contextProvider, new DefaultKeyGenerator(), repositoryDAO, handlerSet, listenerProvider, - hookProvider); + hookProvider, createEmptyPreProcessorUtil()); + } + + /** + * Method description + * + * + * @return + */ + private PreProcessorUtil createEmptyPreProcessorUtil() + { + //J- + return new PreProcessorUtil( + new HashSet(), + new HashSet(), + new HashSet(), + new HashSet(), + new HashSet(), + new HashSet() + ); + //J+ } /**