1 |
|
|
2 |
|
|
3 |
|
|
4 |
|
|
5 |
|
|
6 |
|
|
7 |
|
|
8 |
|
|
9 |
|
|
10 |
|
|
11 |
|
|
12 |
|
|
13 |
|
|
14 |
|
|
15 |
|
|
16 |
|
|
17 |
|
|
18 |
|
|
19 |
|
|
20 |
|
package org.xwiki.observation.internal; |
21 |
|
|
22 |
|
import java.util.ArrayList; |
23 |
|
import java.util.Collection; |
24 |
|
import java.util.List; |
25 |
|
import java.util.Map; |
26 |
|
import java.util.concurrent.ConcurrentHashMap; |
27 |
|
|
28 |
|
import javax.inject.Inject; |
29 |
|
import javax.inject.Singleton; |
30 |
|
|
31 |
|
import org.slf4j.Logger; |
32 |
|
import org.xwiki.component.annotation.Component; |
33 |
|
import org.xwiki.component.descriptor.ComponentDescriptor; |
34 |
|
import org.xwiki.component.event.ComponentDescriptorAddedEvent; |
35 |
|
import org.xwiki.component.event.ComponentDescriptorEvent; |
36 |
|
import org.xwiki.component.event.ComponentDescriptorRemovedEvent; |
37 |
|
import org.xwiki.component.manager.ComponentLookupException; |
38 |
|
import org.xwiki.component.manager.ComponentManager; |
39 |
|
import org.xwiki.component.phase.Initializable; |
40 |
|
import org.xwiki.component.phase.InitializationException; |
41 |
|
import org.xwiki.observation.EventListener; |
42 |
|
import org.xwiki.observation.ObservationManager; |
43 |
|
import org.xwiki.observation.event.AllEvent; |
44 |
|
import org.xwiki.observation.event.Event; |
45 |
|
|
46 |
|
|
47 |
|
@link |
48 |
|
|
49 |
|
|
50 |
|
@link |
51 |
|
|
52 |
|
|
53 |
|
@version |
54 |
|
|
55 |
|
@Component |
56 |
|
@Singleton |
|
|
| 91.7% |
Uncovered Elements: 9 (109) |
Complexity: 31 |
Complexity Density: 0.48 |
|
57 |
|
public class DefaultObservationManager implements ObservationManager, Initializable |
58 |
|
{ |
59 |
|
|
60 |
|
|
61 |
|
@link |
62 |
|
|
63 |
|
|
64 |
|
|
65 |
|
private Map<Class< ? extends Event>, Map<String, RegisteredListener>> listenersByEvent = |
66 |
|
new ConcurrentHashMap<Class< ? extends Event>, Map<String, RegisteredListener>>(); |
67 |
|
|
68 |
|
|
69 |
|
|
70 |
|
|
71 |
|
|
72 |
|
private Map<String, EventListener> listenersByName = new ConcurrentHashMap<String, EventListener>(); |
73 |
|
|
74 |
|
|
75 |
|
@link |
76 |
|
|
77 |
|
@Inject |
78 |
|
private ComponentManager componentManager; |
79 |
|
|
80 |
|
|
81 |
|
|
82 |
|
|
83 |
|
@Inject |
84 |
|
private Logger logger; |
85 |
|
|
86 |
|
|
87 |
|
|
88 |
|
|
89 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (7) |
Complexity: 3 |
Complexity Density: 0.75 |
|
90 |
|
private static class RegisteredListener |
91 |
|
{ |
92 |
|
|
93 |
|
|
94 |
|
|
95 |
|
private List<Event> events = new ArrayList<Event>(); |
96 |
|
|
97 |
|
|
98 |
|
|
99 |
|
|
100 |
|
private EventListener listener; |
101 |
|
|
102 |
|
|
103 |
|
@param |
104 |
|
@param |
105 |
|
@link |
106 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (2) |
Complexity: 1 |
Complexity Density: 0.5 |
|
107 |
733
|
RegisteredListener(EventListener listener, Event event)... |
108 |
|
{ |
109 |
733
|
addEvent(event); |
110 |
|
|
111 |
733
|
this.listener = listener; |
112 |
|
} |
113 |
|
|
114 |
|
|
115 |
|
@param |
116 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
117 |
737
|
void addEvent(Event event)... |
118 |
|
{ |
119 |
737
|
this.events.add(event); |
120 |
|
} |
121 |
|
|
122 |
|
|
123 |
|
@param |
124 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
125 |
1
|
void removeEvent(Event event)... |
126 |
|
{ |
127 |
1
|
this.events.remove(event); |
128 |
|
} |
129 |
|
} |
130 |
|
|
|
|
| 75% |
Uncovered Elements: 1 (4) |
Complexity: 2 |
Complexity Density: 0.5 |
|
131 |
34
|
@Override... |
132 |
|
public void initialize() throws InitializationException |
133 |
|
{ |
134 |
34
|
try { |
135 |
34
|
for (EventListener listener : this.componentManager.lookupList(EventListener.class)) { |
136 |
106
|
addListener(listener); |
137 |
|
} |
138 |
|
} catch (ComponentLookupException e) { |
139 |
0
|
throw new InitializationException("Failed to lookup Event Listeners", e); |
140 |
|
} |
141 |
|
} |
142 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (19) |
Complexity: 4 |
Complexity Density: 0.31 |
|
143 |
490
|
@Override... |
144 |
|
public void addListener(EventListener eventListener) |
145 |
|
{ |
146 |
|
|
147 |
490
|
EventListener previousListener = this.listenersByName.put(eventListener.getName(), eventListener); |
148 |
|
|
149 |
|
|
150 |
490
|
if (previousListener != null) { |
151 |
11
|
this.logger.warn( |
152 |
|
"The [{}] listener has overwritten a previously " |
153 |
|
+ "registered listener [{}] since they both are registered under the same id [{}]. " |
154 |
|
+ "In the future consider removing a Listener first if you really want to register it again.", |
155 |
|
new Object[] {eventListener.getClass().getName(), previousListener.getClass().getName(), |
156 |
|
eventListener.getName()}); |
157 |
|
} |
158 |
|
|
159 |
|
|
160 |
490
|
for (Event event : eventListener.getEvents()) { |
161 |
|
|
162 |
735
|
Map<String, RegisteredListener> eventListeners = this.listenersByEvent.get(event.getClass()); |
163 |
735
|
if (eventListeners == null) { |
164 |
|
|
165 |
534
|
eventListeners = new ConcurrentHashMap<String, RegisteredListener>(); |
166 |
534
|
this.listenersByEvent.put(event.getClass(), eventListeners); |
167 |
|
|
168 |
534
|
eventListeners.put(eventListener.getName(), new RegisteredListener(eventListener, event)); |
169 |
|
} else { |
170 |
|
|
171 |
201
|
RegisteredListener registeredListener = eventListeners.get(eventListener.getName()); |
172 |
201
|
if (registeredListener == null) { |
173 |
199
|
eventListeners.put(eventListener.getName(), new RegisteredListener(eventListener, event)); |
174 |
|
} else { |
175 |
2
|
registeredListener.addEvent(event); |
176 |
|
} |
177 |
|
} |
178 |
|
} |
179 |
|
} |
180 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (7) |
Complexity: 2 |
Complexity Density: 0.4 |
|
181 |
353
|
@Override... |
182 |
|
public void removeListener(String listenerName) |
183 |
|
{ |
184 |
353
|
this.listenersByName.remove(listenerName); |
185 |
353
|
for (Map.Entry<Class< ? extends Event>, Map<String, RegisteredListener>> entry : this.listenersByEvent |
186 |
|
.entrySet()) { |
187 |
2762
|
entry.getValue().remove(listenerName); |
188 |
2762
|
if (entry.getValue().isEmpty()) { |
189 |
419
|
this.listenersByEvent.remove(entry.getKey()); |
190 |
|
} |
191 |
|
} |
192 |
|
} |
193 |
|
|
|
|
| 83.3% |
Uncovered Elements: 1 (6) |
Complexity: 2 |
Complexity Density: 0.5 |
|
194 |
2
|
@Override... |
195 |
|
public void addEvent(String listenerName, Event event) |
196 |
|
{ |
197 |
2
|
Map<String, RegisteredListener> listeners = this.listenersByEvent.get(event.getClass()); |
198 |
2
|
RegisteredListener listener = listeners.get(listenerName); |
199 |
2
|
if (listener != null) { |
200 |
2
|
listener.addEvent(event); |
201 |
|
} |
202 |
|
} |
203 |
|
|
|
|
| 83.3% |
Uncovered Elements: 1 (6) |
Complexity: 2 |
Complexity Density: 0.5 |
|
204 |
1
|
@Override... |
205 |
|
public void removeEvent(String listenerName, Event event) |
206 |
|
{ |
207 |
1
|
Map<String, RegisteredListener> listeners = this.listenersByEvent.get(event.getClass()); |
208 |
1
|
RegisteredListener listener = listeners.get(listenerName); |
209 |
1
|
if (listener != null) { |
210 |
1
|
listener.removeEvent(event); |
211 |
|
} |
212 |
|
} |
213 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
214 |
33
|
@Override... |
215 |
|
public EventListener getListener(String listenerName) |
216 |
|
{ |
217 |
33
|
return this.listenersByName.get(listenerName); |
218 |
|
} |
219 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (14) |
Complexity: 4 |
Complexity Density: 0.5 |
|
220 |
2262
|
@Override... |
221 |
|
public void notify(Event event, Object source, Object data) |
222 |
|
{ |
223 |
|
|
224 |
2262
|
Map<String, RegisteredListener> regListeners = this.listenersByEvent.get(event.getClass()); |
225 |
2262
|
if (regListeners != null) { |
226 |
1950
|
notify(regListeners.values(), event, source, data); |
227 |
|
} |
228 |
|
|
229 |
|
|
230 |
2262
|
Map<String, RegisteredListener> allEventRegListeners = this.listenersByEvent.get(AllEvent.class); |
231 |
2262
|
if (allEventRegListeners != null) { |
232 |
2255
|
notify(allEventRegListeners.values(), event, source, data); |
233 |
|
} |
234 |
|
|
235 |
|
|
236 |
|
|
237 |
|
|
238 |
|
|
239 |
2262
|
if (event instanceof ComponentDescriptorEvent) { |
240 |
123
|
onComponentEvent((ComponentDescriptorEvent) event, (ComponentManager) source, |
241 |
|
(ComponentDescriptor<EventListener>) data); |
242 |
|
} |
243 |
|
} |
244 |
|
|
245 |
|
|
246 |
|
|
247 |
|
|
248 |
|
|
249 |
|
@param |
250 |
|
@param |
251 |
|
@param |
252 |
|
@param |
253 |
|
|
|
|
| 88.9% |
Uncovered Elements: 1 (9) |
Complexity: 3 |
Complexity Density: 0.43 |
|
254 |
4205
|
private void notify(Collection<RegisteredListener> listeners, Event event, Object source, Object data)... |
255 |
|
{ |
256 |
4205
|
for (RegisteredListener listener : listeners) { |
257 |
|
|
258 |
4943
|
for (Event listenerEvent : listener.events) { |
259 |
4945
|
if (listenerEvent.matches(event)) { |
260 |
4942
|
try { |
261 |
4942
|
listener.listener.onEvent(event, source, data); |
262 |
|
} catch (Exception e) { |
263 |
|
|
264 |
0
|
this.logger.error("Failed to send event [{}] to listener [{}]", new Object[] {event, |
265 |
|
listener.listener, e}); |
266 |
|
} |
267 |
|
|
268 |
|
|
269 |
4942
|
break; |
270 |
|
} |
271 |
|
} |
272 |
|
} |
273 |
|
} |
274 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (1) |
Complexity: 1 |
Complexity Density: 1 |
|
275 |
1954
|
@Override... |
276 |
|
public void notify(Event event, Object source) |
277 |
|
{ |
278 |
1954
|
notify(event, source, null); |
279 |
|
} |
280 |
|
|
281 |
|
|
282 |
|
|
283 |
|
|
284 |
|
|
285 |
|
@param |
286 |
|
@param@link |
287 |
|
@param |
288 |
|
|
|
|
| 83.3% |
Uncovered Elements: 2 (12) |
Complexity: 4 |
Complexity Density: 0.67 |
|
289 |
123
|
private void onComponentEvent(ComponentDescriptorEvent componentEvent, ComponentManager componentManager,... |
290 |
|
ComponentDescriptor<EventListener> descriptor) |
291 |
|
{ |
292 |
123
|
if (componentEvent.getRole() == EventListener.class) { |
293 |
46
|
if (componentEvent instanceof ComponentDescriptorAddedEvent) { |
294 |
29
|
onEventListenerComponentAdded((ComponentDescriptorAddedEvent) componentEvent, componentManager, |
295 |
|
descriptor); |
296 |
17
|
} else if (componentEvent instanceof ComponentDescriptorRemovedEvent) { |
297 |
17
|
onEventListenerComponentRemoved((ComponentDescriptorRemovedEvent) componentEvent, componentManager, |
298 |
|
descriptor); |
299 |
|
} else { |
300 |
0
|
this.logger.warn("Ignoring unknown Component event [{}]", componentEvent.getClass().getName()); |
301 |
|
} |
302 |
|
} |
303 |
|
} |
304 |
|
|
305 |
|
|
306 |
|
|
307 |
|
|
308 |
|
@param |
309 |
|
@param@link |
310 |
|
@param |
311 |
|
|
|
|
| 62.5% |
Uncovered Elements: 3 (8) |
Complexity: 3 |
Complexity Density: 0.5 |
|
312 |
29
|
private void onEventListenerComponentAdded(ComponentDescriptorAddedEvent event, ComponentManager componentManager,... |
313 |
|
ComponentDescriptor<EventListener> descriptor) |
314 |
|
{ |
315 |
29
|
try { |
316 |
29
|
EventListener eventListener = componentManager.lookup(EventListener.class, event.getRoleHint()); |
317 |
|
|
318 |
29
|
if (getListener(eventListener.getName()) != eventListener) { |
319 |
29
|
addListener(eventListener); |
320 |
|
} else { |
321 |
0
|
this.logger.warn("An Event Listener named [{}] already exists, ignoring the [{}] component", |
322 |
|
eventListener.getName(), descriptor.getImplementation().getName()); |
323 |
|
} |
324 |
|
} catch (ComponentLookupException e) { |
325 |
0
|
this.logger.error("Failed to lookup the Event Listener [{}] corresponding to the Component registration " |
326 |
|
+ "event for [{}]. Ignoring the event", new Object[] {event.getRoleHint(), |
327 |
|
descriptor.getImplementation().getName(), e}); |
328 |
|
} |
329 |
|
} |
330 |
|
|
331 |
|
|
332 |
|
|
333 |
|
|
334 |
|
@param |
335 |
|
@param@link |
336 |
|
@param |
337 |
|
|
|
|
| 100% |
Uncovered Elements: 0 (10) |
Complexity: 3 |
Complexity Density: 0.5 |
|
338 |
17
|
private void onEventListenerComponentRemoved(ComponentDescriptorRemovedEvent event,... |
339 |
|
ComponentManager componentManager, ComponentDescriptor< ? > descriptor) |
340 |
|
{ |
341 |
17
|
EventListener removedEventListener = null; |
342 |
17
|
for (EventListener eventListener : this.listenersByName.values()) { |
343 |
101
|
if (eventListener.getClass() == descriptor.getImplementation()) { |
344 |
9
|
removedEventListener = eventListener; |
345 |
|
} |
346 |
|
} |
347 |
|
|
348 |
17
|
if (removedEventListener != null) { |
349 |
9
|
removeListener(removedEventListener.getName()); |
350 |
|
} |
351 |
|
} |
352 |
|
} |