View Javadoc

1   // ========================================================================
2   // Copyright (c) 2004-2009 Mort Bay Consulting Pty. Ltd.
3   // ------------------------------------------------------------------------
4   // All rights reserved. This program and the accompanying materials
5   // are made available under the terms of the Eclipse Public License v1.0
6   // and Apache License v2.0 which accompanies this distribution.
7   // The Eclipse Public License is available at 
8   // http://www.eclipse.org/legal/epl-v10.html
9   // The Apache License v2.0 is available at
10  // http://www.opensource.org/licenses/apache2.0.php
11  // You may elect to redistribute this code under either of these licenses. 
12  // ========================================================================
13  
14  package org.eclipse.jetty.server.handler;
15  
16  import java.io.IOException;
17  import java.util.concurrent.CountDownLatch;
18  
19  import javax.servlet.ServletException;
20  import javax.servlet.http.HttpServletRequest;
21  import javax.servlet.http.HttpServletResponse;
22  
23  import org.eclipse.jetty.server.Handler;
24  import org.eclipse.jetty.server.Request;
25  import org.eclipse.jetty.server.Server;
26  import org.eclipse.jetty.util.LazyList;
27  import org.eclipse.jetty.util.MultiException;
28  
29  /* ------------------------------------------------------------ */
30  /** A collection of handlers.  
31   * <p>
32   * The default implementations  calls all handlers in list order, 
33   * regardless of the response status or exceptions. Derived implementation
34   * may alter the order or the conditions of calling the contained 
35   * handlers.
36   * <p>
37   * 
38   * @org.apache.xbean.XBean
39   */
40  public class HandlerCollection extends AbstractHandlerContainer
41  {
42      private final boolean _mutableWhenRunning;
43      private volatile Handler[] _handlers;
44      private boolean _parallelStart=false; 
45  
46      /* ------------------------------------------------------------ */
47      public HandlerCollection()
48      {
49          _mutableWhenRunning=false;
50      }
51      
52      /* ------------------------------------------------------------ */
53      public HandlerCollection(boolean mutableWhenRunning)
54      {
55          _mutableWhenRunning=mutableWhenRunning;
56      }
57  
58      /* ------------------------------------------------------------ */
59      /**
60       * @return Returns the handlers.
61       */
62      public Handler[] getHandlers()
63      {
64          return _handlers;
65      }
66      
67      /* ------------------------------------------------------------ */
68      /**
69       * 
70       * @param handlers The handlers to set.
71       */
72      public void setHandlers(Handler[] handlers)
73      {
74          if (!_mutableWhenRunning && isStarted())
75              throw new IllegalStateException(STARTED);
76          
77          Handler [] old_handlers = _handlers==null?null:_handlers.clone();
78          _handlers = handlers;
79          
80          Server server = getServer();
81          MultiException mex = new MultiException();
82          for (int i=0;handlers!=null && i<handlers.length;i++)
83          {
84              if (handlers[i].getServer()!=server)
85                  handlers[i].setServer(server);
86          }
87  
88          if (getServer()!=null)
89              getServer().getContainer().update(this, old_handlers, handlers, "handler");
90          
91          // stop old handlers
92          for (int i=0;old_handlers!=null && i<old_handlers.length;i++)
93          {
94              if (old_handlers[i]!=null)
95              {
96                  try
97                  {
98                      if (old_handlers[i].isStarted())
99                          old_handlers[i].stop();
100                 }
101                 catch (Throwable e)
102                 {
103                     mex.add(e);
104                 }
105             }
106         }
107                 
108         mex.ifExceptionThrowRuntime();
109     }
110     
111 
112     
113     /* ------------------------------------------------------------ */
114     /** Get the parrallelStart.
115      * @return true if the contained handlers are started in parallel.
116      */
117     public boolean isParallelStart()
118     {
119         return _parallelStart;
120     }
121 
122 
123 
124     /* ------------------------------------------------------------ */
125     /** Set the parallelStart.
126      * @param parallelStart If true, contained handlers are started in parallel.
127      */
128     public void setParallelStart(boolean parallelStart)
129     {
130         this._parallelStart = parallelStart;
131     }
132 
133 
134     /* ------------------------------------------------------------ */
135     /**
136      * @see Handler#handle(String, Request, HttpServletRequest, HttpServletResponse)
137      */
138     public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) 
139         throws IOException, ServletException
140     {
141         if (_handlers!=null && isStarted())
142         {
143             MultiException mex=null;
144             
145             for (int i=0;i<_handlers.length;i++)
146             {
147                 try
148                 {
149                     _handlers[i].handle(target,baseRequest, request, response);
150                 }
151                 catch(IOException e)
152                 {
153                     throw e;
154                 }
155                 catch(RuntimeException e)
156                 {
157                     throw e;
158                 }
159                 catch(Exception e)
160                 {
161                     if (mex==null)
162                         mex=new MultiException();
163                     mex.add(e);
164                 }
165             }
166             if (mex!=null)
167             {
168                 if (mex.size()==1)
169                     throw new ServletException(mex.getThrowable(0));
170                 else
171                     throw new ServletException(mex);
172             }
173             
174         }    
175     }
176 
177     /* ------------------------------------------------------------ */
178     /* 
179      * @see org.eclipse.jetty.server.server.handler.AbstractHandler#doStart()
180      */
181     @Override
182     protected void doStart() throws Exception
183     {
184         final MultiException mex=new MultiException();
185         if (_handlers!=null)
186         {
187             if (_parallelStart)
188             {
189                 final CountDownLatch latch = new CountDownLatch(_handlers.length);
190                 final ClassLoader loader = Thread.currentThread().getContextClassLoader();
191                 for (int i=0;i<_handlers.length;i++)
192                 {
193                     final int h=i;
194                     getServer().getThreadPool().dispatch(
195                             new Runnable()
196                             {
197                                 public void run()
198                                 {
199                                     ClassLoader orig = Thread.currentThread().getContextClassLoader();
200                                     try
201                                     {
202                                         Thread.currentThread().setContextClassLoader(loader);
203                                         _handlers[h].start();
204                                     }
205                                     catch(Throwable e)
206                                     {
207                                         mex.add(e);
208                                     }
209                                     finally
210                                     {
211                                         Thread.currentThread().setContextClassLoader(orig);
212                                         latch.countDown();
213                                     }
214                                 }
215                             }
216                     );
217                 }
218                 latch.await();
219             }
220             else
221             {
222                 for (int i=0;i<_handlers.length;i++)
223                 {
224                     try{_handlers[i].start();}
225                     catch(Throwable e){mex.add(e);}
226                 }
227             }
228         }
229         super.doStart();
230         mex.ifExceptionThrow();
231     }
232 
233     /* ------------------------------------------------------------ */
234     /* 
235      * @see org.eclipse.jetty.server.server.handler.AbstractHandler#doStop()
236      */
237     @Override
238     protected void doStop() throws Exception
239     {
240         MultiException mex=new MultiException();
241         try { super.doStop(); } catch(Throwable e){mex.add(e);}
242         if (_handlers!=null)
243         {
244             for (int i=_handlers.length;i-->0;)
245                 try{_handlers[i].stop();}catch(Throwable e){mex.add(e);}
246         }
247         mex.ifExceptionThrow();
248     }
249     
250     /* ------------------------------------------------------------ */
251     @Override
252     public void setServer(Server server)
253     {
254         if (isStarted())
255             throw new IllegalStateException(STARTED);
256         
257         Server old_server=getServer();
258         
259         super.setServer(server);
260 
261         Handler[] h=getHandlers();
262         for (int i=0;h!=null && i<h.length;i++)
263             h[i].setServer(server);
264         
265         if (server!=null && server!=old_server)
266             server.getContainer().update(this, null,_handlers, "handler");
267         
268     }
269 
270     /* ------------------------------------------------------------ */
271     /* Add a handler.
272      * This implementation adds the passed handler to the end of the existing collection of handlers. 
273      * @see org.eclipse.jetty.server.server.HandlerContainer#addHandler(org.eclipse.jetty.server.server.Handler)
274      */
275     public void addHandler(Handler handler)
276     {
277         setHandlers((Handler[])LazyList.addToArray(getHandlers(), handler, Handler.class));
278     }
279     
280     /* ------------------------------------------------------------ */
281     public void removeHandler(Handler handler)
282     {
283         Handler[] handlers = getHandlers();
284         
285         if (handlers!=null && handlers.length>0 )
286             setHandlers((Handler[])LazyList.removeFromArray(handlers, handler));
287     }
288 
289     /* ------------------------------------------------------------ */
290     @Override
291     protected Object expandChildren(Object list, Class byClass)
292     {
293         Handler[] handlers = getHandlers();
294         for (int i=0;handlers!=null && i<handlers.length;i++)
295             list=expandHandler(handlers[i], list, byClass);
296         return list;
297     }
298 
299     /* ------------------------------------------------------------ */
300     @Override
301     public void destroy()
302     {
303         if (!isStopped())
304             throw new IllegalStateException("!STOPPED");
305         Handler[] children=getChildHandlers();
306         setHandlers(null);
307         for (Handler child: children)
308             child.destroy();
309         super.destroy();
310     }
311 }