1 package com.atlassian.plugin.event.impl;
2
3 import com.atlassian.plugin.event.PluginEventManager;
4
5 import java.lang.reflect.Method;
6 import java.lang.reflect.InvocationTargetException;
7 import java.util.*;
8
9 import org.apache.commons.collections.map.LazyMap;
10 import org.apache.commons.collections.Factory;
11 import org.apache.commons.logging.Log;
12 import org.apache.commons.logging.LogFactory;
13
14
15
16
17
18 public class PluginEventManagerImpl implements PluginEventManager
19 {
20 private final Map
21 private static final Log log = LogFactory.getLog(PluginEventManagerImpl.class);
22 private final ListenerMethodSelector[] listenerMethodSelectors;
23
24
25
26
27 public PluginEventManagerImpl()
28 {
29 this(new ListenerMethodSelector[]{new MethodNameListenerMethodSelector()});
30 }
31
32
33
34
35 public PluginEventManagerImpl(ListenerMethodSelector[] selectors)
36 {
37 this.listenerMethodSelectors = selectors;
38 eventsToListener = LazyMap.decorate(new HashMap(), new Factory() {
39 public Object create() { return new HashSet(); }
40 });
41 }
42
43
44
45
46
47
48 public synchronized void broadcast(Object event)
49 {
50 final Set
51 Set
52 findAllTypes(event.getClass(), types);
53 for (Iterator clsitr = types.iterator(); clsitr.hasNext(); )
54 {
55 Class type = (Class) clsitr.next();
56 Set registrations = (Set) eventsToListener.get(type);
57 for (Iterator i = registrations.iterator(); i.hasNext(); )
58 {
59 ListenerRegistration reg = (ListenerRegistration) i.next();
60 try
61 {
62 if (calledMethods.contains(reg.method))
63 continue;
64 calledMethods.add(reg.method);
65 reg.method.invoke(reg.listener, new Object[]{event});
66 } catch (IllegalAccessException e)
67 {
68 log.error("Unable to access listener method: "+reg.method, e);
69 } catch (InvocationTargetException e)
70 {
71 log.error("Exception calling listener method", e.getCause());
72 }
73 }
74 }
75 }
76
77
78
79
80
81
82
83
84 public synchronized void register(Object listener) throws IllegalArgumentException
85 {
86 if (listener == null)
87 throw new IllegalArgumentException("Listener cannot be null");
88
89 forEveryListenerMethod(listener, new ListenerMethodHandler()
90 {
91 public void handle(Object listener, Method m)
92 {
93 if (m.getParameterTypes().length != 1)
94 throw new IllegalArgumentException("Listener methods must only have one argument");
95 Set
96 listeners.add(new ListenerRegistration(listener, m));
97 }
98 });
99 }
100
101
102
103
104
105 public synchronized void unregister(Object listener)
106 {
107 forEveryListenerMethod(listener, new ListenerMethodHandler()
108 {
109 public void handle(Object listener, Method m)
110 {
111 Set
112 listeners.remove(new ListenerRegistration(listener, m));
113 }
114 });
115 }
116
117
118
119
120 private static interface ListenerMethodHandler
121 {
122 void handle(Object listener, Method m);
123 }
124
125
126
127
128
129
130 void forEveryListenerMethod(Object listener, ListenerMethodHandler handler)
131 {
132 Method[] methods = listener.getClass().getMethods();
133 for (int x=0; x<methods.length; x++)
134 {
135 Method m = methods[x];
136 for (int s = 0; s<listenerMethodSelectors.length; s++)
137 {
138 ListenerMethodSelector selector = listenerMethodSelectors[s];
139 if (selector.isListenerMethod(m))
140 {
141 handler.handle(listener, m);
142 }
143 }
144 }
145 }
146
147
148
149
150
151
152 void findAllTypes(Class cls, Set
153 {
154 if (cls == null)
155 return;
156
157 types.add(cls);
158
159 findAllTypes(cls.getSuperclass(), types);
160 for (int x = 0; x<cls.getInterfaces().length; x++)
161 findAllTypes(cls.getInterfaces()[x], types);
162 }
163
164
165
166
167 private static class ListenerRegistration
168 {
169 public final Object listener;
170 public final Method method;
171
172 public ListenerRegistration(Object listener, Method method)
173 {
174 this.listener = listener;
175 this.method = method;
176 }
177
178 public boolean equals(Object o)
179 {
180 if (this == o) return true;
181 if (o == null || getClass() != o.getClass()) return false;
182
183 ListenerRegistration that = (ListenerRegistration) o;
184
185 if (!listener.equals(that.listener)) return false;
186 if (!method.equals(that.method)) return false;
187
188 return true;
189 }
190
191 public int hashCode()
192 {
193 int result;
194 result = listener.hashCode();
195 result = 31 * result + method.hashCode();
196 return result;
197 }
198 }
199 }