1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.util.component;
20
21 import java.io.IOException;
22 import java.util.ArrayList;
23 import java.util.Collection;
24 import java.util.Collections;
25 import java.util.List;
26 import java.util.concurrent.CopyOnWriteArrayList;
27
28 import org.eclipse.jetty.util.annotation.ManagedObject;
29 import org.eclipse.jetty.util.annotation.ManagedOperation;
30 import org.eclipse.jetty.util.log.Log;
31 import org.eclipse.jetty.util.log.Logger;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74 @ManagedObject("Implementation of Container and LifeCycle")
75 public class ContainerLifeCycle extends AbstractLifeCycle implements Container, Destroyable, Dumpable
76 {
77 private static final Logger LOG = Log.getLogger(ContainerLifeCycle.class);
78 private final List<Bean> _beans = new CopyOnWriteArrayList<>();
79 private final List<Container.Listener> _listeners = new CopyOnWriteArrayList<>();
80 private boolean _doStarted = false;
81
82
83 public ContainerLifeCycle()
84 {
85 }
86
87
88
89
90 @Override
91 protected void doStart() throws Exception
92 {
93
94 _doStarted = true;
95
96
97 for (Bean b : _beans)
98 {
99 if (b._bean instanceof LifeCycle)
100 {
101 LifeCycle l = (LifeCycle)b._bean;
102 switch(b._managed)
103 {
104 case MANAGED:
105 if (!l.isRunning())
106 start(l);
107 break;
108 case AUTO:
109 if (l.isRunning())
110 unmanage(b);
111 else
112 {
113 manage(b);
114 start(l);
115 }
116 break;
117 }
118 }
119 }
120
121 super.doStart();
122 }
123
124
125
126
127
128
129
130 protected void start(LifeCycle l) throws Exception
131 {
132 l.start();
133 }
134
135
136
137
138
139
140
141 protected void stop(LifeCycle l) throws Exception
142 {
143 l.stop();
144 }
145
146
147
148
149 @Override
150 protected void doStop() throws Exception
151 {
152 _doStarted = false;
153 super.doStop();
154 List<Bean> reverse = new ArrayList<>(_beans);
155 Collections.reverse(reverse);
156 for (Bean b : reverse)
157 {
158 if (b._managed==Managed.MANAGED && b._bean instanceof LifeCycle)
159 {
160 LifeCycle l = (LifeCycle)b._bean;
161 if (l.isRunning())
162 stop(l);
163 }
164 }
165 }
166
167
168
169
170 @Override
171 public void destroy()
172 {
173 List<Bean> reverse = new ArrayList<>(_beans);
174 Collections.reverse(reverse);
175 for (Bean b : reverse)
176 {
177 if (b._bean instanceof Destroyable && (b._managed==Managed.MANAGED || b._managed==Managed.POJO))
178 {
179 Destroyable d = (Destroyable)b._bean;
180 d.destroy();
181 }
182 }
183 _beans.clear();
184 }
185
186
187
188
189
190
191 public boolean contains(Object bean)
192 {
193 for (Bean b : _beans)
194 if (b._bean == bean)
195 return true;
196 return false;
197 }
198
199
200
201
202
203 public boolean isManaged(Object bean)
204 {
205 for (Bean b : _beans)
206 if (b._bean == bean)
207 return b.isManaged();
208 return false;
209 }
210
211
212
213
214
215
216
217
218
219
220
221
222 @Override
223 public boolean addBean(Object o)
224 {
225 if (o instanceof LifeCycle)
226 {
227 LifeCycle l = (LifeCycle)o;
228 return addBean(o,l.isRunning()?Managed.UNMANAGED:Managed.AUTO);
229 }
230
231 return addBean(o,Managed.POJO);
232 }
233
234
235
236
237
238
239
240
241 public boolean addBean(Object o, boolean managed)
242 {
243 if (o instanceof LifeCycle)
244 return addBean(o,managed?Managed.MANAGED:Managed.UNMANAGED);
245 return addBean(o,managed?Managed.POJO:Managed.UNMANAGED);
246 }
247
248 public boolean addBean(Object o, Managed managed)
249 {
250 if (contains(o))
251 return false;
252
253 Bean new_bean = new Bean(o);
254
255
256 if (o instanceof Container.Listener)
257 addEventListener((Container.Listener)o);
258
259
260 _beans.add(new_bean);
261
262
263 for (Container.Listener l:_listeners)
264 l.beanAdded(this,o);
265
266 try
267 {
268 switch (managed)
269 {
270 case UNMANAGED:
271 unmanage(new_bean);
272 break;
273
274 case MANAGED:
275 manage(new_bean);
276
277 if (isStarting() && _doStarted)
278 {
279 LifeCycle l = (LifeCycle)o;
280 if (!l.isRunning())
281 start(l);
282 }
283 break;
284
285 case AUTO:
286 if (o instanceof LifeCycle)
287 {
288 LifeCycle l = (LifeCycle)o;
289 if (isStarting())
290 {
291 if (l.isRunning())
292 unmanage(new_bean);
293 else if (_doStarted)
294 {
295 manage(new_bean);
296 start(l);
297 }
298 else
299 new_bean._managed=Managed.AUTO;
300 }
301 else if (isStarted())
302 unmanage(new_bean);
303 else
304 new_bean._managed=Managed.AUTO;
305 }
306 else
307 new_bean._managed=Managed.POJO;
308 break;
309
310 case POJO:
311 new_bean._managed=Managed.POJO;
312 }
313 }
314 catch (RuntimeException | Error e)
315 {
316 throw e;
317 }
318 catch (Exception e)
319 {
320 throw new RuntimeException(e);
321 }
322
323 if (LOG.isDebugEnabled())
324 LOG.debug("{} added {}",this,new_bean);
325
326 return true;
327 }
328
329
330
331
332
333
334
335
336
337
338 public void addManaged(LifeCycle lifecycle)
339 {
340 addBean(lifecycle,true);
341 try
342 {
343 if (isRunning() && !lifecycle.isRunning())
344 start(lifecycle);
345 }
346 catch (RuntimeException | Error e)
347 {
348 throw e;
349 }
350 catch (Exception e)
351 {
352 throw new RuntimeException(e);
353 }
354 }
355
356 @Override
357 public void addEventListener(Container.Listener listener)
358 {
359 if (_listeners.contains(listener))
360 return;
361
362 _listeners.add(listener);
363
364
365 for (Bean b:_beans)
366 {
367 listener.beanAdded(this,b._bean);
368
369
370 if (listener instanceof InheritedListener && b.isManaged() && b._bean instanceof Container)
371 {
372 if (b._bean instanceof ContainerLifeCycle)
373 ((ContainerLifeCycle)b._bean).addBean(listener, false);
374 else
375 ((Container)b._bean).addBean(listener);
376 }
377 }
378 }
379
380
381
382
383
384
385
386 public void manage(Object bean)
387 {
388 for (Bean b : _beans)
389 {
390 if (b._bean == bean)
391 {
392 manage(b);
393 return;
394 }
395 }
396 throw new IllegalArgumentException("Unknown bean " + bean);
397 }
398
399 private void manage(Bean bean)
400 {
401 if (bean._managed!=Managed.MANAGED)
402 {
403 bean._managed=Managed.MANAGED;
404
405 if (bean._bean instanceof Container)
406 {
407 for (Container.Listener l:_listeners)
408 {
409 if (l instanceof InheritedListener)
410 {
411 if (bean._bean instanceof ContainerLifeCycle)
412 ((ContainerLifeCycle)bean._bean).addBean(l,false);
413 else
414 ((Container)bean._bean).addBean(l);
415 }
416 }
417 }
418
419 if (bean._bean instanceof AbstractLifeCycle)
420 {
421 ((AbstractLifeCycle)bean._bean).setStopTimeout(getStopTimeout());
422 }
423 }
424 }
425
426
427
428
429
430
431
432 public void unmanage(Object bean)
433 {
434 for (Bean b : _beans)
435 {
436 if (b._bean == bean)
437 {
438 unmanage(b);
439 return;
440 }
441 }
442 throw new IllegalArgumentException("Unknown bean " + bean);
443 }
444
445 private void unmanage(Bean bean)
446 {
447 if (bean._managed!=Managed.UNMANAGED)
448 {
449 if (bean._managed==Managed.MANAGED && bean._bean instanceof Container)
450 {
451 for (Container.Listener l:_listeners)
452 {
453 if (l instanceof InheritedListener)
454 ((Container)bean._bean).removeBean(l);
455 }
456 }
457 bean._managed=Managed.UNMANAGED;
458 }
459 }
460
461 @Override
462 public Collection<Object> getBeans()
463 {
464 return getBeans(Object.class);
465 }
466
467 public void setBeans(Collection<Object> beans)
468 {
469 for (Object bean : beans)
470 addBean(bean);
471 }
472
473 @Override
474 public <T> Collection<T> getBeans(Class<T> clazz)
475 {
476 ArrayList<T> beans = new ArrayList<>();
477 for (Bean b : _beans)
478 {
479 if (clazz.isInstance(b._bean))
480 beans.add(clazz.cast(b._bean));
481 }
482 return beans;
483 }
484
485 @Override
486 public <T> T getBean(Class<T> clazz)
487 {
488 for (Bean b : _beans)
489 {
490 if (clazz.isInstance(b._bean))
491 return clazz.cast(b._bean);
492 }
493 return null;
494 }
495
496
497
498
499 public void removeBeans()
500 {
501 ArrayList<Bean> beans= new ArrayList<>(_beans);
502 for (Bean b : beans)
503 remove(b);
504 }
505
506 private Bean getBean(Object o)
507 {
508 for (Bean b : _beans)
509 {
510 if (b._bean == o)
511 return b;
512 }
513 return null;
514 }
515
516 @Override
517 public boolean removeBean(Object o)
518 {
519 Bean b=getBean(o);
520 return b!=null && remove(b);
521 }
522
523 private boolean remove(Bean bean)
524 {
525 if (_beans.remove(bean))
526 {
527 boolean wasManaged = bean.isManaged();
528
529 unmanage(bean);
530
531 for (Container.Listener l:_listeners)
532 l.beanRemoved(this,bean._bean);
533
534 if (bean._bean instanceof Container.Listener)
535 removeEventListener((Container.Listener)bean._bean);
536
537
538 if (wasManaged && bean._bean instanceof LifeCycle)
539 {
540 try
541 {
542 stop((LifeCycle)bean._bean);
543 }
544 catch(RuntimeException | Error e)
545 {
546 throw e;
547 }
548 catch (Exception e)
549 {
550 throw new RuntimeException(e);
551 }
552 }
553 return true;
554 }
555 return false;
556 }
557
558 @Override
559 public void removeEventListener(Container.Listener listener)
560 {
561 if (_listeners.remove(listener))
562 {
563
564 for (Bean b:_beans)
565 {
566 listener.beanRemoved(this,b._bean);
567
568 if (listener instanceof InheritedListener && b.isManaged() && b._bean instanceof Container)
569 ((Container)b._bean).removeBean(listener);
570 }
571 }
572 }
573
574 @Override
575 public void setStopTimeout(long stopTimeout)
576 {
577 super.setStopTimeout(stopTimeout);
578 for (Bean bean : _beans)
579 {
580 if (bean.isManaged() && bean._bean instanceof AbstractLifeCycle)
581 ((AbstractLifeCycle)bean._bean).setStopTimeout(stopTimeout);
582 }
583 }
584
585
586
587
588
589 @ManagedOperation("Dump the object to stderr")
590 public void dumpStdErr()
591 {
592 try
593 {
594 dump(System.err, "");
595 }
596 catch (IOException e)
597 {
598 LOG.warn(e);
599 }
600 }
601
602 @Override
603 @ManagedOperation("Dump the object to a string")
604 public String dump()
605 {
606 return dump(this);
607 }
608
609 public static String dump(Dumpable dumpable)
610 {
611 StringBuilder b = new StringBuilder();
612 try
613 {
614 dumpable.dump(b, "");
615 }
616 catch (IOException e)
617 {
618 LOG.warn(e);
619 }
620 return b.toString();
621 }
622
623 public void dump(Appendable out) throws IOException
624 {
625 dump(out, "");
626 }
627
628 protected void dumpThis(Appendable out) throws IOException
629 {
630 out.append(String.valueOf(this)).append(" - ").append(getState()).append("\n");
631 }
632
633 public static void dumpObject(Appendable out, Object o) throws IOException
634 {
635 try
636 {
637 if (o instanceof LifeCycle)
638 out.append(String.valueOf(o)).append(" - ").append((AbstractLifeCycle.getState((LifeCycle)o))).append("\n");
639 else
640 out.append(String.valueOf(o)).append("\n");
641 }
642 catch (Throwable th)
643 {
644 out.append(" => ").append(th.toString()).append('\n');
645 }
646 }
647
648 @Override
649 public void dump(Appendable out, String indent) throws IOException
650 {
651 dumpBeans(out,indent);
652 }
653
654 protected void dumpBeans(Appendable out, String indent, Collection<?>... collections) throws IOException
655 {
656 dumpThis(out);
657 int size = _beans.size();
658 for (Collection<?> c : collections)
659 size += c.size();
660 if (size == 0)
661 return;
662 int i = 0;
663 for (Bean b : _beans)
664 {
665 i++;
666
667 switch(b._managed)
668 {
669 case POJO:
670 out.append(indent).append(" +- ");
671 if (b._bean instanceof Dumpable)
672 ((Dumpable)b._bean).dump(out, indent + (i == size ? " " : " | "));
673 else
674 dumpObject(out, b._bean);
675 break;
676
677 case MANAGED:
678 out.append(indent).append(" += ");
679 if (b._bean instanceof Dumpable)
680 ((Dumpable)b._bean).dump(out, indent + (i == size ? " " : " | "));
681 else
682 dumpObject(out, b._bean);
683 break;
684
685 case UNMANAGED:
686 out.append(indent).append(" +~ ");
687 dumpObject(out, b._bean);
688 break;
689
690 case AUTO:
691 out.append(indent).append(" +? ");
692 if (b._bean instanceof Dumpable)
693 ((Dumpable)b._bean).dump(out, indent + (i == size ? " " : " | "));
694 else
695 dumpObject(out, b._bean);
696 break;
697
698 }
699 }
700
701 if (i<size)
702 out.append(indent).append(" |\n");
703
704 for (Collection<?> c : collections)
705 {
706 for (Object o : c)
707 {
708 i++;
709 out.append(indent).append(" +> ");
710
711 if (o instanceof Dumpable)
712 ((Dumpable)o).dump(out, indent + (i == size ? " " : " | "));
713 else
714 dumpObject(out, o);
715 }
716 }
717 }
718
719 public static void dump(Appendable out, String indent, Collection<?>... collections) throws IOException
720 {
721 if (collections.length == 0)
722 return;
723 int size = 0;
724 for (Collection<?> c : collections)
725 size += c.size();
726 if (size == 0)
727 return;
728
729 int i = 0;
730 for (Collection<?> c : collections)
731 {
732 for (Object o : c)
733 {
734 i++;
735 out.append(indent).append(" +- ");
736
737 if (o instanceof Dumpable)
738 ((Dumpable)o).dump(out, indent + (i == size ? " " : " | "));
739 else
740 dumpObject(out, o);
741 }
742 }
743 }
744
745
746 enum Managed { POJO, MANAGED, UNMANAGED, AUTO };
747
748 private static class Bean
749 {
750 private final Object _bean;
751 private volatile Managed _managed = Managed.POJO;
752
753 private Bean(Object b)
754 {
755 _bean = b;
756 }
757
758 public boolean isManaged()
759 {
760 return _managed==Managed.MANAGED;
761 }
762
763 @Override
764 public String toString()
765 {
766 return String.format("{%s,%s}", _bean, _managed);
767 }
768 }
769
770 public void updateBean(Object oldBean, final Object newBean)
771 {
772 if (newBean!=oldBean)
773 {
774 if (oldBean!=null)
775 removeBean(oldBean);
776 if (newBean!=null)
777 addBean(newBean);
778 }
779 }
780
781 public void updateBeans(Object[] oldBeans, final Object[] newBeans)
782 {
783
784 if (oldBeans!=null)
785 {
786 loop: for (Object o:oldBeans)
787 {
788 if (newBeans!=null)
789 {
790 for (Object n:newBeans)
791 if (o==n)
792 continue loop;
793 }
794 removeBean(o);
795 }
796 }
797
798
799 if (newBeans!=null)
800 {
801 loop: for (Object n:newBeans)
802 {
803 if (oldBeans!=null)
804 {
805 for (Object o:oldBeans)
806 if (o==n)
807 continue loop;
808 }
809 addBean(n);
810 }
811 }
812 }
813 }