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