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