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