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