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