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)
272         .append(" - ").append(AbstractLifeCycle.getState(this)).append("\n");
273         AggregateLifeCycle.dump(out,indent,_initParams.entrySet());
274     }
275 
276     /* ------------------------------------------------------------ */
277     public String dump()
278     {
279         return AggregateLifeCycle.dump(this);
280     }    
281     
282     /* ------------------------------------------------------------ */
283     /* ------------------------------------------------------------ */
284     /* ------------------------------------------------------------ */
285     protected class HolderConfig 
286     {   
287         
288         /* -------------------------------------------------------- */
289         public ServletContext getServletContext()
290         {
291             return _servletHandler.getServletContext();
292         }
293 
294         /* -------------------------------------------------------- */
295         public String getInitParameter(String param)
296         {
297             return Holder.this.getInitParameter(param);
298         }
299     
300         /* -------------------------------------------------------- */
301         public Enumeration getInitParameterNames()
302         {
303             return Holder.this.getInitParameterNames();
304         }
305     }
306 
307     /* -------------------------------------------------------- */
308     /* -------------------------------------------------------- */
309     /* -------------------------------------------------------- */
310     protected class HolderRegistration implements Registration.Dynamic
311     {
312         public void setAsyncSupported(boolean isAsyncSupported)
313         {
314             illegalStateIfContextStarted();
315             Holder.this.setAsyncSupported(isAsyncSupported);
316         }
317 
318         public void setDescription(String description)
319         {
320             if (LOG.isDebugEnabled())
321                 LOG.debug(this+" is "+description);
322         }
323 
324         public String getClassName()
325         {
326             return Holder.this.getClassName();
327         }
328 
329         public String getInitParameter(String name)
330         {
331             return Holder.this.getInitParameter(name);
332         }
333 
334         public Map<String, String> getInitParameters()
335         {
336             return Holder.this.getInitParameters();
337         }
338 
339         public String getName()
340         {
341             return Holder.this.getName();
342         }
343 
344         public boolean setInitParameter(String name, String value)
345         {
346             illegalStateIfContextStarted();
347             if (name == null) {
348                 throw new IllegalArgumentException("init parameter name required");
349             }
350             if (value == null) {
351                 throw new IllegalArgumentException("non-null value required for init parameter " + name);
352             }
353             if (Holder.this.getInitParameter(name)!=null)
354                 return false;
355             Holder.this.setInitParameter(name,value);
356             return true;
357         }
358 
359         public Set<String> setInitParameters(Map<String, String> initParameters)
360         {
361             illegalStateIfContextStarted();
362             Set<String> clash=null;
363             for (Map.Entry<String, String> entry : initParameters.entrySet())
364             {
365                 if (entry.getKey() == null) {
366                     throw new IllegalArgumentException("init parameter name required");
367                 }
368                 if (entry.getValue() == null) {
369                     throw new IllegalArgumentException("non-null value required for init parameter " + entry.getKey());
370                 }
371                 if (Holder.this.getInitParameter(entry.getKey())!=null)
372                 {
373                     if (clash==null)
374                         clash=new HashSet<String>();
375                     clash.add(entry.getKey());
376                 }
377             }
378             if (clash!=null)
379                 return clash;
380             Holder.this.getInitParameters().putAll(initParameters);
381             return Collections.emptySet();
382         }
383         
384         
385     }
386 }
387 
388 
389 
390 
391