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