• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 //  ========================================================================
3 //  Copyright (c) 1995-2014 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.io.IOException;
22 import java.util.Collections;
23 import java.util.Enumeration;
24 import java.util.HashMap;
25 import java.util.HashSet;
26 import java.util.Map;
27 import java.util.Set;
28 
29 import javax.servlet.Registration;
30 import javax.servlet.ServletContext;
31 import javax.servlet.UnavailableException;
32 
33 import org.eclipse.jetty.server.handler.ContextHandler;
34 import org.eclipse.jetty.util.Loader;
35 import org.eclipse.jetty.util.component.AbstractLifeCycle;
36 import org.eclipse.jetty.util.component.AggregateLifeCycle;
37 import org.eclipse.jetty.util.component.Dumpable;
38 import org.eclipse.jetty.util.log.Log;
39 import org.eclipse.jetty.util.log.Logger;
40 
41 
42 /* --------------------------------------------------------------------- */
43 /**
44  *
45  */
46 public class Holder<T> extends AbstractLifeCycle implements Dumpable
47 {
48     public enum Source { EMBEDDED, JAVAX_API, DESCRIPTOR, ANNOTATION };
49     final private Source _source;
50     private static final Logger LOG = Log.getLogger(Holder.class);
51 
52     protected transient Class<? extends T> _class;
53     protected final Map<String,String> _initParams=new HashMap<String,String>(3);
54     protected String _className;
55     protected String _displayName;
56     protected boolean _extInstance;
57     protected boolean _asyncSupported;
58 
59     /* ---------------------------------------------------------------- */
60     protected String _name;
61     protected ServletHandler _servletHandler;
62 
63     /* ---------------------------------------------------------------- */
Holder(Source source)64     protected Holder(Source source)
65     {
66         _source=source;
67         switch(_source)
68         {
69             case JAVAX_API:
70             case DESCRIPTOR:
71             case ANNOTATION:
72                 _asyncSupported=false;
73                 break;
74             default:
75                 _asyncSupported=true;
76         }
77     }
78 
getSource()79     public Source getSource()
80     {
81         return _source;
82     }
83 
84     /* ------------------------------------------------------------ */
85     /**
86      * @return True if this holder was created for a specific instance.
87      */
isInstance()88     public boolean isInstance()
89     {
90         return _extInstance;
91     }
92 
93     /* ------------------------------------------------------------ */
94     @SuppressWarnings("unchecked")
doStart()95     public void doStart()
96         throws Exception
97     {
98         //if no class already loaded and no classname, make servlet permanently unavailable
99         if (_class==null && (_className==null || _className.equals("")))
100             throw new UnavailableException("No class for Servlet or Filter for "+_name);
101 
102         //try to load class
103         if (_class==null)
104         {
105             try
106             {
107                 _class=Loader.loadClass(Holder.class, _className);
108                 if(LOG.isDebugEnabled())
109                     LOG.debug("Holding {}",_class);
110             }
111             catch (Exception e)
112             {
113                 LOG.warn(e);
114                 throw new UnavailableException(e.getMessage());
115             }
116         }
117     }
118 
119     /* ------------------------------------------------------------ */
120     @Override
doStop()121     public void doStop()
122         throws Exception
123     {
124         if (!_extInstance)
125             _class=null;
126     }
127 
128     /* ------------------------------------------------------------ */
getClassName()129     public String getClassName()
130     {
131         return _className;
132     }
133 
134     /* ------------------------------------------------------------ */
getHeldClass()135     public Class<? extends T> getHeldClass()
136     {
137         return _class;
138     }
139 
140     /* ------------------------------------------------------------ */
getDisplayName()141     public String getDisplayName()
142     {
143         return _displayName;
144     }
145 
146     /* ---------------------------------------------------------------- */
getInitParameter(String param)147     public String getInitParameter(String param)
148     {
149         if (_initParams==null)
150             return null;
151         return (String)_initParams.get(param);
152     }
153 
154     /* ------------------------------------------------------------ */
getInitParameterNames()155     public Enumeration getInitParameterNames()
156     {
157         if (_initParams==null)
158             return Collections.enumeration(Collections.EMPTY_LIST);
159         return Collections.enumeration(_initParams.keySet());
160     }
161 
162     /* ---------------------------------------------------------------- */
getInitParameters()163     public Map<String,String> getInitParameters()
164     {
165         return _initParams;
166     }
167 
168     /* ------------------------------------------------------------ */
getName()169     public String getName()
170     {
171         return _name;
172     }
173 
174     /* ------------------------------------------------------------ */
175     /**
176      * @return Returns the servletHandler.
177      */
getServletHandler()178     public ServletHandler getServletHandler()
179     {
180         return _servletHandler;
181     }
182 
183     /* ------------------------------------------------------------ */
destroyInstance(Object instance)184     public void destroyInstance(Object instance)
185     throws Exception
186     {
187     }
188 
189     /* ------------------------------------------------------------ */
190     /**
191      * @param className The className to set.
192      */
setClassName(String className)193     public void setClassName(String className)
194     {
195         _className = className;
196         _class=null;
197         if (_name==null)
198             _name=className+"-"+Integer.toHexString(this.hashCode());
199     }
200 
201     /* ------------------------------------------------------------ */
202     /**
203      * @param held The class to hold
204      */
setHeldClass(Class<? extends T> held)205     public void setHeldClass(Class<? extends T> held)
206     {
207         _class=held;
208         if (held!=null)
209         {
210             _className=held.getName();
211             if (_name==null)
212                 _name=held.getName()+"-"+Integer.toHexString(this.hashCode());
213         }
214     }
215 
216     /* ------------------------------------------------------------ */
setDisplayName(String name)217     public void setDisplayName(String name)
218     {
219         _displayName=name;
220     }
221 
222     /* ------------------------------------------------------------ */
setInitParameter(String param,String value)223     public void setInitParameter(String param,String value)
224     {
225         _initParams.put(param,value);
226     }
227 
228     /* ---------------------------------------------------------------- */
setInitParameters(Map<String,String> map)229     public void setInitParameters(Map<String,String> map)
230     {
231         _initParams.clear();
232         _initParams.putAll(map);
233     }
234 
235     /* ------------------------------------------------------------ */
236     /**
237      * The name is a primary key for the held object.
238      * Ensure that the name is set BEFORE adding a Holder
239      * (eg ServletHolder or FilterHolder) to a ServletHandler.
240      * @param name The name to set.
241      */
setName(String name)242     public void setName(String name)
243     {
244         _name = name;
245     }
246 
247     /* ------------------------------------------------------------ */
248     /**
249      * @param servletHandler The {@link ServletHandler} that will handle requests dispatched to this servlet.
250      */
setServletHandler(ServletHandler servletHandler)251     public void setServletHandler(ServletHandler servletHandler)
252     {
253         _servletHandler = servletHandler;
254     }
255 
256     /* ------------------------------------------------------------ */
setAsyncSupported(boolean suspendable)257     public void setAsyncSupported(boolean suspendable)
258     {
259         _asyncSupported=suspendable;
260     }
261 
262     /* ------------------------------------------------------------ */
isAsyncSupported()263     public boolean isAsyncSupported()
264     {
265         return _asyncSupported;
266     }
267 
268     /* ------------------------------------------------------------ */
toString()269     public String toString()
270     {
271         return _name;
272     }
273 
274     /* ------------------------------------------------------------ */
illegalStateIfContextStarted()275     protected void illegalStateIfContextStarted()
276     {
277         if (_servletHandler!=null)
278         {
279             ContextHandler.Context context=(ContextHandler.Context)_servletHandler.getServletContext();
280             if (context!=null && context.getContextHandler().isStarted())
281                 throw new IllegalStateException("Started");
282         }
283     }
284 
285     /* ------------------------------------------------------------ */
dump(Appendable out, String indent)286     public void dump(Appendable out, String indent) throws IOException
287     {
288         out.append(_name).append("==").append(_className)
289         .append(" - ").append(AbstractLifeCycle.getState(this)).append("\n");
290         AggregateLifeCycle.dump(out,indent,_initParams.entrySet());
291     }
292 
293     /* ------------------------------------------------------------ */
dump()294     public String dump()
295     {
296         return AggregateLifeCycle.dump(this);
297     }
298 
299     /* ------------------------------------------------------------ */
300     /* ------------------------------------------------------------ */
301     /* ------------------------------------------------------------ */
302     protected class HolderConfig
303     {
304 
305         /* -------------------------------------------------------- */
getServletContext()306         public ServletContext getServletContext()
307         {
308             return _servletHandler.getServletContext();
309         }
310 
311         /* -------------------------------------------------------- */
getInitParameter(String param)312         public String getInitParameter(String param)
313         {
314             return Holder.this.getInitParameter(param);
315         }
316 
317         /* -------------------------------------------------------- */
getInitParameterNames()318         public Enumeration getInitParameterNames()
319         {
320             return Holder.this.getInitParameterNames();
321         }
322     }
323 
324     /* -------------------------------------------------------- */
325     /* -------------------------------------------------------- */
326     /* -------------------------------------------------------- */
327     protected class HolderRegistration implements Registration.Dynamic
328     {
setAsyncSupported(boolean isAsyncSupported)329         public void setAsyncSupported(boolean isAsyncSupported)
330         {
331             illegalStateIfContextStarted();
332             Holder.this.setAsyncSupported(isAsyncSupported);
333         }
334 
setDescription(String description)335         public void setDescription(String description)
336         {
337             if (LOG.isDebugEnabled())
338                 LOG.debug(this+" is "+description);
339         }
340 
getClassName()341         public String getClassName()
342         {
343             return Holder.this.getClassName();
344         }
345 
getInitParameter(String name)346         public String getInitParameter(String name)
347         {
348             return Holder.this.getInitParameter(name);
349         }
350 
getInitParameters()351         public Map<String, String> getInitParameters()
352         {
353             return Holder.this.getInitParameters();
354         }
355 
getName()356         public String getName()
357         {
358             return Holder.this.getName();
359         }
360 
setInitParameter(String name, String value)361         public boolean setInitParameter(String name, String value)
362         {
363             illegalStateIfContextStarted();
364             if (name == null) {
365                 throw new IllegalArgumentException("init parameter name required");
366             }
367             if (value == null) {
368                 throw new IllegalArgumentException("non-null value required for init parameter " + name);
369             }
370             if (Holder.this.getInitParameter(name)!=null)
371                 return false;
372             Holder.this.setInitParameter(name,value);
373             return true;
374         }
375 
setInitParameters(Map<String, String> initParameters)376         public Set<String> setInitParameters(Map<String, String> initParameters)
377         {
378             illegalStateIfContextStarted();
379             Set<String> clash=null;
380             for (Map.Entry<String, String> entry : initParameters.entrySet())
381             {
382                 if (entry.getKey() == null) {
383                     throw new IllegalArgumentException("init parameter name required");
384                 }
385                 if (entry.getValue() == null) {
386                     throw new IllegalArgumentException("non-null value required for init parameter " + entry.getKey());
387                 }
388                 if (Holder.this.getInitParameter(entry.getKey())!=null)
389                 {
390                     if (clash==null)
391                         clash=new HashSet<String>();
392                     clash.add(entry.getKey());
393                 }
394             }
395             if (clash!=null)
396                 return clash;
397             Holder.this.getInitParameters().putAll(initParameters);
398             return Collections.emptySet();
399         }
400 
401 
402     }
403 }
404 
405 
406 
407 
408 
409