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())
94                      LOG.debug("Holding {}",_class);
95              }
96              catch (Exception e)
97              {
98                  LOG.warn(e);
99                  throw new UnavailableException(e.getMessage(), -1);
100             }
101         }
102     }
103     
104     /* ------------------------------------------------------------ */
105     @Override
106     public void doStop()
107         throws Exception
108     {
109         if (!_extInstance)
110             _class=null;
111     }
112     
113     /* ------------------------------------------------------------ */
114     public String getClassName()
115     {
116         return _className;
117     }
118     
119     /* ------------------------------------------------------------ */
120     public Class<? extends T> getHeldClass()
121     {
122         return _class;
123     }
124     
125     /* ------------------------------------------------------------ */
126     public String getDisplayName()
127     {
128         return _displayName;
129     }
130 
131     /* ---------------------------------------------------------------- */
132     public String getInitParameter(String param)
133     {
134         if (_initParams==null)
135             return null;
136         return (String)_initParams.get(param);
137     }
138     
139     /* ------------------------------------------------------------ */
140     public Enumeration getInitParameterNames()
141     {
142         if (_initParams==null)
143             return Collections.enumeration(Collections.EMPTY_LIST);
144         return Collections.enumeration(_initParams.keySet());
145     }
146 
147     /* ---------------------------------------------------------------- */
148     public Map<String,String> getInitParameters()
149     {
150         return _initParams;
151     }
152     
153     /* ------------------------------------------------------------ */
154     public String getName()
155     {
156         return _name;
157     }
158     
159     /* ------------------------------------------------------------ */
160     /**
161      * @return Returns the servletHandler.
162      */
163     public ServletHandler getServletHandler()
164     {
165         return _servletHandler;
166     }
167     
168     /* ------------------------------------------------------------ */
169     public void destroyInstance(Object instance)
170     throws Exception
171     {
172     }
173     
174     /* ------------------------------------------------------------ */
175     /**
176      * @param className The className to set.
177      */
178     public void setClassName(String className)
179     {
180         _className = className;
181         _class=null;
182     }
183     
184     /* ------------------------------------------------------------ */
185     /**
186      * @param held The class to hold
187      */
188     public void setHeldClass(Class<? extends T> held)
189     {
190         _class=held;
191         if (held!=null)
192         {
193             _className=held.getName();
194             if (_name==null)
195                 _name=held.getName()+"-"+this.hashCode();
196         }
197     }
198     
199     /* ------------------------------------------------------------ */
200     public void setDisplayName(String name)
201     {
202         _displayName=name;
203     }
204     
205     /* ------------------------------------------------------------ */
206     public void setInitParameter(String param,String value)
207     {
208         _initParams.put(param,value);
209     }
210     
211     /* ---------------------------------------------------------------- */
212     public void setInitParameters(Map<String,String> map)
213     {
214         _initParams.clear();
215         _initParams.putAll(map);
216     }
217     
218     /* ------------------------------------------------------------ */
219     /**
220      * The name is a primary key for the held object.
221      * Ensure that the name is set BEFORE adding a Holder
222      * (eg ServletHolder or FilterHolder) to a ServletHandler.
223      * @param name The name to set.
224      */
225     public void setName(String name)
226     {
227         _name = name;
228     }
229     
230     /* ------------------------------------------------------------ */
231     /**
232      * @param servletHandler The {@link ServletHandler} that will handle requests dispatched to this servlet.
233      */
234     public void setServletHandler(ServletHandler servletHandler)
235     {
236         _servletHandler = servletHandler;
237     }
238 
239     /* ------------------------------------------------------------ */
240     public void setAsyncSupported(boolean suspendable)
241     {
242         _asyncSupported=suspendable;
243     }
244 
245     /* ------------------------------------------------------------ */
246     public boolean isAsyncSupported()
247     {
248         return _asyncSupported;
249     }
250     
251     /* ------------------------------------------------------------ */
252     public String toString()
253     {
254         return _name;
255     }
256 
257     /* ------------------------------------------------------------ */
258     protected void illegalStateIfContextStarted()
259     {
260         if (_servletHandler!=null)
261         {
262             ContextHandler.Context context=(ContextHandler.Context)_servletHandler.getServletContext();
263             if (context!=null && context.getContextHandler().isStarted())
264                 throw new IllegalStateException("Started");
265         }
266     }
267 
268     /* ------------------------------------------------------------ */
269     public void dump(Appendable out, String indent) throws IOException
270     {
271         out.append(_name).append("==").append(_className).append("\n");
272         AggregateLifeCycle.dump(out,indent,_initParams.entrySet());
273     }
274 
275     /* ------------------------------------------------------------ */
276     public String dump()
277     {
278         return AggregateLifeCycle.dump(this);
279     }    
280     
281     /* ------------------------------------------------------------ */
282     /* ------------------------------------------------------------ */
283     /* ------------------------------------------------------------ */
284     protected class HolderConfig 
285     {   
286         
287         /* -------------------------------------------------------- */
288         public ServletContext getServletContext()
289         {
290             return _servletHandler.getServletContext();
291         }
292 
293         /* -------------------------------------------------------- */
294         public String getInitParameter(String param)
295         {
296             return Holder.this.getInitParameter(param);
297         }
298     
299         /* -------------------------------------------------------- */
300         public Enumeration getInitParameterNames()
301         {
302             return Holder.this.getInitParameterNames();
303         }
304     }
305 
306     /* -------------------------------------------------------- */
307     /* -------------------------------------------------------- */
308     /* -------------------------------------------------------- */
309     protected class HolderRegistration implements Registration.Dynamic
310     {
311         public void setAsyncSupported(boolean isAsyncSupported)
312         {
313             illegalStateIfContextStarted();
314             Holder.this.setAsyncSupported(isAsyncSupported);
315         }
316 
317         public void setDescription(String description)
318         {
319             if (LOG.isDebugEnabled())
320                 LOG.debug(this+" is "+description);
321         }
322 
323         public String getClassName()
324         {
325             return Holder.this.getClassName();
326         }
327 
328         public String getInitParameter(String name)
329         {
330             return Holder.this.getInitParameter(name);
331         }
332 
333         public Map<String, String> getInitParameters()
334         {
335             return Holder.this.getInitParameters();
336         }
337 
338         public String getName()
339         {
340             return Holder.this.getName();
341         }
342 
343         public boolean setInitParameter(String name, String value)
344         {
345             illegalStateIfContextStarted();
346             if (name == null) {
347                 throw new IllegalArgumentException("init parameter name required");
348             }
349             if (value == null) {
350                 throw new IllegalArgumentException("non-null value required for init parameter " + name);
351             }
352             if (Holder.this.getInitParameter(name)!=null)
353                 return false;
354             Holder.this.setInitParameter(name,value);
355             return true;
356         }
357 
358         public Set<String> setInitParameters(Map<String, String> initParameters)
359         {
360             illegalStateIfContextStarted();
361             Set<String> clash=null;
362             for (Map.Entry<String, String> entry : initParameters.entrySet())
363             {
364                 if (entry.getKey() == null) {
365                     throw new IllegalArgumentException("init parameter name required");
366                 }
367                 if (entry.getValue() == null) {
368                     throw new IllegalArgumentException("non-null value required for init parameter " + entry.getKey());
369                 }
370                 if (Holder.this.getInitParameter(entry.getKey())!=null)
371                 {
372                     if (clash==null)
373                         clash=new HashSet<String>();
374                     clash.add(entry.getKey());
375                 }
376             }
377             if (clash!=null)
378                 return clash;
379             Holder.this.getInitParameters().putAll(initParameters);
380             return Collections.emptySet();
381         }
382         
383         
384     }
385 }
386 
387 
388 
389 
390