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