1   //========================================================================
2   //$Id: HandlerCollection.java,v 1.5 2005/11/11 22:55:39 gregwilkins Exp $
3   //Copyright 2004-2005 Mort Bay Consulting Pty. Ltd.
4   //------------------------------------------------------------------------
5   //Licensed under the Apache License, Version 2.0 (the "License");
6   //you may not use this file except in compliance with the License.
7   //You may obtain a copy of the License at 
8   //http://www.apache.org/licenses/LICENSE-2.0
9   //Unless required by applicable law or agreed to in writing, software
10  //distributed under the License is distributed on an "AS IS" BASIS,
11  //WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
12  //See the License for the specific language governing permissions and
13  //limitations under the License.
14  //========================================================================
15  
16  package org.mortbay.jetty.handler;
17  
18  import java.io.IOException;
19  
20  import javax.servlet.ServletException;
21  import javax.servlet.http.HttpServletRequest;
22  import javax.servlet.http.HttpServletResponse;
23  
24  import org.mortbay.jetty.Handler;
25  import org.mortbay.jetty.Server;
26  import org.mortbay.util.LazyList;
27  import org.mortbay.util.MultiException;
28  
29  /* ------------------------------------------------------------ */
30  /** A collection of handlers.  
31   * For each request, all handler are called, regardless of 
32   * the response status or exceptions.
33   *  
34   * @author gregw
35   * @org.apache.xbean.XBean
36   */
37  public class HandlerCollection extends AbstractHandlerContainer
38  {
39      private Handler[] _handlers;
40  
41      /* ------------------------------------------------------------ */
42      public HandlerCollection()
43      {
44          super();
45      }
46  
47      /* ------------------------------------------------------------ */
48      /**
49       * @return Returns the handlers.
50       */
51      public Handler[] getHandlers()
52      {
53          return _handlers;
54      }
55      
56      /* ------------------------------------------------------------ */
57      /**
58       * 
59       * @param handlers The handlers to set.
60       */
61      public void setHandlers(Handler[] handlers)
62      {
63          Handler [] old_handlers = _handlers==null?null:(Handler[])_handlers.clone();
64          
65          if (getServer()!=null)
66              getServer().getContainer().update(this, old_handlers, handlers, "handler");
67          
68          Server server = getServer();
69          MultiException mex = new MultiException();
70          for (int i=0;handlers!=null && i<handlers.length;i++)
71          {
72              if (handlers[i].getServer()!=server)
73                  handlers[i].setServer(server);
74          }
75  
76          // quasi atomic.... so don't go doing this under load on a SMP system.
77          _handlers = handlers;
78  
79          for (int i=0;old_handlers!=null && i<old_handlers.length;i++)
80          {
81              if (old_handlers[i]!=null)
82              {
83                  try
84                  {
85                      if (old_handlers[i].isStarted())
86                          old_handlers[i].stop();
87                  }
88                  catch (Throwable e)
89                  {
90                      mex.add(e);
91                  }
92              }
93          }
94                  
95          mex.ifExceptionThrowRuntime();
96      }
97  
98      /* ------------------------------------------------------------ */
99      /* 
100      * @see org.mortbay.jetty.EventHandler#handle(javax.servlet.http.HttpServletRequest, javax.servlet.http.HttpServletResponse)
101      */
102     public void handle(String target, HttpServletRequest request, HttpServletResponse response, int dispatch) 
103         throws IOException, ServletException
104     {
105         if (_handlers!=null && isStarted())
106         {
107             MultiException mex=null;
108             
109             for (int i=0;i<_handlers.length;i++)
110             {
111                 try
112                 {
113                     _handlers[i].handle(target,request, response, dispatch);
114                 }
115                 catch(IOException e)
116                 {
117                     throw e;
118                 }
119                 catch(RuntimeException e)
120                 {
121                     throw e;
122                 }
123                 catch(Exception e)
124                 {
125                     if (mex==null)
126                         mex=new MultiException();
127                     mex.add(e);
128                 }
129             }
130             if (mex!=null)
131             {
132                 if (mex.size()==1)
133                     throw new ServletException(mex.getThrowable(0));
134                 else
135                     throw new ServletException(mex);
136             }
137             
138         }    
139     }
140 
141     /* ------------------------------------------------------------ */
142     /* 
143      * @see org.mortbay.jetty.handler.AbstractHandler#doStart()
144      */
145     protected void doStart() throws Exception
146     {
147         MultiException mex=new MultiException();
148         if (_handlers!=null)
149         {
150             for (int i=0;i<_handlers.length;i++)
151                 try{_handlers[i].start();}catch(Throwable e){mex.add(e);}
152         }
153         super.doStart();
154         mex.ifExceptionThrow();
155     }
156 
157     /* ------------------------------------------------------------ */
158     /* 
159      * @see org.mortbay.jetty.handler.AbstractHandler#doStop()
160      */
161     protected void doStop() throws Exception
162     {
163         MultiException mex=new MultiException();
164         try { super.doStop(); } catch(Throwable e){mex.add(e);}
165         if (_handlers!=null)
166         {
167             for (int i=_handlers.length;i-->0;)
168                 try{_handlers[i].stop();}catch(Throwable e){mex.add(e);}
169         }
170         mex.ifExceptionThrow();
171     }
172     
173     /* ------------------------------------------------------------ */
174     public void setServer(Server server)
175     {
176         Server old_server=getServer();
177         
178         super.setServer(server);
179 
180         Handler[] h=getHandlers();
181         for (int i=0;h!=null && i<h.length;i++)
182             h[i].setServer(server);
183         
184         if (server!=null && server!=old_server)
185             server.getContainer().update(this, null,_handlers, "handler");
186         
187     }
188 
189     /* ------------------------------------------------------------ */
190     /* Add a handler.
191      * This implementation adds the passed handler to the end of the existing collection of handlers. 
192      * @see org.mortbay.jetty.HandlerContainer#addHandler(org.mortbay.jetty.Handler)
193      */
194     public void addHandler(Handler handler)
195     {
196         setHandlers((Handler[])LazyList.addToArray(getHandlers(), handler, Handler.class));
197     }
198     
199     /* ------------------------------------------------------------ */
200     public void removeHandler(Handler handler)
201     {
202         Handler[] handlers = getHandlers();
203         
204         if (handlers!=null && handlers.length>0 )
205             setHandlers((Handler[])LazyList.removeFromArray(handlers, handler));
206     }
207 
208     /* ------------------------------------------------------------ */
209     protected Object expandChildren(Object list, Class byClass)
210     {
211         Handler[] handlers = getHandlers();
212         for (int i=0;handlers!=null && i<handlers.length;i++)
213             list=expandHandler(handlers[i], list, byClass);
214         return list;
215     }
216 
217 
218 }