Mercurial Hosting > luan
comparison src/org/eclipse/jetty/util/component/AggregateLifeCycle.java @ 802:3428c60d7cfc
replace jetty jars with source
author | Franklin Schmidt <fschmidt@gmail.com> |
---|---|
date | Wed, 07 Sep 2016 21:15:48 -0600 |
parents | |
children | 8e9db0bbf4f9 |
comparison
equal
deleted
inserted
replaced
801:6a21393191c1 | 802:3428c60d7cfc |
---|---|
1 // | |
2 // ======================================================================== | |
3 // Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd. | |
4 // ------------------------------------------------------------------------ | |
5 // All rights reserved. This program and the accompanying materials | |
6 // are made available under the terms of the Eclipse Public License v1.0 | |
7 // and Apache License v2.0 which accompanies this distribution. | |
8 // | |
9 // The Eclipse Public License is available at | |
10 // http://www.eclipse.org/legal/epl-v10.html | |
11 // | |
12 // The Apache License v2.0 is available at | |
13 // http://www.opensource.org/licenses/apache2.0.php | |
14 // | |
15 // You may elect to redistribute this code under either of these licenses. | |
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.Iterator; | |
26 import java.util.List; | |
27 import java.util.concurrent.CopyOnWriteArrayList; | |
28 | |
29 import org.eclipse.jetty.util.log.Log; | |
30 import org.eclipse.jetty.util.log.Logger; | |
31 | |
32 /** | |
33 * An AggregateLifeCycle is an {@link LifeCycle} implementation for a collection of contained beans. | |
34 * <p> | |
35 * Beans can be added the AggregateLifeCycle either as managed beans or as unmanaged beans. A managed bean is started, stopped and destroyed with the aggregate. | |
36 * An unmanaged bean is associated with the aggregate for the purposes of {@link #dump()}, but it's lifecycle must be managed externally. | |
37 * <p> | |
38 * When a bean is added, if it is a {@link LifeCycle} and it is already started, then it is assumed to be an unmanaged bean. | |
39 * Otherwise the methods {@link #addBean(Object, boolean)}, {@link #manage(Object)} and {@link #unmanage(Object)} can be used to | |
40 * explicitly control the life cycle relationship. | |
41 * <p> | |
42 * If adding a bean that is shared between multiple {@link AggregateLifeCycle} instances, then it should be started before being added, so it is unmanaged, or | |
43 * the API must be used to explicitly set it as unmanaged. | |
44 * <p> | |
45 */ | |
46 public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable, Dumpable | |
47 { | |
48 private static final Logger LOG = Log.getLogger(AggregateLifeCycle.class); | |
49 private final List<Bean> _beans=new CopyOnWriteArrayList<Bean>(); | |
50 private boolean _started=false; | |
51 | |
52 private class Bean | |
53 { | |
54 Bean(Object b) | |
55 { | |
56 _bean=b; | |
57 } | |
58 final Object _bean; | |
59 volatile boolean _managed=true; | |
60 | |
61 public String toString() | |
62 { | |
63 return "{"+_bean+","+_managed+"}"; | |
64 } | |
65 } | |
66 | |
67 /* ------------------------------------------------------------ */ | |
68 /** | |
69 * Start the managed lifecycle beans in the order they were added. | |
70 * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart() | |
71 */ | |
72 @Override | |
73 protected void doStart() throws Exception | |
74 { | |
75 for (Bean b:_beans) | |
76 { | |
77 if (b._managed && b._bean instanceof LifeCycle) | |
78 { | |
79 LifeCycle l=(LifeCycle)b._bean; | |
80 if (!l.isRunning()) | |
81 l.start(); | |
82 } | |
83 } | |
84 // indicate that we are started, so that addBean will start other beans added. | |
85 _started=true; | |
86 super.doStart(); | |
87 } | |
88 | |
89 /* ------------------------------------------------------------ */ | |
90 /** | |
91 * Stop the joined lifecycle beans in the reverse order they were added. | |
92 * @see org.eclipse.jetty.util.component.AbstractLifeCycle#doStart() | |
93 */ | |
94 @Override | |
95 protected void doStop() throws Exception | |
96 { | |
97 _started=false; | |
98 super.doStop(); | |
99 List<Bean> reverse = new ArrayList<Bean>(_beans); | |
100 Collections.reverse(reverse); | |
101 for (Bean b:reverse) | |
102 { | |
103 if (b._managed && b._bean instanceof LifeCycle) | |
104 { | |
105 LifeCycle l=(LifeCycle)b._bean; | |
106 if (l.isRunning()) | |
107 l.stop(); | |
108 } | |
109 } | |
110 } | |
111 | |
112 | |
113 /* ------------------------------------------------------------ */ | |
114 /** | |
115 * Destroy the joined Destroyable beans in the reverse order they were added. | |
116 * @see org.eclipse.jetty.util.component.Destroyable#destroy() | |
117 */ | |
118 public void destroy() | |
119 { | |
120 List<Bean> reverse = new ArrayList<Bean>(_beans); | |
121 Collections.reverse(reverse); | |
122 for (Bean b:reverse) | |
123 { | |
124 if (b._bean instanceof Destroyable && b._managed) | |
125 { | |
126 Destroyable d=(Destroyable)b._bean; | |
127 d.destroy(); | |
128 } | |
129 } | |
130 _beans.clear(); | |
131 } | |
132 | |
133 | |
134 /* ------------------------------------------------------------ */ | |
135 /** Is the bean contained in the aggregate. | |
136 * @param bean | |
137 * @return True if the aggregate contains the bean | |
138 */ | |
139 public boolean contains(Object bean) | |
140 { | |
141 for (Bean b:_beans) | |
142 if (b._bean==bean) | |
143 return true; | |
144 return false; | |
145 } | |
146 | |
147 /* ------------------------------------------------------------ */ | |
148 /** Is the bean joined to the aggregate. | |
149 * @param bean | |
150 * @return True if the aggregate contains the bean and it is joined | |
151 */ | |
152 public boolean isManaged(Object bean) | |
153 { | |
154 for (Bean b:_beans) | |
155 if (b._bean==bean) | |
156 return b._managed; | |
157 return false; | |
158 } | |
159 | |
160 /* ------------------------------------------------------------ */ | |
161 /** | |
162 * Add an associated bean. | |
163 * If the bean is a {@link LifeCycle}, then it will be managed if it is not | |
164 * already started and umanaged if it is already started. The {@link #addBean(Object, boolean)} | |
165 * method should be used if this is not correct, or the {@link #manage(Object)} and {@link #unmanage(Object)} | |
166 * methods may be used after an add to change the status. | |
167 * @param o the bean object to add | |
168 * @return true if the bean was added or false if it has already been added. | |
169 */ | |
170 public boolean addBean(Object o) | |
171 { | |
172 // beans are joined unless they are started lifecycles | |
173 return addBean(o,!((o instanceof LifeCycle)&&((LifeCycle)o).isStarted())); | |
174 } | |
175 | |
176 /* ------------------------------------------------------------ */ | |
177 /** Add an associated lifecycle. | |
178 * @param o The lifecycle to add | |
179 * @param managed True if the LifeCycle is to be joined, otherwise it will be disjoint. | |
180 * @return true if bean was added, false if already present. | |
181 */ | |
182 public boolean addBean(Object o, boolean managed) | |
183 { | |
184 if (contains(o)) | |
185 return false; | |
186 | |
187 Bean b = new Bean(o); | |
188 b._managed=managed; | |
189 _beans.add(b); | |
190 | |
191 if (o instanceof LifeCycle) | |
192 { | |
193 LifeCycle l=(LifeCycle)o; | |
194 | |
195 // Start the bean if we are started | |
196 if (managed && _started) | |
197 { | |
198 try | |
199 { | |
200 l.start(); | |
201 } | |
202 catch(Exception e) | |
203 { | |
204 throw new RuntimeException (e); | |
205 } | |
206 } | |
207 } | |
208 return true; | |
209 } | |
210 | |
211 /* ------------------------------------------------------------ */ | |
212 /** | |
213 * Manage a bean by this aggregate, so that it is started/stopped/destroyed with the | |
214 * aggregate lifecycle. | |
215 * @param bean The bean to manage (must already have been added). | |
216 */ | |
217 public void manage(Object bean) | |
218 { | |
219 for (Bean b :_beans) | |
220 { | |
221 if (b._bean==bean) | |
222 { | |
223 b._managed=true; | |
224 return; | |
225 } | |
226 } | |
227 throw new IllegalArgumentException(); | |
228 } | |
229 | |
230 /* ------------------------------------------------------------ */ | |
231 /** | |
232 * Unmanage a bean by this aggregate, so that it is not started/stopped/destroyed with the | |
233 * aggregate lifecycle. | |
234 * @param bean The bean to manage (must already have been added). | |
235 */ | |
236 public void unmanage(Object bean) | |
237 { | |
238 for (Bean b :_beans) | |
239 { | |
240 if (b._bean==bean) | |
241 { | |
242 b._managed=false; | |
243 return; | |
244 } | |
245 } | |
246 throw new IllegalArgumentException(); | |
247 } | |
248 | |
249 /* ------------------------------------------------------------ */ | |
250 /** Get dependent beans | |
251 * @return List of beans. | |
252 */ | |
253 public Collection<Object> getBeans() | |
254 { | |
255 return getBeans(Object.class); | |
256 } | |
257 | |
258 /* ------------------------------------------------------------ */ | |
259 /** Get dependent beans of a specific class | |
260 * @see #addBean(Object) | |
261 * @param clazz | |
262 * @return List of beans. | |
263 */ | |
264 public <T> List<T> getBeans(Class<T> clazz) | |
265 { | |
266 ArrayList<T> beans = new ArrayList<T>(); | |
267 for (Bean b:_beans) | |
268 { | |
269 if (clazz.isInstance(b._bean)) | |
270 beans.add((T)(b._bean)); | |
271 } | |
272 return beans; | |
273 } | |
274 | |
275 | |
276 /* ------------------------------------------------------------ */ | |
277 /** Get dependent beans of a specific class. | |
278 * If more than one bean of the type exist, the first is returned. | |
279 * @see #addBean(Object) | |
280 * @param clazz | |
281 * @return bean or null | |
282 */ | |
283 public <T> T getBean(Class<T> clazz) | |
284 { | |
285 for (Bean b:_beans) | |
286 { | |
287 if (clazz.isInstance(b._bean)) | |
288 return (T)b._bean; | |
289 } | |
290 | |
291 return null; | |
292 } | |
293 | |
294 /* ------------------------------------------------------------ */ | |
295 /** | |
296 * Remove all associated bean. | |
297 */ | |
298 public void removeBeans () | |
299 { | |
300 _beans.clear(); | |
301 } | |
302 | |
303 /* ------------------------------------------------------------ */ | |
304 /** | |
305 * Remove an associated bean. | |
306 */ | |
307 public boolean removeBean (Object o) | |
308 { | |
309 Iterator<Bean> i = _beans.iterator(); | |
310 while(i.hasNext()) | |
311 { | |
312 Bean b=i.next(); | |
313 if (b._bean==o) | |
314 { | |
315 _beans.remove(b); | |
316 return true; | |
317 } | |
318 } | |
319 return false; | |
320 } | |
321 | |
322 /* ------------------------------------------------------------ */ | |
323 public void dumpStdErr() | |
324 { | |
325 try | |
326 { | |
327 dump(System.err,""); | |
328 } | |
329 catch (IOException e) | |
330 { | |
331 LOG.warn(e); | |
332 } | |
333 } | |
334 | |
335 /* ------------------------------------------------------------ */ | |
336 public String dump() | |
337 { | |
338 return dump(this); | |
339 } | |
340 | |
341 /* ------------------------------------------------------------ */ | |
342 public static String dump(Dumpable dumpable) | |
343 { | |
344 StringBuilder b = new StringBuilder(); | |
345 try | |
346 { | |
347 dumpable.dump(b,""); | |
348 } | |
349 catch (IOException e) | |
350 { | |
351 LOG.warn(e); | |
352 } | |
353 return b.toString(); | |
354 } | |
355 | |
356 /* ------------------------------------------------------------ */ | |
357 public void dump(Appendable out) throws IOException | |
358 { | |
359 dump(out,""); | |
360 } | |
361 | |
362 /* ------------------------------------------------------------ */ | |
363 protected void dumpThis(Appendable out) throws IOException | |
364 { | |
365 out.append(String.valueOf(this)).append(" - ").append(getState()).append("\n"); | |
366 } | |
367 | |
368 /* ------------------------------------------------------------ */ | |
369 public static void dumpObject(Appendable out,Object o) throws IOException | |
370 { | |
371 try | |
372 { | |
373 if (o instanceof LifeCycle) | |
374 out.append(String.valueOf(o)).append(" - ").append((AbstractLifeCycle.getState((LifeCycle)o))).append("\n"); | |
375 else | |
376 out.append(String.valueOf(o)).append("\n"); | |
377 } | |
378 catch(Throwable th) | |
379 { | |
380 out.append(" => ").append(th.toString()).append('\n'); | |
381 } | |
382 } | |
383 | |
384 /* ------------------------------------------------------------ */ | |
385 public void dump(Appendable out,String indent) throws IOException | |
386 { | |
387 dumpThis(out); | |
388 int size=_beans.size(); | |
389 if (size==0) | |
390 return; | |
391 int i=0; | |
392 for (Bean b : _beans) | |
393 { | |
394 i++; | |
395 | |
396 out.append(indent).append(" +- "); | |
397 if (b._managed) | |
398 { | |
399 if (b._bean instanceof Dumpable) | |
400 ((Dumpable)b._bean).dump(out,indent+(i==size?" ":" | ")); | |
401 else | |
402 dumpObject(out,b._bean); | |
403 } | |
404 else | |
405 dumpObject(out,b._bean); | |
406 } | |
407 | |
408 if (i!=size) | |
409 out.append(indent).append(" |\n"); | |
410 } | |
411 | |
412 /* ------------------------------------------------------------ */ | |
413 public static void dump(Appendable out,String indent,Collection<?>... collections) throws IOException | |
414 { | |
415 if (collections.length==0) | |
416 return; | |
417 int size=0; | |
418 for (Collection<?> c : collections) | |
419 size+=c.size(); | |
420 if (size==0) | |
421 return; | |
422 | |
423 int i=0; | |
424 for (Collection<?> c : collections) | |
425 { | |
426 for (Object o : c) | |
427 { | |
428 i++; | |
429 out.append(indent).append(" +- "); | |
430 | |
431 if (o instanceof Dumpable) | |
432 ((Dumpable)o).dump(out,indent+(i==size?" ":" | ")); | |
433 else | |
434 dumpObject(out,o); | |
435 } | |
436 | |
437 if (i!=size) | |
438 out.append(indent).append(" |\n"); | |
439 } | |
440 } | |
441 } |