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