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