1   //========================================================================
2   //$Id: WebAppContext.java,v 1.5 2005/11/16 22:02:45 gregwilkins Exp $
3   //Copyright 2004-2006 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.servlet;
17  
18  import java.util.EnumSet;
19  import java.util.Map;
20  
21  import javax.servlet.DispatcherType;
22  import javax.servlet.RequestDispatcher;
23  import javax.servlet.ServletContext;
24  
25  import org.mortbay.jetty.HandlerContainer;
26  import org.mortbay.jetty.handler.ContextHandler;
27  import org.mortbay.jetty.handler.ErrorHandler;
28  import org.mortbay.jetty.security.SecurityHandler;
29  import org.mortbay.log.Log;
30  import org.mortbay.util.URIUtil;
31  
32  
33  /* ------------------------------------------------------------ */
34  /** Servlet Context.
35   * This conveniance extention to the ContextHandler allows for
36   * simple construction of a context with ServletHandler and optionally
37   * session and security handlers, et.<pre>
38   *   new ServletContext("/context",Context.SESSIONS|Context.NO_SECURITY);
39   * </pre>
40   * <p/>
41   * This class should have been called ServletContext, but this would have
42   * cause confusion with {@link ServletContext}.
43   */
44  public class Context extends ContextHandler
45  {   
46      public final static int SESSIONS=1;
47      public final static int SECURITY=2;
48      public final static int NO_SESSIONS=0;
49      public final static int NO_SECURITY=0;
50      
51      protected SecurityHandler _securityHandler;
52      protected ServletHandler _servletHandler;
53      protected SessionHandler _sessionHandler;
54      
55      /* ------------------------------------------------------------ */
56      public Context()
57      {
58          this(null,null,null,null,null);
59      }
60      
61      /* ------------------------------------------------------------ */
62      public Context(int options)
63      {
64          this(null,null,options);
65      }
66      
67      /* ------------------------------------------------------------ */
68      public Context(HandlerContainer parent, String contextPath)
69      {
70          this(parent,contextPath,null,null,null,null);
71      }
72      
73      /* ------------------------------------------------------------ */
74      public Context(HandlerContainer parent, String contextPath, int options)
75      {
76          this(parent,contextPath,((options&SESSIONS)!=0)?new SessionHandler():null,((options&SECURITY)!=0)?new SecurityHandler():null,null,null);
77      }
78      
79      /* ------------------------------------------------------------ */
80      public Context(HandlerContainer parent, String contextPath, boolean sessions, boolean security)
81      {
82          this(parent,contextPath,(sessions?SESSIONS:0)|(security?SECURITY:0));
83      }
84  
85      /* ------------------------------------------------------------ */
86      public Context(HandlerContainer parent, SessionHandler sessionHandler,SecurityHandler securityHandler, ServletHandler servletHandler, ErrorHandler errorHandler)
87      {   
88          this(parent,null,sessionHandler,securityHandler,servletHandler,errorHandler);
89      }
90  
91      /* ------------------------------------------------------------ */
92      public Context(HandlerContainer parent, String contextPath, SessionHandler sessionHandler,SecurityHandler securityHandler, ServletHandler servletHandler, ErrorHandler errorHandler)
93      {   
94          super((ContextHandler.SContext)null);
95          _scontext = new SContext();
96          _sessionHandler = sessionHandler;
97          _securityHandler = securityHandler;
98          _servletHandler = servletHandler!=null?servletHandler:new ServletHandler();
99          
100         if (_sessionHandler!=null)
101         {
102             setHandler(_sessionHandler);
103             
104             if (securityHandler!=null)
105             {
106                 _sessionHandler.setHandler(_securityHandler);
107                 _securityHandler.setHandler(_servletHandler);
108             }
109             else
110             {
111                 _sessionHandler.setHandler(_servletHandler);
112             }
113         }
114         else if (_securityHandler!=null)
115         {
116             setHandler(_securityHandler);
117             _securityHandler.setHandler(_servletHandler);
118         }
119         else
120         {
121             setHandler(_servletHandler);
122         }
123             
124         if (errorHandler!=null)
125             setErrorHandler(errorHandler);
126 
127         if (contextPath!=null)
128             setContextPath(contextPath);
129 
130         if (parent!=null)
131             parent.addHandler(this);
132     }    
133     
134     /* ------------------------------------------------------------ */
135     /**
136      * @see org.mortbay.jetty.handler.ContextHandler#startContext()
137      */
138     protected void startContext() throws Exception
139     {
140     	super.startContext();
141 
142     	// OK to Initialize servlet handler now
143     	if (_servletHandler != null && _servletHandler.isStarted())
144     		_servletHandler.initialize();
145     }
146 
147     /* ------------------------------------------------------------ */
148     /**
149      * @return Returns the securityHandler.
150      */
151     public SecurityHandler getSecurityHandler()
152     {
153         return _securityHandler;
154     }
155 
156     /* ------------------------------------------------------------ */
157     /**
158      * @return Returns the servletHandler.
159      */
160     public ServletHandler getServletHandler()
161     {
162         return _servletHandler;
163     }
164 
165     /* ------------------------------------------------------------ */
166     /**
167      * @return Returns the sessionHandler.
168      */
169     public SessionHandler getSessionHandler()
170     {
171         return _sessionHandler;
172     }
173 
174     /* ------------------------------------------------------------ */
175     /** conveniance method to add a servlet.
176      */
177     public ServletHolder addServlet(String className,String pathSpec)
178     {
179         return _servletHandler.addServletWithMapping(className, pathSpec);
180     }
181 
182     /* ------------------------------------------------------------ */
183     /** conveniance method to add a servlet.
184      */
185     public ServletHolder addServlet(Class servlet,String pathSpec)
186     {
187         return _servletHandler.addServletWithMapping(servlet.getName(), pathSpec);
188     }
189     
190     /* ------------------------------------------------------------ */
191     /** conveniance method to add a servlet.
192      */
193     public void addServlet(ServletHolder servlet,String pathSpec)
194     {
195         _servletHandler.addServletWithMapping(servlet, pathSpec);
196     }
197 
198     /* ------------------------------------------------------------ */
199     /** conveniance method to add a filter
200      */
201     public void addFilter(FilterHolder holder,String pathSpec,int dispatches)
202     {
203         _servletHandler.addFilterWithMapping(holder,pathSpec,dispatches);
204     }
205 
206     /* ------------------------------------------------------------ */
207     /** conveniance method to add a filter
208      */
209     public FilterHolder addFilter(Class filterClass,String pathSpec,int dispatches)
210     {
211         return _servletHandler.addFilterWithMapping(filterClass,pathSpec,dispatches);
212     }
213 
214     /* ------------------------------------------------------------ */
215     /** conveniance method to add a filter
216      */
217     public FilterHolder addFilter(String filterClass,String pathSpec,int dispatches)
218     {
219         return _servletHandler.addFilterWithMapping(filterClass,pathSpec,dispatches);
220     }
221     
222 
223 
224     /* ------------------------------------------------------------ */
225     /**
226      * @param sessionHandler The sessionHandler to set.
227      */
228     public void setSessionHandler(SessionHandler sessionHandler)
229     {
230         if (_sessionHandler==sessionHandler)
231             return;
232         
233         if (_sessionHandler!=null)
234             _sessionHandler.setHandler(null);
235 
236         _sessionHandler = sessionHandler;
237         
238         setHandler(_sessionHandler);
239         
240         if (_securityHandler!=null)
241             _sessionHandler.setHandler(_securityHandler);
242         else if (_servletHandler!=null)
243             _sessionHandler.setHandler(_servletHandler);
244             
245         
246     }
247 
248     /* ------------------------------------------------------------ */
249     /**
250      * @param securityHandler The {@link SecurityHandler} to set on this context.
251      */
252     public void setSecurityHandler(SecurityHandler securityHandler)
253     {
254         if(_securityHandler==securityHandler)
255             return;
256                     
257         if (_securityHandler!=null)
258             _securityHandler.setHandler(null);
259         
260         _securityHandler = securityHandler;
261         
262         if (_securityHandler==null)
263         {
264             if (_sessionHandler!=null)
265                 _sessionHandler.setHandler(_servletHandler);
266             else 
267                 setHandler(_servletHandler);
268         }
269         else
270         {
271             if (_sessionHandler!=null)
272                 _sessionHandler.setHandler(_securityHandler);
273             else 
274                 setHandler(_securityHandler);
275 
276             if (_servletHandler!=null)
277                 _securityHandler.setHandler(_servletHandler);
278         }
279     }
280 
281     /* ------------------------------------------------------------ */
282     /**
283      * @param servletHandler The servletHandler to set.
284      */
285     public void setServletHandler(ServletHandler servletHandler)
286     {
287         if (_servletHandler==servletHandler)
288             return;
289         
290         _servletHandler = servletHandler;
291 
292         if (_securityHandler!=null)
293             _securityHandler.setHandler(_servletHandler);
294         else if (_sessionHandler!=null)
295             _sessionHandler.setHandler(_servletHandler);
296         else 
297             setHandler(_servletHandler);
298         
299     }
300 
301     /* ------------------------------------------------------------ */
302     public class SContext extends ContextHandler.SContext
303     {
304 
305         /* ------------------------------------------------------------ */
306         /* 
307          * @see javax.servlet.ServletContext#getNamedDispatcher(java.lang.String)
308          */
309         public RequestDispatcher getNamedDispatcher(String name)
310         {
311             ContextHandler context=org.mortbay.jetty.servlet.Context.this;
312             if (_servletHandler==null || _servletHandler.getServlet(name)==null)
313                 return null;
314             return new Dispatcher(context, name);
315         }
316 
317         /* ------------------------------------------------------------ */
318         /* 
319          * @see javax.servlet.ServletContext#getRequestDispatcher(java.lang.String)
320          */
321         public RequestDispatcher getRequestDispatcher(String uriInContext)
322         {
323             if (uriInContext == null)
324                 return null;
325 
326             if (!uriInContext.startsWith("/"))
327                 return null;
328             
329             try
330             {
331                 String query=null;
332                 int q=0;
333                 if ((q=uriInContext.indexOf('?'))>0)
334                 {
335                     query=uriInContext.substring(q+1);
336                     uriInContext=uriInContext.substring(0,q);
337                 }
338                 if ((q=uriInContext.indexOf(';'))>0)
339                     uriInContext=uriInContext.substring(0,q);
340 
341                 String pathInContext=URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
342                 String uri=URIUtil.addPaths(getContextPath(), uriInContext);
343                 ContextHandler context=org.mortbay.jetty.servlet.Context.this;
344                 return new Dispatcher(context,uri, pathInContext, query);
345             }
346             catch(Exception e)
347             {
348                 Log.ignore(e);
349             }
350             return null;
351         }
352 
353         /* ------------------------------------------------------------ */
354         /* (non-Javadoc)
355          * @see org.mortbay.jetty.handler.ContextHandler.SContext#addFilter(java.lang.String, java.lang.String, java.lang.String, java.util.Map)
356          */
357         public void addFilter(String filterName, String description, String className, Map<String, String> initParameters)
358         {
359         	if (!isStarting())
360         		throw new IllegalStateException();
361         	
362             ServletHandler handler = Context.this.getServletHandler();
363             FilterHolder holder= handler.newFilterHolder();
364             holder.setClassName(className);
365             holder.setName(filterName);
366             holder.setInitParameters(initParameters);
367             handler.addFilter(holder);
368         }
369 
370         /* ------------------------------------------------------------ */
371         /* (non-Javadoc)
372          * @see org.mortbay.jetty.handler.ContextHandler.SContext#addFilterMapping(java.lang.String, java.lang.String[], java.lang.String[], java.util.EnumSet, boolean)
373          */
374         public void addFilterMapping(String filterName, String[] urlPatterns, String[] servletNames, EnumSet<DispatcherType> dispatcherTypes,
375                 boolean isMatchAfter)
376         {
377         	if (!isStarting())
378         		throw new IllegalStateException();
379             ServletHandler handler = Context.this.getServletHandler();
380             FilterMapping mapping = new FilterMapping();
381             mapping.setFilterName(filterName);
382             mapping.setPathSpecs(urlPatterns);
383             mapping.setServletNames(servletNames);
384             
385             int dispatches=mapping.getDispatches();
386             if (dispatcherTypes.contains(DispatcherType.ERROR)) 
387                 dispatches|=ERROR;
388             if (dispatcherTypes.contains(DispatcherType.FORWARD)) 
389                 dispatches|=FORWARD;
390             if (dispatcherTypes.contains(DispatcherType.INCLUDE)) 
391                 dispatches|=INCLUDE;
392             if (dispatcherTypes.contains(DispatcherType.REQUEST)) 
393                 dispatches|=REQUEST;
394             mapping.setDispatches(dispatches);
395             
396             handler.addFilterMapping(mapping);
397         }
398 
399         /* ------------------------------------------------------------ */
400         /* (non-Javadoc)
401          * @see org.mortbay.jetty.handler.ContextHandler.SContext#addServlet(java.lang.String, java.lang.String, java.lang.String, java.util.Map, int)
402          */
403         public void addServlet(String servletName, String description, String className, Map<String, String> initParameters, int loadOnStartup)
404         {
405         	if (!isStarting())
406         		throw new IllegalStateException();
407             ServletHandler handler = Context.this.getServletHandler();
408             ServletHolder holder= handler.newServletHolder();
409             holder.setClassName(className);
410             holder.setName(servletName);
411             holder.setInitParameters(initParameters);
412             holder.setInitOrder(loadOnStartup);
413             handler.addServlet(holder);
414         }
415 
416         /* ------------------------------------------------------------ */
417         /* (non-Javadoc)
418          * @see org.mortbay.jetty.handler.ContextHandler.SContext#addServletMapping(java.lang.String, java.lang.String[])
419          */
420         public void addServletMapping(String servletName, String[] urlPattern)
421         {
422         	if (!isStarting())
423         		throw new IllegalStateException();
424             ServletHandler handler = Context.this.getServletHandler();
425             ServletMapping mapping = new ServletMapping();
426             mapping.setPathSpecs(urlPattern);
427             handler.addServletMapping(mapping);
428         }   
429     }
430 }