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