1 package com.atlassian.plugin.event.impl;
2
3 import com.atlassian.event.spi.ListenerHandler;
4 import com.atlassian.event.spi.ListenerInvoker;
5
6 import static com.google.common.base.Preconditions.checkNotNull;
7 import com.google.common.base.Function;
8 import com.google.common.collect.Iterables;
9 import com.google.common.collect.Lists;
10 import com.google.common.collect.Sets;
11
12 import java.util.List;
13 import java.util.Set;
14 import java.lang.reflect.Method;
15 import java.lang.reflect.InvocationTargetException;
16
17
18
19
20
21
22
23 final class MethodSelectorListenerHandler implements ListenerHandler
24 {
25 private final ListenerMethodSelector listenerMethodSelector;
26
27 public MethodSelectorListenerHandler(ListenerMethodSelector listenerMethodSelector)
28 {
29 this.listenerMethodSelector = listenerMethodSelector;
30 }
31
32 public List<? extends ListenerInvoker> getInvokers(final Object listener)
33 {
34 final List<Method> validMethods = getValidMethods(checkNotNull(listener));
35
36 return Lists.newArrayList(Iterables.transform(validMethods, new Function<Method, ListenerInvoker>()
37 {
38 public ListenerInvoker apply(final Method method)
39 {
40 return new ListenerInvoker()
41 {
42 public Set<Class<?>> getSupportedEventTypes()
43 {
44 return Sets.newHashSet(method.getParameterTypes());
45 }
46
47 public void invoke(Object event)
48 {
49 try
50 {
51 method.invoke(listener, event);
52 }
53 catch (IllegalAccessException e)
54 {
55 throw new RuntimeException(e);
56 }
57 catch (InvocationTargetException e)
58 {
59 if (e.getCause() == null)
60 {
61 throw new RuntimeException(e);
62 }
63 else if (e.getCause().getMessage() == null)
64 {
65 throw new RuntimeException(e.getCause());
66 }
67 else
68 {
69 throw new RuntimeException(e.getCause().getMessage(), e);
70 }
71 }
72 }
73
74 public boolean supportAsynchronousEvents()
75 {
76 return true;
77 }
78 };
79 }
80 }));
81 }
82
83 private List<Method> getValidMethods(Object listener)
84 {
85 final List<Method> listenerMethods = Lists.newArrayList();
86 for (Method method : listener.getClass().getMethods())
87 {
88 if (isValidMethod(method))
89 {
90 listenerMethods.add(method);
91 }
92 }
93 return listenerMethods;
94 }
95
96 private boolean isValidMethod(Method method)
97 {
98 if (listenerMethodSelector.isListenerMethod(method))
99 {
100 if (hasOneAndOnlyOneParameter(method))
101 {
102 return true;
103 }
104 else
105 {
106 throw new RuntimeException("Method <" + method + "> of class <" + method.getDeclaringClass() + "> " +
107 "is being registered as a listener but has 0 or more than 1 parameters! " +
108 "Listener methods MUST have 1 and only 1 parameter.");
109 }
110 }
111 return false;
112 }
113
114 private boolean hasOneAndOnlyOneParameter(Method method)
115 {
116 return method.getParameterTypes().length == 1;
117 }
118 }