View Javadoc

1   //
2   //  ========================================================================
3   //  Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4   //  ------------------------------------------------------------------------
5   //  All rights reserved. This program and the accompanying materials
6   //  are made available under the terms of the Eclipse Public License v1.0
7   //  and Apache License v2.0 which accompanies this distribution.
8   //
9   //      The Eclipse Public License is available at
10  //      http://www.eclipse.org/legal/epl-v10.html
11  //
12  //      The Apache License v2.0 is available at
13  //      http://www.opensource.org/licenses/apache2.0.php
14  //
15  //  You may elect to redistribute this code under either of these licenses.
16  //  ========================================================================
17  //
18  
19  package org.eclipse.jetty.servlet;
20  
21  import java.util.ArrayList;
22  import java.util.Arrays;
23  import java.util.Collection;
24  import java.util.Collections;
25  import java.util.EnumSet;
26  import java.util.EventListener;
27  import java.util.HashMap;
28  import java.util.HashSet;
29  import java.util.List;
30  import java.util.Map;
31  import java.util.Set;
32  
33  import javax.servlet.DispatcherType;
34  import javax.servlet.Filter;
35  import javax.servlet.FilterRegistration;
36  import javax.servlet.RequestDispatcher;
37  import javax.servlet.Servlet;
38  import javax.servlet.ServletContainerInitializer;
39  import javax.servlet.ServletContext;
40  import javax.servlet.ServletContextEvent;
41  import javax.servlet.ServletContextListener;
42  import javax.servlet.ServletException;
43  import javax.servlet.ServletRegistration;
44  import javax.servlet.ServletSecurityElement;
45  import javax.servlet.SessionCookieConfig;
46  import javax.servlet.SessionTrackingMode;
47  import javax.servlet.descriptor.JspConfigDescriptor;
48  import javax.servlet.descriptor.JspPropertyGroupDescriptor;
49  import javax.servlet.descriptor.TaglibDescriptor;
50  
51  import org.eclipse.jetty.security.ConstraintAware;
52  import org.eclipse.jetty.security.ConstraintMapping;
53  import org.eclipse.jetty.security.ConstraintSecurityHandler;
54  import org.eclipse.jetty.security.SecurityHandler;
55  import org.eclipse.jetty.server.Dispatcher;
56  import org.eclipse.jetty.server.Handler;
57  import org.eclipse.jetty.server.HandlerContainer;
58  import org.eclipse.jetty.server.handler.ContextHandler;
59  import org.eclipse.jetty.server.handler.ErrorHandler;
60  import org.eclipse.jetty.server.handler.HandlerCollection;
61  import org.eclipse.jetty.server.handler.HandlerWrapper;
62  import org.eclipse.jetty.server.session.SessionHandler;
63  import org.eclipse.jetty.servlet.BaseHolder.Source;
64  import org.eclipse.jetty.util.annotation.ManagedAttribute;
65  import org.eclipse.jetty.util.annotation.ManagedObject;
66  import org.eclipse.jetty.util.component.LifeCycle;
67  
68  
69  /* ------------------------------------------------------------ */
70  /** Servlet Context.
71   * This extension to the ContextHandler allows for
72   * simple construction of a context with ServletHandler and optionally
73   * session and security handlers, et.<pre>
74   *   new ServletContext("/context",Context.SESSIONS|Context.NO_SECURITY);
75   * </pre>
76   * <p/>
77   * This class should have been called ServletContext, but this would have
78   * cause confusion with {@link ServletContext}.
79   */
80  @ManagedObject("Servlet Context Handler")
81  public class ServletContextHandler extends ContextHandler
82  {
83      public final static int SESSIONS=1;
84      public final static int SECURITY=2;
85      public final static int NO_SESSIONS=0;
86      public final static int NO_SECURITY=0;
87      
88      public interface ServletContainerInitializerCaller extends LifeCycle {};
89  
90      protected final List<Decorator> _decorators= new ArrayList<>();
91      protected Class<? extends SecurityHandler> _defaultSecurityHandlerClass=org.eclipse.jetty.security.ConstraintSecurityHandler.class;
92      protected SessionHandler _sessionHandler;
93      protected SecurityHandler _securityHandler;
94      protected ServletHandler _servletHandler;
95      protected int _options;
96      protected JspConfigDescriptor _jspConfig;
97  
98      /* ------------------------------------------------------------ */
99      public ServletContextHandler()
100     {
101         this(null,null,null,null,null);
102     }
103 
104     /* ------------------------------------------------------------ */
105     public ServletContextHandler(int options)
106     {
107         this(null,null,options);
108     }
109 
110     /* ------------------------------------------------------------ */
111     public ServletContextHandler(HandlerContainer parent, String contextPath)
112     {
113         this(parent,contextPath,null,null,null,null);
114     }
115 
116     /* ------------------------------------------------------------ */
117     public ServletContextHandler(HandlerContainer parent, String contextPath, int options)
118     {
119         this(parent,contextPath,null,null,null,null,options);
120     }
121 
122     /* ------------------------------------------------------------ */
123     public ServletContextHandler(HandlerContainer parent, String contextPath, boolean sessions, boolean security)
124     {
125         this(parent,contextPath,(sessions?SESSIONS:0)|(security?SECURITY:0));
126     }
127 
128     /* ------------------------------------------------------------ */
129     public ServletContextHandler(HandlerContainer parent, SessionHandler sessionHandler, SecurityHandler securityHandler, ServletHandler servletHandler, ErrorHandler errorHandler)
130     {
131         this(parent,null,sessionHandler,securityHandler,servletHandler,errorHandler);
132     }
133 
134     /* ------------------------------------------------------------ */
135     public ServletContextHandler(HandlerContainer parent, String contextPath, SessionHandler sessionHandler, SecurityHandler securityHandler, ServletHandler servletHandler, ErrorHandler errorHandler)
136     {
137         this(parent,contextPath,sessionHandler,securityHandler,servletHandler,errorHandler,0);
138     }
139     
140     public ServletContextHandler(HandlerContainer parent, String contextPath, SessionHandler sessionHandler, SecurityHandler securityHandler, ServletHandler servletHandler, ErrorHandler errorHandler,int options)
141     {
142         super((ContextHandler.Context)null);
143         _options=options;
144         _scontext = new Context();
145         _sessionHandler = sessionHandler;
146         _securityHandler = securityHandler;
147         _servletHandler = servletHandler;
148 
149         if (contextPath!=null)
150             setContextPath(contextPath);
151         
152         if (parent instanceof HandlerWrapper)
153             ((HandlerWrapper)parent).setHandler(this);
154         else if (parent instanceof HandlerCollection)
155             ((HandlerCollection)parent).addHandler(this);
156         
157         
158         // Link the handlers
159         relinkHandlers();
160         
161         if (errorHandler!=null)
162             setErrorHandler(errorHandler);
163 
164     }
165     
166     /* ------------------------------------------------------------ */
167     private void relinkHandlers()
168     {
169         HandlerWrapper handler=this;
170         
171         // Skip any injected handlers
172         while (handler.getHandler() instanceof HandlerWrapper)
173         {
174             HandlerWrapper wrapper = (HandlerWrapper)handler.getHandler();
175             if (wrapper instanceof SessionHandler ||
176                 wrapper instanceof SecurityHandler ||
177                 wrapper instanceof ServletHandler)
178                 break;
179             handler=wrapper;
180         }
181         
182         if (getSessionHandler()!=null)
183         {
184             if (handler==this)
185                 super.setHandler(_sessionHandler);
186             else
187                 handler.setHandler(_sessionHandler);
188             handler=_sessionHandler;
189         }
190 
191         if (getSecurityHandler()!=null)
192         {
193             if (handler==this)
194                 super.setHandler(_securityHandler);
195             else
196                 handler.setHandler(_securityHandler);
197             handler=_securityHandler;
198         }
199 
200         if (getServletHandler()!=null)
201         {
202             if (handler==this)
203                 super.setHandler(_servletHandler);
204             else
205                 handler.setHandler(_servletHandler);
206             handler=_servletHandler;
207         } 
208     }
209     
210     /* ------------------------------------------------------------ */
211     /**
212      * @see org.eclipse.jetty.server.handler.ContextHandler#doStop()
213      */
214     @Override
215     protected void doStop() throws Exception
216     {
217         super.doStop();
218         if (_decorators != null)
219             _decorators.clear();
220     }
221 
222     /* ------------------------------------------------------------ */
223     /** Get the defaultSecurityHandlerClass.
224      * @return the defaultSecurityHandlerClass
225      */
226     public Class<? extends SecurityHandler> getDefaultSecurityHandlerClass()
227     {
228         return _defaultSecurityHandlerClass;
229     }
230 
231     /* ------------------------------------------------------------ */
232     /** Set the defaultSecurityHandlerClass.
233      * @param defaultSecurityHandlerClass the defaultSecurityHandlerClass to set
234      */
235     public void setDefaultSecurityHandlerClass(Class<? extends SecurityHandler> defaultSecurityHandlerClass)
236     {
237         _defaultSecurityHandlerClass = defaultSecurityHandlerClass;
238     }
239 
240     /* ------------------------------------------------------------ */
241     protected SessionHandler newSessionHandler()
242     {
243         return new SessionHandler();
244     }
245 
246     /* ------------------------------------------------------------ */
247     protected SecurityHandler newSecurityHandler()
248     {
249         try
250         {
251             return (SecurityHandler)_defaultSecurityHandlerClass.newInstance();
252         }
253         catch(Exception e)
254         {
255             throw new IllegalStateException(e);
256         }
257     }
258 
259     /* ------------------------------------------------------------ */
260     protected ServletHandler newServletHandler()
261     {
262         return new ServletHandler();
263     }
264 
265     /* ------------------------------------------------------------ */
266     /**
267      * Finish constructing handlers and link them together.
268      *
269      * @see org.eclipse.jetty.server.handler.ContextHandler#startContext()
270      */
271     @Override
272     protected void startContext() throws Exception
273     {
274         ServletContainerInitializerCaller sciBean = getBean(ServletContainerInitializerCaller.class);
275         if (sciBean!=null)
276             sciBean.start();
277 
278         if (_servletHandler != null)
279         {
280             //Call decorators on all holders, and also on any EventListeners before
281             //decorators are called on any other classes (like servlets and filters)
282             for (int i=_decorators.size()-1;i>=0; i--)
283             {
284                 Decorator decorator = _decorators.get(i);
285                 //Do any decorations on the ListenerHolders AND the listener instances first up
286                 if (_servletHandler.getListeners()!=null)
287                 {
288                     for (ListenerHolder holder:_servletHandler.getListeners())
289                     {             
290                         decorator.decorate(holder.getListener());
291                     }
292                 }
293     	    }
294     	}
295     	
296         super.startContext();
297 
298         // OK to Initialize servlet handler now that all relevant object trees have been started
299         if (_servletHandler != null)
300             _servletHandler.initialize();
301     }
302 
303     /* ------------------------------------------------------------ */
304     /**
305      * @return Returns the securityHandler.
306      */
307     @ManagedAttribute(value="context security handler", readonly=true)
308     public SecurityHandler getSecurityHandler()
309     {
310         if (_securityHandler==null && (_options&SECURITY)!=0 && !isStarted())
311             _securityHandler=newSecurityHandler();
312 
313         return _securityHandler;
314     }
315 
316     /* ------------------------------------------------------------ */
317     /**
318      * @return Returns the servletHandler.
319      */
320     @ManagedAttribute(value="context servlet handler", readonly=true)
321     public ServletHandler getServletHandler()
322     {
323         if (_servletHandler==null && !isStarted())
324             _servletHandler=newServletHandler();
325         return _servletHandler;
326     }
327 
328     /* ------------------------------------------------------------ */
329     /**
330      * @return Returns the sessionHandler.
331      */
332     @ManagedAttribute(value="context session handler", readonly=true)
333     public SessionHandler getSessionHandler()
334     {
335         if (_sessionHandler==null && (_options&SESSIONS)!=0 && !isStarted())
336             _sessionHandler=newSessionHandler();
337         return _sessionHandler;
338     }
339 
340     /* ------------------------------------------------------------ */
341     /** conveniance method to add a servlet.
342      */
343     public ServletHolder addServlet(String className,String pathSpec)
344     {
345         return getServletHandler().addServletWithMapping(className, pathSpec);
346     }
347 
348     /* ------------------------------------------------------------ */
349     /** conveniance method to add a servlet.
350      */
351     public ServletHolder addServlet(Class<? extends Servlet> servlet,String pathSpec)
352     {
353         return getServletHandler().addServletWithMapping(servlet.getName(), pathSpec);
354     }
355 
356     /* ------------------------------------------------------------ */
357     /** conveniance method to add a servlet.
358      */
359     public void addServlet(ServletHolder servlet,String pathSpec)
360     {
361         getServletHandler().addServletWithMapping(servlet, pathSpec);
362     }
363 
364     /* ------------------------------------------------------------ */
365     /** conveniance method to add a filter
366      */
367     public void addFilter(FilterHolder holder,String pathSpec,EnumSet<DispatcherType> dispatches)
368     {
369         getServletHandler().addFilterWithMapping(holder,pathSpec,dispatches);
370     }
371 
372     /* ------------------------------------------------------------ */
373     /** convenience method to add a filter
374      */
375     public FilterHolder addFilter(Class<? extends Filter> filterClass,String pathSpec,EnumSet<DispatcherType> dispatches)
376     {
377         return getServletHandler().addFilterWithMapping(filterClass,pathSpec,dispatches);
378     }
379 
380     /* ------------------------------------------------------------ */
381     /** convenience method to add a filter
382      */
383     public FilterHolder addFilter(String filterClass,String pathSpec,EnumSet<DispatcherType> dispatches)
384     {
385         return getServletHandler().addFilterWithMapping(filterClass,pathSpec,dispatches);
386     }
387 
388     /**
389      * notification that a ServletRegistration has been created so we can track the annotations
390      * @param holder new holder created through the api.
391      * @return the ServletRegistration.Dynamic
392      */
393     protected ServletRegistration.Dynamic dynamicHolderAdded(ServletHolder holder) {
394         return holder.getRegistration();
395     }
396 
397     /**
398      * delegate for ServletContext.declareRole method
399      * @param roleNames role names to add
400      */
401     protected void addRoles(String... roleNames) {
402         //Get a reference to the SecurityHandler, which must be ConstraintAware
403         if (_securityHandler != null && _securityHandler instanceof ConstraintAware)
404         {
405             HashSet<String> union = new HashSet<String>();
406             Set<String> existing = ((ConstraintAware)_securityHandler).getRoles();
407             if (existing != null)
408                 union.addAll(existing);
409             union.addAll(Arrays.asList(roleNames));
410             ((ConstraintSecurityHandler)_securityHandler).setRoles(union);
411         }
412     }
413 
414     /**
415      * Delegate for ServletRegistration.Dynamic.setServletSecurity method
416      * @param registration ServletRegistration.Dynamic instance that setServletSecurity was called on
417      * @param servletSecurityElement new security info
418      * @return the set of exact URL mappings currently associated with the registration that are also present in the web.xml
419      * security constraints and thus will be unaffected by this call.
420      */
421     public Set<String> setServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement)
422     {
423         //Default implementation is to just accept them all. If using a webapp, then this behaviour is overridden in WebAppContext.setServletSecurity       
424         Collection<String> pathSpecs = registration.getMappings();
425         if (pathSpecs != null)
426         {
427             for (String pathSpec:pathSpecs)
428             {
429                 List<ConstraintMapping> mappings = ConstraintSecurityHandler.createConstraintsWithMappingsForPath(registration.getName(), pathSpec, servletSecurityElement);
430                 for (ConstraintMapping m:mappings)
431                     ((ConstraintAware)getSecurityHandler()).addConstraintMapping(m);
432             }
433         }
434         return Collections.emptySet();
435     }
436 
437     @Override
438     public void callContextInitialized(ServletContextListener l, ServletContextEvent e)
439     {
440         try
441         {
442             //toggle state of the dynamic API so that the listener cannot use it
443             if(isProgrammaticListener(l))
444                 this.getServletContext().setEnabled(false);
445 
446             super.callContextInitialized(l, e);
447         }
448         finally
449         {
450             //untoggle the state of the dynamic API
451             this.getServletContext().setEnabled(true);
452         }
453     }
454 
455 
456     @Override
457     public void callContextDestroyed(ServletContextListener l, ServletContextEvent e)
458     {
459         super.callContextDestroyed(l, e);
460     }
461 
462     /* ------------------------------------------------------------ */
463     /**
464      * @param sessionHandler The sessionHandler to set.
465      */
466     public void setSessionHandler(SessionHandler sessionHandler)
467     {
468         if (isStarted())
469             throw new IllegalStateException("STARTED");
470 
471         if (_sessionHandler!=null)
472             _sessionHandler.setHandler(null);
473 
474         _sessionHandler = sessionHandler;
475         relinkHandlers();
476     }
477 
478     /* ------------------------------------------------------------ */
479     /**
480      * @param securityHandler The {@link SecurityHandler} to set on this context.
481      */
482     public void setSecurityHandler(SecurityHandler securityHandler)
483     {
484         if (isStarted())
485             throw new IllegalStateException("STARTED");
486 
487         if (_securityHandler!=null)
488             _securityHandler.setHandler(null);
489         _securityHandler = securityHandler;
490         relinkHandlers();
491     }
492 
493     /* ------------------------------------------------------------ */
494     /**
495      * @param servletHandler The servletHandler to set.
496      */
497     public void setServletHandler(ServletHandler servletHandler)
498     {
499         if (isStarted())
500             throw new IllegalStateException("STARTED");
501 
502         Handler next=null;
503         if (_servletHandler!=null)
504         {
505             next=_servletHandler.getHandler();
506             _servletHandler.setHandler(null);
507         }
508         _servletHandler = servletHandler;
509         relinkHandlers();
510         _servletHandler.setHandler(next);
511     }
512     
513     /* ------------------------------------------------------------ */
514     @Override
515     public void setHandler(Handler handler)
516     {
517         if (handler instanceof ServletHandler)
518             setServletHandler((ServletHandler) handler);
519         else if (handler instanceof SessionHandler)
520             setSessionHandler((SessionHandler) handler);
521         else if (handler instanceof SecurityHandler)
522             setSecurityHandler((SecurityHandler)handler);
523         else if (handler == null || handler instanceof HandlerWrapper)
524         {
525             super.setHandler(handler);
526             relinkHandlers();
527         }
528         else
529             throw new IllegalArgumentException();
530     }
531     
532     
533     /* ------------------------------------------------------------ */
534     /**
535      * Insert a HandlerWrapper before the first Session,Security or ServletHandler
536      * but after any other HandlerWrappers.
537      */
538     public void insertHandler(HandlerWrapper handler)
539     {
540         HandlerWrapper h=this;
541         
542         // Skip any injected handlers
543         while (h.getHandler() instanceof HandlerWrapper)
544         {
545             HandlerWrapper wrapper = (HandlerWrapper)h.getHandler();
546             if (wrapper instanceof SessionHandler ||
547                 wrapper instanceof SecurityHandler ||
548                 wrapper instanceof ServletHandler)
549                 break;
550             h=wrapper;
551         }
552         
553         h.setHandler(handler);
554         relinkHandlers();
555     }
556 
557     /* ------------------------------------------------------------ */
558     /**
559      * @return The decorator list used to resource inject new Filters, Servlets and EventListeners
560      */
561     public List<Decorator> getDecorators()
562     {
563         return Collections.unmodifiableList(_decorators);
564     }
565 
566     /* ------------------------------------------------------------ */
567     /**
568      * @param decorators The lis of {@link Decorator}s
569      */
570     public void setDecorators(List<Decorator> decorators)
571     {
572         _decorators.clear();
573         _decorators.addAll(decorators);
574     }
575 
576     /* ------------------------------------------------------------ */
577     /**
578      * @param decorator The decorator to add
579      */
580     public void addDecorator(Decorator decorator)
581     {
582         _decorators.add(decorator);
583     }
584 
585     /* ------------------------------------------------------------ */
586     void destroyServlet(Servlet servlet)
587     {
588         for (Decorator decorator : _decorators)
589             decorator.destroy(servlet);
590     }
591 
592     /* ------------------------------------------------------------ */
593     void destroyFilter(Filter filter)
594     {
595         for (Decorator decorator : _decorators)
596             decorator.destroy(filter);
597     }
598 
599     /* ------------------------------------------------------------ */
600     public static class JspPropertyGroup implements JspPropertyGroupDescriptor
601     {
602         private List<String> _urlPatterns = new ArrayList<String>();
603         private String _elIgnored;
604         private String _pageEncoding;
605         private String _scriptingInvalid;
606         private String _isXml;
607         private List<String> _includePreludes = new ArrayList<String>();
608         private List<String> _includeCodas = new ArrayList<String>();
609         private String _deferredSyntaxAllowedAsLiteral;
610         private String _trimDirectiveWhitespaces;
611         private String _defaultContentType;
612         private String _buffer;
613         private String _errorOnUndeclaredNamespace;
614 
615 
616 
617         /**
618          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getUrlPatterns()
619          */
620         public Collection<String> getUrlPatterns()
621         {
622             return new ArrayList<String>(_urlPatterns); // spec says must be a copy
623         }
624 
625         public void addUrlPattern (String s)
626         {
627             if (!_urlPatterns.contains(s))
628                 _urlPatterns.add(s);
629         }
630 
631         /**
632          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getElIgnored()
633          */
634         public String getElIgnored()
635         {
636             return _elIgnored;
637         }
638 
639         public void setElIgnored (String s)
640         {
641             _elIgnored = s;
642         }
643 
644         /**
645          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getPageEncoding()
646          */
647         public String getPageEncoding()
648         {
649             return _pageEncoding;
650         }
651 
652         public void setPageEncoding(String pageEncoding)
653         {
654             _pageEncoding = pageEncoding;
655         }
656 
657         public void setScriptingInvalid(String scriptingInvalid)
658         {
659             _scriptingInvalid = scriptingInvalid;
660         }
661 
662         public void setIsXml(String isXml)
663         {
664             _isXml = isXml;
665         }
666 
667         public void setDeferredSyntaxAllowedAsLiteral(String deferredSyntaxAllowedAsLiteral)
668         {
669             _deferredSyntaxAllowedAsLiteral = deferredSyntaxAllowedAsLiteral;
670         }
671 
672         public void setTrimDirectiveWhitespaces(String trimDirectiveWhitespaces)
673         {
674             _trimDirectiveWhitespaces = trimDirectiveWhitespaces;
675         }
676 
677         public void setDefaultContentType(String defaultContentType)
678         {
679             _defaultContentType = defaultContentType;
680         }
681 
682         public void setBuffer(String buffer)
683         {
684             _buffer = buffer;
685         }
686 
687         public void setErrorOnUndeclaredNamespace(String errorOnUndeclaredNamespace)
688         {
689             _errorOnUndeclaredNamespace = errorOnUndeclaredNamespace;
690         }
691 
692         /**
693          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getScriptingInvalid()
694          */
695         public String getScriptingInvalid()
696         {
697             return _scriptingInvalid;
698         }
699 
700         /**
701          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getIsXml()
702          */
703         public String getIsXml()
704         {
705             return _isXml;
706         }
707 
708         /**
709          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getIncludePreludes()
710          */
711         public Collection<String> getIncludePreludes()
712         {
713             return new ArrayList<String>(_includePreludes); //must be a copy
714         }
715 
716         public void addIncludePrelude(String prelude)
717         {
718             if (!_includePreludes.contains(prelude))
719                 _includePreludes.add(prelude);
720         }
721 
722         /**
723          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getIncludeCodas()
724          */
725         public Collection<String> getIncludeCodas()
726         {
727             return new ArrayList<String>(_includeCodas); //must be a copy
728         }
729 
730         public void addIncludeCoda (String coda)
731         {
732             if (!_includeCodas.contains(coda))
733                 _includeCodas.add(coda);
734         }
735 
736         /**
737          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getDeferredSyntaxAllowedAsLiteral()
738          */
739         public String getDeferredSyntaxAllowedAsLiteral()
740         {
741             return _deferredSyntaxAllowedAsLiteral;
742         }
743 
744         /**
745          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getTrimDirectiveWhitespaces()
746          */
747         public String getTrimDirectiveWhitespaces()
748         {
749             return _trimDirectiveWhitespaces;
750         }
751 
752         /**
753          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getDefaultContentType()
754          */
755         public String getDefaultContentType()
756         {
757             return _defaultContentType;
758         }
759 
760         /**
761          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getBuffer()
762          */
763         public String getBuffer()
764         {
765             return _buffer;
766         }
767 
768         /**
769          * @see javax.servlet.descriptor.JspPropertyGroupDescriptor#getErrorOnUndeclaredNamespace()
770          */
771         public String getErrorOnUndeclaredNamespace()
772         {
773             return _errorOnUndeclaredNamespace;
774         }
775 
776         public String toString ()
777         {
778             StringBuffer sb = new StringBuffer();
779             sb.append("JspPropertyGroupDescriptor:");
780             sb.append(" el-ignored="+_elIgnored);
781             sb.append(" is-xml="+_isXml);
782             sb.append(" page-encoding="+_pageEncoding);
783             sb.append(" scripting-invalid="+_scriptingInvalid);
784             sb.append(" deferred-syntax-allowed-as-literal="+_deferredSyntaxAllowedAsLiteral);
785             sb.append(" trim-directive-whitespaces"+_trimDirectiveWhitespaces);
786             sb.append(" default-content-type="+_defaultContentType);
787             sb.append(" buffer="+_buffer);
788             sb.append(" error-on-undeclared-namespace="+_errorOnUndeclaredNamespace);
789             for (String prelude:_includePreludes)
790                 sb.append(" include-prelude="+prelude);
791             for (String coda:_includeCodas)
792                 sb.append(" include-coda="+coda);
793             return sb.toString();
794         }
795     }
796 
797     /* ------------------------------------------------------------ */
798     public static class TagLib implements TaglibDescriptor
799     {
800         private String _uri;
801         private String _location;
802 
803         /**
804          * @see javax.servlet.descriptor.TaglibDescriptor#getTaglibURI()
805          */
806         public String getTaglibURI()
807         {
808            return _uri;
809         }
810 
811         public void setTaglibURI(String uri)
812         {
813             _uri = uri;
814         }
815 
816         /**
817          * @see javax.servlet.descriptor.TaglibDescriptor#getTaglibLocation()
818          */
819         public String getTaglibLocation()
820         {
821             return _location;
822         }
823 
824         public void setTaglibLocation(String location)
825         {
826             _location = location;
827         }
828 
829         public String toString()
830         {
831             return ("TagLibDescriptor: taglib-uri="+_uri+" location="+_location);
832         }
833     }
834 
835 
836     /* ------------------------------------------------------------ */
837     public static class JspConfig implements JspConfigDescriptor
838     {
839         private List<TaglibDescriptor> _taglibs = new ArrayList<TaglibDescriptor>();
840         private List<JspPropertyGroupDescriptor> _jspPropertyGroups = new ArrayList<JspPropertyGroupDescriptor>();
841 
842         public JspConfig() {}
843 
844         /**
845          * @see javax.servlet.descriptor.JspConfigDescriptor#getTaglibs()
846          */
847         public Collection<TaglibDescriptor> getTaglibs()
848         {
849             return new ArrayList<TaglibDescriptor>(_taglibs);
850         }
851 
852         public void addTaglibDescriptor (TaglibDescriptor d)
853         {
854             _taglibs.add(d);
855         }
856 
857         /**
858          * @see javax.servlet.descriptor.JspConfigDescriptor#getJspPropertyGroups()
859          */
860         public Collection<JspPropertyGroupDescriptor> getJspPropertyGroups()
861         {
862            return new ArrayList<JspPropertyGroupDescriptor>(_jspPropertyGroups);
863         }
864 
865         public void addJspPropertyGroup(JspPropertyGroupDescriptor g)
866         {
867             _jspPropertyGroups.add(g);
868         }
869 
870         public String toString()
871         {
872             StringBuffer sb = new StringBuffer();
873             sb.append("JspConfigDescriptor: \n");
874             for (TaglibDescriptor taglib:_taglibs)
875                 sb.append(taglib+"\n");
876             for (JspPropertyGroupDescriptor jpg:_jspPropertyGroups)
877                 sb.append(jpg+"\n");
878             return sb.toString();
879         }
880     }
881 
882 
883     /* ------------------------------------------------------------ */
884     public class Context extends ContextHandler.Context
885     {
886         /* ------------------------------------------------------------ */
887         /*
888          * @see javax.servlet.ServletContext#getNamedDispatcher(java.lang.String)
889          */
890         @Override
891         public RequestDispatcher getNamedDispatcher(String name)
892         {
893             ContextHandler context=org.eclipse.jetty.servlet.ServletContextHandler.this;
894             if (_servletHandler==null)
895                 return null;
896             ServletHolder holder = _servletHandler.getServlet(name);
897             if (holder==null || !holder.isEnabled())
898                 return null;
899             return new Dispatcher(context, name);
900         }
901 
902         /* ------------------------------------------------------------ */
903         /**
904          * @since servlet-api-3.0
905          */
906         @Override
907         public FilterRegistration.Dynamic addFilter(String filterName, Class<? extends Filter> filterClass)
908         {
909             if (isStarted())
910                 throw new IllegalStateException();
911             
912             if (filterName == null || "".equals(filterName.trim()))
913                 throw new IllegalStateException("Missing filter name");
914 
915             if (!_enabled)
916                 throw new UnsupportedOperationException();
917 
918             final ServletHandler handler = ServletContextHandler.this.getServletHandler();
919             FilterHolder holder = handler.getFilter(filterName);
920             if (holder == null)
921             {
922                 //new filter
923                 holder = handler.newFilterHolder(Source.JAVAX_API);
924                 holder.setName(filterName);
925                 holder.setHeldClass(filterClass);
926                 handler.addFilter(holder);
927                 return holder.getRegistration();
928             }
929             if (holder.getClassName()==null && holder.getHeldClass()==null)
930             {
931                 //preliminary filter registration completion
932                 holder.setHeldClass(filterClass);
933                 return holder.getRegistration();
934             }
935             else
936                 return null; //existing filter
937         }
938 
939         /* ------------------------------------------------------------ */
940         /**
941          * @since servlet-api-3.0
942          */
943         @Override
944         public FilterRegistration.Dynamic addFilter(String filterName, String className)
945         {
946             if (isStarted())
947                 throw new IllegalStateException();
948             
949             if (filterName == null || "".equals(filterName.trim()))
950                 throw new IllegalStateException("Missing filter name");
951 
952             if (!_enabled)
953                 throw new UnsupportedOperationException();
954 
955             final ServletHandler handler = ServletContextHandler.this.getServletHandler();
956             FilterHolder holder = handler.getFilter(filterName);
957             if (holder == null)
958             {
959                 //new filter
960                 holder = handler.newFilterHolder(Source.JAVAX_API);
961                 holder.setName(filterName);
962                 holder.setClassName(className);
963                 handler.addFilter(holder);
964                 return holder.getRegistration();
965             }
966             if (holder.getClassName()==null && holder.getHeldClass()==null)
967             {
968                 //preliminary filter registration completion
969                 holder.setClassName(className);
970                 return holder.getRegistration();
971             }
972             else
973                 return null; //existing filter
974         }
975 
976 
977         /* ------------------------------------------------------------ */
978         /**
979          * @since servlet-api-3.0
980          */
981         @Override
982         public FilterRegistration.Dynamic addFilter(String filterName, Filter filter)
983         {
984             if (isStarted())
985                 throw new IllegalStateException();
986 
987             if (filterName == null || "".equals(filterName.trim()))
988                 throw new IllegalStateException("Missing filter name");
989             
990             if (!_enabled)
991                 throw new UnsupportedOperationException();
992 
993             final ServletHandler handler = ServletContextHandler.this.getServletHandler();
994             FilterHolder holder = handler.getFilter(filterName);
995             if (holder == null)
996             {
997                 //new filter
998                 holder = handler.newFilterHolder(Source.JAVAX_API);
999                 holder.setName(filterName);
1000                 holder.setFilter(filter);
1001                 handler.addFilter(holder);
1002                 return holder.getRegistration();
1003             }
1004 
1005             if (holder.getClassName()==null && holder.getHeldClass()==null)
1006             {
1007                 //preliminary filter registration completion
1008                 holder.setFilter(filter);
1009                 return holder.getRegistration();
1010             }
1011             else
1012                 return null; //existing filter
1013         }
1014 
1015         /* ------------------------------------------------------------ */
1016         /**
1017          * @since servlet-api-3.0
1018          */
1019         @Override
1020         public ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass)
1021         {
1022             if (!isStarting())
1023                 throw new IllegalStateException();
1024 
1025             if (servletName == null || "".equals(servletName.trim()))
1026                 throw new IllegalStateException("Missing servlet name");
1027             
1028             if (!_enabled)
1029                 throw new UnsupportedOperationException();
1030 
1031             final ServletHandler handler = ServletContextHandler.this.getServletHandler();
1032             ServletHolder holder = handler.getServlet(servletName);
1033             if (holder == null)
1034             {
1035                 //new servlet
1036                 holder = handler.newServletHolder(Source.JAVAX_API);
1037                 holder.setName(servletName);
1038                 holder.setHeldClass(servletClass);
1039                 handler.addServlet(holder);
1040                 return dynamicHolderAdded(holder);
1041             }
1042 
1043             //complete a partial registration
1044             if (holder.getClassName()==null && holder.getHeldClass()==null)
1045             {
1046                 holder.setHeldClass(servletClass);
1047                 return holder.getRegistration();
1048             }
1049             else
1050                 return null; //existing completed registration for servlet name
1051         }
1052 
1053         /* ------------------------------------------------------------ */
1054         /**
1055          * @since servlet-api-3.0
1056          */
1057         @Override
1058         public ServletRegistration.Dynamic addServlet(String servletName, String className)
1059         {
1060             if (!isStarting())
1061                 throw new IllegalStateException();
1062 
1063             if (servletName == null || "".equals(servletName.trim()))
1064                 throw new IllegalStateException("Missing servlet name");
1065             
1066             if (!_enabled)
1067                 throw new UnsupportedOperationException();
1068 
1069 
1070             final ServletHandler handler = ServletContextHandler.this.getServletHandler();
1071             ServletHolder holder = handler.getServlet(servletName);
1072             if (holder == null)
1073             {
1074                 //new servlet
1075                 holder = handler.newServletHolder(Source.JAVAX_API);
1076                 holder.setName(servletName);
1077                 holder.setClassName(className);
1078                 handler.addServlet(holder);
1079                 return dynamicHolderAdded(holder);
1080             }
1081 
1082             //complete a partial registration
1083             if (holder.getClassName()==null && holder.getHeldClass()==null)
1084             {
1085                 holder.setClassName(className);
1086                 return holder.getRegistration();
1087             }
1088             else
1089                 return null; //existing completed registration for servlet name
1090         }
1091 
1092         /* ------------------------------------------------------------ */
1093         /**
1094          * @since servlet-api-3.0
1095          */
1096         @Override
1097         public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
1098         {
1099             if (!isStarting())
1100                 throw new IllegalStateException();
1101             
1102             if (servletName == null || "".equals(servletName.trim()))
1103                 throw new IllegalStateException("Missing servlet name");
1104             
1105             if (!_enabled)
1106                 throw new UnsupportedOperationException();
1107 
1108             final ServletHandler handler = ServletContextHandler.this.getServletHandler();
1109             ServletHolder holder = handler.getServlet(servletName);
1110             if (holder == null)
1111             {
1112                 holder = handler.newServletHolder(Source.JAVAX_API);
1113                 holder.setName(servletName);
1114                 holder.setServlet(servlet);
1115                 handler.addServlet(holder);
1116                 return dynamicHolderAdded(holder);
1117             }
1118 
1119             //complete a partial registration
1120             if (holder.getClassName()==null && holder.getHeldClass()==null)
1121             {
1122                 holder.setServlet(servlet);
1123                 return holder.getRegistration();
1124             }
1125             else
1126                 return null; //existing completed registration for servlet name
1127         }
1128 
1129         /* ------------------------------------------------------------ */
1130         @Override
1131         public boolean setInitParameter(String name, String value)
1132         {
1133             if (!isStarting())
1134                 throw new IllegalStateException();
1135 
1136             if (!_enabled)
1137                 throw new UnsupportedOperationException();
1138 
1139             return super.setInitParameter(name,value);
1140         }
1141 
1142         /* ------------------------------------------------------------ */
1143         @Override
1144         public <T extends Filter> T createFilter(Class<T> c) throws ServletException
1145         {
1146             try
1147             {
1148                 T f = createInstance(c);
1149                 for (int i=_decorators.size()-1; i>=0; i--)
1150                 {
1151                     Decorator decorator = _decorators.get(i);
1152                     f=decorator.decorate(f);
1153                 }
1154                 return f;
1155             }
1156             catch (Exception e)
1157             {
1158                 throw new ServletException(e);
1159             }
1160         }
1161 
1162         /* ------------------------------------------------------------ */
1163         @Override
1164         public <T extends Servlet> T createServlet(Class<T> c) throws ServletException
1165         {
1166             try
1167             {
1168                 T s = createInstance(c);
1169                 for (int i=_decorators.size()-1; i>=0; i--)
1170                 {
1171                     Decorator decorator = _decorators.get(i);
1172                     s=decorator.decorate(s);
1173                 }
1174                 return s;
1175             }
1176             catch (Exception e)
1177             {
1178                 throw new ServletException(e);
1179             }
1180         }
1181         
1182 
1183         @Override
1184         public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
1185         {
1186             if (_sessionHandler!=null)
1187                 return _sessionHandler.getSessionManager().getDefaultSessionTrackingModes();
1188             return null;
1189         }
1190 
1191         @Override
1192         public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
1193         {
1194             if (_sessionHandler!=null)
1195                 return _sessionHandler.getSessionManager().getEffectiveSessionTrackingModes();
1196             return null;
1197         }
1198 
1199         @Override
1200         public FilterRegistration getFilterRegistration(String filterName)
1201         {
1202             if (!_enabled)
1203                 throw new UnsupportedOperationException();
1204 
1205             final FilterHolder holder=ServletContextHandler.this.getServletHandler().getFilter(filterName);
1206             return (holder==null)?null:holder.getRegistration();
1207         }
1208 
1209         @Override
1210         public Map<String, ? extends FilterRegistration> getFilterRegistrations()
1211         {
1212             if (!_enabled)
1213                 throw new UnsupportedOperationException();
1214 
1215             HashMap<String, FilterRegistration> registrations = new HashMap<String, FilterRegistration>();
1216             ServletHandler handler=ServletContextHandler.this.getServletHandler();
1217             FilterHolder[] holders=handler.getFilters();
1218             if (holders!=null)
1219             {
1220                 for (FilterHolder holder : holders)
1221                     registrations.put(holder.getName(),holder.getRegistration());
1222             }
1223             return registrations;
1224         }
1225 
1226         @Override
1227         public ServletRegistration getServletRegistration(String servletName)
1228         {
1229             if (!_enabled)
1230                 throw new UnsupportedOperationException();
1231 
1232             final ServletHolder holder=ServletContextHandler.this.getServletHandler().getServlet(servletName);
1233             return (holder==null)?null:holder.getRegistration();
1234         }
1235 
1236         @Override
1237         public Map<String, ? extends ServletRegistration> getServletRegistrations()
1238         {
1239             if (!_enabled)
1240                 throw new UnsupportedOperationException();
1241 
1242             HashMap<String, ServletRegistration> registrations = new HashMap<String, ServletRegistration>();
1243             ServletHandler handler=ServletContextHandler.this.getServletHandler();
1244             ServletHolder[] holders=handler.getServlets();
1245             if (holders!=null)
1246             {
1247                 for (ServletHolder holder : holders)
1248                     registrations.put(holder.getName(),holder.getRegistration());
1249             }
1250             return registrations;
1251         }
1252 
1253         @Override
1254         public SessionCookieConfig getSessionCookieConfig()
1255         {
1256             if (!_enabled)
1257                 throw new UnsupportedOperationException();
1258 
1259             if (_sessionHandler!=null)
1260                 return _sessionHandler.getSessionManager().getSessionCookieConfig();
1261             return null;
1262         }
1263 
1264         @Override
1265         public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
1266         {
1267             if (!isStarting())
1268                 throw new IllegalStateException();
1269             if (!_enabled)
1270                 throw new UnsupportedOperationException();
1271 
1272 
1273             if (_sessionHandler!=null)
1274                 _sessionHandler.getSessionManager().setSessionTrackingModes(sessionTrackingModes);
1275         }
1276 
1277         @Override
1278         public void addListener(String className)
1279         {
1280             if (!isStarting())
1281                 throw new IllegalStateException();
1282             if (!_enabled)
1283                 throw new UnsupportedOperationException();
1284             super.addListener(className);
1285         }
1286 
1287         @Override
1288         public <T extends EventListener> void addListener(T t)
1289         {
1290             if (!isStarting())
1291                 throw new IllegalStateException();
1292             if (!_enabled)
1293                 throw new UnsupportedOperationException();
1294             super.addListener(t);
1295             ListenerHolder holder = getServletHandler().newListenerHolder(Source.JAVAX_API);
1296             holder.setListener(t);
1297             getServletHandler().addListener(holder);
1298         }
1299 
1300         @Override
1301         public void addListener(Class<? extends EventListener> listenerClass)
1302         {
1303             if (!isStarting())
1304                 throw new IllegalStateException();
1305             if (!_enabled)
1306                 throw new UnsupportedOperationException();
1307             super.addListener(listenerClass);
1308         }
1309 
1310         @Override
1311         public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException
1312         {
1313             try
1314             {
1315                 T l = createInstance(clazz);
1316                 for (int i=_decorators.size()-1; i>=0; i--)
1317                 {
1318                     Decorator decorator = _decorators.get(i);
1319                     l=decorator.decorate(l);
1320                 }
1321                 return l;
1322             }            
1323             catch (Exception e)
1324             {
1325                 throw new ServletException(e);
1326             }
1327         }
1328 
1329 
1330         @Override
1331         public JspConfigDescriptor getJspConfigDescriptor()
1332         {
1333             return _jspConfig;
1334         }
1335 
1336         @Override
1337         public void setJspConfigDescriptor(JspConfigDescriptor d)
1338         {
1339             _jspConfig = d;
1340         }
1341 
1342 
1343         @Override
1344         public void declareRoles(String... roleNames)
1345         {
1346             if (!isStarting())
1347                 throw new IllegalStateException();
1348             if (!_enabled)
1349                 throw new UnsupportedOperationException();
1350             addRoles(roleNames);
1351 
1352 
1353         }
1354 
1355     }
1356 
1357 
1358 
1359     /* ------------------------------------------------------------ */
1360     /** Interface to decorate loaded classes.
1361      */
1362     public interface Decorator
1363     {
1364         <T> T decorate (T o);
1365         void destroy (Object o);
1366     }
1367 }