1/*
2 * Copyright (C) 2007 The Guava Authors
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17package com.google.common.eventbus;
18
19import com.google.common.base.Preconditions;
20import java.lang.reflect.InvocationTargetException;
21import java.lang.reflect.Method;
22
23/**
24 * Wraps a single-argument 'handler' method on a specific object.
25 *
26 * <p>This class only verifies the suitability of the method and event type if
27 * something fails.  Callers are expected to verify their uses of this class.
28 *
29 * <p>Two EventHandlers are equivalent when they refer to the same method on the
30 * same object (not class).   This property is used to ensure that no handler
31 * method is registered more than once.
32 *
33 * @author Cliff Biffle
34 */
35class EventHandler {
36
37  /** Object sporting the handler method. */
38  private final Object target;
39  /** Handler method. */
40  private final Method method;
41
42  /**
43   * Creates a new EventHandler to wrap {@code method} on @{code target}.
44   *
45   * @param target  object to which the method applies.
46   * @param method  handler method.
47   */
48  EventHandler(Object target, Method method) {
49    Preconditions.checkNotNull(target,
50        "EventHandler target cannot be null.");
51    Preconditions.checkNotNull(method, "EventHandler method cannot be null.");
52
53    this.target = target;
54    this.method = method;
55    method.setAccessible(true);
56  }
57
58  /**
59   * Invokes the wrapped handler method to handle {@code event}.
60   *
61   * @param event  event to handle
62   * @throws InvocationTargetException  if the wrapped method throws any
63   *     {@link Throwable} that is not an {@link Error} ({@code Error}s are
64   *     propagated as-is).
65   */
66  public void handleEvent(Object event) throws InvocationTargetException {
67    try {
68      method.invoke(target, new Object[] { event });
69    } catch (IllegalArgumentException e) {
70      throw new Error("Method rejected target/argument: " + event, e);
71    } catch (IllegalAccessException e) {
72      throw new Error("Method became inaccessible: " + event, e);
73    } catch (InvocationTargetException e) {
74      if (e.getCause() instanceof Error) {
75        throw (Error) e.getCause();
76      }
77      throw e;
78    }
79  }
80
81  @Override public String toString() {
82    return "[wrapper " + method + "]";
83  }
84
85  @Override public int hashCode() {
86    final int PRIME = 31;
87    return (PRIME + method.hashCode()) * PRIME + target.hashCode();
88  }
89
90  @Override public boolean equals(Object obj) {
91    if(this == obj) {
92      return true;
93    }
94
95    if(obj == null) {
96      return false;
97    }
98
99    if(getClass() != obj.getClass()) {
100      return false;
101    }
102
103    final EventHandler other = (EventHandler) obj;
104
105    return method.equals(other.method) && target == other.target;
106  }
107
108}
109