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          
79          if (getServer()!=null)
80              getServer().getContainer().update(this, old_handlers, handlers, "handler");
81          
82          Server server = getServer();
83          MultiException mex = new MultiException();
84          for (int i=0;handlers!=null && i<handlers.length;i++)
85          {
86              if (handlers[i].getServer()!=server)
87                  handlers[i].setServer(server);
88          }
89  
90          // handlers is volatile
91          _handlers = handlers;
92  
93          // stop old handlers
94          for (int i=0;old_handlers!=null && i<old_handlers.length;i++)
95          {
96              if (old_handlers[i]!=null)
97              {
98                  try
99                  {
100                     if (old_handlers[i].isStarted())
101                         old_handlers[i].stop();
102                 }
103                 catch (Throwable e)
104                 {
105                     mex.add(e);
106                 }
107             }
108         }
109                 
110         mex.ifExceptionThrowRuntime();
111     }
112     
113 
114     
115     /* ------------------------------------------------------------ */
116     /** Get the parrallelStart.
117      * @return true if the contained handlers are started in parallel.
118      */
119     public boolean isParallelStart()
120     {
121         return _parallelStart;
122     }
123 
124 
125 
126     /* ------------------------------------------------------------ */
127     /** Set the parallelStart.
128      * @param parallelStart If true, contained handlers are started in parallel.
129      */
130     public void setParallelStart(boolean parallelStart)
131     {
132         this._parallelStart = parallelStart;
133     }
134 
135 
136     /* ------------------------------------------------------------ */
137     /**
138      * @see Handler#handle(String, Request, HttpServletRequest, HttpServletResponse)
139      */
140     public void handle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) 
141         throws IOException, ServletException
142     {
143         if (_handlers!=null && isStarted())
144         {
145             MultiException mex=null;
146             
147             for (int i=0;i<_handlers.length;i++)
148             {
149                 try
150                 {
151                     _handlers[i].handle(target,baseRequest, request, response);
152                 }
153                 catch(IOException e)
154                 {
155                     throw e;
156                 }
157                 catch(RuntimeException e)
158                 {
159                     throw e;
160                 }
161                 catch(Exception e)
162                 {
163                     if (mex==null)
164                         mex=new MultiException();
165                     mex.add(e);
166                 }
167             }
168             if (mex!=null)
169             {
170                 if (mex.size()==1)
171                     throw new ServletException(mex.getThrowable(0));
172                 else
173                     throw new ServletException(mex);
174             }
175             
176         }    
177     }
178 
179     /* ------------------------------------------------------------ */
180     /* 
181      * @see org.eclipse.jetty.server.server.handler.AbstractHandler#doStart()
182      */
183     @Override
184     protected void doStart() throws Exception
185     {
186         final MultiException mex=new MultiException();
187         if (_handlers!=null)
188         {
189             if (_parallelStart)
190             {
191                 final CountDownLatch latch = new CountDownLatch(_handlers.length);
192                 final ClassLoader loader = Thread.currentThread().getContextClassLoader();
193                 for (int i=0;i<_handlers.length;i++)
194                 {
195                     final int h=i;
196                     getServer().getThreadPool().dispatch(
197                             new Runnable()
198                             {
199                                 public void run()
200                                 {
201                                     ClassLoader orig = Thread.currentThread().getContextClassLoader();
202                                     try
203                                     {
204                                         Thread.currentThread().setContextClassLoader(loader);
205                                         _handlers[h].start();
206                                     }
207                                     catch(Throwable e)
208                                     {
209                                         mex.add(e);
210                                     }
211                                     finally
212                                     {
213                                         Thread.currentThread().setContextClassLoader(orig);
214                                         latch.countDown();
215                                     }
216                                 }
217                             }
218                     );
219                 }
220                 latch.await();
221             }
222             else
223             {
224                 for (int i=0;i<_handlers.length;i++)
225                 {
226                     try{_handlers[i].start();}
227                     catch(Throwable e){mex.add(e);}
228                 }
229             }
230         }
231         super.doStart();
232         mex.ifExceptionThrow();
233     }
234 
235     /* ------------------------------------------------------------ */
236     /* 
237      * @see org.eclipse.jetty.server.server.handler.AbstractHandler#doStop()
238      */
239     @Override
240     protected void doStop() throws Exception
241     {
242         MultiException mex=new MultiException();
243         try { super.doStop(); } catch(Throwable e){mex.add(e);}
244         if (_handlers!=null)
245         {
246             for (int i=_handlers.length;i-->0;)
247                 try{_handlers[i].stop();}catch(Throwable e){mex.add(e);}
248         }
249         mex.ifExceptionThrow();
250     }
251     
252     /* ------------------------------------------------------------ */
253     @Override
254     public void setServer(Server server)
255     {
256         if (isStarted())
257             throw new IllegalStateException(STARTED);
258         
259         Server old_server=getServer();
260         
261         super.setServer(server);
262 
263         Handler[] h=getHandlers();
264         for (int i=0;h!=null && i<h.length;i++)
265             h[i].setServer(server);
266         
267         if (server!=null && server!=old_server)
268             server.getContainer().update(this, null,_handlers, "handler");
269         
270     }
271 
272     /* ------------------------------------------------------------ */
273     /* Add a handler.
274      * This implementation adds the passed handler to the end of the existing collection of handlers. 
275      * @see org.eclipse.jetty.server.server.HandlerContainer#addHandler(org.eclipse.jetty.server.server.Handler)
276      */
277     public void addHandler(Handler handler)
278     {
279         setHandlers((Handler[])LazyList.addToArray(getHandlers(), handler, Handler.class));
280     }
281     
282     /* ------------------------------------------------------------ */
283     public void removeHandler(Handler handler)
284     {
285         Handler[] handlers = getHandlers();
286         
287         if (handlers!=null && handlers.length>0 )
288             setHandlers((Handler[])LazyList.removeFromArray(handlers, handler));
289     }
290 
291     /* ------------------------------------------------------------ */
292     @Override
293     protected Object expandChildren(Object list, Class byClass)
294     {
295         Handler[] handlers = getHandlers();
296         for (int i=0;handlers!=null && i<handlers.length;i++)
297             list=expandHandler(handlers[i], list, byClass);
298         return list;
299     }
300 
301 
302 }