View Javadoc

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