View Javadoc

1   package com.atlassian.event.internal;
2   
3   import com.atlassian.event.spi.EventDispatcher;
4   import com.atlassian.event.spi.EventExecutorFactory;
5   import com.atlassian.event.spi.EventRunnableFactory;
6   import com.atlassian.event.spi.ListenerInvoker;
7   import com.google.common.util.concurrent.MoreExecutors;
8   import org.slf4j.Logger;
9   import org.slf4j.LoggerFactory;
10  
11  import java.util.concurrent.Executor;
12  
13  import static com.google.common.base.Preconditions.checkNotNull;
14  
15  /**
16   * This dispatcher will dispatch event asynchronously if: <ul> <li>the event 'is' asynchronous, as resolved by the
17   * {@link AsynchronousEventResolver} and</li> <li>the invoker {@link com.atlassian.event.spi.ListenerInvoker#supportAsynchronousEvents()
18   * supports asynchronous events}</li> </ul>
19   *
20   * @since 2.0
21   */
22  public class AsynchronousAbleEventDispatcher implements EventDispatcher {
23      private static final Logger log = LoggerFactory.getLogger(AsynchronousAbleEventDispatcher.class);
24  
25      /**
26       * An executor that execute commands synchronously
27       */
28      private static final Executor SYNCHRONOUS_EXECUTOR = MoreExecutors.directExecutor();
29  
30      /**
31       * {@link EventRunnableFactory} that creates a simple runnable that runs the invoker.
32       */
33      private static final EventRunnableFactory SIMPLE_RUNNABLE_FACTORY = new EventRunnableFactory() {
34          public Runnable getRunnable(final ListenerInvoker invoker, final Object event) {
35              return new Runnable() {
36                  public void run() {
37                      try {
38                          invoker.invoke(event);
39                      } catch (Exception e) {
40                          // Cannot use placeholder syntax until we upgrade to SLF4J 1.6+ - see EVENT-26
41                          // Add an enabled guard to avoid unnecessary String construction
42                          if (log.isErrorEnabled()) {
43                              log.error("There was an exception thrown trying to dispatch event [" + event + "] from the invoker [" + invoker + "]", e);
44                          }
45                      }
46                  }
47              };
48          }
49      };
50  
51      /**
52       * An asynchronous executor
53       */
54      private final Executor asynchronousExecutor;
55  
56      private final AsynchronousEventResolver asynchronousEventResolver;
57  
58      private final EventRunnableFactory runnableFactory;
59  
60      public AsynchronousAbleEventDispatcher(Executor executor, AsynchronousEventResolver asynchronousEventResolver, EventRunnableFactory runnableFactory) {
61          this.asynchronousEventResolver = checkNotNull(asynchronousEventResolver);
62          this.asynchronousExecutor = checkNotNull(executor);
63          this.runnableFactory = checkNotNull(runnableFactory);
64      }
65  
66  
67      public AsynchronousAbleEventDispatcher(Executor executor, AsynchronousEventResolver asynchronousEventResolver) {
68          this(executor, asynchronousEventResolver, SIMPLE_RUNNABLE_FACTORY);
69      }
70  
71  
72      public AsynchronousAbleEventDispatcher(EventExecutorFactory executorFactory, AsynchronousEventResolver asynchronousEventResolver, EventRunnableFactory runnableFactory) {
73          this(checkNotNull(executorFactory).getExecutor(), asynchronousEventResolver, runnableFactory);
74      }
75  
76  
77      public AsynchronousAbleEventDispatcher(EventExecutorFactory executorFactory, AsynchronousEventResolver asynchronousEventResolver) {
78          this(executorFactory, asynchronousEventResolver, SIMPLE_RUNNABLE_FACTORY);
79      }
80  
81  
82      public AsynchronousAbleEventDispatcher(EventExecutorFactory executorFactory) {
83          this(executorFactory, new AnnotationAsynchronousEventResolver(), SIMPLE_RUNNABLE_FACTORY);
84      }
85  
86  
87      public void dispatch(final ListenerInvoker invoker, final Object event) {
88          executorFor(checkNotNull(invoker), checkNotNull(event)).execute(runnableFactory.getRunnable(invoker, event));
89      }
90  
91      protected Executor executorFor(ListenerInvoker invoker, Object event) {
92          return asynchronousEventResolver.isAsynchronousEvent(event) && invoker.supportAsynchronousEvents()
93                  ? getAsynchronousExecutor()
94                  : getSynchronousExecutor();
95      }
96  
97      protected Executor getSynchronousExecutor() {
98          return SYNCHRONOUS_EXECUTOR;
99      }
100 
101     protected Executor getAsynchronousExecutor() {
102         return asynchronousExecutor;
103     }
104 
105 }