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 }
220
221
222
223
224
225 public void setHeldClass(Class<? extends T> held)
226 {
227 _class=held;
228 if (held!=null)
229 {
230 _className=held.getName();
231 if (_name==null)
232 _name=held.getName()+"-"+this.hashCode();
233 }
234 }
235
236
237 public void setDisplayName(String name)
238 {
239 _displayName=name;
240 }
241
242
243 public void setInitParameter(String param,String value)
244 {
245 _initParams.put(param,value);
246 }
247
248
249 public void setInitParameters(Map<String,String> map)
250 {
251 _initParams.clear();
252 _initParams.putAll(map);
253 }
254
255
256
257
258
259
260
261
262 public void setName(String name)
263 {
264 _name = name;
265 }
266
267
268
269
270
271 public void setServletHandler(ServletHandler servletHandler)
272 {
273 _servletHandler = servletHandler;
274 }
275
276
277 public void setAsyncSupported(boolean suspendable)
278 {
279 _asyncSupported=suspendable;
280 }
281
282
283 public boolean isAsyncSupported()
284 {
285 return _asyncSupported;
286 }
287
288
289 protected void illegalStateIfContextStarted()
290 {
291 if (_servletHandler!=null)
292 {
293 ServletContext context=_servletHandler.getServletContext();
294 if ((context instanceof ContextHandler.Context) && ((ContextHandler.Context)context).getContextHandler().isStarted())
295 throw new IllegalStateException("Started");
296 }
297 }
298
299
300 @Override
301 public void dump(Appendable out, String indent) throws IOException
302 {
303 out.append(toString())
304 .append(" - ").append(AbstractLifeCycle.getState(this)).append("\n");
305 ContainerLifeCycle.dump(out,indent,_initParams.entrySet());
306 }
307
308
309 @Override
310 public String dump()
311 {
312 return ContainerLifeCycle.dump(this);
313 }
314
315
316 @Override
317 public String toString()
318 {
319 return String.format("%s@%x==%s",_name,hashCode(),_className);
320 }
321
322
323
324
325 protected class HolderConfig
326 {
327
328
329 public ServletContext getServletContext()
330 {
331 return _servletHandler.getServletContext();
332 }
333
334
335 public String getInitParameter(String param)
336 {
337 return Holder.this.getInitParameter(param);
338 }
339
340
341 public Enumeration getInitParameterNames()
342 {
343 return Holder.this.getInitParameterNames();
344 }
345 }
346
347
348
349
350 protected class HolderRegistration implements Registration.Dynamic
351 {
352 public void setAsyncSupported(boolean isAsyncSupported)
353 {
354 illegalStateIfContextStarted();
355 Holder.this.setAsyncSupported(isAsyncSupported);
356 }
357
358 public void setDescription(String description)
359 {
360 if (LOG.isDebugEnabled())
361 LOG.debug(this+" is "+description);
362 }
363
364 public String getClassName()
365 {
366 return Holder.this.getClassName();
367 }
368
369 public String getInitParameter(String name)
370 {
371 return Holder.this.getInitParameter(name);
372 }
373
374 public Map<String, String> getInitParameters()
375 {
376 return Holder.this.getInitParameters();
377 }
378
379 public String getName()
380 {
381 return Holder.this.getName();
382 }
383
384 public boolean setInitParameter(String name, String value)
385 {
386 illegalStateIfContextStarted();
387 if (name == null) {
388 throw new IllegalArgumentException("init parameter name required");
389 }
390 if (value == null) {
391 throw new IllegalArgumentException("non-null value required for init parameter " + name);
392 }
393 if (Holder.this.getInitParameter(name)!=null)
394 return false;
395 Holder.this.setInitParameter(name,value);
396 return true;
397 }
398
399 public Set<String> setInitParameters(Map<String, String> initParameters)
400 {
401 illegalStateIfContextStarted();
402 Set<String> clash=null;
403 for (Map.Entry<String, String> entry : initParameters.entrySet())
404 {
405 if (entry.getKey() == null) {
406 throw new IllegalArgumentException("init parameter name required");
407 }
408 if (entry.getValue() == null) {
409 throw new IllegalArgumentException("non-null value required for init parameter " + entry.getKey());
410 }
411 if (Holder.this.getInitParameter(entry.getKey())!=null)
412 {
413 if (clash==null)
414 clash=new HashSet<String>();
415 clash.add(entry.getKey());
416 }
417 }
418 if (clash!=null)
419 return clash;
420 Holder.this.getInitParameters().putAll(initParameters);
421 return Collections.emptySet();
422 }
423
424
425 }
426 }
427
428
429
430
431