Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/mortbay/jetty/servlet/WebApplicationHandler.java


1   // ===========================================================================
2   // Copyright (c) 1996 Mort Bay Consulting Pty. Ltd. All rights reserved.
3   // $Id: WebApplicationHandler.java,v 1.30 2003/10/12 11:58:33 gregwilkins Exp $
4   // ---------------------------------------------------------------------------
5   
6   package org.mortbay.jetty.servlet;
7   
8   import java.io.IOException;
9   import java.util.ArrayList;
10  import java.util.EventListener;
11  import java.util.HashMap;
12  import java.util.Iterator;
13  import java.util.List;
14  import java.util.Map;
15  
16  import javax.servlet.Filter;
17  import javax.servlet.FilterChain;
18  import javax.servlet.ServletException;
19  import javax.servlet.ServletRequest;
20  import javax.servlet.ServletRequestAttributeListener;
21  import javax.servlet.ServletRequestListener;
22  import javax.servlet.ServletResponse;
23  import javax.servlet.UnavailableException;
24  import javax.servlet.http.HttpServletRequest;
25  import javax.servlet.http.HttpServletResponse;
26  import javax.servlet.http.HttpSessionActivationListener;
27  import javax.servlet.http.HttpSessionAttributeListener;
28  import javax.servlet.http.HttpSessionBindingListener;
29  import javax.servlet.http.HttpSessionListener;
30  
31  import org.apache.commons.logging.Log;
32  import org.apache.commons.logging.LogFactory;
33  import org.mortbay.http.HttpContext;
34  import org.mortbay.http.HttpResponse;
35  import org.mortbay.util.LazyList;
36  import org.mortbay.util.MultiException;
37  import org.mortbay.util.MultiMap;
38  import org.mortbay.util.StringUtil;
39  import org.mortbay.util.TypeUtil;
40  import org.mortbay.util.LogSupport;
41  
42  /* --------------------------------------------------------------------- */
43  /** WebApp HttpHandler.
44   * This handler extends the ServletHandler with security, filter and resource
45   * capabilities to provide full J2EE web container support.
46   * <p>
47   * @since Jetty 4.1
48   * @see org.mortbay.jetty.servlet.WebApplicationContext
49   * @version $Id: WebApplicationHandler.java,v 1.30 2003/10/12 11:58:33 gregwilkins Exp $
50   * @author Greg Wilkins
51   */
52  public class WebApplicationHandler extends ServletHandler
53  {
54      private static Log log= LogFactory.getLog(WebApplicationHandler.class);
55  
56      private Map _filterMap= new HashMap();
57      private List _pathFilters= new ArrayList();
58      private List _filters= new ArrayList();
59      private MultiMap _servletFilterMap= new MultiMap();
60      private boolean _acceptRanges= true;
61  
62      private transient boolean _started= false;
63      private transient WebApplicationContext _webApplicationContext;
64  
65      protected transient Object _requestListeners;
66      protected transient Object _requestAttributeListeners;
67      protected transient Object _sessionListeners;
68  
69      /* ------------------------------------------------------------ */
70      public boolean isAcceptRanges()
71      {
72          return _acceptRanges;
73      }
74  
75      /* ------------------------------------------------------------ */
76      /** Set if the handler accepts range requests.
77       * Default is false;
78       * @param ar True if the handler should accept ranges
79       */
80      public void setAcceptRanges(boolean ar)
81      {
82          _acceptRanges= ar;
83      }
84  
85      /* ------------------------------------------------------------ */
86      public FilterHolder defineFilter(String name, String className)
87      {
88          FilterHolder holder= new FilterHolder(this, name, className);
89          _filterMap.put(holder.getName(), holder);
90          _filters.add(holder);
91          return holder;
92      }
93  
94      /* ------------------------------------------------------------ */
95      public FilterHolder getFilter(String name)
96      {
97          return (FilterHolder)_filterMap.get(name);
98      }
99  
100     /* ------------------------------------------------------------ */
101     public FilterHolder mapServletToFilter(String servletName, String filterName)
102     {
103         FilterHolder holder= (FilterHolder)_filterMap.get(filterName);
104         if (holder == null)
105             throw new IllegalArgumentException("Unknown filter :" + filterName);
106         if (log.isDebugEnabled())
107             log.debug("Filter servlet " + servletName + " --> " + filterName);
108         _servletFilterMap.add(servletName, holder);
109         holder.addServlet(servletName);
110         return holder;
111     }
112 
113     /* ------------------------------------------------------------ */
114     public List getFilters()
115     {
116         return _filters;
117     }
118 
119     /* ------------------------------------------------------------ */
120     public FilterHolder mapPathToFilter(String pathSpec, String filterName)
121     {
122         FilterHolder holder= (FilterHolder)_filterMap.get(filterName);
123         if (holder == null)
124             throw new IllegalArgumentException("Unknown filter :" + filterName);
125 
126         if (log.isDebugEnabled())
127             log.debug("Filter path " + pathSpec + " --> " + filterName);
128 
129         if (!holder.isMappedToPath())
130             _pathFilters.add(holder);
131         holder.addPathSpec(pathSpec);
132 
133         return holder;
134     }
135 
136     /* ------------------------------------------------------------ */
137     public synchronized void addEventListener(EventListener listener)
138         throws IllegalArgumentException
139     {
140         boolean known= false;
141 
142         if ((listener instanceof HttpSessionActivationListener)
143             || (listener instanceof HttpSessionAttributeListener)
144             || (listener instanceof HttpSessionBindingListener)
145             || (listener instanceof HttpSessionListener))
146         {
147             if (_sessionManager != null)
148                 _sessionManager.addEventListener(listener);
149             _sessionListeners= LazyList.add(_sessionListeners, listener);
150             known= true;
151         }
152 
153         if (listener instanceof ServletRequestListener)
154         {
155             known= true;
156             _requestListeners= LazyList.add(_requestListeners, listener);
157         }
158 
159         if (listener instanceof ServletRequestAttributeListener)
160         {
161             known= true;
162             _requestAttributeListeners= LazyList.add(_requestAttributeListeners, listener);
163         }
164 
165         if (!known)
166             throw new IllegalArgumentException(listener.toString());
167     }
168 
169     /* ------------------------------------------------------------ */
170     public synchronized void removeEventListener(EventListener listener)
171     {
172         if (_sessionManager != null)
173             _sessionManager.removeEventListener(listener);
174 
175         _sessionListeners= LazyList.remove(_sessionListeners, listener);
176         _requestListeners= LazyList.remove(_requestListeners, listener);
177         _requestAttributeListeners= LazyList.remove(_requestAttributeListeners, listener);
178     }
179 
180     /* ------------------------------------------------------------ */
181     public void setSessionManager(SessionManager sm)
182     {
183         if (isStarted())
184             throw new IllegalStateException("Started");
185 
186         SessionManager old= getSessionManager();
187 
188         int mii= 0;
189         boolean setMii= false;
190 
191         if (getHttpContext() != null)
192         {
193             // recover config and remove listeners from old session manager
194             if (old != null && old != sm)
195             {
196                 old.initialize(null);
197                 if (_sessionListeners != null)
198                 {
199                     for (Iterator i= LazyList.iterator(_sessionListeners); i.hasNext();)
200                     {
201                         EventListener listener= (EventListener)i.next();
202                         _sessionManager.removeEventListener(listener);
203                     }
204                 }
205                 mii= _sessionManager.getMaxInactiveInterval();
206                 setMii= true;
207             }
208 
209             // Set listeners and config on new listener.
210             if (sm != null && sm != sm)
211             {
212                 if (_sessionListeners != null)
213                 {
214                     for (Iterator i= LazyList.iterator(_sessionListeners); i.hasNext();)
215                     {
216                         EventListener listener= (EventListener)i.next();
217                         sm.addEventListener(listener);
218                     }
219                 }
220                 sm.initialize(this);
221                 if (setMii)
222                     sm.setMaxInactiveInterval(mii);
223             }
224         }
225 
226         super.setSessionManager(sm);
227     }
228 
229     /* ------------------------------------------------------------ */
230     public boolean isStarted()
231     {
232         return _started && super.isStarted();
233     }
234 
235     /* ----------------------------------------------------------------- */
236     public synchronized void start() throws Exception
237     {
238         // Start Servlet Handler
239         super.start();
240         if (log.isDebugEnabled())
241             log.debug("Path Filters: " + _pathFilters);
242         if (log.isDebugEnabled())
243             log.debug("Servlet Filters: " + _servletFilterMap);
244         _started= true;
245         if (getHttpContext() instanceof WebApplicationContext)
246             _webApplicationContext= (WebApplicationContext)getHttpContext();
247 
248         if (LazyList.size(_requestAttributeListeners) > 0 || LazyList.size(_requestListeners) > 0)
249         {
250             FilterHolder holder=
251                 new FilterHolder(
252                     this,
253                     "RequestAttributeListener",
254                     "org.mortbay.jetty.servlet.RequestListenerFilter");
255             holder.addAppliesTo(FilterHolder.__ALL);
256             holder.addPathSpec("/");
257             holder.start();
258             RequestListenerFilter filter= (RequestListenerFilter)holder.getFilter();
259             filter.setRequestAttributeListeners(_requestAttributeListeners);
260             filter.setRequestListeners(_requestListeners);
261             _pathFilters.add(0, holder);
262         }
263     }
264 
265     /* ------------------------------------------------------------ */
266     public void initializeServlets() throws Exception
267     {
268         // initialize Filters
269         MultiException mex= new MultiException();
270         Iterator iter= _filters.iterator();
271         while (iter.hasNext())
272         {
273             FilterHolder holder= (FilterHolder)iter.next();
274             try
275             {
276                 holder.start();
277             }
278             catch (Exception e)
279             {
280                 mex.add(e);
281             }
282         }
283 
284         // initialize Servlets
285         try
286         {
287             super.initializeServlets();
288         }
289         catch (Exception e)
290         {
291             mex.add(e);
292         }
293 
294         mex.ifExceptionThrow();
295     }
296 
297     /* ------------------------------------------------------------ */
298     public synchronized void stop() throws InterruptedException
299     {
300         try
301         {
302             // Stop servlets
303             super.stop();
304 
305             // Stop filters
306             for (int i= _filters.size(); i-- > 0;)
307             {
308                 FilterHolder holder= (FilterHolder)_filters.get(i);
309                 holder.stop();
310             }
311         }
312         finally
313         {
314             _started= false;
315             _webApplicationContext= null;
316             _sessionListeners= null;
317             _requestListeners= null;
318             _requestAttributeListeners= null;
319         }
320     }
321 
322     /* ------------------------------------------------------------ */
323     protected String getErrorPage(int status, ServletHttpRequest request)
324     {
325         String error_page= null;
326         Class exClass= (Class)request.getAttribute(ServletHandler.__J_S_ERROR_EXCEPTION_TYPE);
327 
328         if (ServletException.class.equals(exClass))
329         {
330             error_page= _webApplicationContext.getErrorPage(exClass.getName());
331             if (error_page == null)
332             {
333                 Throwable th= (Throwable)request.getAttribute(ServletHandler.__J_S_ERROR_EXCEPTION);
334                 while (th instanceof ServletException)
335                     th= ((ServletException)th).getRootCause();
336                 if (th != null)
337                     exClass= th.getClass();
338             }
339         }
340 
341         if (error_page == null && exClass != null)
342         {
343             while (error_page == null && exClass != null && _webApplicationContext != null)
344             {
345                 error_page= _webApplicationContext.getErrorPage(exClass.getName());
346                 exClass= exClass.getSuperclass();
347             }
348 
349             if (error_page == null)
350             {}
351         }
352 
353         if (error_page == null && _webApplicationContext != null)
354             error_page= _webApplicationContext.getErrorPage(TypeUtil.toString(status));
355 
356         return error_page;
357     }
358 
359     /* ------------------------------------------------------------ */
360     protected void dispatch(
361         String pathInContext,
362         HttpServletRequest request,
363         HttpServletResponse response,
364         ServletHolder servletHolder)
365         throws ServletException, UnavailableException, IOException
366     {
367         // Determine request type.
368         int requestType= 0;
369 
370         if (request instanceof Dispatcher.DispatcherRequest)
371         {
372             // Handle dispatch to j_security_check
373             HttpContext context= getHttpContext();
374             if (context != null
375                 && context instanceof ServletHttpContext
376                 && pathInContext != null
377                 && pathInContext.endsWith(FormAuthenticator.__J_SECURITY_CHECK))
378             {
379                 ServletHttpRequest servletHttpRequest= (ServletHttpRequest)request;
380                 ServletHttpResponse servletHttpResponse= (ServletHttpResponse)response;
381                 ServletHttpContext servletContext= (ServletHttpContext)context;
382 
383                 if (!servletContext
384                     .jSecurityCheck(
385                         pathInContext,
386                         servletHttpRequest.getHttpRequest(),
387                         servletHttpResponse.getHttpResponse()))
388                     return;
389             }
390 
391             // Forward or include
392             requestType= ((Dispatcher.DispatcherRequest)request).getFilterType();
393             if (requestType == FilterHolder.__FORWARD)
394             {
395                 // Error
396                 requestType= FilterHolder.__ERROR;
397             }
398         }
399         else
400         {
401             // Error or request
402             ServletHttpRequest servletHttpRequest= (ServletHttpRequest)request;
403             ServletHttpResponse servletHttpResponse= (ServletHttpResponse)response;
404             HttpResponse httpResponse= servletHttpResponse.getHttpResponse();
405 
406             // Request
407             requestType= FilterHolder.__REQUEST;
408             // protect web-inf and meta-inf
409             if (StringUtil.startsWithIgnoreCase(pathInContext, "/web-inf")
410                 || StringUtil.startsWithIgnoreCase(pathInContext, "/meta-inf"))
411             {
412                 response.sendError(HttpResponse.__404_Not_Found);
413                 return;
414             }
415 
416             // Security Check
417             if (!getHttpContext()
418                 .checkSecurityConstraints(
419                     pathInContext,
420                     servletHttpRequest.getHttpRequest(),
421                     httpResponse))
422                 return;
423         }
424 
425         // Build list of filters
426         Object filters= null;
427 
428         // Path filters
429         if (pathInContext != null && _pathFilters.size() > 0)
430         {
431             for (int i= 0; i < _pathFilters.size(); i++)
432             {
433                 FilterHolder holder= (FilterHolder)_pathFilters.get(i);
434                 if (holder.appliesTo(pathInContext, requestType))
435                     filters= LazyList.add(filters, holder);
436             }
437         }
438 
439         // Servlet filters
440         if (servletHolder != null && _servletFilterMap.size() > 0)
441         {
442             Object o= _servletFilterMap.get(servletHolder.getName());
443             if (o != null)
444             {
445                 if (o instanceof List)
446                 {
447                     List list= (List)o;
448                     for (int i= 0; i < list.size(); i++)
449                     {
450                         FilterHolder holder= (FilterHolder)list.get(i);
451                         if (holder.appliesTo(requestType))
452                             filters= LazyList.add(filters, holder);
453                     }
454                 }
455                 else
456                 {
457                     FilterHolder holder= (FilterHolder)o;
458                     if (holder.appliesTo(requestType))
459                         filters= LazyList.add(filters, holder);
460                 }
461             }
462         }
463 
464         // Do the handling thang
465         if (LazyList.size(filters) > 0)
466         {
467             Chain chain= new Chain(pathInContext, filters, servletHolder);
468             chain.doFilter(request, response);
469         }
470         else
471         {
472             // Call servlet
473             if (servletHolder != null)
474             {
475                 if (LogSupport.isTraceEnabled(log))
476                     log.trace("call servlet " + servletHolder);
477                 servletHolder.handle(request, response);
478             }
479             else // Not found
480                 notFound(request, response);
481         }
482     }
483 
484     /* ------------------------------------------------------------ */
485     /* ------------------------------------------------------------ */
486     /* ------------------------------------------------------------ */
487     private class Chain implements FilterChain
488     {
489         String _pathInContext;
490         int _filter= 0;
491         Object _filters;
492         ServletHolder _servletHolder;
493 
494         /* ------------------------------------------------------------ */
495         Chain(String pathInContext, Object filters, ServletHolder servletHolder)
496         {
497             _pathInContext= pathInContext;
498             _filters= filters;
499             _servletHolder= servletHolder;
500         }
501 
502         /* ------------------------------------------------------------ */
503         public void doFilter(ServletRequest request, ServletResponse response)
504             throws IOException, ServletException
505         {
506             if (LogSupport.isTraceEnabled(log))
507                 log.trace("doFilter " + _filter);
508 
509             // pass to next filter
510             if (_filter < LazyList.size(_filters))
511             {
512                 FilterHolder holder= (FilterHolder)LazyList.get(_filters, _filter++);
513                 if (LogSupport.isTraceEnabled(log))
514                     log.trace("call filter " + holder);
515                 Filter filter= holder.getFilter();
516                 filter.doFilter(request, response, this);
517                 return;
518             }
519 
520             // Call servlet
521             if (_servletHolder != null)
522             {
523                 if (LogSupport.isTraceEnabled(log))
524                     log.trace("call servlet " + _servletHolder);
525                 _servletHolder.handle(request, response);
526             }
527             else // Not found
528                 notFound((HttpServletRequest)request, (HttpServletResponse)response);
529         }
530     }
531 }