1 package cz.cuni.amis.pogamut.base.component.lifecyclebus;
2
3 import java.util.Collection;
4 import java.util.Collections;
5 import java.util.HashMap;
6 import java.util.HashSet;
7 import java.util.Map;
8 import java.util.Queue;
9 import java.util.Set;
10 import java.util.concurrent.ConcurrentHashMap;
11 import java.util.concurrent.ConcurrentLinkedQueue;
12 import java.util.logging.Level;
13 import java.util.logging.Logger;
14
15 import com.google.inject.Inject;
16
17 import cz.cuni.amis.pogamut.base.agent.IAgentId;
18 import cz.cuni.amis.pogamut.base.component.IComponent;
19 import cz.cuni.amis.pogamut.base.component.IComponentAware;
20 import cz.cuni.amis.pogamut.base.component.bus.ComponentBus;
21 import cz.cuni.amis.pogamut.base.component.bus.IComponentBus;
22 import cz.cuni.amis.pogamut.base.component.bus.IComponentEvent;
23 import cz.cuni.amis.pogamut.base.component.bus.IComponentEventListener;
24 import cz.cuni.amis.pogamut.base.component.bus.event.IFatalErrorEvent;
25 import cz.cuni.amis.pogamut.base.component.bus.event.IPausedEvent;
26 import cz.cuni.amis.pogamut.base.component.bus.event.IPausingEvent;
27 import cz.cuni.amis.pogamut.base.component.bus.event.IResetEvent;
28 import cz.cuni.amis.pogamut.base.component.bus.event.IResumedEvent;
29 import cz.cuni.amis.pogamut.base.component.bus.event.IResumingEvent;
30 import cz.cuni.amis.pogamut.base.component.bus.event.IStartedEvent;
31 import cz.cuni.amis.pogamut.base.component.bus.event.IStartingEvent;
32 import cz.cuni.amis.pogamut.base.component.bus.event.IStartingPausedEvent;
33 import cz.cuni.amis.pogamut.base.component.bus.event.IStoppedEvent;
34 import cz.cuni.amis.pogamut.base.component.bus.event.IStoppingEvent;
35 import cz.cuni.amis.pogamut.base.component.bus.event.impl.ComponentBusErrorEvent;
36 import cz.cuni.amis.pogamut.base.component.bus.event.impl.FatalErrorEvent;
37 import cz.cuni.amis.pogamut.base.component.bus.event.impl.FatalErrorPropagatingEvent;
38 import cz.cuni.amis.pogamut.base.component.bus.event.impl.ResetEvent;
39 import cz.cuni.amis.pogamut.base.component.bus.exception.ComponentBusErrorException;
40 import cz.cuni.amis.pogamut.base.component.bus.exception.ComponentBusNotRunningException;
41 import cz.cuni.amis.pogamut.base.component.bus.exception.ComponentIdClashException;
42 import cz.cuni.amis.pogamut.base.component.bus.exception.FatalErrorPropagatingEventException;
43 import cz.cuni.amis.pogamut.base.component.bus.exception.MoreComponentsForClassException;
44 import cz.cuni.amis.pogamut.base.component.bus.exception.ResetFailedException;
45 import cz.cuni.amis.pogamut.base.component.controller.ComponentController;
46 import cz.cuni.amis.pogamut.base.component.controller.ComponentDependencies;
47 import cz.cuni.amis.pogamut.base.component.controller.ComponentState;
48 import cz.cuni.amis.pogamut.base.component.controller.IComponentControlHelper;
49 import cz.cuni.amis.pogamut.base.component.controller.IComponentController;
50 import cz.cuni.amis.pogamut.base.component.exception.ComponentLifecycleManagementAlreadyRegisteredException;
51 import cz.cuni.amis.pogamut.base.utils.guice.AgentScoped;
52 import cz.cuni.amis.pogamut.base.utils.logging.IAgentLogger;
53 import cz.cuni.amis.pogamut.base.utils.logging.LogCategory;
54 import cz.cuni.amis.utils.ClassUtils;
55 import cz.cuni.amis.utils.Const;
56 import cz.cuni.amis.utils.ExceptionToString;
57 import cz.cuni.amis.utils.NullCheck;
58 import cz.cuni.amis.utils.flag.Flag;
59 import cz.cuni.amis.utils.flag.ImmutableFlag;
60 import cz.cuni.amis.utils.flag.WaitForFlagChange.IAccept;
61 import cz.cuni.amis.utils.maps.LazyMap;
62 import cz.cuni.amis.utils.sets.ConcurrentHashSet;
63 import cz.cuni.amis.utils.sets.ConcurrentLinkedHashSet;
64 import cz.cuni.amis.utils.token.IToken;
65 import cz.cuni.amis.utils.token.Tokens;
66
67
68
69
70
71
72
73
74
75
76
77
78
79 @AgentScoped
80 public class LifecycleBus implements ILifecycleBus, IComponentAware {
81
82
83
84
85
86
87
88
89
90
91 public static final IToken COMPONENT_ID = Tokens.get("LifecycleBus");
92
93 private Map<IToken, IComponent> componentsByToken = new ConcurrentHashMap<IToken, IComponent>();
94
95 private Map<Class, Set<IComponent>> componentsByClass = new LazyMap<Class, Set<IComponent>>(new ConcurrentHashMap<Class, Set<IComponent>>()) {
96
97 @Override
98 protected Set<IComponent> create(Class key) {
99 return new ConcurrentHashSet<IComponent>();
100 }
101
102 };
103
104 private Map<Class, Set<IComponentEventListener>> eventListeners = new LazyMap<Class, Set<IComponentEventListener>>(new ConcurrentHashMap<Class, Set<IComponentEventListener>>()) {
105
106 @Override
107 protected Set<IComponentEventListener> create(Class key) {
108 return new ConcurrentLinkedHashSet<IComponentEventListener>();
109 }
110
111 };
112
113 private Map<Class, Map<Class, Set<IComponentEventListener>>> componentEventListeners = new LazyMap<Class, Map<Class, Set<IComponentEventListener>>>(new ConcurrentHashMap<Class, Map<Class, Set<IComponentEventListener>>>()) {
114
115 @Override
116 protected Map<Class, Set<IComponentEventListener>> create(Class key) {
117 return new LazyMap<Class, Set<IComponentEventListener>>(new ConcurrentHashMap<Class, Set<IComponentEventListener>>()) {
118
119 @Override
120 protected Set<IComponentEventListener> create(Class key) {
121 return new ConcurrentLinkedHashSet<IComponentEventListener>();
122 }
123
124 };
125 }
126
127 };
128
129 private Map<IToken, Map<Class, Set<IComponentEventListener>>> componentNameEventListeners = new LazyMap<IToken, Map<Class, Set<IComponentEventListener>>>() {
130
131 @Override
132 protected Map<Class, Set<IComponentEventListener>> create(IToken key) {
133 return new LazyMap<Class, Set<IComponentEventListener>>(new ConcurrentHashMap<Class, Set<IComponentEventListener>>()) {
134
135 @Override
136 protected Set<IComponentEventListener> create(Class key) {
137 return new ConcurrentLinkedHashSet<IComponentEventListener>();
138 }
139
140 };
141 }
142
143 };
144
145
146
147
148 private boolean running = true;
149
150
151
152
153
154
155 private Queue<IComponentEvent> queue = new ConcurrentLinkedQueue();
156
157
158
159
160
161
162 private boolean queueProcessing = false;
163
164
165
166
167 private Object queueProcessingMutex = new Object();
168
169 private LogCategory log;
170
171 private IAgentId agentId;
172
173 @Inject
174 public LifecycleBus(IAgentLogger logger) {
175 NullCheck.check(logger, "logger");
176 this.agentId = logger.getAgentId();
177 this.log = logger.getCategory(this);
178 NullCheck.check(this.log, "log category returned by the logger");
179 registerComponentStateListeners();
180 }
181
182 @Override
183 public String toString() {
184 return "LifecycleBus[" + agentId.getToken() + ", running=" + running + ", queue length=" + (this.queue == null ? "null" : this.queue.size()) + "]";
185 }
186
187 @Override
188 public IComponentBus getEventBus() {
189 return this;
190 }
191
192 @Override
193 public IToken getComponentId() {
194 return COMPONENT_ID;
195 }
196
197 public Logger getLog() {
198 return log;
199 }
200
201 @Override
202 public boolean isRunning() {
203 return running;
204 }
205
206 @Override
207 public synchronized void reset() throws ResetFailedException {
208 if (log.isLoggable(Level.WARNING)) log.warning("reset() called.");
209 try {
210 if (running) {
211 if (log.isLoggable(Level.WARNING)) log.warning(LifecycleBus.COMPONENT_ID.getToken() + " is still running, broadcasting fatal error to stop all components.");
212 event(new FatalErrorEvent<IComponent>(this, "Resetting."));
213 }
214 if (log.isLoggable(Level.WARNING)) log.warning("Broadcasting reset event.");
215 resetBus();
216 innerRaiseEvent(new ResetEvent(this));
217 } catch (Exception e) {
218 if (e instanceof ComponentBusErrorException) {
219 innerRaiseEvent(new FatalErrorEvent(this, "Reset failed.", e.getCause()));
220 throw new ResetFailedException(e.getCause(), log, this);
221 } else {
222 innerRaiseEvent(new FatalErrorEvent(this, "Reset failed.", e));
223 throw new ResetFailedException(e, log, this);
224 }
225 }
226 if (log.isLoggable(Level.WARNING)) log.warning("Reseted, bus is running again.");
227 }
228
229 private void resetBus() {
230 running = true;
231 queue.clear();
232 queueProcessing = false;
233 }
234
235
236
237
238
239
240
241 @Override
242 public <T> T getComponent(Class<T> cls) throws MoreComponentsForClassException {
243 Set<T> components = (Set<T>) componentsByClass.get(cls);
244 if (components.size() > 0) throw new MoreComponentsForClassException(cls, components, this);
245 return components.iterator().next();
246 }
247
248 @Override
249 public <T> Set<T> getComponents(Class<T> cls) {
250 return (Set<T>) Collections.unmodifiableSet(componentsByClass.get(cls));
251 }
252
253 @Override
254 public void register(IComponent component) throws ComponentIdClashException {
255 synchronized(componentsByToken) {
256 NullCheck.check(component.getComponentId(), "component's id is null ("+ component + ")");
257 if (componentsByToken.get(component.getComponentId()) != null) {
258 if (componentsByToken.get(component.getComponentId()) == component) {
259 return;
260 } else {
261 ComponentIdClashException e = new ComponentIdClashException(component.getComponentId(), log, this);
262 try {
263 event(new FatalErrorEvent(this, e));
264 } catch (Exception e1) {
265 }
266 throw e;
267 }
268 }
269 registerComponent(component);
270 }
271 }
272
273 @Override
274 public void remove(IComponent component) {
275 synchronized(componentsByToken) {
276 componentsByToken.remove(component.getComponentId());
277 Collection<Class> componentClasses = ClassUtils.getSubclasses(component.getClass());
278 for (Class cls : componentClasses) {
279 componentsByClass.get(cls).remove(component);
280 }
281 if (log.isLoggable(Level.INFO)) log.info(component + " of the id " + component.getComponentId().getToken() + " removed from the bus.");
282 }
283 }
284
285
286
287
288
289
290
291
292
293
294
295 private void registerComponent(IComponent component) {
296 componentsByToken.put(component.getComponentId(), component);
297 Collection<Class> componentClasses = ClassUtils.getSubclasses(component.getClass());
298 for (Class cls : componentClasses) {
299 componentsByClass.get(cls).add(component);
300 }
301 setComponentState(component.getComponentId(), ComponentState.INSTANTIATED);
302 if (log.isLoggable(Level.INFO)) log.info(component + " registered under id " + component.getComponentId().getToken());
303 }
304
305 @Override
306 public IComponent getComponent(IToken name) {
307 return componentsByToken.get(name);
308 }
309
310
311
312
313
314
315
316 @Override
317 public void addEventListener(Class<?> event, IComponentEventListener<?> listener) {
318 NullCheck.check(event, "event");
319 NullCheck.check(listener, "listener");
320 eventListeners.get(event).add(listener);
321 }
322
323 @Override
324 public void addEventListener(Class<?> event, Class<?> component, IComponentEventListener<?> listener) {
325 NullCheck.check(event, "event");
326 NullCheck.check(component, "comopnent");
327 NullCheck.check(listener, "listener");
328 componentEventListeners.get(component).get(event).add(listener);
329 }
330
331 @Override
332 public void addEventListener(Class<?> event, IToken componentName, IComponentEventListener<?> listener) {
333 NullCheck.check(event, "event");
334 NullCheck.check(componentName, "componentName");
335 NullCheck.check(listener, "listener");
336 componentNameEventListeners.get(componentName).get(event).add(listener);
337 }
338
339 @Override
340 public void addEventListener(Class<?> event, IComponent component, IComponentEventListener<?> listener) {
341 NullCheck.check(component, "component");
342 addEventListener(event, component.getComponentId(), listener);
343 }
344
345 @Override
346 public boolean isListening(Class<?> event, IComponentEventListener<?> listener) {
347 NullCheck.check(event, "event");
348 NullCheck.check(listener, "listener");
349 if (!eventListeners.containsKey(event)) return false;
350 return eventListeners.get(event).contains(listener);
351 }
352
353 @Override
354 public boolean isListening(Class<?> event, Class<?> component, IComponentEventListener<?> listener) {
355 NullCheck.check(event, "event");
356 NullCheck.check(component, "component");
357 NullCheck.check(listener, "listener");
358 if (!componentEventListeners.containsKey(component)) return false;
359 Map<Class, Set<IComponentEventListener>> listeners = componentEventListeners.get(component);
360 if (!listeners.containsKey(event)) return false;
361 return listeners.get(event).contains(listener);
362 }
363
364 @Override
365 public boolean isListening(Class<?> event, IToken componentId, IComponentEventListener<?> listener) {
366 NullCheck.check(event, "event");
367 NullCheck.check(componentId, "componentId");
368 NullCheck.check(listener, "listener");
369 if (!componentNameEventListeners.containsKey(componentId)) return false;
370 Map<Class, Set<IComponentEventListener>> listeners = componentNameEventListeners.get(componentId);
371 if (!listeners.containsKey(event)) return false;
372 return listeners.get(event).contains(listener);
373 }
374
375 @Override
376 public boolean isListening(Class<?> event, IComponent component, IComponentEventListener<?> listener) {
377 NullCheck.check(component, "component");
378 return isListening(event, component.getComponentId(), listener);
379 }
380
381 @Override
382 public void removeEventListener(Class<?> event, IComponentEventListener<?> listener) {
383 NullCheck.check(event, "event");
384 NullCheck.check(listener, "listener");
385 if (!eventListeners.containsKey(event)) return;
386 eventListeners.get(event).remove(listener);
387 }
388
389 @Override
390 public void removeEventListener(Class<?> event, Class<?> component, IComponentEventListener<?> listener) {
391 NullCheck.check(event, "event");
392 NullCheck.check(component, "component");
393 NullCheck.check(listener, "listener");
394 if (!componentEventListeners.containsKey(component)) return;
395 Map<Class, Set<IComponentEventListener>> listeners = componentEventListeners.get(component);
396 if (!listeners.containsKey(event)) return;
397 listeners.get(event).remove(listener);
398 }
399
400 @Override
401 public void removeEventListener(Class<?> event, IToken componentId, IComponentEventListener<?> listener) {
402 NullCheck.check(event, "event");
403 NullCheck.check(componentId, "componentId");
404 NullCheck.check(listener, "listener");
405 if (!componentNameEventListeners.containsKey(componentId)) return;
406 Map<Class, Set<IComponentEventListener>> listeners = componentNameEventListeners.get(componentId);
407 if (!listeners.containsKey(event)) return;
408 listeners.get(event).remove(listener);
409 }
410
411 @Override
412 public void removeEventListener(Class<?> event, IComponent component, IComponentEventListener<?> listener) {
413 NullCheck.check(component, "component");
414 removeEventListener(event, component.getComponentId(), listener);
415 }
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430 private void notifyListenersA(IComponentEvent event) {
431 Collection<Class> eventClasses = ClassUtils.getSubclasses(event.getClass());
432 for (Class eventClass : eventClasses) {
433 if (!eventListeners.containsKey(eventClass)) continue;
434 for (IComponentEventListener listener : eventListeners.get(eventClass)) {
435 if (!isRunning()) return;
436 listener.notify(event);
437 }
438 }
439 }
440
441
442
443
444
445
446
447
448 private void notifyListenersB(IComponentEvent event) {
449 Collection<Class> componentClasses = ClassUtils.getSubclasses(event.getSource().getClass());
450 Collection<Class> eventClasses = ClassUtils.getSubclasses(event.getClass());
451 for (Class componentClass : componentClasses) {
452 if (!componentEventListeners.containsKey(componentClass)) continue;
453 Map<Class, Set<IComponentEventListener>> listeners = componentEventListeners.get(componentClass);
454 for (Class eventClass : eventClasses) {
455 if (!listeners.containsKey(eventClass)) continue;
456 for (IComponentEventListener listener : listeners.get(eventClass)) {
457 if (!isRunning()) return;
458 listener.notify(event);
459 }
460 }
461 }
462 }
463
464
465
466
467
468
469
470
471 private void notifyListenersC(IComponentEvent event) {
472 if (!componentNameEventListeners.containsKey(event.getSource().getComponentId())) return;
473 Map<Class, Set<IComponentEventListener>> listeners = componentNameEventListeners.get(event.getSource().getComponentId());
474 Collection<Class> eventClasses = ClassUtils.getSubclasses(event.getClass());
475 for (Class eventClass : eventClasses) {
476 if (!listeners.containsKey(eventClass)) continue;
477 for (IComponentEventListener listener : listeners.get(eventClass)) {
478 if (!isRunning()) return;
479 listener.notify(event);
480 }
481 }
482 }
483
484
485
486
487
488
489
490
491
492
493 private void notifyListenersA_Safe(IComponentEvent event) {
494 Collection<Class> eventClasses = ClassUtils.getSubclasses(event.getClass());
495 for (Class eventClass : eventClasses) {
496 if (!eventListeners.containsKey(eventClass)) continue;
497 for (IComponentEventListener listener : eventListeners.get(eventClass)) {
498 try {
499 listener.notify(event);
500 } catch (Exception e) {
501 if (log.isLoggable(Level.WARNING)) log.warning(ExceptionToString.process("Exception happened during notification of event " + event + " on listener " + listener + ".", e));
502 }
503 }
504 }
505 }
506
507
508
509
510
511
512
513
514
515
516 private void notifyListenersB_Safe(IComponentEvent event) {
517 Collection<Class> componentClasses = ClassUtils.getSubclasses(event.getSource().getClass());
518 Collection<Class> eventClasses = ClassUtils.getSubclasses(event.getClass());
519 for (Class componentClass : componentClasses) {
520 if (!componentEventListeners.containsKey(componentClass)) continue;
521 Map<Class, Set<IComponentEventListener>> listeners = componentEventListeners.get(componentClass);
522 for (Class eventClass : eventClasses) {
523 if (!listeners.containsKey(eventClass)) continue;
524 for (IComponentEventListener listener : listeners.get(eventClass)) {
525 try {
526 listener.notify(event);
527 } catch (Exception e) {
528 if (log.isLoggable(Level.WARNING)) log.warning(ExceptionToString.process("Exception happened during notification of event " + event + " on listener " + listener + ".", e));
529 }
530 }
531 }
532 }
533 }
534
535
536
537
538
539
540
541
542
543
544 private void notifyListenersC_Safe(IComponentEvent event) {
545 if (!componentNameEventListeners.containsKey(event.getSource().getComponentId())) return;
546 Map<Class, Set<IComponentEventListener>> listeners = componentNameEventListeners.get(event.getSource().getComponentId());
547 Collection<Class> eventClasses = ClassUtils.getSubclasses(event.getClass());
548 for (Class eventClass : eventClasses) {
549 if (!listeners.containsKey(eventClass)) continue;
550 for (IComponentEventListener listener : listeners.get(eventClass)) {
551 try {
552 listener.notify(event);
553 } catch (Exception e) {
554 if (log.isLoggable(Level.WARNING)) log.warning(ExceptionToString.process("Exception happened during notification of event " + event + " on listener " + listener + ".", e));
555 }
556 }
557 }
558 }
559
560
561
562
563
564
565
566
567 private void innerRaiseEvent(IComponentEvent event) {
568 if (event instanceof IFatalErrorEvent) {
569 if (log.isLoggable(Level.SEVERE)) log.severe("Fatal error happenned - component bus is stopping." + Const.NEW_LINE + ((IFatalErrorEvent)event).getSummary());
570 queue.clear();
571 running = false;
572 notifyListenersA_Safe(event);
573 notifyListenersB_Safe(event);
574 notifyListenersC_Safe(event);
575 return;
576 } else {
577 if (log.isLoggable(Level.FINE)) log.fine("Notifying " + event);
578 }
579 if (!isRunning()) return;
580 notifyListenersA(event);
581 if (!isRunning()) return;
582 notifyListenersB(event);
583 if (!isRunning()) return;
584 notifyListenersC(event);
585 }
586
587
588
589
590
591
592
593
594
595
596
597 private void innerRaiseEvent_Safe(IComponentEvent event) {
598 if (event instanceof IFatalErrorEvent) {
599 if (log.isLoggable(Level.SEVERE)) log.severe("Fatal error happenned - component bus is stopping." + Const.NEW_LINE + ((IFatalErrorEvent)event).getSummary());
600 queue.clear();
601 running = false;
602 } else {
603 if (log.isLoggable(Level.FINE)) log.fine("Notifying (safe) " + event);
604 }
605 notifyListenersA_Safe(event);
606 notifyListenersB_Safe(event);
607 notifyListenersC_Safe(event);
608 }
609
610 @Override
611 public synchronized boolean event(IComponentEvent event) throws ComponentBusNotRunningException, ComponentBusErrorException, FatalErrorPropagatingEventException {
612
613
614 NullCheck.check(event, "event");
615 if (event instanceof IResetEvent) throw new IllegalArgumentException("you can't broadcast reset event this way, use reset() instead");
616
617 if (!isRunning()) {
618 if (event instanceof IFatalErrorEvent) {
619 try {
620 if (log.isLoggable(Level.WARNING)) log.warning("Component bus is not running, ignoring fatal error event from " + event.getSource() + ".");
621 } catch (Exception e) {
622 }
623 return false;
624 }
625 throw new ComponentBusNotRunningException(event, log, this);
626 }
627
628
629 if (event instanceof IFatalErrorEvent) {
630 if (!isRunning()) {
631 try {
632 if (log.isLoggable(Level.WARNING)) log.warning("Component bus is not running, ignoring fatal error event from " + event.getSource() + ".");
633 } catch (Exception e) {
634 }
635 return false;
636 }
637
638 innerRaiseEvent(event);
639 return false;
640 }
641
642
643 if (queueProcessing) {
644
645
646
647 queue.add(event);
648 return false;
649 }
650
651
652 if (queue.size() > 0) {
653 ComponentBusErrorException e = new ComponentBusErrorException("Previous events has not been fully processed! ComponenBus fatal error.", event, this);
654 innerRaiseEvent_Safe(
655 new ComponentBusErrorEvent(this, e)
656 );
657 throw e;
658 }
659
660
661 queue.add(event);
662
663 processQueue();
664
665
666 return true;
667 }
668
669 @Override
670 public synchronized void eventTransactional(IComponentEvent event) throws ComponentBusNotRunningException, ComponentBusErrorException, FatalErrorPropagatingEventException {
671
672
673 NullCheck.check(event, "event");
674 if (event instanceof IResetEvent) throw new IllegalArgumentException("you can't broadcast reset event this way, use reset() instead");
675
676 if (!isRunning()) {
677 if (event instanceof IFatalErrorEvent) {
678 try {
679 if (log.isLoggable(Level.WARNING)) log.warning("Component bus is not running, ignoring fatal error event from " + event.getSource() + ".");
680 } catch (Exception e) {
681 }
682 return;
683 }
684 throw new ComponentBusNotRunningException(event, log, this);
685 }
686
687 if (!queueProcessing) {
688
689 event(event);
690 return;
691 }
692
693
694 innerRaiseEvent(event);
695 }
696
697
698
699
700 private void processQueue() throws FatalErrorPropagatingEventException, ComponentBusErrorException {
701
702 boolean dropQueueProcessing = !queueProcessing;
703 queueProcessing = true;
704 IComponentEvent event = null;
705 while(queue.size() != 0) {
706
707 try {
708 event = queue.poll();
709 } catch (Exception e) {
710 ComponentBusErrorException e1 = new ComponentBusErrorException("Can't poll next event.", e, this);
711 innerRaiseEvent_Safe(
712 new ComponentBusErrorEvent(this, e)
713 );
714 throw e1;
715 }
716 try {
717 innerRaiseEvent(event);
718 } catch (FatalErrorPropagatingEventException e1) {
719 throw e1;
720 } catch (ComponentBusErrorException e2) {
721 throw e2;
722 } catch (Exception e3) {
723 innerRaiseEvent_Safe(
724 new FatalErrorPropagatingEvent<LifecycleBus>(this, "Exception happened during the event propagation.", e3, event)
725 );
726 queueProcessing = false;
727 throw new FatalErrorPropagatingEventException(event, e3, this);
728 }
729 }
730 if (!isRunning()) {
731
732 if (log.isLoggable(Level.SEVERE)) log.severe("Stopped.");
733 if (event != null && (!(event instanceof IFatalErrorEvent))) {
734
735 throw new FatalErrorPropagatingEventException(event, this);
736 }
737 }
738
739 if (dropQueueProcessing) {
740
741 queueProcessing = false;
742 }
743 }
744
745
746
747
748
749
750
751
752
753
754
755
756 private Object ctrlMutex = new Object();
757
758
759
760
761 private ComponentDependencies dependencies;
762
763
764
765
766 private Map<IToken, ComponentState> dependencyState = new HashMap<IToken, ComponentState>();
767
768
769
770
771 private Map<ComponentState, Integer> stateCount = new HashMap<ComponentState, Integer>();
772
773
774
775
776
777
778 private Flag<ComponentState> componentState = new Flag<ComponentState>(ComponentState.INSTANTIATED);
779
780
781
782
783 private IFatalErrorEvent lastFatalError = null;
784
785
786
787
788
789 private static class AwaitState implements IAccept<ComponentState> {
790
791 Set<ComponentState> awaiting = new HashSet<ComponentState>();
792
793 public AwaitState(ComponentState... states) {
794 for (ComponentState state : states) {
795 awaiting.add(state);
796 }
797 }
798
799 @Override
800 public boolean accept(ComponentState flagValue) {
801 return awaiting.contains(flagValue);
802 }
803
804 };
805
806
807
808
809
810 private IComponentEventListener<IStartingEvent> startingListener = new IComponentEventListener<IStartingEvent>() {
811
812 @Override
813 public void notify(IStartingEvent event) {
814 setComponentState(event.getSource().getComponentId(), ComponentState.STARTING);
815 }
816
817 };
818
819 private IComponentEventListener<IStartingPausedEvent> startingPausedListener = new IComponentEventListener<IStartingPausedEvent>() {
820
821 @Override
822 public void notify(IStartingPausedEvent event) {
823 setComponentState(event.getSource().getComponentId(), ComponentState.STARTING_PAUSED);
824 }
825
826 };
827
828 private IComponentEventListener<IStartedEvent> startedListener = new IComponentEventListener<IStartedEvent>() {
829
830 @Override
831 public void notify(IStartedEvent event) {
832 setComponentState(event.getSource().getComponentId(), ComponentState.RUNNING);
833 }
834
835 };
836
837 private IComponentEventListener<IPausingEvent> pausingListener = new IComponentEventListener<IPausingEvent>() {
838
839 @Override
840 public void notify(IPausingEvent event) {
841 setComponentState(event.getSource().getComponentId(), ComponentState.PAUSING);
842 }
843
844 };
845
846 private IComponentEventListener<IPausedEvent> pausedListener = new IComponentEventListener<IPausedEvent>() {
847
848 @Override
849 public void notify(IPausedEvent event) {
850 setComponentState(event.getSource().getComponentId(), ComponentState.PAUSED);
851 }
852
853 };
854
855 private IComponentEventListener<IResumingEvent> resumingListener = new IComponentEventListener<IResumingEvent>() {
856
857 @Override
858 public void notify(IResumingEvent event) {
859 setComponentState(event.getSource().getComponentId(), ComponentState.RESUMING);
860 }
861
862 };
863
864 private IComponentEventListener<IResumedEvent> resumedListener = new IComponentEventListener<IResumedEvent>() {
865
866 @Override
867 public void notify(IResumedEvent event) {
868 setComponentState(event.getSource().getComponentId(), ComponentState.RUNNING);
869 }
870
871 };
872
873 private IComponentEventListener<IStoppingEvent> stoppingListener = new IComponentEventListener<IStoppingEvent>() {
874
875 @Override
876 public void notify(IStoppingEvent event) {
877 setComponentState(event.getSource().getComponentId(), ComponentState.STOPPING);
878 }
879
880 };
881
882 private IComponentEventListener<IStoppedEvent> stoppedListener = new IComponentEventListener<IStoppedEvent>() {
883
884 @Override
885 public void notify(IStoppedEvent event) {
886 setComponentState(event.getSource().getComponentId(), ComponentState.STOPPED);
887 }
888
889 };
890
891 private IComponentEventListener<IFatalErrorEvent> fatalErrorListener = new IComponentEventListener<IFatalErrorEvent>() {
892
893 @Override
894 public void notify(IFatalErrorEvent event) {
895 setComponentStates(ComponentState.KILLED);
896 }
897
898 };
899
900 private IComponentEventListener<IResetEvent> resetEventListener = new IComponentEventListener<IResetEvent>() {
901
902 @Override
903 public void notify(IResetEvent event) {
904 setComponentStates(ComponentState.RESETED);
905 }
906
907 };
908
909
910
911
912 private Map<IToken, ComponentController> controls = new HashMap<IToken, ComponentController>();
913
914
915
916
917 private Map<IToken, Flag<ComponentState>> componentStates = new LazyMap<IToken, Flag<ComponentState>>() {
918
919 @Override
920 protected Flag<ComponentState> create(IToken key) {
921 return new Flag<ComponentState>(ComponentState.INSTANTIATED);
922 }
923
924 };
925
926 private void registerComponentStateListeners() {
927 this.addEventListener(IStartingEvent.class, startingListener);
928 this.addEventListener(IStartingPausedEvent.class, startingPausedListener);
929 this.addEventListener(IStartedEvent.class, startedListener);
930 this.addEventListener(IStoppingEvent.class, stoppingListener);
931 this.addEventListener(IStoppedEvent.class, stoppedListener);
932 this.addEventListener(IPausingEvent.class, pausingListener);
933 this.addEventListener(IPausedEvent.class, pausedListener);
934 this.addEventListener(IResumingEvent.class, resumingListener);
935 this.addEventListener(IResumedEvent.class, resumedListener);
936 }
937
938
939
940
941
942
943 private void setComponentState(IToken componentId, ComponentState newState) {
944 componentStates.get(componentId).setFlag(newState);
945 }
946
947
948
949
950
951 private void setComponentStates(ComponentState newState) {
952 for(Flag<ComponentState> state : componentStates.values()) {
953 state.setFlag(newState);
954 }
955 }
956
957 @Override
958 public <T extends IComponent> IComponentController<T> addLifecycleManagement(T component, IComponentControlHelper lifecyleMethods, ComponentDependencies componentDependencies) throws ComponentLifecycleManagementAlreadyRegisteredException {
959 synchronized(controls) {
960 if (controls.containsKey(component.getComponentId())) throw new ComponentLifecycleManagementAlreadyRegisteredException("Lifecycle already registered at " + this + " for component " + component.getComponentId() + ".", this);
961 ComponentController controller = new ComponentController(component, lifecyleMethods, this, getLog(), componentDependencies);
962 controls.put(component.getComponentId(), controller);
963 return controller;
964 }
965 }
966
967 @Override
968 public ImmutableFlag<ComponentState> getComponentState(IToken componentId) {
969 return componentStates.get(componentId).getImmutable();
970 }
971
972 @Override
973 public ImmutableFlag<ComponentState> getComponentState(Class<? extends IComponent> cls) throws MoreComponentsForClassException {
974 IComponent component = getComponent(cls);
975 if (component == null) return null;
976 return getComponentState(component.getComponentId());
977 }
978
979 @Override
980 public void removeLifecycleManagement(IComponent component) {
981 synchronized(controls) {
982 controls.remove(component.getComponentId());
983 }
984 }
985
986 }
987