View Javadoc

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