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