blob: 30542b12910a932eace9f5a24e3c139231b3d854 [file] [log] [blame]
Jake Slack03928ae2014-05-13 18:41:56 -07001//
2// ========================================================================
3// Copyright (c) 1995-2014 Mort Bay Consulting Pty. Ltd.
4// ------------------------------------------------------------------------
5// All rights reserved. This program and the accompanying materials
6// are made available under the terms of the Eclipse Public License v1.0
7// and Apache License v2.0 which accompanies this distribution.
8//
9// The Eclipse Public License is available at
10// http://www.eclipse.org/legal/epl-v10.html
11//
12// The Apache License v2.0 is available at
13// http://www.opensource.org/licenses/apache2.0.php
14//
15// You may elect to redistribute this code under either of these licenses.
16// ========================================================================
17//
18
19package org.eclipse.jetty.servlet;
20
21import java.io.IOException;
22import java.util.ArrayList;
23import java.util.Arrays;
24import java.util.Collection;
25import java.util.Collections;
26import java.util.HashMap;
27import java.util.HashSet;
28import java.util.List;
29import java.util.Map;
30import java.util.Set;
31import java.util.Stack;
32
33import javax.servlet.MultipartConfigElement;
34import javax.servlet.Servlet;
35import javax.servlet.ServletConfig;
36import javax.servlet.ServletException;
37import javax.servlet.ServletRegistration;
38import javax.servlet.ServletContext;
39import javax.servlet.ServletRequest;
40import javax.servlet.ServletResponse;
41import javax.servlet.ServletSecurityElement;
42import javax.servlet.SingleThreadModel;
43import javax.servlet.UnavailableException;
44
45import org.eclipse.jetty.security.IdentityService;
46import org.eclipse.jetty.security.RunAsToken;
47import org.eclipse.jetty.server.Request;
48import org.eclipse.jetty.server.UserIdentity;
49import org.eclipse.jetty.server.handler.ContextHandler;
50import org.eclipse.jetty.util.Loader;
51import org.eclipse.jetty.util.log.Log;
52import org.eclipse.jetty.util.log.Logger;
53
54
55
56
57/* --------------------------------------------------------------------- */
58/** Servlet Instance and Context Holder.
59 * Holds the name, params and some state of a javax.servlet.Servlet
60 * instance. It implements the ServletConfig interface.
61 * This class will organise the loading of the servlet when needed or
62 * requested.
63 *
64 *
65 */
66public class ServletHolder extends Holder<Servlet> implements UserIdentity.Scope, Comparable
67{
68 private static final Logger LOG = Log.getLogger(ServletHolder.class);
69
70 /* ---------------------------------------------------------------- */
71 private int _initOrder;
72 private boolean _initOnStartup=false;
73 private Map<String, String> _roleMap;
74 private String _forcedPath;
75 private String _runAsRole;
76 private RunAsToken _runAsToken;
77 private IdentityService _identityService;
78 private ServletRegistration.Dynamic _registration;
79
80
81 private transient Servlet _servlet;
82 private transient Config _config;
83 private transient long _unavailable;
84 private transient boolean _enabled = true;
85 private transient UnavailableException _unavailableEx;
86 public static final Map<String,String> NO_MAPPED_ROLES = Collections.emptyMap();
87
88 /* ---------------------------------------------------------------- */
89 /** Constructor .
90 */
91 public ServletHolder()
92 {
93 this(Source.EMBEDDED);
94 }
95
96 /* ---------------------------------------------------------------- */
97 /** Constructor .
98 */
99 public ServletHolder(Holder.Source creator)
100 {
101 super(creator);
102 }
103
104 /* ---------------------------------------------------------------- */
105 /** Constructor for existing servlet.
106 */
107 public ServletHolder(Servlet servlet)
108 {
109 this(Source.EMBEDDED);
110 setServlet(servlet);
111 }
112
113 /* ---------------------------------------------------------------- */
114 /** Constructor for servlet class.
115 */
116 public ServletHolder(String name, Class<? extends Servlet> servlet)
117 {
118 this(Source.EMBEDDED);
119 setName(name);
120 setHeldClass(servlet);
121 }
122
123 /* ---------------------------------------------------------------- */
124 /** Constructor for servlet class.
125 */
126 public ServletHolder(String name, Servlet servlet)
127 {
128 this(Source.EMBEDDED);
129 setName(name);
130 setServlet(servlet);
131 }
132
133 /* ---------------------------------------------------------------- */
134 /** Constructor for servlet class.
135 */
136 public ServletHolder(Class<? extends Servlet> servlet)
137 {
138 this(Source.EMBEDDED);
139 setHeldClass(servlet);
140 }
141
142 /* ---------------------------------------------------------------- */
143 /**
144 * @return The unavailable exception or null if not unavailable
145 */
146 public UnavailableException getUnavailableException()
147 {
148 return _unavailableEx;
149 }
150
151 /* ------------------------------------------------------------ */
152 public synchronized void setServlet(Servlet servlet)
153 {
154 if (servlet==null || servlet instanceof SingleThreadModel)
155 throw new IllegalArgumentException();
156
157 _extInstance=true;
158 _servlet=servlet;
159 setHeldClass(servlet.getClass());
160 if (getName()==null)
161 setName(servlet.getClass().getName()+"-"+super.hashCode());
162 }
163
164 /* ------------------------------------------------------------ */
165 public int getInitOrder()
166 {
167 return _initOrder;
168 }
169
170 /* ------------------------------------------------------------ */
171 /** Set the initialize order.
172 * Holders with order<0, are initialized on use. Those with
173 * order>=0 are initialized in increasing order when the handler
174 * is started.
175 */
176 public void setInitOrder(int order)
177 {
178 _initOnStartup=true;
179 _initOrder = order;
180 }
181
182 public boolean isSetInitOrder()
183 {
184 return _initOnStartup;
185 }
186
187 /* ------------------------------------------------------------ */
188 /** Comparitor by init order.
189 */
190 public int compareTo(Object o)
191 {
192 if (o instanceof ServletHolder)
193 {
194 ServletHolder sh= (ServletHolder)o;
195 if (sh==this)
196 return 0;
197 if (sh._initOrder<_initOrder)
198 return 1;
199 if (sh._initOrder>_initOrder)
200 return -1;
201
202 int c=(_className!=null && sh._className!=null)?_className.compareTo(sh._className):0;
203 if (c==0)
204 c=_name.compareTo(sh._name);
205 return c;
206 }
207 return 1;
208 }
209
210 /* ------------------------------------------------------------ */
211 public boolean equals(Object o)
212 {
213 return compareTo(o)==0;
214 }
215
216 /* ------------------------------------------------------------ */
217 public int hashCode()
218 {
219 return _name==null?System.identityHashCode(this):_name.hashCode();
220 }
221
222 /* ------------------------------------------------------------ */
223 /** Link a user role.
224 * Translate the role name used by a servlet, to the link name
225 * used by the container.
226 * @param name The role name as used by the servlet
227 * @param link The role name as used by the container.
228 */
229 public synchronized void setUserRoleLink(String name,String link)
230 {
231 if (_roleMap==null)
232 _roleMap=new HashMap<String, String>();
233 _roleMap.put(name,link);
234 }
235
236 /* ------------------------------------------------------------ */
237 /** get a user role link.
238 * @param name The name of the role
239 * @return The name as translated by the link. If no link exists,
240 * the name is returned.
241 */
242 public String getUserRoleLink(String name)
243 {
244 if (_roleMap==null)
245 return name;
246 String link= _roleMap.get(name);
247 return (link==null)?name:link;
248 }
249
250 /* ------------------------------------------------------------ */
251 public Map<String, String> getRoleMap()
252 {
253 return _roleMap == null? NO_MAPPED_ROLES : _roleMap;
254 }
255
256 /* ------------------------------------------------------------ */
257 /**
258 * @return Returns the forcedPath.
259 */
260 public String getForcedPath()
261 {
262 return _forcedPath;
263 }
264
265 /* ------------------------------------------------------------ */
266 /**
267 * @param forcedPath The forcedPath to set.
268 */
269 public void setForcedPath(String forcedPath)
270 {
271 _forcedPath = forcedPath;
272 }
273
274 public boolean isEnabled()
275 {
276 return _enabled;
277 }
278
279
280 public void setEnabled(boolean enabled)
281 {
282 _enabled = enabled;
283 }
284
285
286 /* ------------------------------------------------------------ */
287 public void doStart()
288 throws Exception
289 {
290 _unavailable=0;
291 if (!_enabled)
292 return;
293
294
295 //check servlet has a class (ie is not a preliminary registration). If preliminary, fail startup.
296 try
297 {
298 super.doStart();
299 }
300 catch (UnavailableException ue)
301 {
302 makeUnavailable(ue);
303 if (_servletHandler.isStartWithUnavailable())
304 {
305 LOG.ignore(ue);
306 return;
307 }
308 else
309 throw ue;
310 }
311
312
313 //servlet is not an instance of javax.servlet.Servlet
314 try
315 {
316 checkServletType();
317 }
318 catch (UnavailableException ue)
319 {
320 makeUnavailable(ue);
321 if (_servletHandler.isStartWithUnavailable())
322 {
323 LOG.ignore(ue);
324 return;
325 }
326 else
327 throw ue;
328 }
329
330
331 _identityService = _servletHandler.getIdentityService();
332 if (_identityService!=null && _runAsRole!=null)
333 _runAsToken=_identityService.newRunAsToken(_runAsRole);
334
335 _config=new Config();
336
337 if (_class!=null && javax.servlet.SingleThreadModel.class.isAssignableFrom(_class))
338 _servlet = new SingleThreadedWrapper();
339
340 if (_extInstance || _initOnStartup)
341 {
342 try
343 {
344 initServlet();
345 }
346 catch(Exception e)
347 {
348 if (_servletHandler.isStartWithUnavailable())
349 LOG.ignore(e);
350 else
351 throw e;
352 }
353 }
354 }
355
356 /* ------------------------------------------------------------ */
357 public void doStop()
358 throws Exception
359 {
360 Object old_run_as = null;
361 if (_servlet!=null)
362 {
363 try
364 {
365 if (_identityService!=null)
366 old_run_as=_identityService.setRunAs(_identityService.getSystemUserIdentity(),_runAsToken);
367
368 destroyInstance(_servlet);
369 }
370 catch (Exception e)
371 {
372 LOG.warn(e);
373 }
374 finally
375 {
376 if (_identityService!=null)
377 _identityService.unsetRunAs(old_run_as);
378 }
379 }
380
381 if (!_extInstance)
382 _servlet=null;
383
384 _config=null;
385 }
386
387 /* ------------------------------------------------------------ */
388 public void destroyInstance (Object o)
389 throws Exception
390 {
391 if (o==null)
392 return;
393 Servlet servlet = ((Servlet)o);
394 getServletHandler().destroyServlet(servlet);
395 servlet.destroy();
396 }
397
398 /* ------------------------------------------------------------ */
399 /** Get the servlet.
400 * @return The servlet
401 */
402 public synchronized Servlet getServlet()
403 throws ServletException
404 {
405 // Handle previous unavailability
406 if (_unavailable!=0)
407 {
408 if (_unavailable<0 || _unavailable>0 && System.currentTimeMillis()<_unavailable)
409 throw _unavailableEx;
410 _unavailable=0;
411 _unavailableEx=null;
412 }
413
414 if (_servlet==null)
415 initServlet();
416 return _servlet;
417 }
418
419 /* ------------------------------------------------------------ */
420 /** Get the servlet instance (no initialization done).
421 * @return The servlet or null
422 */
423 public Servlet getServletInstance()
424 {
425 return _servlet;
426 }
427
428 /* ------------------------------------------------------------ */
429 /**
430 * Check to ensure class of servlet is acceptable.
431 * @throws UnavailableException
432 */
433 public void checkServletType ()
434 throws UnavailableException
435 {
436 if (_class==null || !javax.servlet.Servlet.class.isAssignableFrom(_class))
437 {
438 throw new UnavailableException("Servlet "+_class+" is not a javax.servlet.Servlet");
439 }
440 }
441
442 /* ------------------------------------------------------------ */
443 /**
444 * @return true if the holder is started and is not unavailable
445 */
446 public boolean isAvailable()
447 {
448 if (isStarted()&& _unavailable==0)
449 return true;
450 try
451 {
452 getServlet();
453 }
454 catch(Exception e)
455 {
456 LOG.ignore(e);
457 }
458
459 return isStarted()&& _unavailable==0;
460 }
461
462 /* ------------------------------------------------------------ */
463 private void makeUnavailable(UnavailableException e)
464 {
465 if (_unavailableEx==e && _unavailable!=0)
466 return;
467
468 _servletHandler.getServletContext().log("unavailable",e);
469
470 _unavailableEx=e;
471 _unavailable=-1;
472 if (e.isPermanent())
473 _unavailable=-1;
474 else
475 {
476 if (_unavailableEx.getUnavailableSeconds()>0)
477 _unavailable=System.currentTimeMillis()+1000*_unavailableEx.getUnavailableSeconds();
478 else
479 _unavailable=System.currentTimeMillis()+5000; // TODO configure
480 }
481 }
482
483 /* ------------------------------------------------------------ */
484
485 private void makeUnavailable(final Throwable e)
486 {
487 if (e instanceof UnavailableException)
488 makeUnavailable((UnavailableException)e);
489 else
490 {
491 ServletContext ctx = _servletHandler.getServletContext();
492 if (ctx==null)
493 LOG.info("unavailable",e);
494 else
495 ctx.log("unavailable",e);
496 _unavailableEx=new UnavailableException(String.valueOf(e),-1)
497 {
498 {
499 initCause(e);
500 }
501 };
502 _unavailable=-1;
503 }
504 }
505
506 /* ------------------------------------------------------------ */
507 private void initServlet()
508 throws ServletException
509 {
510 Object old_run_as = null;
511 try
512 {
513 if (_servlet==null)
514 _servlet=newInstance();
515 if (_config==null)
516 _config=new Config();
517
518 // Handle run as
519 if (_identityService!=null)
520 {
521 old_run_as=_identityService.setRunAs(_identityService.getSystemUserIdentity(),_runAsToken);
522 }
523
524 // Handle configuring servlets that implement org.apache.jasper.servlet.JspServlet
525 if (isJspServlet())
526 {
527 initJspServlet();
528 }
529
530 initMultiPart();
531
532 _servlet.init(_config);
533 }
534 catch (UnavailableException e)
535 {
536 makeUnavailable(e);
537 _servlet=null;
538 _config=null;
539 throw e;
540 }
541 catch (ServletException e)
542 {
543 makeUnavailable(e.getCause()==null?e:e.getCause());
544 _servlet=null;
545 _config=null;
546 throw e;
547 }
548 catch (Exception e)
549 {
550 makeUnavailable(e);
551 _servlet=null;
552 _config=null;
553 throw new ServletException(this.toString(),e);
554 }
555 finally
556 {
557 // pop run-as role
558 if (_identityService!=null)
559 _identityService.unsetRunAs(old_run_as);
560 }
561 }
562
563
564 /* ------------------------------------------------------------ */
565 /**
566 * @throws Exception
567 */
568 protected void initJspServlet () throws Exception
569 {
570 ContextHandler ch = ((ContextHandler.Context)getServletHandler().getServletContext()).getContextHandler();
571
572 /* Set the webapp's classpath for Jasper */
573 ch.setAttribute("org.apache.catalina.jsp_classpath", ch.getClassPath());
574
575 /* Set the system classpath for Jasper */
576 setInitParameter("com.sun.appserv.jsp.classpath", Loader.getClassPath(ch.getClassLoader().getParent()));
577
578 /* Set up other classpath attribute */
579 if ("?".equals(getInitParameter("classpath")))
580 {
581 String classpath = ch.getClassPath();
582 LOG.debug("classpath=" + classpath);
583 if (classpath != null)
584 setInitParameter("classpath", classpath);
585 }
586 }
587
588 /* ------------------------------------------------------------ */
589 /**
590 * Register a ServletRequestListener that will ensure tmp multipart
591 * files are deleted when the request goes out of scope.
592 *
593 * @throws Exception
594 */
595 protected void initMultiPart () throws Exception
596 {
597 //if this servlet can handle multipart requests, ensure tmp files will be
598 //cleaned up correctly
599 if (((Registration)getRegistration()).getMultipartConfig() != null)
600 {
601 //Register a listener to delete tmp files that are created as a result of this
602 //servlet calling Request.getPart() or Request.getParts()
603 ContextHandler ch = ((ContextHandler.Context)getServletHandler().getServletContext()).getContextHandler();
604 ch.addEventListener(new Request.MultiPartCleanerListener());
605 }
606 }
607
608 /* ------------------------------------------------------------ */
609 /**
610 * @see org.eclipse.jetty.server.UserIdentity.Scope#getContextPath()
611 */
612 public String getContextPath()
613 {
614 return _config.getServletContext().getContextPath();
615 }
616
617 /* ------------------------------------------------------------ */
618 /**
619 * @see org.eclipse.jetty.server.UserIdentity.Scope#getRoleRefMap()
620 */
621 public Map<String, String> getRoleRefMap()
622 {
623 return _roleMap;
624 }
625
626 /* ------------------------------------------------------------ */
627 public String getRunAsRole()
628 {
629 return _runAsRole;
630 }
631
632 /* ------------------------------------------------------------ */
633 public void setRunAsRole(String role)
634 {
635 _runAsRole = role;
636 }
637
638 /* ------------------------------------------------------------ */
639 /** Service a request with this servlet.
640 */
641 public void handle(Request baseRequest,
642 ServletRequest request,
643 ServletResponse response)
644 throws ServletException,
645 UnavailableException,
646 IOException
647 {
648 if (_class==null)
649 throw new UnavailableException("Servlet Not Initialized");
650
651 Servlet servlet=_servlet;
652 synchronized(this)
653 {
654 if (!isStarted())
655 throw new UnavailableException("Servlet not initialized", -1);
656 if (_unavailable!=0 || !_initOnStartup)
657 servlet=getServlet();
658 if (servlet==null)
659 throw new UnavailableException("Could not instantiate "+_class);
660 }
661
662 // Service the request
663 boolean servlet_error=true;
664 Object old_run_as = null;
665 boolean suspendable = baseRequest.isAsyncSupported();
666 try
667 {
668 // Handle aliased path
669 if (_forcedPath!=null)
670 // TODO complain about poor naming to the Jasper folks
671 request.setAttribute("org.apache.catalina.jsp_file",_forcedPath);
672
673 // Handle run as
674 if (_identityService!=null)
675 old_run_as=_identityService.setRunAs(baseRequest.getResolvedUserIdentity(),_runAsToken);
676
677 if (!isAsyncSupported())
678 baseRequest.setAsyncSupported(false);
679
680 MultipartConfigElement mpce = ((Registration)getRegistration()).getMultipartConfig();
681 if (mpce != null)
682 request.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, mpce);
683
684 servlet.service(request,response);
685 servlet_error=false;
686 }
687 catch(UnavailableException e)
688 {
689 makeUnavailable(e);
690 throw _unavailableEx;
691 }
692 finally
693 {
694 baseRequest.setAsyncSupported(suspendable);
695
696 // pop run-as role
697 if (_identityService!=null)
698 _identityService.unsetRunAs(old_run_as);
699
700 // Handle error params.
701 if (servlet_error)
702 request.setAttribute("javax.servlet.error.servlet_name",getName());
703 }
704 }
705
706
707 /* ------------------------------------------------------------ */
708 private boolean isJspServlet ()
709 {
710 if (_servlet == null)
711 return false;
712
713 Class c = _servlet.getClass();
714
715 boolean result = false;
716 while (c != null && !result)
717 {
718 result = isJspServlet(c.getName());
719 c = c.getSuperclass();
720 }
721
722 return result;
723 }
724
725
726 /* ------------------------------------------------------------ */
727 private boolean isJspServlet (String classname)
728 {
729 if (classname == null)
730 return false;
731 return ("org.apache.jasper.servlet.JspServlet".equals(classname));
732 }
733
734
735 /* ------------------------------------------------------------ */
736 /* ------------------------------------------------------------ */
737 /* ------------------------------------------------------------ */
738 protected class Config extends HolderConfig implements ServletConfig
739 {
740 /* -------------------------------------------------------- */
741 public String getServletName()
742 {
743 return getName();
744 }
745
746 }
747
748 /* -------------------------------------------------------- */
749 /* -------------------------------------------------------- */
750 /* -------------------------------------------------------- */
751 public class Registration extends HolderRegistration implements ServletRegistration.Dynamic
752 {
753 protected MultipartConfigElement _multipartConfig;
754
755 public Set<String> addMapping(String... urlPatterns)
756 {
757 illegalStateIfContextStarted();
758 Set<String> clash=null;
759 for (String pattern : urlPatterns)
760 {
761 ServletMapping mapping = _servletHandler.getServletMapping(pattern);
762 if (mapping!=null)
763 {
764 //if the servlet mapping was from a default descriptor, then allow it to be overridden
765 if (!mapping.isDefault())
766 {
767 if (clash==null)
768 clash=new HashSet<String>();
769 clash.add(pattern);
770 }
771 }
772 }
773
774 //if there were any clashes amongst the urls, return them
775 if (clash!=null)
776 return clash;
777
778 //otherwise apply all of them
779 ServletMapping mapping = new ServletMapping();
780 mapping.setServletName(ServletHolder.this.getName());
781 mapping.setPathSpecs(urlPatterns);
782 _servletHandler.addServletMapping(mapping);
783
784 return Collections.emptySet();
785 }
786
787 public Collection<String> getMappings()
788 {
789 ServletMapping[] mappings =_servletHandler.getServletMappings();
790 List<String> patterns=new ArrayList<String>();
791 if (mappings!=null)
792 {
793 for (ServletMapping mapping : mappings)
794 {
795 if (!mapping.getServletName().equals(getName()))
796 continue;
797 String[] specs=mapping.getPathSpecs();
798 if (specs!=null && specs.length>0)
799 patterns.addAll(Arrays.asList(specs));
800 }
801 }
802 return patterns;
803 }
804
805 @Override
806 public String getRunAsRole()
807 {
808 return _runAsRole;
809 }
810
811 @Override
812 public void setLoadOnStartup(int loadOnStartup)
813 {
814 illegalStateIfContextStarted();
815 ServletHolder.this.setInitOrder(loadOnStartup);
816 }
817
818 public int getInitOrder()
819 {
820 return ServletHolder.this.getInitOrder();
821 }
822
823 @Override
824 public void setMultipartConfig(MultipartConfigElement element)
825 {
826 _multipartConfig = element;
827 }
828
829 public MultipartConfigElement getMultipartConfig()
830 {
831 return _multipartConfig;
832 }
833
834 @Override
835 public void setRunAsRole(String role)
836 {
837 _runAsRole = role;
838 }
839
840 @Override
841 public Set<String> setServletSecurity(ServletSecurityElement securityElement)
842 {
843 return _servletHandler.setServletSecurity(this, securityElement);
844 }
845 }
846
847 public ServletRegistration.Dynamic getRegistration()
848 {
849 if (_registration == null)
850 _registration = new Registration();
851 return _registration;
852 }
853
854 /* -------------------------------------------------------- */
855 /* -------------------------------------------------------- */
856 /* -------------------------------------------------------- */
857 private class SingleThreadedWrapper implements Servlet
858 {
859 Stack<Servlet> _stack=new Stack<Servlet>();
860
861 public void destroy()
862 {
863 synchronized(this)
864 {
865 while(_stack.size()>0)
866 try { (_stack.pop()).destroy(); } catch (Exception e) { LOG.warn(e); }
867 }
868 }
869
870 public ServletConfig getServletConfig()
871 {
872 return _config;
873 }
874
875 public String getServletInfo()
876 {
877 return null;
878 }
879
880 public void init(ServletConfig config) throws ServletException
881 {
882 synchronized(this)
883 {
884 if(_stack.size()==0)
885 {
886 try
887 {
888 Servlet s = newInstance();
889 s.init(config);
890 _stack.push(s);
891 }
892 catch (ServletException e)
893 {
894 throw e;
895 }
896 catch (Exception e)
897 {
898 throw new ServletException(e);
899 }
900 }
901 }
902 }
903
904 public void service(ServletRequest req, ServletResponse res) throws ServletException, IOException
905 {
906 Servlet s;
907 synchronized(this)
908 {
909 if(_stack.size()>0)
910 s=(Servlet)_stack.pop();
911 else
912 {
913 try
914 {
915 s = newInstance();
916 s.init(_config);
917 }
918 catch (ServletException e)
919 {
920 throw e;
921 }
922 catch (Exception e)
923 {
924 throw new ServletException(e);
925 }
926 }
927 }
928
929 try
930 {
931 s.service(req,res);
932 }
933 finally
934 {
935 synchronized(this)
936 {
937 _stack.push(s);
938 }
939 }
940 }
941 }
942
943 /* ------------------------------------------------------------ */
944 /**
945 * @return the newly created Servlet instance
946 * @throws ServletException
947 * @throws IllegalAccessException
948 * @throws InstantiationException
949 */
950 protected Servlet newInstance() throws ServletException, IllegalAccessException, InstantiationException
951 {
952 try
953 {
954 ServletContext ctx = getServletHandler().getServletContext();
955 if (ctx==null)
956 return getHeldClass().newInstance();
957 return ((ServletContextHandler.Context)ctx).createServlet(getHeldClass());
958 }
959 catch (ServletException se)
960 {
961 Throwable cause = se.getRootCause();
962 if (cause instanceof InstantiationException)
963 throw (InstantiationException)cause;
964 if (cause instanceof IllegalAccessException)
965 throw (IllegalAccessException)cause;
966 throw se;
967 }
968 }
969}