1
2
3
4
5
6
7
8
9
10
11
12
13
14
15 package org.mortbay.jetty.servlet;
16
17 import java.io.IOException;
18 import java.security.Principal;
19 import java.util.Enumeration;
20 import java.util.HashMap;
21 import java.util.Map;
22 import java.util.Stack;
23
24 import javax.servlet.Servlet;
25 import javax.servlet.ServletConfig;
26 import javax.servlet.ServletContext;
27 import javax.servlet.ServletException;
28 import javax.servlet.ServletRequest;
29 import javax.servlet.ServletResponse;
30 import javax.servlet.SingleThreadModel;
31 import javax.servlet.UnavailableException;
32
33 import org.mortbay.jetty.HttpConnection;
34 import org.mortbay.jetty.Request;
35 import org.mortbay.jetty.handler.ContextHandler;
36 import org.mortbay.jetty.security.SecurityHandler;
37 import org.mortbay.jetty.security.UserRealm;
38 import org.mortbay.log.Log;
39
40
41
42
43
44
45
46
47
48
49
50
51 public class ServletHolder extends Holder
52 implements Comparable
53 {
54
55 private int _initOrder;
56 private boolean _initOnStartup=false;
57 private Map _roleMap;
58 private String _forcedPath;
59 private String _runAs;
60 private UserRealm _realm;
61
62 private transient Servlet _servlet;
63 private transient Config _config;
64 private transient long _unavailable;
65 private transient UnavailableException _unavailableEx;
66
67
68
69
70
71 public ServletHolder()
72 {}
73
74
75
76
77 public ServletHolder(Servlet servlet)
78 {
79 setServlet(servlet);
80 }
81
82
83
84
85 public ServletHolder(Class servlet)
86 {
87 super(servlet);
88 }
89
90
91 public synchronized void setServlet(Servlet servlet)
92 {
93 if (servlet==null || servlet instanceof SingleThreadModel)
94 throw new IllegalArgumentException();
95
96 _extInstance=true;
97 _servlet=servlet;
98 setHeldClass(servlet.getClass());
99 if (getName()==null)
100 setName(servlet.getClass().getName()+"-"+super.hashCode());
101 }
102
103
104 public int getInitOrder()
105 {
106 return _initOrder;
107 }
108
109
110
111
112
113
114
115 public void setInitOrder(int order)
116 {
117 _initOnStartup=true;
118 _initOrder = order;
119 }
120
121
122
123
124 public int compareTo(Object o)
125 {
126 if (o instanceof ServletHolder)
127 {
128 ServletHolder sh= (ServletHolder)o;
129 if (sh==this)
130 return 0;
131 if (sh._initOrder<_initOrder)
132 return 1;
133 if (sh._initOrder>_initOrder)
134 return -1;
135
136 int c=(_className!=null && sh._className!=null)?_className.compareTo(sh._className):0;
137 if (c==0)
138 c=_name.compareTo(sh._name);
139 if (c==0)
140 c=this.hashCode()>o.hashCode()?1:-1;
141 return c;
142 }
143 return 1;
144 }
145
146
147 public boolean equals(Object o)
148 {
149 return compareTo(o)==0;
150 }
151
152
153 public int hashCode()
154 {
155 return _name==null?System.identityHashCode(this):_name.hashCode();
156 }
157
158
159
160
161
162
163
164
165 public synchronized void setUserRoleLink(String name,String link)
166 {
167 if (_roleMap==null)
168 _roleMap=new HashMap();
169 _roleMap.put(name,link);
170 }
171
172
173
174
175
176
177
178 public String getUserRoleLink(String name)
179 {
180 if (_roleMap==null)
181 return name;
182 String link=(String)_roleMap.get(name);
183 return (link==null)?name:link;
184 }
185
186
187 public Map getRoleMap()
188 {
189 return _roleMap;
190 }
191
192
193
194
195
196
197 public void setRunAs(String role)
198 {
199 _runAs=role;
200 }
201
202
203 public String getRunAs()
204 {
205 return _runAs;
206 }
207
208
209
210
211
212 public String getForcedPath()
213 {
214 return _forcedPath;
215 }
216
217
218
219
220
221 public void setForcedPath(String forcedPath)
222 {
223 _forcedPath = forcedPath;
224 }
225
226
227 public void doStart()
228 throws Exception
229 {
230 _unavailable=0;
231 try
232 {
233 super.doStart();
234 checkServletType();
235 }
236 catch (UnavailableException ue)
237 {
238 makeUnavailable(ue);
239 }
240
241 _config=new Config();
242
243 if (_runAs!=null)
244 _realm=((SecurityHandler)(ContextHandler.getCurrentContext()
245 .getContextHandler().getChildHandlerByClass(SecurityHandler.class))).getUserRealm();
246
247 if (javax.servlet.SingleThreadModel.class.isAssignableFrom(_class))
248 _servlet = new SingleThreadedWrapper();
249
250 if (_extInstance || _initOnStartup)
251 {
252 if (_servlet==null)
253 _servlet=(Servlet)newInstance();
254 try
255 {
256 initServlet(_servlet,_config);
257 }
258 catch(Throwable e)
259 {
260 _servlet=null;
261 _config=null;
262 if (e instanceof Exception)
263 throw (Exception) e;
264 else if (e instanceof Error)
265 throw (Error)e;
266 else
267 throw new ServletException(e);
268 }
269 }
270 }
271
272
273 public void doStop()
274 {
275 Principal user=null;
276 try
277 {
278
279 if (_runAs!=null && _realm!=null)
280 user=_realm.pushRole(null,_runAs);
281
282 if (_servlet!=null)
283 {
284 try
285 {
286 destroyInstance(_servlet);
287 }
288 catch (Exception e)
289 {
290 Log.warn(e);
291 }
292 }
293
294 if (!_extInstance)
295 _servlet=null;
296
297 _config=null;
298 }
299 finally
300 {
301 super.doStop();
302
303 if (_runAs!=null && _realm!=null && user!=null)
304 _realm.popRole(user);
305 }
306 }
307
308
309 public void destroyInstance (Object o)
310 throws Exception
311 {
312 if (o==null)
313 return;
314 Servlet servlet = ((Servlet)o);
315 servlet.destroy();
316 getServletHandler().customizeServletDestroy(servlet);
317 }
318
319
320
321
322
323 public synchronized Servlet getServlet()
324 throws ServletException
325 {
326
327 if (_unavailable!=0)
328 {
329 if (_unavailable<0 || _unavailable>0 && System.currentTimeMillis()<_unavailable)
330 throw _unavailableEx;
331 _unavailable=0;
332 _unavailableEx=null;
333 }
334
335 try
336 {
337 if (_servlet==null)
338 {
339 _servlet=(Servlet)newInstance();
340 if (_config==null)
341 _config=new Config();
342 initServlet(_servlet,_config);
343 }
344
345 return _servlet;
346 }
347 catch(UnavailableException e)
348 {
349 _servlet=null;
350 _config=null;
351 return makeUnavailable(e);
352 }
353 catch(ServletException e)
354 {
355 _servlet=null;
356 _config=null;
357 throw e;
358 }
359 catch(Throwable e)
360 {
361 _servlet=null;
362 _config=null;
363 throw new ServletException("init",e);
364 }
365 }
366
367
368
369
370
371
372 public void checkServletType ()
373 throws UnavailableException
374 {
375 if (!javax.servlet.Servlet.class.isAssignableFrom(_class))
376 {
377 throw new UnavailableException("Servlet "+_class+" is not a javax.servlet.Servlet");
378 }
379 }
380
381
382
383
384
385 public boolean isAvailable()
386 {
387 if (isStarted()&& _unavailable==0)
388 return true;
389 try
390 {
391 getServlet();
392 }
393 catch(Exception e)
394 {
395 Log.ignore(e);
396 }
397
398 return isStarted()&& _unavailable==0;
399 }
400
401
402 private Servlet makeUnavailable(UnavailableException e)
403 throws UnavailableException
404 {
405 _unavailableEx=e;
406 _unavailable=-1;
407 if (e.isPermanent())
408 _unavailable=-1;
409 else
410 {
411 if (_unavailableEx.getUnavailableSeconds()>0)
412 _unavailable=System.currentTimeMillis()+1000*_unavailableEx.getUnavailableSeconds();
413 else
414 _unavailable=System.currentTimeMillis()+5000;
415 }
416
417 throw _unavailableEx;
418 }
419
420
421 private void initServlet(Servlet servlet, ServletConfig config)
422 throws ServletException
423 {
424 Principal user=null;
425 try
426 {
427
428 _servlet = getServletHandler().customizeServlet(servlet);
429
430
431 if (_runAs!=null && _realm!=null)
432 user=_realm.pushRole(null,_runAs);
433 servlet.init(config);
434 }
435 catch (Exception e)
436 {
437 throw new ServletException(e);
438 }
439 finally
440 {
441
442 if (_runAs!=null && _realm!=null && user!=null)
443 _realm.popRole(user);
444 }
445 }
446
447
448
449
450 public void handle(ServletRequest request,
451 ServletResponse response)
452 throws ServletException,
453 UnavailableException,
454 IOException
455 {
456 if (_class==null)
457 throw new UnavailableException("Servlet Not Initialized");
458
459 Servlet servlet=_servlet;
460 synchronized(this)
461 {
462 if (_unavailable!=0 || !_initOnStartup)
463 servlet=getServlet();
464 if (servlet==null)
465 throw new UnavailableException("Could not instantiate "+_class);
466 }
467
468
469 boolean servlet_error=true;
470 Principal user=null;
471 Request base_request=null;
472 try
473 {
474
475 if (_forcedPath!=null)
476
477 request.setAttribute("org.apache.catalina.jsp_file",_forcedPath);
478
479
480 if (_runAs!=null && _realm!=null)
481 {
482 base_request=HttpConnection.getCurrentConnection().getRequest();
483 user=_realm.pushRole(base_request.getUserPrincipal(),_runAs);
484 base_request.setUserPrincipal(user);
485 }
486
487 servlet.service(request,response);
488 servlet_error=false;
489 }
490 catch(UnavailableException e)
491 {
492 makeUnavailable(e);
493 }
494 finally
495 {
496
497 if (_runAs!=null && _realm!=null && user!=null && base_request!=null)
498 {
499 user=_realm.popRole(user);
500 base_request.setUserPrincipal(user);
501 }
502
503
504 if (servlet_error)
505 request.setAttribute("javax.servlet.error.servlet_name",getName());
506 }
507 }
508
509
510
511
512
513 class Config implements ServletConfig
514 {
515
516 public String getServletName()
517 {
518 return getName();
519 }
520
521
522 public ServletContext getServletContext()
523 {
524 return _servletHandler.getServletContext();
525 }
526
527
528 public String getInitParameter(String param)
529 {
530 return ServletHolder.this.getInitParameter(param);
531 }
532
533
534 public Enumeration getInitParameterNames()
535 {
536 return ServletHolder.this.getInitParameterNames();
537 }
538 }
539
540
541
542
543 private class SingleThreadedWrapper implements Servlet
544 {
545 Stack _stack=new Stack();
546
547 public void destroy()
548 {
549 synchronized(this)
550 {
551 while(_stack.size()>0)
552 try { ((Servlet)_stack.pop()).destroy(); } catch (Exception e) { Log.warn(e); }
553 }
554 }
555
556 public ServletConfig getServletConfig()
557 {
558 return _config;
559 }
560
561 public String getServletInfo()
562 {
563 return null;
564 }
565
566 public void init(ServletConfig config) throws ServletException
567 {
568 synchronized(this)
569 {
570 if(_stack.size()==0)
571 {
572 try
573 {
574 Servlet s = (Servlet) newInstance();
575 s.init(config);
576 _stack.push(s);
577 }
578 catch(IllegalAccessException e)
579 {
580 throw new ServletException(e);
581 }
582 catch (InstantiationException e)
583 {
584 throw new ServletException(e);
585 }
586 }
587 }
588 }
589
590 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
591 {
592 Servlet s;
593 synchronized(this)
594 {
595 if(_stack.size()>0)
596 s=(Servlet)_stack.pop();
597 else
598 {
599 try
600 {
601 s = (Servlet) newInstance();
602 s.init(_config);
603 }
604 catch(IllegalAccessException e)
605 {
606 throw new ServletException(e);
607 }
608 catch (InstantiationException e)
609 {
610 throw new ServletException(e);
611 }
612 }
613 }
614
615 try
616 {
617 s.service(req,res);
618 }
619 finally
620 {
621 synchronized(this)
622 {
623 _stack.push(s);
624 }
625 }
626 }
627
628 }
629 }
630
631
632
633
634