1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18 package org.apache.commons.lang3.event;
19
20 import java.lang.reflect.InvocationHandler;
21 import java.lang.reflect.InvocationTargetException;
22 import java.lang.reflect.Method;
23 import java.lang.reflect.Proxy;
24 import java.util.Arrays;
25 import java.util.HashSet;
26 import java.util.Set;
27
28 import org.apache.commons.lang3.reflect.MethodUtils;
29
30
31
32
33
34
35 public class EventUtils {
36
37 private static final class EventBindingInvocationHandler implements InvocationHandler {
38 private final Object target;
39 private final String methodName;
40 private final Set<String> eventTypes;
41
42
43
44
45
46
47
48
49 EventBindingInvocationHandler(final Object target, final String methodName, final String[] eventTypes) {
50 this.target = target;
51 this.methodName = methodName;
52 this.eventTypes = new HashSet<>(Arrays.asList(eventTypes));
53 }
54
55
56
57
58
59
60
61 private boolean hasMatchingParametersMethod(final Method method) {
62 return MethodUtils.getAccessibleMethod(target.getClass(), methodName, method.getParameterTypes()) != null;
63 }
64
65
66
67
68
69
70
71
72
73
74 @Override
75 public Object invoke(final Object proxy, final Method method, final Object[] parameters) throws Throwable {
76 if (eventTypes.isEmpty() || eventTypes.contains(method.getName())) {
77 if (hasMatchingParametersMethod(method)) {
78 return MethodUtils.invokeMethod(target, methodName, parameters);
79 }
80 return MethodUtils.invokeMethod(target, methodName);
81 }
82 return null;
83 }
84 }
85
86
87
88
89
90
91
92
93
94
95
96 public static <L> void addEventListener(final Object eventSource, final Class<L> listenerType, final L listener) {
97 try {
98 MethodUtils.invokeMethod(eventSource, "add" + listenerType.getSimpleName(), listener);
99 } catch (final NoSuchMethodException e) {
100 throw new IllegalArgumentException("Class " + eventSource.getClass().getName()
101 + " does not have a public add" + listenerType.getSimpleName()
102 + " method which takes a parameter of type " + listenerType.getName() + ".");
103 } catch (final IllegalAccessException e) {
104 throw new IllegalArgumentException("Class " + eventSource.getClass().getName()
105 + " does not have an accessible add" + listenerType.getSimpleName ()
106 + " method which takes a parameter of type " + listenerType.getName() + ".");
107 } catch (final InvocationTargetException e) {
108 throw new IllegalArgumentException("Unable to add listener.", e.getCause());
109 }
110 }
111
112
113
114
115
116
117
118
119
120
121
122
123 public static <L> void bindEventsToMethod(final Object target, final String methodName, final Object eventSource,
124 final Class<L> listenerType, final String... eventTypes) {
125 final L listener = listenerType.cast(Proxy.newProxyInstance(target.getClass().getClassLoader(),
126 new Class[] { listenerType }, new EventBindingInvocationHandler(target, methodName, eventTypes)));
127 addEventListener(eventSource, listenerType, listener);
128 }
129 }