View Javadoc

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