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=true; 
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                 for (int i=0;i<_handlers.length;i++)
193                 {
194                     final int h=i;
195                     getServer().getThreadPool().dispatch(
196                             new Runnable()
197                             {
198                                 public void run()
199                                 {
200                                     try{_handlers[h].start();}
201                                     catch(Throwable e){mex.add(e);}
202                                     finally{latch.countDown();}
203                                 }
204                             }
205                     );
206 
207                 }
208                 latch.await();
209             }
210             else
211             {
212                 for (int i=0;i<_handlers.length;i++)
213                 {
214                     try{_handlers[i].start();}
215                     catch(Throwable e){mex.add(e);}
216                 }
217             }
218         }
219         super.doStart();
220         mex.ifExceptionThrow();
221     }
222 
223     /* ------------------------------------------------------------ */
224     /* 
225      * @see org.eclipse.jetty.server.server.handler.AbstractHandler#doStop()
226      */
227     @Override
228     protected void doStop() throws Exception
229     {
230         MultiException mex=new MultiException();
231         try { super.doStop(); } catch(Throwable e){mex.add(e);}
232         if (_handlers!=null)
233         {
234             for (int i=_handlers.length;i-->0;)
235                 try{_handlers[i].stop();}catch(Throwable e){mex.add(e);}
236         }
237         mex.ifExceptionThrow();
238     }
239     
240     /* ------------------------------------------------------------ */
241     @Override
242     public void setServer(Server server)
243     {
244         if (isStarted())
245             throw new IllegalStateException(STARTED);
246         
247         Server old_server=getServer();
248         
249         super.setServer(server);
250 
251         Handler[] h=getHandlers();
252         for (int i=0;h!=null && i<h.length;i++)
253             h[i].setServer(server);
254         
255         if (server!=null && server!=old_server)
256             server.getContainer().update(this, null,_handlers, "handler");
257         
258     }
259 
260     /* ------------------------------------------------------------ */
261     /* Add a handler.
262      * This implementation adds the passed handler to the end of the existing collection of handlers. 
263      * @see org.eclipse.jetty.server.server.HandlerContainer#addHandler(org.eclipse.jetty.server.server.Handler)
264      */
265     public void addHandler(Handler handler)
266     {
267         setHandlers((Handler[])LazyList.addToArray(getHandlers(), handler, Handler.class));
268     }
269     
270     /* ------------------------------------------------------------ */
271     public void removeHandler(Handler handler)
272     {
273         Handler[] handlers = getHandlers();
274         
275         if (handlers!=null && handlers.length>0 )
276             setHandlers((Handler[])LazyList.removeFromArray(handlers, handler));
277     }
278 
279     /* ------------------------------------------------------------ */
280     @Override
281     protected Object expandChildren(Object list, Class byClass)
282     {
283         Handler[] handlers = getHandlers();
284         for (int i=0;handlers!=null && i<handlers.length;i++)
285             list=expandHandler(handlers[i], list, byClass);
286         return list;
287     }
288 
289 
290 }