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