11d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/*
21d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Copyright (C) 2007 The Guava Authors
31d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
41d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Licensed under the Apache License, Version 2.0 (the "License");
51d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * you may not use this file except in compliance with the License.
61d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * You may obtain a copy of the License at
71d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
81d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * http://www.apache.org/licenses/LICENSE-2.0
91d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Unless required by applicable law or agreed to in writing, software
111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * distributed under the License is distributed on an "AS IS" BASIS,
121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * See the License for the specific language governing permissions and
141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * limitations under the License.
151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpackage com.google.common.eventbus;
181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.Beta;
201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.annotations.VisibleForTesting;
211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Supplier;
221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.base.Throwables;
231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.cache.CacheBuilder;
241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.cache.CacheLoader;
251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.cache.LoadingCache;
261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Lists;
271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Multimap;
281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Multimaps;
291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.SetMultimap;
301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport com.google.common.collect.Sets;
311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.lang.reflect.InvocationTargetException;
331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Collection;
341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.List;
351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Map.Entry;
361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.Set;
371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ConcurrentHashMap;
381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ConcurrentLinkedQueue;
391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.CopyOnWriteArraySet;
401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.concurrent.ExecutionException;
411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.logging.Level;
421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertimport java.util.logging.Logger;
431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert/**
451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Dispatches events to listeners, and provides ways for listeners to register
461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * themselves.
471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The EventBus allows publish-subscribe-style communication between
491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * components without requiring the components to explicitly register with one
501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * another (and thus be aware of each other).  It is designed exclusively to
511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * replace traditional Java in-process event distribution using explicit
521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * registration. It is <em>not</em> a general-purpose publish-subscribe system,
531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * nor is it intended for interprocess communication.
541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <h2>Receiving Events</h2>
561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * To receive events, an object should:<ol>
571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>Expose a public method, known as the <i>event handler</i>, which accepts
581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     a single argument of the type of event desired;</li>
591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>Mark it with a {@link Subscribe} annotation;</li>
601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <li>Pass itself to an EventBus instance's {@link #register(Object)} method.
611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *     </li>
621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * </ol>
631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <h2>Posting Events</h2>
651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * To post an event, simply provide the event object to the
661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * {@link #post(Object)} method.  The EventBus instance will determine the type
671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * of event and route it to all registered listeners.
681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Events are routed based on their type &mdash; an event will be delivered
701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * to any handler for any type to which the event is <em>assignable.</em>  This
711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * includes implemented interfaces, all superclasses, and all interfaces
721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * implemented by superclasses.
731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>When {@code post} is called, all registered handlers for an event are run
751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * in sequence, so handlers should be reasonably quick.  If an event may trigger
761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * an extended process (such as a database load), spawn a thread or queue it for
771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * later.  (For a convenient way to do this, use an {@link AsyncEventBus}.)
781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <h2>Handler Methods</h2>
801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Event handler methods must accept only one argument: the event.
811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>Handlers should not, in general, throw.  If they do, the EventBus will
831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * catch and log the exception.  This is rarely the right solution for error
841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * handling and should not be relied upon; it is intended solely to help find
851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * problems during development.
861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>The EventBus guarantees that it will not call a handler method from
881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * multiple threads simultaneously, unless the method explicitly allows it by
891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * bearing the {@link AllowConcurrentEvents} annotation.  If this annotation is
901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * not present, handler methods need not worry about being reentrant, unless
911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * also called from outside the EventBus.
921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <h2>Dead Events</h2>
941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * If an event is posted, but no registered handlers can accept it, it is
951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * considered "dead."  To give the system a second chance to handle dead events,
961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * they are wrapped in an instance of {@link DeadEvent} and reposted.
971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>If a handler for a supertype of all events (such as Object) is registered,
991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * no event will ever be considered dead, and no DeadEvents will be generated.
1001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * Accordingly, while DeadEvent extends {@link Object}, a handler registered to
1011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * receive any Object will never receive a DeadEvent.
1021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * <p>This class is safe for concurrent use.
1041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert *
1051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @author Cliff Biffle
1061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert * @since 10.0
1071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert */
1081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert@Beta
1091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringertpublic class EventBus {
1101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * All registered event handlers, indexed by event type.
1131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final SetMultimap<Class<?>, EventHandler> handlersByType =
1151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Multimaps.newSetMultimap(new ConcurrentHashMap<Class<?>, Collection<EventHandler>>(),
1161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          new Supplier<Set<EventHandler>>() {
1171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            @Override
1181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            public Set<EventHandler> get() {
1191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return new CopyOnWriteArraySet<EventHandler>();
1201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
1211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          });
1221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Logger for event dispatch failures.  Named by the fully-qualified name of
1251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * this class, followed by the identifier provided at construction.
1261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final Logger logger;
1281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Strategy for finding handler methods in registered objects.  Currently,
1311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * only the {@link AnnotatedHandlerFinder} is supported, but this is
1321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * encapsulated for future expansion.
1331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final HandlerFindingStrategy finder = new AnnotatedHandlerFinder();
1351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** queues of events for the current thread to dispatch */
1371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final ThreadLocal<ConcurrentLinkedQueue<EventWithHandler>>
1381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      eventsToDispatch =
1391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      new ThreadLocal<ConcurrentLinkedQueue<EventWithHandler>>() {
1401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override protected ConcurrentLinkedQueue<EventWithHandler> initialValue() {
1411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return new ConcurrentLinkedQueue<EventWithHandler>();
1421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  };
1441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** true if the current thread is currently dispatching an event */
1461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private final ThreadLocal<Boolean> isDispatching =
1471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      new ThreadLocal<Boolean>() {
1481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    @Override protected Boolean initialValue() {
1491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return false;
1501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
1511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  };
1521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * A thread-safe cache for flattenHierarch(). The Class class is immutable.
1551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  private LoadingCache<Class<?>, Set<Class<?>>> flattenHierarchyCache =
1571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      CacheBuilder.newBuilder()
1581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          .weakKeys()
1591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          .build(new CacheLoader<Class<?>, Set<Class<?>>>() {
1601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            @Override
1611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            public Set<Class<?>> load(Class<?> concreteClass) throws Exception {
1621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              List<Class<?>> parents = Lists.newLinkedList();
1631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              Set<Class<?>> classes = Sets.newHashSet();
1641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              parents.add(concreteClass);
1661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              while (!parents.isEmpty()) {
1681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                Class<?> clazz = parents.remove(0);
1691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                classes.add(clazz);
1701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                Class<?> parent = clazz.getSuperclass();
1721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                if (parent != null) {
1731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  parents.add(parent);
1741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                }
1751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                for (Class<?> iface : clazz.getInterfaces()) {
1771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                  parents.add(iface);
1781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert                }
1791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              }
1801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert              return classes;
1821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            }
1831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          });
1841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates a new EventBus named "default".
1871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public EventBus() {
1891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    this("default");
1901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
1911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
1921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
1931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates a new EventBus with the given {@code identifier}.
1941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
1951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param identifier  a brief name for this bus, for logging purposes.  Should
1961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *                    be a valid Java identifier.
1971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
1981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public EventBus(String identifier) {
1991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    logger = Logger.getLogger(EventBus.class.getName() + "." + identifier);
2001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Registers all handler methods on {@code object} to receive events.
2041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Handler methods are selected and classified using this EventBus's
2051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link HandlerFindingStrategy}; the default strategy is the
2061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link AnnotatedHandlerFinder}.
2071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param object  object whose handler methods should be registered.
2091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void register(Object object) {
2111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    handlersByType.putAll(finder.findAllHandlers(object));
2121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Unregisters all handler methods on a registered {@code object}.
2161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param object  object whose handler methods should be unregistered.
2181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @throws IllegalArgumentException if the object was not previously registered.
2191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void unregister(Object object) {
2211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Multimap<Class<?>, EventHandler> methodsInListener = finder.findAllHandlers(object);
2221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (Entry<Class<?>, Collection<EventHandler>> entry : methodsInListener.asMap().entrySet()) {
2231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Set<EventHandler> currentHandlers = getHandlersForEventType(entry.getKey());
2241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Collection<EventHandler> eventMethodsInListener = entry.getValue();
2251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (currentHandlers == null || !currentHandlers.containsAll(entry.getValue())) {
2271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        throw new IllegalArgumentException(
2281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert            "missing event handler for an annotated method. Is " + object + " registered?");
2291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      currentHandlers.removeAll(eventMethodsInListener);
2311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Posts an event to all registered handlers.  This method will return
2361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * successfully after the event has been posted to all handlers, and
2371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * regardless of any exceptions thrown by handlers.
2381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * <p>If no handlers have been subscribed for {@code event}'s class, and
2401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code event} is not already a {@link DeadEvent}, it will be wrapped in a
2411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * DeadEvent and reposted.
2421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
2431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param event  event to post.
2441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  public void post(Object event) {
2461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    Set<Class<?>> dispatchTypes = flattenHierarchy(event.getClass());
2471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    boolean dispatched = false;
2491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    for (Class<?> eventType : dispatchTypes) {
2501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      Set<EventHandler> wrappers = getHandlersForEventType(eventType);
2511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      if (wrappers != null && !wrappers.isEmpty()) {
2531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        dispatched = true;
2541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        for (EventHandler wrapper : wrappers) {
2551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          enqueueEvent(event, wrapper);
2561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (!dispatched && !(event instanceof DeadEvent)) {
2611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      post(new DeadEvent(this, event));
2621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    dispatchQueuedEvents();
2651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Queue the {@code event} for dispatch during
2691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@link #dispatchQueuedEvents()}. Events are queued in-order of occurrence
2701d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * so they can be dispatched in the same order.
2711d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2721d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  protected void enqueueEvent(Object event, EventHandler handler) {
2731d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    eventsToDispatch.get().offer(new EventWithHandler(event, handler));
2741d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
2751d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2761d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
2771d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Drain the queue of events to be dispatched. As the queue is being drained,
2781d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * new events may be posted to the end of the queue.
2791d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
2801d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  protected void dispatchQueuedEvents() {
2811d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // don't dispatch if we're already dispatching, that would allow reentrancy
2821d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // and out-of-order events. Instead, leave the events to be dispatched
2831d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    // after the in-progress dispatch is complete.
2841d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    if (isDispatching.get()) {
2851d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return;
2861d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
2871d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2881d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    isDispatching.set(true);
2891d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
2901d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      while (true) {
2911d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        EventWithHandler eventWithHandler = eventsToDispatch.get().poll();
2921d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        if (eventWithHandler == null) {
2931d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          break;
2941d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        }
2951d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
2961d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert        dispatch(eventWithHandler.event, eventWithHandler.handler);
2971d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      }
2981d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } finally {
2991d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      isDispatching.set(false);
3001d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3011d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3021d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3031d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3041d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Dispatches {@code event} to the handler in {@code wrapper}.  This method
3051d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * is an appropriate override point for subclasses that wish to make
3061d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * event delivery asynchronous.
3071d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3081d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param event  event to dispatch.
3091d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param wrapper  wrapper that will call the handler.
3101d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3111d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  protected void dispatch(Object event, EventHandler wrapper) {
3121d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3131d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      wrapper.handleEvent(event);
3141d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (InvocationTargetException e) {
3151d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      logger.log(Level.SEVERE,
3161d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert          "Could not dispatch event: " + event + " to handler " + wrapper, e);
3171d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3181d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3191d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3201d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3211d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Retrieves a mutable set of the currently registered handlers for
3221d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * {@code type}.  If no handlers are currently registered for {@code type},
3231d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * this method may either return {@code null} or an empty set.
3241d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3251d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param type  type of handlers to retrieve.
3261d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return currently registered handlers, or {@code null}.
3271d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3281d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Set<EventHandler> getHandlersForEventType(Class<?> type) {
3291d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return handlersByType.get(type);
3301d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3311d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3321d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3331d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Creates a new Set for insertion into the handler map.  This is provided
3341d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * as an override point for subclasses. The returned set should support
3351d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * concurrent access.
3361d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3371d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return a new, mutable set for handlers.
3381d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3391d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  protected Set<EventHandler> newHandlerSet() {
3401d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    return new CopyOnWriteArraySet<EventHandler>();
3411d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3421d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3431d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /**
3441d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * Flattens a class's type hierarchy into a set of Class objects.  The set
3451d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * will include all superclasses (transitively), and all interfaces
3461d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * implemented by these superclasses.
3471d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   *
3481d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @param concreteClass  class whose type hierarchy will be retrieved.
3491d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   * @return {@code clazz}'s complete type hierarchy, flattened and uniqued.
3501d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert   */
3511d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  @VisibleForTesting
3521d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  Set<Class<?>> flattenHierarchy(Class<?> concreteClass) {
3531d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    try {
3541d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      return flattenHierarchyCache.get(concreteClass);
3551d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    } catch (ExecutionException e) {
3561d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      throw Throwables.propagate(e.getCause());
3571d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3581d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3591d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert
3601d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  /** simple struct representing an event and it's handler */
3611d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  static class EventWithHandler {
3621d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final Object event;
3631d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    final EventHandler handler;
3641d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    public EventWithHandler(Object event, EventHandler handler) {
3651d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.event = event;
3661d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert      this.handler = handler;
3671d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert    }
3681d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert  }
3691d580d0f6ee4f21eb309ba7b509d2c6d671c4044Bjorn Bringert}
370