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 } |
