View Javadoc

1   package org.eclipse.jetty.util.component;
2   
3   import java.io.IOException;
4   import java.util.ArrayList;
5   import java.util.Collection;
6   import java.util.Collections;
7   import java.util.Iterator;
8   import java.util.List;
9   import java.util.Queue;
10  import java.util.concurrent.ConcurrentLinkedQueue;
11  import java.util.concurrent.CopyOnWriteArrayList;
12  
13  import org.eclipse.jetty.util.log.Log;
14  import org.eclipse.jetty.util.log.Logger;
15  
16  /**
17   * An AggregateLifeCycle is an AbstractLifeCycle with a collection of dependent beans.
18   * <p>
19   * Dependent beans are started and stopped with the {@link LifeCycle} and if they are destroyed if they are also {@link Destroyable}.
20   *
21   */
22  public class AggregateLifeCycle extends AbstractLifeCycle implements Destroyable, Dumpable
23  {
24      private static final Logger LOG = Log.getLogger(AggregateLifeCycle.class);
25      private final List<Object> _dependentBeans=new CopyOnWriteArrayList<Object>();
26  
27      public void destroy()
28      {
29          for (Object o : _dependentBeans)
30          {
31              if (o instanceof Destroyable)
32              {
33                  ((Destroyable)o).destroy();
34              }
35          }
36          _dependentBeans.clear();
37      }
38  
39      @Override
40      protected void doStart() throws Exception
41      {
42          for (Object o:_dependentBeans)
43          {
44              if (o instanceof LifeCycle)
45                  ((LifeCycle)o).start();
46          }
47          super.doStart();
48      }
49  
50      @Override
51      protected void doStop() throws Exception
52      {
53          super.doStop();
54          List<Object> reverse = new ArrayList<Object>(_dependentBeans);
55          Collections.reverse(reverse);
56          for (Object o:reverse)
57          {
58              if (o instanceof LifeCycle)
59                  ((LifeCycle)o).stop();
60          }
61      }
62  
63  
64      /* ------------------------------------------------------------ */
65      /**
66       * Add an associated bean.
67       * The bean will be added to this LifeCycle and if it is also a 
68       * {@link LifeCycle} instance, it will be 
69       * started/stopped. Any beans that are also 
70       * {@link Destroyable}, will be destroyed with the server.
71       * @param o the bean object to add
72       */
73      public boolean addBean(Object o)
74      {
75          if (o == null)
76              return false;
77          boolean added=false;
78          if (!_dependentBeans.contains(o)) 
79          {
80              _dependentBeans.add(o);
81              added=true;
82          }
83          
84          try
85          {
86              if (isStarted() && o instanceof LifeCycle)
87                  ((LifeCycle)o).start();
88          }
89          catch (Exception e)
90          {
91              throw new RuntimeException (e);
92          }
93          return added;
94      }
95  
96      /* ------------------------------------------------------------ */
97      /** Get dependent beans 
98       * @return List of beans.
99       */
100     public Collection<Object> getBeans()
101     {
102         return _dependentBeans;
103     }
104     
105     /* ------------------------------------------------------------ */
106     /** Get dependent beans of a specific class
107      * @see #addBean(Object)
108      * @param clazz
109      * @return List of beans.
110      */
111     public <T> List<T> getBeans(Class<T> clazz)
112     {
113         ArrayList<T> beans = new ArrayList<T>();
114         Iterator<?> iter = _dependentBeans.iterator();
115         while (iter.hasNext())
116         {
117             Object o = iter.next();
118             if (clazz.isInstance(o))
119                 beans.add((T)o);
120         }
121         return beans;
122     }
123 
124     
125     /* ------------------------------------------------------------ */
126     /** Get dependent bean of a specific class.
127      * If more than one bean of the type exist, the first is returned.
128      * @see #addBean(Object)
129      * @param clazz
130      * @return bean or null
131      */
132     public <T> T getBean(Class<T> clazz)
133     {
134         Iterator<?> iter = _dependentBeans.iterator();
135         T t=null;
136         int count=0;
137         while (iter.hasNext())
138         {
139             Object o = iter.next();
140             if (clazz.isInstance(o))
141             {
142                 count++;
143                 if (t==null)
144                     t=(T)o;
145             }
146         }
147         if (count>1 && LOG.isDebugEnabled())
148             LOG.debug("getBean({}) 1 of {}",clazz.getName(),count);
149         
150         return t;
151     }
152     
153     /* ------------------------------------------------------------ */
154     /**
155      * Remove all associated bean.
156      */
157     public void removeBeans ()
158     {
159         _dependentBeans.clear();
160     }
161 
162     /* ------------------------------------------------------------ */
163     /**
164      * Remove an associated bean.
165      */
166     public boolean removeBean (Object o)
167     {
168         if (o == null)
169             return false;
170         return _dependentBeans.remove(o);
171     }
172 
173     /* ------------------------------------------------------------ */
174     public void dumpStdErr()
175     {
176         try
177         {
178             dump(System.err,"");
179         }
180         catch (IOException e)
181         {
182             LOG.warn(e);
183         }
184     }
185     
186     /* ------------------------------------------------------------ */
187     public String dump()
188     {
189         return dump(this);
190     }    
191     
192     /* ------------------------------------------------------------ */
193     public static String dump(Dumpable dumpable)
194     {
195         StringBuilder b = new StringBuilder();
196         try
197         {
198             dumpable.dump(b,"");
199         }
200         catch (IOException e)
201         {
202             LOG.warn(e);
203         }
204         return b.toString();
205     }    
206 
207     /* ------------------------------------------------------------ */
208     public void dump(Appendable out) throws IOException
209     {
210         dump(out,"");
211     }
212 
213     /* ------------------------------------------------------------ */
214     protected void dumpThis(Appendable out) throws IOException
215     {
216         out.append(String.valueOf(this)).append("\n");
217     }
218     
219     /* ------------------------------------------------------------ */
220     public void dump(Appendable out,String indent) throws IOException
221     {
222         dumpThis(out);
223         dump(out,indent,_dependentBeans);
224     }
225     
226     /* ------------------------------------------------------------ */
227     public static void dump(Appendable out,String indent,Collection<?>... collections) throws IOException
228     {
229         if (collections.length==0)
230             return;
231         int size=0;
232         for (Collection<?> c : collections)
233             size+=c.size();    
234         if (size==0)
235             return;
236 
237         int i=0;
238         for (Collection<?> c : collections)
239         {
240             for (Object o : c)
241             {
242                 i++;
243                 out.append(indent).append(" +- ");
244 
245                 if (o instanceof Dumpable)
246                     ((Dumpable)o).dump(out,indent+(i==size?"    ":" |  "));
247                 else
248                     out.append(String.valueOf(o)).append("\n");
249             }
250             
251             if (i!=size)
252                 out.append(indent).append(" |\n");
253                 
254         }
255     }
256     
257     
258     
259 }