diff --git a/scm-core/src/main/java/com/google/common/eventbus/ThrowingEventBus.java b/scm-core/src/main/java/com/google/common/eventbus/ThrowingEventBus.java new file mode 100644 index 0000000000..81794590e7 --- /dev/null +++ b/scm-core/src/main/java/com/google/common/eventbus/ThrowingEventBus.java @@ -0,0 +1,70 @@ +/** + * 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 com.google.common.eventbus; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.event.EventBusException; + +//~--- JDK imports ------------------------------------------------------------ + +import java.lang.reflect.InvocationTargetException; + +/** + * + * @author Sebastian Sdorra + * @since 1.23 + */ +public class ThrowingEventBus extends EventBus +{ + + /** + * Method description + * + * + * @param event + * @param wrapper + */ + @Override + void dispatch(Object event, EventHandler wrapper) + { + try + { + wrapper.handleEvent(event); + } + catch (InvocationTargetException ex) + { + throw new EventBusException( + "could not handle event ".concat(event.toString()), ex); + } + } +} diff --git a/scm-core/src/main/java/sonia/scm/event/EventBusException.java b/scm-core/src/main/java/sonia/scm/event/EventBusException.java new file mode 100644 index 0000000000..6ae22bb43e --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/event/EventBusException.java @@ -0,0 +1,86 @@ +/** + * 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.event; + +/** + * + * @author Sebastian Sdorra + * @since 1.23 + */ +public class EventBusException extends RuntimeException +{ + + /** Field description */ + private static final long serialVersionUID = -6090833234971972368L; + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + public EventBusException() {} + + /** + * Constructs ... + * + * + * @param message + */ + public EventBusException(String message) + { + super(message); + } + + /** + * Constructs ... + * + * + * @param cause + */ + public EventBusException(Throwable cause) + { + super(cause); + } + + /** + * Constructs ... + * + * + * @param message + * @param cause + */ + public EventBusException(String message, Throwable cause) + { + super(message, cause); + } +} diff --git a/scm-core/src/main/java/sonia/scm/event/HandlerEventBase.java b/scm-core/src/main/java/sonia/scm/event/HandlerEventBase.java new file mode 100644 index 0000000000..573267f015 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/event/HandlerEventBase.java @@ -0,0 +1,65 @@ +/** + * 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.event; + +//~--- non-JDK imports -------------------------------------------------------- + +import sonia.scm.HandlerEvent; + +/** + * + * TODO for 2.0 rename to HandlerEvent + * + * @author Sebastian Sdorra + * @since 1.23 + * + * @param + */ +public interface HandlerEventBase +{ + + /** + * Method description + * + * + * @return + */ + public HandlerEvent getEventType(); + + /** + * Method description + * + * + * @return + */ + public T getItem(); +} diff --git a/scm-core/src/main/java/sonia/scm/event/ScmEventBus.java b/scm-core/src/main/java/sonia/scm/event/ScmEventBus.java new file mode 100644 index 0000000000..70bc0cf8b2 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/event/ScmEventBus.java @@ -0,0 +1,149 @@ +/** + * 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.event; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.common.eventbus.AsyncEventBus; +import com.google.common.eventbus.EventBus; +import com.google.common.eventbus.ThrowingEventBus; + +import org.apache.shiro.concurrent.SubjectAwareExecutorService; + +//~--- JDK imports ------------------------------------------------------------ + +import java.util.concurrent.Executors; + +/** + * + * @author Sebastian Sdorra + * @since 1.23 + */ +public class ScmEventBus extends EventBus +{ + + /** Field description */ + private static ScmEventBus instance = new ScmEventBus(); + + //~--- constructors --------------------------------------------------------- + + /** + * Constructs ... + * + */ + private ScmEventBus() + { + eventBus = new ThrowingEventBus(); + asyncEventBus = new AsyncEventBus( + new SubjectAwareExecutorService(Executors.newCachedThreadPool())); + } + + //~--- get methods ---------------------------------------------------------- + + /** + * Method description + * + * + * @return + */ + public static ScmEventBus getInstance() + { + return instance; + } + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + * + * @param event + */ + @Override + public void post(Object event) + { + asyncEventBus.post(event); + eventBus.post(event); + } + + /** + * Method description + * + * + * @param object + */ + @Override + public void register(Object object) + { + register(object, true); + } + + /** + * Method description + * + * + * @param object + * @param async + */ + public void register(Object object, boolean async) + { + if (async) + { + asyncEventBus.register(object); + } + else + { + eventBus.register(object); + } + } + + /** + * Method description + * + * + * @param object + */ + @Override + public void unregister(Object object) + { + asyncEventBus.unregister(object); + eventBus.unregister(object); + } + + //~--- fields --------------------------------------------------------------- + + /** Field description */ + private AsyncEventBus asyncEventBus; + + /** Field description */ + private EventBus eventBus; +} diff --git a/scm-core/src/main/java/sonia/scm/event/Subscriber.java b/scm-core/src/main/java/sonia/scm/event/Subscriber.java new file mode 100644 index 0000000000..d695cf2495 --- /dev/null +++ b/scm-core/src/main/java/sonia/scm/event/Subscriber.java @@ -0,0 +1,53 @@ +/** + * 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.event; + +//~--- JDK imports ------------------------------------------------------------ + +import java.lang.annotation.Documented; +import java.lang.annotation.ElementType; +import java.lang.annotation.Retention; +import java.lang.annotation.RetentionPolicy; +import java.lang.annotation.Target; + +/** + * + * @author Sebastian Sdorra + * @since 1.23 + */ +@Documented +@Target({ ElementType.TYPE }) +@Retention(RetentionPolicy.RUNTIME) +public @interface Subscriber +{ + boolean async() default true; +} diff --git a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java index 4c421e60a0..c4aee0f3fe 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmContextListener.java @@ -185,6 +185,7 @@ public class ScmContextListener extends GuiceServletContextListener List moduleList = Lists.newArrayList(); moduleList.add(new ScmInitializerModule()); + moduleList.add(new ScmSubscriberModule()); moduleList.add(ShiroWebModule.guiceFilterModule()); moduleList.add(main); moduleList.add(new ScmSecurityModule(servletContext)); diff --git a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java index 26b1b8b972..3878466199 100644 --- a/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java +++ b/scm-webapp/src/main/java/sonia/scm/ScmServletModule.java @@ -35,6 +35,7 @@ package sonia.scm; //~--- non-JDK imports -------------------------------------------------------- +import com.google.common.eventbus.EventBus; import com.google.inject.Provider; import com.google.inject.multibindings.Multibinder; import com.google.inject.name.Names; @@ -49,6 +50,7 @@ import sonia.scm.api.rest.UriExtensionsConfig; import sonia.scm.cache.CacheManager; import sonia.scm.cache.EhCacheManager; import sonia.scm.config.ScmConfiguration; +import sonia.scm.event.ScmEventBus; import sonia.scm.filter.AdminSecurityFilter; import sonia.scm.filter.BaseUrlFilter; import sonia.scm.filter.GZipFilter; @@ -248,6 +250,10 @@ public class ScmServletModule extends ServletModule RepositoryProvider.class, Repository.class).to( DefaultRepositoryProvider.class).in(RequestScoped.class); + // bind event api + bind(ScmEventBus.class).toInstance(ScmEventBus.getInstance()); + bind(EventBus.class).toInstance(ScmEventBus.getInstance()); + // bind core bind(StoreFactory.class, JAXBStoreFactory.class); bind(ListenableStoreFactory.class, JAXBStoreFactory.class); diff --git a/scm-webapp/src/main/java/sonia/scm/ScmSubscriberModule.java b/scm-webapp/src/main/java/sonia/scm/ScmSubscriberModule.java new file mode 100644 index 0000000000..f535398743 --- /dev/null +++ b/scm-webapp/src/main/java/sonia/scm/ScmSubscriberModule.java @@ -0,0 +1,172 @@ +/** + * 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; + +//~--- non-JDK imports -------------------------------------------------------- + +import com.google.inject.AbstractModule; +import com.google.inject.TypeLiteral; +import com.google.inject.matcher.AbstractMatcher; +import com.google.inject.matcher.Matcher; +import com.google.inject.spi.InjectionListener; +import com.google.inject.spi.TypeEncounter; +import com.google.inject.spi.TypeListener; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +import sonia.scm.event.ScmEventBus; +import sonia.scm.event.Subscriber; + +//~--- JDK imports ------------------------------------------------------------ + +import java.lang.annotation.Annotation; + +/** + * + * @author Sebastian Sdorra + */ +public class ScmSubscriberModule extends AbstractModule +{ + + /** + * the logger for ScmSubscriberModule + */ + private static final Logger logger = + LoggerFactory.getLogger(ScmSubscriberModule.class); + + //~--- methods -------------------------------------------------------------- + + /** + * Method description + * + */ + @Override + protected void configure() + { + bindListener(annotatedWith(Subscriber.class), new TypeListener() + { + + @Override + public void hear(TypeLiteral type, + final TypeEncounter encounter) + { + encounter.register(new InjectionListener() + { + @Override + public void afterInjection(Object object) + { + if (logger.isTraceEnabled()) + { + logger.trace("register subscriber {}", object.getClass()); + } + + Subscriber subscriber = + object.getClass().getAnnotation(Subscriber.class); + + + ScmEventBus.getInstance().register(object, subscriber.async()); + } + }); + } + + }); + } + + /** + * Method description + * + * + * @param aClass + * + * @return + */ + private Matcher> annotatedWith( + Class aClass) + { + return new AnnotatedWith(aClass); + } + + //~--- inner classes -------------------------------------------------------- + + /** + * Class description + * + * + * @version Enter version here..., 12/12/07 + * @author Enter your name here... + */ + private static class AnnotatedWith extends AbstractMatcher> + { + + /** + * Constructs ... + * + * + * @param baseClass + */ + private AnnotatedWith(Class baseClass) + { + this.baseClass = baseClass; + } + + //~--- methods ------------------------------------------------------------ + + /** + * Method description + * + * + * @param t + * + * @return + */ + @Override + public boolean matches(TypeLiteral t) + { + try + { + return t.getRawType().isAnnotationPresent(baseClass); + } + catch (Exception e) + { + + // LOG e + return false; + } + } + + //~--- fields ------------------------------------------------------------- + + /** Field description */ + private final Class baseClass; + } +}