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