View Javadoc

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