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