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.File;
22 import java.io.IOException;
23 import java.lang.reflect.Method;
24 import java.util.ArrayList;
25 import java.util.Arrays;
26 import java.util.Collection;
27 import java.util.Collections;
28 import java.util.HashMap;
29 import java.util.HashSet;
30 import java.util.List;
31 import java.util.Map;
32 import java.util.Set;
33 import java.util.Stack;
34
35 import javax.servlet.MultipartConfigElement;
36 import javax.servlet.Servlet;
37 import javax.servlet.ServletConfig;
38 import javax.servlet.ServletContext;
39 import javax.servlet.ServletException;
40 import javax.servlet.ServletRegistration;
41 import javax.servlet.ServletRequest;
42 import javax.servlet.ServletResponse;
43 import javax.servlet.ServletSecurityElement;
44 import javax.servlet.SingleThreadModel;
45 import javax.servlet.UnavailableException;
46
47 import org.eclipse.jetty.security.IdentityService;
48 import org.eclipse.jetty.security.RunAsToken;
49 import org.eclipse.jetty.server.MultiPartCleanerListener;
50 import org.eclipse.jetty.server.Request;
51 import org.eclipse.jetty.server.UserIdentity;
52 import org.eclipse.jetty.server.handler.ContextHandler;
53 import org.eclipse.jetty.util.Loader;
54 import org.eclipse.jetty.util.annotation.ManagedAttribute;
55 import org.eclipse.jetty.util.annotation.ManagedObject;
56 import org.eclipse.jetty.util.log.Log;
57 import org.eclipse.jetty.util.log.Logger;
58
59
60
61
62
63
64
65
66
67 @ManagedObject("Servlet Holder")
68 public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope, Comparable<ServletHolder>
69 {
70
71
72 private static final Logger LOG = Log.getLogger(ServletHolder.class);
73 private int _initOrder = -1;
74 private boolean _initOnStartup=false;
75 private Map<String, String> _roleMap;
76 private String _forcedPath;
77 private String _runAsRole;
78 private RunAsToken _runAsToken;
79 private IdentityService _identityService;
80 private ServletRegistration.Dynamic _registration;
81 private JspContainer _jspContainer;
82
83
84 private transient Servlet _servlet;
85 private transient Config _config;
86 private transient long _unavailable;
87 private transient boolean _enabled = true;
88 private transient UnavailableException _unavailableEx;
89
90
91 public static final String APACHE_SENTINEL_CLASS = "org.apache.tomcat.InstanceManager";
92 public static final String JSP_GENERATED_PACKAGE_NAME = "org.eclipse.jetty.servlet.jspPackagePrefix";
93 public static final Map<String,String> NO_MAPPED_ROLES = Collections.emptyMap();
94 public static enum JspContainer {APACHE, OTHER};
95
96
97
98
99 public ServletHolder()
100 {
101 this(Source.EMBEDDED);
102 }
103
104
105
106
107
108 public ServletHolder(Holder.Source creator)
109 {
110 super(creator);
111 }
112
113
114
115
116
117 public ServletHolder(Servlet servlet)
118 {
119 this(Source.EMBEDDED);
120 setServlet(servlet);
121 }
122
123
124
125
126
127
128 public ServletHolder(String name, Class<? extends Servlet> servlet)
129 {
130 this(Source.EMBEDDED);
131 setName(name);
132 setHeldClass(servlet);
133 }
134
135
136
137
138
139
140 public ServletHolder(String name, Servlet servlet)
141 {
142 this(Source.EMBEDDED);
143 setName(name);
144 setServlet(servlet);
145 }
146
147
148
149
150
151 public ServletHolder(Class<? extends Servlet> servlet)
152 {
153 this(Source.EMBEDDED);
154 setHeldClass(servlet);
155 }
156
157
158
159
160
161 public UnavailableException getUnavailableException()
162 {
163 return _unavailableEx;
164 }
165
166
167 public synchronized void setServlet(Servlet servlet)
168 {
169 if (servlet==null || servlet instanceof SingleThreadModel)
170 throw new IllegalArgumentException();
171
172 _extInstance=true;
173 _servlet=servlet;
174 setHeldClass(servlet.getClass());
175 if (getName()==null)
176 setName(servlet.getClass().getName()+"-"+super.hashCode());
177 }
178
179
180 @ManagedAttribute(value="initialization order", readonly=true)
181 public int getInitOrder()
182 {
183 return _initOrder;
184 }
185
186
187
188
189
190
191
192
193
194
195 public void setInitOrder(int order)
196 {
197 _initOnStartup=order>=0;
198 _initOrder = order;
199 }
200
201
202
203
204
205 @Override
206 public int compareTo(ServletHolder sh)
207 {
208 if (sh==this)
209 return 0;
210 if (sh._initOrder<_initOrder)
211 return 1;
212 if (sh._initOrder>_initOrder)
213 return -1;
214
215 int c=(_className!=null && sh._className!=null)?_className.compareTo(sh._className):0;
216 if (c==0)
217 c=_name.compareTo(sh._name);
218 return c;
219 }
220
221
222 public boolean equals(Object o)
223 {
224 return o instanceof ServletHolder && compareTo((ServletHolder)o)==0;
225 }
226
227
228 public int hashCode()
229 {
230 return _name==null?System.identityHashCode(this):_name.hashCode();
231 }
232
233
234
235
236
237
238
239
240 public synchronized void setUserRoleLink(String name,String link)
241 {
242 if (_roleMap==null)
243 _roleMap=new HashMap<String, String>();
244 _roleMap.put(name,link);
245 }
246
247
248
249
250
251
252
253 public String getUserRoleLink(String name)
254 {
255 if (_roleMap==null)
256 return name;
257 String link= _roleMap.get(name);
258 return (link==null)?name:link;
259 }
260
261
262
263
264
265 @ManagedAttribute(value="forced servlet path", readonly=true)
266 public String getForcedPath()
267 {
268 return _forcedPath;
269 }
270
271
272
273
274
275 public void setForcedPath(String forcedPath)
276 {
277 _forcedPath = forcedPath;
278 }
279
280 public boolean isEnabled()
281 {
282 return _enabled;
283 }
284
285
286 public void setEnabled(boolean enabled)
287 {
288 _enabled = enabled;
289 }
290
291
292
293 public void doStart()
294 throws Exception
295 {
296 _unavailable=0;
297 if (!_enabled)
298 return;
299
300
301 if (_forcedPath != null)
302 {
303
304 String precompiled=getClassNameForJsp(_forcedPath);
305 if (LOG.isDebugEnabled())
306 LOG.debug("Checking for precompiled servlet {} for jsp {}", precompiled, _forcedPath);
307 ServletHolder jsp=getServletHandler().getServlet(precompiled);
308 if (jsp!=null && jsp.getClassName() != null)
309 {
310 if (LOG.isDebugEnabled())
311 LOG.debug("JSP file {} for {} mapped to Servlet {}",_forcedPath, getName(),jsp.getClassName());
312
313 setClassName(jsp.getClassName());
314 }
315 else
316 {
317 if (getClassName() == null)
318 {
319
320 jsp=getServletHandler().getServlet("jsp");
321 if (jsp!=null)
322 {
323 if (LOG.isDebugEnabled())
324 LOG.debug("JSP file {} for {} mapped to Servlet class {}",_forcedPath, getName(),jsp.getClassName());
325 setClassName(jsp.getClassName());
326
327 for (Map.Entry<String, String> entry:jsp.getInitParameters().entrySet())
328 {
329 if (!_initParams.containsKey(entry.getKey()))
330 setInitParameter(entry.getKey(), entry.getValue());
331 }
332
333
334
335
336 setInitParameter("jspFile", _forcedPath);
337 }
338 }
339 }
340 }
341
342
343
344 try
345 {
346 super.doStart();
347 }
348 catch (UnavailableException ue)
349 {
350 makeUnavailable(ue);
351 if (_servletHandler.isStartWithUnavailable())
352 {
353 LOG.ignore(ue);
354 return;
355 }
356 else
357 throw ue;
358 }
359
360
361
362 try
363 {
364 checkServletType();
365 }
366 catch (UnavailableException ue)
367 {
368 makeUnavailable(ue);
369 if (_servletHandler.isStartWithUnavailable())
370 {
371 LOG.ignore(ue);
372 return;
373 }
374 else
375 throw ue;
376 }
377
378
379 checkInitOnStartup();
380
381 _identityService = _servletHandler.getIdentityService();
382 if (_identityService!=null && _runAsRole!=null)
383 _runAsToken=_identityService.newRunAsToken(_runAsRole);
384
385 _config=new Config();
386
387 if (_class!=null && javax.servlet.SingleThreadModel.class.isAssignableFrom(_class))
388 _servlet = new SingleThreadedWrapper();
389
390 }
391
392
393
394 @Override
395 public void initialize ()
396 throws Exception
397 {
398 super.initialize();
399 if (_extInstance || _initOnStartup)
400 {
401 try
402 {
403 initServlet();
404 }
405 catch(Exception e)
406 {
407 if (_servletHandler.isStartWithUnavailable())
408 LOG.ignore(e);
409 else
410 throw e;
411 }
412 }
413 }
414
415
416
417 public void doStop()
418 throws Exception
419 {
420 Object old_run_as = null;
421 if (_servlet!=null)
422 {
423 try
424 {
425 if (_identityService!=null)
426 old_run_as=_identityService.setRunAs(_identityService.getSystemUserIdentity(),_runAsToken);
427
428 destroyInstance(_servlet);
429 }
430 catch (Exception e)
431 {
432 LOG.warn(e);
433 }
434 finally
435 {
436 if (_identityService!=null)
437 _identityService.unsetRunAs(old_run_as);
438 }
439 }
440
441 if (!_extInstance)
442 _servlet=null;
443
444 _config=null;
445 }
446
447
448 @Override
449 public void destroyInstance (Object o)
450 throws Exception
451 {
452 if (o==null)
453 return;
454 Servlet servlet = ((Servlet)o);
455 getServletHandler().destroyServlet(servlet);
456 servlet.destroy();
457 }
458
459
460
461
462
463
464 public synchronized Servlet getServlet()
465 throws ServletException
466 {
467
468 if (_unavailable!=0)
469 {
470 if (_unavailable<0 || _unavailable>0 && System.currentTimeMillis()<_unavailable)
471 throw _unavailableEx;
472 _unavailable=0;
473 _unavailableEx=null;
474 }
475
476 if (_servlet==null)
477 initServlet();
478 return _servlet;
479 }
480
481
482
483
484
485 public Servlet getServletInstance()
486 {
487 return _servlet;
488 }
489
490
491
492
493
494
495 public void checkServletType ()
496 throws UnavailableException
497 {
498 if (_class==null || !javax.servlet.Servlet.class.isAssignableFrom(_class))
499 {
500 throw new UnavailableException("Servlet "+_class+" is not a javax.servlet.Servlet");
501 }
502 }
503
504
505
506
507
508 public boolean isAvailable()
509 {
510 if (isStarted()&& _unavailable==0)
511 return true;
512 try
513 {
514 getServlet();
515 }
516 catch(Exception e)
517 {
518 LOG.ignore(e);
519 }
520
521 return isStarted()&& _unavailable==0;
522 }
523
524
525
526
527
528
529
530
531
532 private void checkInitOnStartup()
533 {
534 if (_class==null)
535 return;
536
537 if ((_class.getAnnotation(javax.servlet.annotation.ServletSecurity.class) != null) && !_initOnStartup)
538 setInitOrder(Integer.MAX_VALUE);
539 }
540
541
542 private void makeUnavailable(UnavailableException e)
543 {
544 if (_unavailableEx==e && _unavailable!=0)
545 return;
546
547 _servletHandler.getServletContext().log("unavailable",e);
548
549 _unavailableEx=e;
550 _unavailable=-1;
551 if (e.isPermanent())
552 _unavailable=-1;
553 else
554 {
555 if (_unavailableEx.getUnavailableSeconds()>0)
556 _unavailable=System.currentTimeMillis()+1000*_unavailableEx.getUnavailableSeconds();
557 else
558 _unavailable=System.currentTimeMillis()+5000;
559 }
560 }
561
562
563
564 private void makeUnavailable(final Throwable e)
565 {
566 if (e instanceof UnavailableException)
567 makeUnavailable((UnavailableException)e);
568 else
569 {
570 ServletContext ctx = _servletHandler.getServletContext();
571 if (ctx==null)
572 LOG.info("unavailable",e);
573 else
574 ctx.log("unavailable",e);
575 _unavailableEx=new UnavailableException(String.valueOf(e),-1)
576 {
577 {
578 initCause(e);
579 }
580 };
581 _unavailable=-1;
582 }
583 }
584
585
586 private void initServlet()
587 throws ServletException
588 {
589 Object old_run_as = null;
590 try
591 {
592 if (_servlet==null)
593 _servlet=newInstance();
594 if (_config==null)
595 _config=new Config();
596
597
598
599
600 if (_identityService!=null)
601 {
602 old_run_as=_identityService.setRunAs(_identityService.getSystemUserIdentity(),_runAsToken);
603 }
604
605
606 if (isJspServlet())
607 {
608 initJspServlet();
609 detectJspContainer();
610 }
611
612 initMultiPart();
613
614 if (_forcedPath != null && _jspContainer == null)
615 {
616 detectJspContainer();
617 }
618
619 if (LOG.isDebugEnabled())
620 LOG.debug("Servlet.init {} for {}",_servlet,getName());
621 _servlet.init(_config);
622 }
623 catch (UnavailableException e)
624 {
625 makeUnavailable(e);
626 _servlet=null;
627 _config=null;
628 throw e;
629 }
630 catch (ServletException e)
631 {
632 makeUnavailable(e.getCause()==null?e:e.getCause());
633 _servlet=null;
634 _config=null;
635 throw e;
636 }
637 catch (Exception e)
638 {
639 makeUnavailable(e);
640 _servlet=null;
641 _config=null;
642 throw new ServletException(this.toString(),e);
643 }
644 finally
645 {
646
647 if (_identityService!=null)
648 _identityService.unsetRunAs(old_run_as);
649 }
650 }
651
652
653
654
655
656
657 protected void initJspServlet () throws Exception
658 {
659 ContextHandler ch = ContextHandler.getContextHandler(getServletHandler().getServletContext());
660
661
662 ch.setAttribute("org.apache.catalina.jsp_classpath", ch.getClassPath());
663
664
665 if ("?".equals(getInitParameter("classpath")))
666 {
667 String classpath = ch.getClassPath();
668 if (LOG.isDebugEnabled())
669 LOG.debug("classpath=" + classpath);
670 if (classpath != null)
671 setInitParameter("classpath", classpath);
672 }
673
674
675 File scratch = null;
676 if (getInitParameter("scratchdir") == null)
677 {
678 File tmp = (File)getServletHandler().getServletContext().getAttribute(ServletContext.TEMPDIR);
679 scratch = new File(tmp, "jsp");
680 setInitParameter("scratchdir", scratch.getAbsolutePath());
681 }
682
683 scratch = new File (getInitParameter("scratchdir"));
684 if (!scratch.exists()) scratch.mkdir();
685 }
686
687
688
689
690
691
692
693
694 protected void initMultiPart () throws Exception
695 {
696
697
698 if (((Registration)getRegistration()).getMultipartConfig() != null)
699 {
700
701
702
703 ContextHandler ch = ContextHandler.getContextHandler(getServletHandler().getServletContext());
704 ch.addEventListener(MultiPartCleanerListener.INSTANCE);
705 }
706 }
707
708
709
710
711
712 @Override
713 public String getContextPath()
714 {
715 return _config.getServletContext().getContextPath();
716 }
717
718
719
720
721
722 @Override
723 public Map<String, String> getRoleRefMap()
724 {
725 return _roleMap;
726 }
727
728
729 @ManagedAttribute(value="role to run servlet as", readonly=true)
730 public String getRunAsRole()
731 {
732 return _runAsRole;
733 }
734
735
736 public void setRunAsRole(String role)
737 {
738 _runAsRole = role;
739 }
740
741
742
743
744
745
746
747
748
749
750
751 protected void prepare (Request baseRequest, ServletRequest request, ServletResponse response)
752 throws ServletException, UnavailableException
753 {
754 ensureInstance();
755 MultipartConfigElement mpce = ((Registration)getRegistration()).getMultipartConfig();
756 if (mpce != null)
757 baseRequest.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce);
758 }
759
760 public synchronized Servlet ensureInstance()
761 throws ServletException, UnavailableException
762 {
763 if (_class==null)
764 throw new UnavailableException("Servlet Not Initialized");
765 Servlet servlet=_servlet;
766 if (!isStarted())
767 throw new UnavailableException("Servlet not initialized", -1);
768 if (_unavailable!=0 || (!_initOnStartup && servlet==null))
769 servlet=getServlet();
770 if (servlet==null)
771 throw new UnavailableException("Could not instantiate "+_class);
772
773 return servlet;
774 }
775
776
777
778
779
780
781
782
783
784
785
786
787 public void handle(Request baseRequest,
788 ServletRequest request,
789 ServletResponse response)
790 throws ServletException,
791 UnavailableException,
792 IOException
793 {
794 if (_class==null)
795 throw new UnavailableException("Servlet Not Initialized");
796
797 Servlet servlet = ensureInstance();
798
799
800 boolean servlet_error=true;
801 Object old_run_as = null;
802 boolean suspendable = baseRequest.isAsyncSupported();
803 try
804 {
805
806 if (_forcedPath!=null)
807 adaptForcedPathToJspContainer(request);
808
809
810 if (_identityService!=null)
811 old_run_as=_identityService.setRunAs(baseRequest.getResolvedUserIdentity(),_runAsToken);
812
813 if (!isAsyncSupported())
814 baseRequest.setAsyncSupported(false);
815
816 servlet.service(request,response);
817 servlet_error=false;
818 }
819 catch(UnavailableException e)
820 {
821 makeUnavailable(e);
822 throw _unavailableEx;
823 }
824 finally
825 {
826 baseRequest.setAsyncSupported(suspendable);
827
828
829 if (_identityService!=null)
830 _identityService.unsetRunAs(old_run_as);
831
832
833 if (servlet_error)
834 request.setAttribute("javax.servlet.error.servlet_name",getName());
835 }
836 }
837
838
839
840 private boolean isJspServlet ()
841 {
842 if (_servlet == null)
843 return false;
844
845 Class<?> c = _servlet.getClass();
846
847 boolean result = false;
848 while (c != null && !result)
849 {
850 result = isJspServlet(c.getName());
851 c = c.getSuperclass();
852 }
853
854 return result;
855 }
856
857
858
859 private boolean isJspServlet (String classname)
860 {
861 if (classname == null)
862 return false;
863 return ("org.apache.jasper.servlet.JspServlet".equals(classname));
864 }
865
866
867 private void adaptForcedPathToJspContainer (ServletRequest request)
868 {
869
870 }
871
872
873 private void detectJspContainer ()
874 {
875 if (_jspContainer == null)
876 {
877 try
878 {
879
880 Loader.loadClass(Holder.class, APACHE_SENTINEL_CLASS);
881 if (LOG.isDebugEnabled())LOG.debug("Apache jasper detected");
882 _jspContainer = JspContainer.APACHE;
883 }
884 catch (ClassNotFoundException x)
885 {
886 if (LOG.isDebugEnabled())LOG.debug("Other jasper detected");
887 _jspContainer = JspContainer.OTHER;
888 }
889 }
890 }
891
892
893 private String getNameOfJspClass (String jsp)
894 {
895 if (jsp == null)
896 return "";
897
898 int i = jsp.lastIndexOf('/') + 1;
899 jsp = jsp.substring(i);
900 try
901 {
902 Class<?> jspUtil = Loader.loadClass(Holder.class, "org.apache.jasper.compiler.JspUtil");
903 Method makeJavaIdentifier = jspUtil.getMethod("makeJavaIdentifier", String.class);
904 return (String)makeJavaIdentifier.invoke(null, jsp);
905 }
906 catch (Exception e)
907 {
908 String tmp = jsp.replace('.','_');
909 LOG.warn("Unable to make identifier for jsp "+jsp +" trying "+tmp+" instead");
910 if (LOG.isDebugEnabled())
911 LOG.warn(e);
912 return tmp;
913 }
914 }
915
916
917
918 private String getPackageOfJspClass (String jsp)
919 {
920 if (jsp == null)
921 return "";
922
923 int i = jsp.lastIndexOf('/');
924 if (i <= 0)
925 return "";
926 try
927 {
928 Class<?> jspUtil = Loader.loadClass(Holder.class, "org.apache.jasper.compiler.JspUtil");
929 Method makeJavaPackage = jspUtil.getMethod("makeJavaPackage", String.class);
930 return (String)makeJavaPackage.invoke(null, jsp.substring(0,i));
931 }
932 catch (Exception e)
933 {
934 String tmp = jsp.substring(1).replace('/','.');
935 LOG.warn("Unable to make package for jsp "+jsp +" trying "+tmp+" instead");
936 if (LOG.isDebugEnabled())
937 LOG.warn(e);
938 return tmp;
939 }
940 }
941
942
943
944 private String getJspPackagePrefix ()
945 {
946 String jspPackageName = (String)getServletHandler().getServletContext().getInitParameter(JSP_GENERATED_PACKAGE_NAME );
947 if (jspPackageName == null)
948 jspPackageName = "org.apache.jsp";
949
950 return jspPackageName;
951 }
952
953
954
955 private String getClassNameForJsp (String jsp)
956 {
957 if (jsp == null)
958 return null;
959
960 return getJspPackagePrefix() + "." +getPackageOfJspClass(jsp) + "." + getNameOfJspClass(jsp);
961 }
962
963
964
965
966
967 protected class Config extends HolderConfig implements ServletConfig
968 {
969
970 @Override
971 public String getServletName()
972 {
973 return getName();
974 }
975
976 }
977
978
979
980
981 public class Registration extends HolderRegistration implements ServletRegistration.Dynamic
982 {
983 protected MultipartConfigElement _multipartConfig;
984
985 @Override
986 public Set<String> addMapping(String... urlPatterns)
987 {
988 illegalStateIfContextStarted();
989 Set<String> clash=null;
990 for (String pattern : urlPatterns)
991 {
992 ServletMapping mapping = _servletHandler.getServletMapping(pattern);
993 if (mapping!=null)
994 {
995
996 if (!mapping.isDefault())
997 {
998 if (clash==null)
999 clash=new HashSet<String>();
1000 clash.add(pattern);
1001 }
1002 }
1003 }
1004
1005
1006 if (clash!=null)
1007 return clash;
1008
1009
1010 ServletMapping mapping = new ServletMapping();
1011 mapping.setServletName(ServletHolder.this.getName());
1012 mapping.setPathSpecs(urlPatterns);
1013 _servletHandler.addServletMapping(mapping);
1014
1015 return Collections.emptySet();
1016 }
1017
1018 @Override
1019 public Collection<String> getMappings()
1020 {
1021 ServletMapping[] mappings =_servletHandler.getServletMappings();
1022 List<String> patterns=new ArrayList<String>();
1023 if (mappings!=null)
1024 {
1025 for (ServletMapping mapping : mappings)
1026 {
1027 if (!mapping.getServletName().equals(getName()))
1028 continue;
1029 String[] specs=mapping.getPathSpecs();
1030 if (specs!=null && specs.length>0)
1031 patterns.addAll(Arrays.asList(specs));
1032 }
1033 }
1034 return patterns;
1035 }
1036
1037 @Override
1038 public String getRunAsRole()
1039 {
1040 return _runAsRole;
1041 }
1042
1043 @Override
1044 public void setLoadOnStartup(int loadOnStartup)
1045 {
1046 illegalStateIfContextStarted();
1047 ServletHolder.this.setInitOrder(loadOnStartup);
1048 }
1049
1050 public int getInitOrder()
1051 {
1052 return ServletHolder.this.getInitOrder();
1053 }
1054
1055 @Override
1056 public void setMultipartConfig(MultipartConfigElement element)
1057 {
1058 _multipartConfig = element;
1059 }
1060
1061 public MultipartConfigElement getMultipartConfig()
1062 {
1063 return _multipartConfig;
1064 }
1065
1066 @Override
1067 public void setRunAsRole(String role)
1068 {
1069 _runAsRole = role;
1070 }
1071
1072 @Override
1073 public Set<String> setServletSecurity(ServletSecurityElement securityElement)
1074 {
1075 return _servletHandler.setServletSecurity(this, securityElement);
1076 }
1077 }
1078
1079 public ServletRegistration.Dynamic getRegistration()
1080 {
1081 if (_registration == null)
1082 _registration = new Registration();
1083 return _registration;
1084 }
1085
1086
1087
1088
1089 private class SingleThreadedWrapper implements Servlet
1090 {
1091 Stack<Servlet> _stack=new Stack<Servlet>();
1092
1093 @Override
1094 public void destroy()
1095 {
1096 synchronized(this)
1097 {
1098 while(_stack.size()>0)
1099 try { (_stack.pop()).destroy(); } catch (Exception e) { LOG.warn(e); }
1100 }
1101 }
1102
1103 @Override
1104 public ServletConfig getServletConfig()
1105 {
1106 return _config;
1107 }
1108
1109 @Override
1110 public String getServletInfo()
1111 {
1112 return null;
1113 }
1114
1115 @Override
1116 public void init(ServletConfig config) throws ServletException
1117 {
1118 synchronized(this)
1119 {
1120 if(_stack.size()==0)
1121 {
1122 try
1123 {
1124 Servlet s = newInstance();
1125 s.init(config);
1126 _stack.push(s);
1127 }
1128 catch (ServletException e)
1129 {
1130 throw e;
1131 }
1132 catch (Exception e)
1133 {
1134 throw new ServletException(e);
1135 }
1136 }
1137 }
1138 }
1139
1140 @Override
1141 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
1142 {
1143 Servlet s;
1144 synchronized(this)
1145 {
1146 if(_stack.size()>0)
1147 s=(Servlet)_stack.pop();
1148 else
1149 {
1150 try
1151 {
1152 s = newInstance();
1153 s.init(_config);
1154 }
1155 catch (ServletException e)
1156 {
1157 throw e;
1158 }
1159 catch (Exception e)
1160 {
1161 throw new ServletException(e);
1162 }
1163 }
1164 }
1165
1166 try
1167 {
1168 s.service(req,res);
1169 }
1170 finally
1171 {
1172 synchronized(this)
1173 {
1174 _stack.push(s);
1175 }
1176 }
1177 }
1178 }
1179
1180
1181
1182
1183
1184
1185
1186
1187 protected Servlet newInstance() throws ServletException, IllegalAccessException, InstantiationException
1188 {
1189 try
1190 {
1191 ServletContext ctx = getServletHandler().getServletContext();
1192 if (ctx instanceof ServletContextHandler.Context)
1193 return ((ServletContextHandler.Context)ctx).createServlet(getHeldClass());
1194 return getHeldClass().newInstance();
1195 }
1196 catch (ServletException se)
1197 {
1198 Throwable cause = se.getRootCause();
1199 if (cause instanceof InstantiationException)
1200 throw (InstantiationException)cause;
1201 if (cause instanceof IllegalAccessException)
1202 throw (IllegalAccessException)cause;
1203 throw se;
1204 }
1205 }
1206
1207
1208
1209 @Override
1210 public String toString()
1211 {
1212 return String.format("%s@%x==%s,%d,%b",_name,hashCode(),_className,_initOrder,_servlet!=null);
1213 }
1214 }