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