View Javadoc

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