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 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
527 unmanage(bean);
528
529 for (Container.Listener l:_listeners)
530 l.beanRemoved(this,bean._bean);
531
532 if (bean._bean instanceof Container.Listener)
533 removeEventListener((Container.Listener)bean._bean);
534
535
536 if (bean._managed==Managed.MANAGED && bean._bean instanceof LifeCycle)
537 {
538 try
539 {
540 stop((LifeCycle)bean._bean);
541 }
542 catch(RuntimeException | Error e)
543 {
544 throw e;
545 }
546 catch (Exception e)
547 {
548 throw new RuntimeException(e);
549 }
550 }
551 return true;
552 }
553 return false;
554 }
555
556 @Override
557 public void removeEventListener(Container.Listener listener)
558 {
559 if (_listeners.remove(listener))
560 {
561
562 for (Bean b:_beans)
563 {
564 listener.beanRemoved(this,b._bean);
565
566 if (listener instanceof InheritedListener && b.isManaged() && b._bean instanceof Container)
567 ((Container)b._bean).removeBean(listener);
568 }
569 }
570 }
571
572 @Override
573 public void setStopTimeout(long stopTimeout)
574 {
575 super.setStopTimeout(stopTimeout);
576 for (Bean bean : _beans)
577 {
578 if (bean.isManaged() && bean._bean instanceof AbstractLifeCycle)
579 ((AbstractLifeCycle)bean._bean).setStopTimeout(stopTimeout);
580 }
581 }
582
583
584
585
586
587 @ManagedOperation("Dump the object to stderr")
588 public void dumpStdErr()
589 {
590 try
591 {
592 dump(System.err, "");
593 }
594 catch (IOException e)
595 {
596 LOG.warn(e);
597 }
598 }
599
600 @Override
601 @ManagedOperation("Dump the object to a string")
602 public String dump()
603 {
604 return dump(this);
605 }
606
607 public static String dump(Dumpable dumpable)
608 {
609 StringBuilder b = new StringBuilder();
610 try
611 {
612 dumpable.dump(b, "");
613 }
614 catch (IOException e)
615 {
616 LOG.warn(e);
617 }
618 return b.toString();
619 }
620
621 public void dump(Appendable out) throws IOException
622 {
623 dump(out, "");
624 }
625
626 protected void dumpThis(Appendable out) throws IOException
627 {
628 out.append(String.valueOf(this)).append(" - ").append(getState()).append("\n");
629 }
630
631 public static void dumpObject(Appendable out, Object o) throws IOException
632 {
633 try
634 {
635 if (o instanceof LifeCycle)
636 out.append(String.valueOf(o)).append(" - ").append((AbstractLifeCycle.getState((LifeCycle)o))).append("\n");
637 else
638 out.append(String.valueOf(o)).append("\n");
639 }
640 catch (Throwable th)
641 {
642 out.append(" => ").append(th.toString()).append('\n');
643 }
644 }
645
646 @Override
647 public void dump(Appendable out, String indent) throws IOException
648 {
649 dumpBeans(out,indent);
650 }
651
652 protected void dumpBeans(Appendable out, String indent, Collection<?>... collections) throws IOException
653 {
654 dumpThis(out);
655 int size = _beans.size();
656 for (Collection<?> c : collections)
657 size += c.size();
658 if (size == 0)
659 return;
660 int i = 0;
661 for (Bean b : _beans)
662 {
663 i++;
664
665 switch(b._managed)
666 {
667 case POJO:
668 out.append(indent).append(" +- ");
669 if (b._bean instanceof Dumpable)
670 ((Dumpable)b._bean).dump(out, indent + (i == size ? " " : " | "));
671 else
672 dumpObject(out, b._bean);
673 break;
674
675 case MANAGED:
676 out.append(indent).append(" += ");
677 if (b._bean instanceof Dumpable)
678 ((Dumpable)b._bean).dump(out, indent + (i == size ? " " : " | "));
679 else
680 dumpObject(out, b._bean);
681 break;
682
683 case UNMANAGED:
684 out.append(indent).append(" +~ ");
685 dumpObject(out, b._bean);
686 break;
687
688 case AUTO:
689 out.append(indent).append(" +? ");
690 if (b._bean instanceof Dumpable)
691 ((Dumpable)b._bean).dump(out, indent + (i == size ? " " : " | "));
692 else
693 dumpObject(out, b._bean);
694 break;
695
696 }
697 }
698
699 if (i<size)
700 out.append(indent).append(" |\n");
701
702 for (Collection<?> c : collections)
703 {
704 for (Object o : c)
705 {
706 i++;
707 out.append(indent).append(" +> ");
708
709 if (o instanceof Dumpable)
710 ((Dumpable)o).dump(out, indent + (i == size ? " " : " | "));
711 else
712 dumpObject(out, o);
713 }
714 }
715 }
716
717 public static void dump(Appendable out, String indent, Collection<?>... collections) throws IOException
718 {
719 if (collections.length == 0)
720 return;
721 int size = 0;
722 for (Collection<?> c : collections)
723 size += c.size();
724 if (size == 0)
725 return;
726
727 int i = 0;
728 for (Collection<?> c : collections)
729 {
730 for (Object o : c)
731 {
732 i++;
733 out.append(indent).append(" +- ");
734
735 if (o instanceof Dumpable)
736 ((Dumpable)o).dump(out, indent + (i == size ? " " : " | "));
737 else
738 dumpObject(out, o);
739 }
740 }
741 }
742
743
744 enum Managed { POJO, MANAGED, UNMANAGED, AUTO };
745
746 private static class Bean
747 {
748 private final Object _bean;
749 private volatile Managed _managed = Managed.POJO;
750
751 private Bean(Object b)
752 {
753 _bean = b;
754 }
755
756 public boolean isManaged()
757 {
758 return _managed==Managed.MANAGED;
759 }
760
761 @Override
762 public String toString()
763 {
764 return String.format("{%s,%s}", _bean, _managed);
765 }
766 }
767
768 public void updateBean(Object oldBean, final Object newBean)
769 {
770 if (newBean!=oldBean)
771 {
772 if (oldBean!=null)
773 removeBean(oldBean);
774 if (newBean!=null)
775 addBean(newBean);
776 }
777 }
778
779 public void updateBeans(Object[] oldBeans, final Object[] newBeans)
780 {
781
782 if (oldBeans!=null)
783 {
784 loop: for (Object o:oldBeans)
785 {
786 if (newBeans!=null)
787 {
788 for (Object n:newBeans)
789 if (o==n)
790 continue loop;
791 }
792 removeBean(o);
793 }
794 }
795
796
797 if (newBeans!=null)
798 {
799 loop: for (Object n:newBeans)
800 {
801 if (oldBeans!=null)
802 {
803 for (Object o:oldBeans)
804 if (o==n)
805 continue loop;
806 }
807 addBean(n);
808 }
809 }
810 }
811 }