1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.servlet;
15
16 import java.io.IOException;
17 import java.util.ArrayList;
18 import java.util.Arrays;
19 import java.util.Collections;
20 import java.util.EnumSet;
21 import java.util.HashMap;
22 import java.util.HashSet;
23 import java.util.Set;
24 import java.util.List;
25 import java.util.Map;
26 import java.util.Queue;
27 import java.util.concurrent.ConcurrentHashMap;
28 import java.util.concurrent.ConcurrentLinkedQueue;
29 import java.util.concurrent.ConcurrentMap;
30
31 import javax.servlet.DispatcherType;
32 import javax.servlet.Filter;
33 import javax.servlet.FilterChain;
34 import javax.servlet.RequestDispatcher;
35 import javax.servlet.Servlet;
36 import javax.servlet.ServletContext;
37 import javax.servlet.ServletException;
38 import javax.servlet.ServletRegistration;
39 import javax.servlet.ServletRequest;
40 import javax.servlet.ServletResponse;
41 import javax.servlet.ServletSecurityElement;
42 import javax.servlet.UnavailableException;
43 import javax.servlet.http.HttpServletRequest;
44 import javax.servlet.http.HttpServletResponse;
45
46 import org.eclipse.jetty.continuation.ContinuationThrowable;
47 import org.eclipse.jetty.http.HttpException;
48 import org.eclipse.jetty.http.PathMap;
49 import org.eclipse.jetty.io.EofException;
50 import org.eclipse.jetty.io.UncheckedIOException;
51 import org.eclipse.jetty.security.IdentityService;
52 import org.eclipse.jetty.security.SecurityHandler;
53 import org.eclipse.jetty.server.Dispatcher;
54 import org.eclipse.jetty.server.HttpConnection;
55 import org.eclipse.jetty.server.Request;
56 import org.eclipse.jetty.server.Server;
57 import org.eclipse.jetty.server.ServletRequestHttpWrapper;
58 import org.eclipse.jetty.server.ServletResponseHttpWrapper;
59 import org.eclipse.jetty.server.UserIdentity;
60 import org.eclipse.jetty.server.handler.ContextHandler;
61 import org.eclipse.jetty.server.handler.ScopedHandler;
62 import org.eclipse.jetty.util.LazyList;
63 import org.eclipse.jetty.util.MultiException;
64 import org.eclipse.jetty.util.MultiMap;
65 import org.eclipse.jetty.util.TypeUtil;
66 import org.eclipse.jetty.util.URIUtil;
67 import org.eclipse.jetty.util.log.Log;
68
69
70
71
72
73
74
75
76
77
78
79
80
81 public class ServletHandler extends ScopedHandler
82 {
83
84 public static final String __DEFAULT_SERVLET="default";
85
86
87 private ServletContextHandler _contextHandler;
88 private ContextHandler.Context _servletContext;
89 private FilterHolder[] _filters=new FilterHolder[0];
90 private FilterMapping[] _filterMappings;
91 private boolean _filterChainsCached=true;
92 private int _maxFilterChainsCacheSize=512;
93 private boolean _startWithUnavailable=true;
94 private IdentityService _identityService;
95 private SecurityHandler _securityHandler;
96
97 private ServletHolder[] _servlets=new ServletHolder[0];
98 private ServletMapping[] _servletMappings;
99
100 private final Map<String,FilterHolder> _filterNameMap= new HashMap<String,FilterHolder>();
101 private List<FilterMapping> _filterPathMappings;
102 private MultiMap<String> _filterNameMappings;
103
104 private final Map<String,ServletHolder> _servletNameMap=new HashMap<String,ServletHolder>();
105 private PathMap _servletPathMap;
106
107 protected final ConcurrentMap<String,FilterChain> _chainCache[] = new ConcurrentMap[FilterMapping.ALL];
108 protected final Queue<String>[] _chainLRU = new Queue[FilterMapping.ALL];
109
110
111
112
113
114 public ServletHandler()
115 {
116 }
117
118
119
120
121
122 public void setServer(Server server)
123 {
124 Server old=getServer();
125 if (old!=null && old!=server)
126 {
127 getServer().getContainer().update(this, _filters, null, "filter",true);
128 getServer().getContainer().update(this, _filterMappings, null, "filterMapping",true);
129 getServer().getContainer().update(this, _servlets, null, "servlet",true);
130 getServer().getContainer().update(this, _servletMappings, null, "servletMapping",true);
131 }
132
133 super.setServer(server);
134
135 if (server!=null && old!=server)
136 {
137 server.getContainer().update(this, null, _filters, "filter",true);
138 server.getContainer().update(this, null, _filterMappings, "filterMapping",true);
139 server.getContainer().update(this, null, _servlets, "servlet",true);
140 server.getContainer().update(this, null, _servletMappings, "servletMapping",true);
141 }
142 }
143
144
145 @Override
146 protected synchronized void doStart()
147 throws Exception
148 {
149 _servletContext=ContextHandler.getCurrentContext();
150 _contextHandler=(ServletContextHandler)(_servletContext==null?null:_servletContext.getContextHandler());
151
152 if (_contextHandler!=null)
153 {
154 _securityHandler = (SecurityHandler)_contextHandler.getChildHandlerByClass(SecurityHandler.class);
155 if (_securityHandler!=null)
156 _identityService=_securityHandler.getIdentityService();
157 }
158
159 updateNameMappings();
160 updateMappings();
161
162 if(_filterChainsCached)
163 {
164 _chainCache[FilterMapping.REQUEST]=new ConcurrentHashMap<String,FilterChain>();
165 _chainCache[FilterMapping.FORWARD]=new ConcurrentHashMap<String,FilterChain>();
166 _chainCache[FilterMapping.INCLUDE]=new ConcurrentHashMap<String,FilterChain>();
167 _chainCache[FilterMapping.ERROR]=new ConcurrentHashMap<String,FilterChain>();
168 _chainCache[FilterMapping.ASYNC]=new ConcurrentHashMap<String,FilterChain>();
169
170 _chainLRU[FilterMapping.REQUEST]=new ConcurrentLinkedQueue<String>();
171 _chainLRU[FilterMapping.FORWARD]=new ConcurrentLinkedQueue<String>();
172 _chainLRU[FilterMapping.INCLUDE]=new ConcurrentLinkedQueue<String>();
173 _chainLRU[FilterMapping.ERROR]=new ConcurrentLinkedQueue<String>();
174 _chainLRU[FilterMapping.ASYNC]=new ConcurrentLinkedQueue<String>();
175 }
176
177 super.doStart();
178
179 if (_contextHandler==null || !(_contextHandler instanceof ServletContextHandler))
180 initialize();
181 }
182
183
184 @Override
185 protected synchronized void doStop()
186 throws Exception
187 {
188 super.doStop();
189
190
191 if (_filters!=null)
192 {
193 for (int i=_filters.length; i-->0;)
194 {
195 try { _filters[i].stop(); }catch(Exception e){Log.warn(Log.EXCEPTION,e);}
196 }
197 }
198
199
200 if (_servlets!=null)
201 {
202 for (int i=_servlets.length; i-->0;)
203 {
204 try { _servlets[i].stop(); }catch(Exception e){Log.warn(Log.EXCEPTION,e);}
205 }
206 }
207
208 _filterPathMappings=null;
209 _filterNameMappings=null;
210
211 _servletPathMap=null;
212 }
213
214
215 IdentityService getIdentityService()
216 {
217 return _identityService;
218 }
219
220
221
222
223
224 public Object getContextLog()
225 {
226 return null;
227 }
228
229
230
231
232
233 public FilterMapping[] getFilterMappings()
234 {
235 return _filterMappings;
236 }
237
238
239
240
241
242 public FilterHolder[] getFilters()
243 {
244 return _filters;
245 }
246
247
248
249
250
251
252 public PathMap.Entry getHolderEntry(String pathInContext)
253 {
254 if (_servletPathMap==null)
255 return null;
256 return _servletPathMap.getMatch(pathInContext);
257 }
258
259
260
261
262
263
264
265 public RequestDispatcher getRequestDispatcher(String uriInContext)
266 {
267 if (uriInContext == null || _contextHandler==null)
268 return null;
269
270 if (!uriInContext.startsWith("/"))
271 return null;
272
273 try
274 {
275 String query=null;
276 int q;
277 if ((q=uriInContext.indexOf('?'))>0)
278 {
279 query=uriInContext.substring(q+1);
280 uriInContext=uriInContext.substring(0,q);
281 }
282 if ((q=uriInContext.indexOf(';'))>0)
283 uriInContext=uriInContext.substring(0,q);
284
285 String pathInContext=URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
286 String uri=URIUtil.addPaths(_contextHandler.getContextPath(), uriInContext);
287 return new Dispatcher(_contextHandler, uri, pathInContext, query);
288 }
289 catch(Exception e)
290 {
291 Log.ignore(e);
292 }
293 return null;
294 }
295
296
297 public ServletContext getServletContext()
298 {
299 return _servletContext;
300 }
301
302
303
304
305
306 public ServletMapping[] getServletMappings()
307 {
308 return _servletMappings;
309 }
310
311
312
313
314
315 public ServletMapping getServletMapping(String pattern)
316 {
317 if (_servletMappings!=null)
318 {
319 for (ServletMapping m:_servletMappings)
320 {
321 String[] paths=m.getPathSpecs();
322 if (paths!=null)
323 {
324 for (String path:paths)
325 {
326 if (pattern.equals(path))
327 return m;
328 }
329 }
330 }
331 }
332 return null;
333 }
334
335
336
337
338
339 public ServletHolder[] getServlets()
340 {
341 return _servlets;
342 }
343
344
345 public ServletHolder getServlet(String name)
346 {
347 return (ServletHolder)_servletNameMap.get(name);
348 }
349
350
351 @Override
352 public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
353 {
354
355 final String old_servlet_path=baseRequest.getServletPath();
356 final String old_path_info=baseRequest.getPathInfo();
357
358 DispatcherType type = baseRequest.getDispatcherType();
359
360 ServletHolder servlet_holder=null;
361 UserIdentity.Scope old_scope=null;
362
363
364 if (target.startsWith("/"))
365 {
366
367 PathMap.Entry entry=getHolderEntry(target);
368 if (entry!=null)
369 {
370 servlet_holder=(ServletHolder)entry.getValue();
371
372 String servlet_path_spec=(String)entry.getKey();
373 String servlet_path=entry.getMapped()!=null?entry.getMapped():PathMap.pathMatch(servlet_path_spec,target);
374 String path_info=PathMap.pathInfo(servlet_path_spec,target);
375
376 if (DispatcherType.INCLUDE.equals(type))
377 {
378 baseRequest.setAttribute(Dispatcher.INCLUDE_SERVLET_PATH,servlet_path);
379 baseRequest.setAttribute(Dispatcher.INCLUDE_PATH_INFO, path_info);
380 }
381 else
382 {
383 baseRequest.setServletPath(servlet_path);
384 baseRequest.setPathInfo(path_info);
385 }
386 }
387 }
388 else
389 {
390
391 servlet_holder=(ServletHolder)_servletNameMap.get(target);
392 }
393
394 if (Log.isDebugEnabled())
395 Log.debug("servlet {} -> {}",baseRequest.getContextPath()+"|"+baseRequest.getServletPath()+"|"+baseRequest.getPathInfo(),servlet_holder);
396
397 try
398 {
399
400 if (servlet_holder!=null)
401 {
402 old_scope=baseRequest.getUserIdentityScope();
403 baseRequest.setUserIdentityScope(servlet_holder);
404
405
406 baseRequest.setAttribute(Request.__MULTIPART_CONFIG_ELEMENT, ((ServletHolder.Registration)servlet_holder.getRegistration()).getMultipartConfig());
407
408
409 if (never())
410 nextScope(target,baseRequest,request,response);
411 else if (_nextScope!=null)
412 _nextScope.doScope(target,baseRequest,request, response);
413 else if (_outerScope!=null)
414 _outerScope.doHandle(target,baseRequest,request, response);
415 else
416 doHandle(target,baseRequest,request, response);
417
418 }
419 }
420 finally
421 {
422 if (old_scope!=null)
423 baseRequest.setUserIdentityScope(old_scope);
424
425 if (!(DispatcherType.INCLUDE.equals(type)))
426 {
427 baseRequest.setServletPath(old_servlet_path);
428 baseRequest.setPathInfo(old_path_info);
429 }
430 }
431 }
432
433
434
435
436
437 @Override
438 public void doHandle(String target, Request baseRequest,HttpServletRequest request, HttpServletResponse response)
439 throws IOException, ServletException
440 {
441 DispatcherType type = baseRequest.getDispatcherType();
442
443 ServletHolder servlet_holder=(ServletHolder) baseRequest.getUserIdentityScope();
444 FilterChain chain=null;
445
446
447 if (target.startsWith("/"))
448 {
449 if (servlet_holder!=null && _filterMappings!=null && _filterMappings.length>0)
450 chain=getFilterChain(baseRequest, target, servlet_holder);
451 }
452 else
453 {
454 if (servlet_holder!=null)
455 {
456 if (_filterMappings!=null && _filterMappings.length>0)
457 {
458 chain=getFilterChain(baseRequest, null,servlet_holder);
459 }
460 }
461 }
462
463 Log.debug("chain=",chain);
464
465 try
466 {
467 if (servlet_holder==null)
468 {
469 notFound(request, response);
470 }
471 else
472 {
473
474 ServletRequest req = request;
475 if (req instanceof ServletRequestHttpWrapper)
476 req = ((ServletRequestHttpWrapper)req).getRequest();
477 ServletResponse res = response;
478 if (res instanceof ServletResponseHttpWrapper)
479 res = ((ServletResponseHttpWrapper)res).getResponse();
480
481
482 baseRequest.setHandled(true);
483 if (chain!=null)
484 chain.doFilter(req, res);
485 else
486 servlet_holder.handle(baseRequest,req,res);
487 }
488 }
489 catch(EofException e)
490 {
491 throw e;
492 }
493 catch(UncheckedIOException e)
494 {
495 throw e;
496 }
497 catch(ContinuationThrowable e)
498 {
499 throw e;
500 }
501 catch(Exception e)
502 {
503 if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
504 {
505 if (e instanceof IOException)
506 throw (IOException)e;
507 if (e instanceof RuntimeException)
508 throw (RuntimeException)e;
509 if (e instanceof ServletException)
510 throw (ServletException)e;
511 }
512
513
514 Throwable th=e;
515 if (th instanceof UnavailableException)
516 {
517 Log.debug(th);
518 }
519 else if (th instanceof ServletException)
520 {
521 Log.debug(th);
522 Throwable cause=((ServletException)th).getRootCause();
523 if (cause!=null)
524 th=cause;
525 }
526 else if (th instanceof UncheckedIOException)
527 {
528 Log.debug(th);
529 Throwable cause=(IOException)((UncheckedIOException)th).getCause();
530 if (cause!=null)
531 th=cause;
532 }
533
534
535 if (th instanceof HttpException)
536 throw (HttpException)th;
537 else if (th instanceof UncheckedIOException)
538 throw (UncheckedIOException)th;
539 else if (th instanceof EofException)
540 throw (EofException)th;
541
542 else if (Log.isDebugEnabled())
543 {
544 Log.warn(request.getRequestURI(), th);
545 Log.debug(request.toString());
546 }
547 else if (th instanceof IOException || th instanceof UnavailableException)
548 {
549 Log.debug(request.getRequestURI(),th);
550 }
551 else
552 {
553 Log.warn(request.getRequestURI(),th);
554 }
555
556 if (!response.isCommitted())
557 {
558 request.setAttribute(Dispatcher.ERROR_EXCEPTION_TYPE,th.getClass());
559 request.setAttribute(Dispatcher.ERROR_EXCEPTION,th);
560 if (th instanceof UnavailableException)
561 {
562 UnavailableException ue = (UnavailableException)th;
563 if (ue.isPermanent())
564 response.sendError(HttpServletResponse.SC_NOT_FOUND,th.getMessage());
565 else
566 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,th.getMessage());
567 }
568 else
569 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,th.getMessage());
570 }
571 else
572 Log.debug("Response already committed for handling "+th);
573 }
574 catch(Error e)
575 {
576 if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
577 throw e;
578 Log.warn("Error for "+request.getRequestURI(),e);
579 if(Log.isDebugEnabled())Log.debug(request.toString());
580
581
582 if (!response.isCommitted())
583 {
584 request.setAttribute(Dispatcher.ERROR_EXCEPTION_TYPE,e.getClass());
585 request.setAttribute(Dispatcher.ERROR_EXCEPTION,e);
586 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,e.getMessage());
587 }
588 else
589 Log.debug("Response already committed for handling ",e);
590 }
591 }
592
593
594 private FilterChain getFilterChain(Request baseRequest, String pathInContext, ServletHolder servletHolder)
595 {
596 String key=pathInContext==null?servletHolder.getName():pathInContext;
597 int dispatch = FilterMapping.dispatch(baseRequest.getDispatcherType());
598
599 if (_filterChainsCached && _chainCache!=null)
600 {
601 FilterChain chain = (FilterChain)_chainCache[dispatch].get(key);
602 if (chain!=null)
603 return chain;
604 }
605
606
607 Object filters= null;
608
609 if (pathInContext!=null && _filterPathMappings!=null)
610 {
611 for (int i= 0; i < _filterPathMappings.size(); i++)
612 {
613 FilterMapping mapping = (FilterMapping)_filterPathMappings.get(i);
614 if (mapping.appliesTo(pathInContext, dispatch))
615 filters= LazyList.add(filters, mapping.getFilterHolder());
616 }
617 }
618
619
620 if (servletHolder != null && _filterNameMappings!=null && _filterNameMappings.size() > 0)
621 {
622
623 if (_filterNameMappings.size() > 0)
624 {
625 Object o= _filterNameMappings.get(servletHolder.getName());
626 for (int i=0; i<LazyList.size(o);i++)
627 {
628 FilterMapping mapping = (FilterMapping)LazyList.get(o,i);
629 if (mapping.appliesTo(dispatch))
630 filters=LazyList.add(filters,mapping.getFilterHolder());
631 }
632
633 o= _filterNameMappings.get("*");
634 for (int i=0; i<LazyList.size(o);i++)
635 {
636 FilterMapping mapping = (FilterMapping)LazyList.get(o,i);
637 if (mapping.appliesTo(dispatch))
638 filters=LazyList.add(filters,mapping.getFilterHolder());
639 }
640 }
641 }
642
643 if (filters==null)
644 return null;
645
646
647 FilterChain chain = null;
648 if (_filterChainsCached)
649 {
650 if (LazyList.size(filters) > 0)
651 chain= new CachedChain(filters, servletHolder);
652
653 final Map<String,FilterChain> cache=_chainCache[dispatch];
654 final Queue<String> lru=_chainLRU[dispatch];
655
656
657 while (_maxFilterChainsCacheSize>0 && cache.size()>=_maxFilterChainsCacheSize)
658 {
659
660
661
662 String k=lru.poll();
663 if (k==null)
664 {
665 cache.clear();
666 break;
667 }
668 cache.remove(k);
669 }
670
671 cache.put(key,chain);
672 lru.add(key);
673 }
674 else if (LazyList.size(filters) > 0)
675 chain = new Chain(baseRequest,filters, servletHolder);
676
677 return chain;
678 }
679
680
681 private void invalidateChainsCache()
682 {
683 if (_chainLRU[FilterMapping.REQUEST]!=null)
684 {
685 _chainLRU[FilterMapping.REQUEST].clear();
686 _chainLRU[FilterMapping.FORWARD].clear();
687 _chainLRU[FilterMapping.INCLUDE].clear();
688 _chainLRU[FilterMapping.ERROR].clear();
689 _chainLRU[FilterMapping.ASYNC].clear();
690
691 _chainCache[FilterMapping.REQUEST].clear();
692 _chainCache[FilterMapping.FORWARD].clear();
693 _chainCache[FilterMapping.INCLUDE].clear();
694 _chainCache[FilterMapping.ERROR].clear();
695 _chainCache[FilterMapping.ASYNC].clear();
696 }
697 }
698
699
700
701
702
703 public boolean isAvailable()
704 {
705 if (!isStarted())
706 return false;
707 ServletHolder[] holders = getServlets();
708 for (int i=0;i<holders.length;i++)
709 {
710 ServletHolder holder = holders[i];
711 if (holder!=null && !holder.isAvailable())
712 return false;
713 }
714 return true;
715 }
716
717
718
719
720
721 public void setStartWithUnavailable(boolean start)
722 {
723 _startWithUnavailable=start;
724 }
725
726
727
728
729
730 public boolean isStartWithUnavailable()
731 {
732 return _startWithUnavailable;
733 }
734
735
736
737
738
739
740
741 public void initialize()
742 throws Exception
743 {
744 MultiException mx = new MultiException();
745
746
747 if (_filters!=null)
748 {
749 for (int i=0;i<_filters.length; i++)
750 _filters[i].start();
751 }
752
753 if (_servlets!=null)
754 {
755
756 ServletHolder[] servlets = (ServletHolder[])_servlets.clone();
757 Arrays.sort(servlets);
758 for (int i=0; i<servlets.length; i++)
759 {
760 try
761 {
762 if (servlets[i].getClassName()==null && servlets[i].getForcedPath()!=null)
763 {
764 ServletHolder forced_holder = (ServletHolder)_servletPathMap.match(servlets[i].getForcedPath());
765 if (forced_holder==null || forced_holder.getClassName()==null)
766 {
767 mx.add(new IllegalStateException("No forced path servlet for "+servlets[i].getForcedPath()));
768 continue;
769 }
770 servlets[i].setClassName(forced_holder.getClassName());
771 }
772
773 servlets[i].start();
774 }
775 catch(Throwable e)
776 {
777 Log.debug(Log.EXCEPTION,e);
778 mx.add(e);
779 }
780 }
781 mx.ifExceptionThrow();
782 }
783 }
784
785
786
787
788
789 public boolean isFilterChainsCached()
790 {
791 return _filterChainsCached;
792 }
793
794
795
796
797
798 public ServletHolder newServletHolder(Holder.Source source)
799 {
800 return new ServletHolder(source);
801 }
802
803
804
805
806
807
808
809
810
811
812
813
814 public ServletHolder addServletWithMapping (String className,String pathSpec)
815 {
816 ServletHolder holder = newServletHolder(null);
817 holder.setName(className+"-"+LazyList.size(_servlets));
818 holder.setClassName(className);
819 addServletWithMapping(holder,pathSpec);
820 return holder;
821 }
822
823
824
825
826
827 public ServletHolder addServletWithMapping (Class<? extends Servlet> servlet,String pathSpec)
828 {
829 ServletHolder holder = newServletHolder(Holder.Source.EMBEDDED);
830 holder.setHeldClass(servlet);
831 setServlets((ServletHolder[])LazyList.addToArray(getServlets(), holder, ServletHolder.class));
832 addServletWithMapping(holder,pathSpec);
833
834 return holder;
835 }
836
837
838
839
840
841
842 public void addServletWithMapping (ServletHolder servlet,String pathSpec)
843 {
844 ServletHolder[] holders=getServlets();
845 if (holders!=null)
846 holders = holders.clone();
847
848 try
849 {
850 setServlets((ServletHolder[])LazyList.addToArray(holders, servlet, ServletHolder.class));
851
852 ServletMapping mapping = new ServletMapping();
853 mapping.setServletName(servlet.getName());
854 mapping.setPathSpec(pathSpec);
855 setServletMappings((ServletMapping[])LazyList.addToArray(getServletMappings(), mapping, ServletMapping.class));
856 }
857 catch (Exception e)
858 {
859 setServlets(holders);
860 if (e instanceof RuntimeException)
861 throw (RuntimeException)e;
862 throw new RuntimeException(e);
863 }
864 }
865
866
867
868
869
870
871 public void addServlet(ServletHolder holder)
872 {
873 setServlets((ServletHolder[])LazyList.addToArray(getServlets(), holder, ServletHolder.class));
874 }
875
876
877
878
879
880 public void addServletMapping (ServletMapping mapping)
881 {
882 setServletMappings((ServletMapping[])LazyList.addToArray(getServletMappings(), mapping, ServletMapping.class));
883 }
884
885 public Set<String> setServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement) {
886 if (_contextHandler != null) {
887 return _contextHandler.setServletSecurity(registration, servletSecurityElement);
888 }
889 return Collections.emptySet();
890 }
891
892
893
894
895
896 public FilterHolder newFilterHolder(Holder.Source source)
897 {
898 return new FilterHolder(source);
899 }
900
901
902 public FilterHolder getFilter(String name)
903 {
904 return (FilterHolder)_filterNameMap.get(name);
905 }
906
907
908
909
910
911
912
913
914
915 public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,EnumSet<DispatcherType> dispatches)
916 {
917 FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
918 holder.setHeldClass(filter);
919 addFilterWithMapping(holder,pathSpec,dispatches);
920
921 return holder;
922 }
923
924
925
926
927
928
929
930
931 public FilterHolder addFilterWithMapping (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
932 {
933 FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
934 holder.setName(className+"-"+_filters.length);
935 holder.setClassName(className);
936
937 addFilterWithMapping(holder,pathSpec,dispatches);
938 return holder;
939 }
940
941
942
943
944
945
946
947 public void addFilterWithMapping (FilterHolder holder,String pathSpec,EnumSet<DispatcherType> dispatches)
948 {
949 FilterHolder[] holders = getFilters();
950 if (holders!=null)
951 holders = (FilterHolder[])holders.clone();
952
953 try
954 {
955 setFilters((FilterHolder[])LazyList.addToArray(holders, holder, FilterHolder.class));
956
957 FilterMapping mapping = new FilterMapping();
958 mapping.setFilterName(holder.getName());
959 mapping.setPathSpec(pathSpec);
960 mapping.setDispatcherTypes(dispatches);
961 setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), mapping, FilterMapping.class));
962 }
963 catch (RuntimeException e)
964 {
965 setFilters(holders);
966 throw e;
967 }
968 catch (Error e)
969 {
970 setFilters(holders);
971 throw e;
972 }
973
974 }
975
976
977
978
979
980
981
982
983 public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,int dispatches)
984 {
985 FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
986 holder.setHeldClass(filter);
987 addFilterWithMapping(holder,pathSpec,dispatches);
988
989 return holder;
990 }
991
992
993
994
995
996
997
998
999 public FilterHolder addFilterWithMapping (String className,String pathSpec,int dispatches)
1000 {
1001 FilterHolder holder = newFilterHolder(null);
1002 holder.setName(className+"-"+_filters.length);
1003 holder.setClassName(className);
1004
1005 addFilterWithMapping(holder,pathSpec,dispatches);
1006 return holder;
1007 }
1008
1009
1010
1011
1012
1013
1014
1015 public void addFilterWithMapping (FilterHolder holder,String pathSpec,int dispatches)
1016 {
1017 FilterHolder[] holders = getFilters();
1018 if (holders!=null)
1019 holders = (FilterHolder[])holders.clone();
1020
1021 try
1022 {
1023 setFilters((FilterHolder[])LazyList.addToArray(holders, holder, FilterHolder.class));
1024
1025 FilterMapping mapping = new FilterMapping();
1026 mapping.setFilterName(holder.getName());
1027 mapping.setPathSpec(pathSpec);
1028 mapping.setDispatches(dispatches);
1029 setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), mapping, FilterMapping.class));
1030 }
1031 catch (RuntimeException e)
1032 {
1033 setFilters(holders);
1034 throw e;
1035 }
1036 catch (Error e)
1037 {
1038 setFilters(holders);
1039 throw e;
1040 }
1041
1042 }
1043
1044
1045
1046
1047
1048
1049
1050
1051
1052 public FilterHolder addFilter (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
1053 {
1054 return addFilterWithMapping(className, pathSpec, dispatches);
1055 }
1056
1057
1058
1059
1060
1061
1062
1063 public void addFilter (FilterHolder filter, FilterMapping filterMapping)
1064 {
1065 if (filter != null)
1066 setFilters((FilterHolder[])LazyList.addToArray(getFilters(), filter, FilterHolder.class));
1067 if (filterMapping != null)
1068 setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), filterMapping, FilterMapping.class));
1069 }
1070
1071
1072
1073
1074
1075 public void addFilter (FilterHolder filter)
1076 {
1077 if (filter != null)
1078 setFilters((FilterHolder[])LazyList.addToArray(getFilters(), filter, FilterHolder.class));
1079 }
1080
1081
1082
1083
1084
1085 public void addFilterMapping (FilterMapping mapping)
1086 {
1087 if (mapping != null)
1088 setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), mapping, FilterMapping.class));
1089 }
1090
1091
1092
1093
1094
1095 public void prependFilterMapping (FilterMapping mapping)
1096 {
1097 if (mapping != null)
1098 {
1099 FilterMapping[] mappings =getFilterMappings();
1100 if (mappings==null || mappings.length==0)
1101 setFilterMappings(new FilterMapping[] {mapping});
1102 else
1103 {
1104
1105 FilterMapping[] new_mappings=new FilterMapping[mappings.length+1];
1106 System.arraycopy(mappings,0,new_mappings,1,mappings.length);
1107 new_mappings[0]=mapping;
1108 setFilterMappings(new_mappings);
1109 }
1110 }
1111 }
1112
1113
1114 protected synchronized void updateNameMappings()
1115 {
1116
1117 _filterNameMap.clear();
1118 if (_filters!=null)
1119 {
1120 for (int i=0;i<_filters.length;i++)
1121 {
1122 _filterNameMap.put(_filters[i].getName(),_filters[i]);
1123 _filters[i].setServletHandler(this);
1124 }
1125 }
1126
1127
1128 _servletNameMap.clear();
1129 if (_servlets!=null)
1130 {
1131
1132 for (int i=0;i<_servlets.length;i++)
1133 {
1134 _servletNameMap.put(_servlets[i].getName(),_servlets[i]);
1135 _servlets[i].setServletHandler(this);
1136 }
1137 }
1138 }
1139
1140
1141 protected synchronized void updateMappings()
1142 {
1143
1144 if (_filterMappings==null)
1145 {
1146 _filterPathMappings=null;
1147 _filterNameMappings=null;
1148 }
1149 else
1150 {
1151 _filterPathMappings=new ArrayList();
1152 _filterNameMappings=new MultiMap();
1153 for (int i=0;i<_filterMappings.length;i++)
1154 {
1155 FilterHolder filter_holder = (FilterHolder)_filterNameMap.get(_filterMappings[i].getFilterName());
1156 if (filter_holder==null)
1157 throw new IllegalStateException("No filter named "+_filterMappings[i].getFilterName());
1158 _filterMappings[i].setFilterHolder(filter_holder);
1159 if (_filterMappings[i].getPathSpecs()!=null)
1160 _filterPathMappings.add(_filterMappings[i]);
1161
1162 if (_filterMappings[i].getServletNames()!=null)
1163 {
1164 String[] names=_filterMappings[i].getServletNames();
1165 for (int j=0;j<names.length;j++)
1166 {
1167 if (names[j]!=null)
1168 _filterNameMappings.add(names[j], _filterMappings[i]);
1169 }
1170 }
1171 }
1172 }
1173
1174
1175 if (_servletMappings==null || _servletNameMap==null)
1176 {
1177 _servletPathMap=null;
1178 }
1179 else
1180 {
1181 PathMap pm = new PathMap();
1182
1183
1184 for (int i=0;i<_servletMappings.length;i++)
1185 {
1186 ServletHolder servlet_holder = (ServletHolder)_servletNameMap.get(_servletMappings[i].getServletName());
1187 if (servlet_holder==null)
1188 throw new IllegalStateException("No such servlet: "+_servletMappings[i].getServletName());
1189 else if (_servletMappings[i].getPathSpecs()!=null)
1190 {
1191 String[] pathSpecs = _servletMappings[i].getPathSpecs();
1192 for (int j=0;j<pathSpecs.length;j++)
1193 if (pathSpecs[j]!=null)
1194 pm.put(pathSpecs[j],servlet_holder);
1195 }
1196 }
1197
1198 _servletPathMap=pm;
1199 }
1200
1201
1202 if (_chainCache!=null)
1203 {
1204 for (int i=_chainCache.length;i-->0;)
1205 {
1206 if (_chainCache[i]!=null)
1207 _chainCache[i].clear();
1208 }
1209 }
1210
1211 if (Log.isDebugEnabled())
1212 {
1213 Log.debug("filterNameMap="+_filterNameMap);
1214 Log.debug("pathFilters="+_filterPathMappings);
1215 Log.debug("servletFilterMap="+_filterNameMappings);
1216 Log.debug("servletPathMap="+_servletPathMap);
1217 Log.debug("servletNameMap="+_servletNameMap);
1218 }
1219
1220 try
1221 {
1222 if (isStarted())
1223 initialize();
1224 }
1225 catch (Exception e)
1226 {
1227 throw new RuntimeException(e);
1228 }
1229 }
1230
1231
1232 protected void notFound(HttpServletRequest request,
1233 HttpServletResponse response)
1234 throws IOException
1235 {
1236 if(Log.isDebugEnabled())Log.debug("Not Found "+request.getRequestURI());
1237 response.sendError(HttpServletResponse.SC_NOT_FOUND);
1238 }
1239
1240
1241
1242
1243
1244 public void setFilterChainsCached(boolean filterChainsCached)
1245 {
1246 _filterChainsCached = filterChainsCached;
1247 }
1248
1249
1250
1251
1252
1253 public void setFilterMappings(FilterMapping[] filterMappings)
1254 {
1255 if (getServer()!=null)
1256 getServer().getContainer().update(this,_filterMappings,filterMappings,"filterMapping",true);
1257 _filterMappings = filterMappings;
1258 updateMappings();
1259 invalidateChainsCache();
1260 }
1261
1262
1263 public synchronized void setFilters(FilterHolder[] holders)
1264 {
1265 if (getServer()!=null)
1266 getServer().getContainer().update(this,_filters,holders,"filter",true);
1267 _filters=holders;
1268 updateNameMappings();
1269 invalidateChainsCache();
1270 }
1271
1272
1273
1274
1275
1276 public void setServletMappings(ServletMapping[] servletMappings)
1277 {
1278 if (getServer()!=null)
1279 getServer().getContainer().update(this,_servletMappings,servletMappings,"servletMapping",true);
1280 _servletMappings = servletMappings;
1281 updateMappings();
1282 invalidateChainsCache();
1283 }
1284
1285
1286
1287
1288
1289 public synchronized void setServlets(ServletHolder[] holders)
1290 {
1291 if (getServer()!=null)
1292 getServer().getContainer().update(this,_servlets,holders,"servlet",true);
1293 _servlets=holders;
1294 updateNameMappings();
1295 invalidateChainsCache();
1296 }
1297
1298
1299
1300 private class CachedChain implements FilterChain
1301 {
1302 FilterHolder _filterHolder;
1303 CachedChain _next;
1304 ServletHolder _servletHolder;
1305
1306
1307 CachedChain(Object filters, ServletHolder servletHolder)
1308 {
1309 if (LazyList.size(filters)>0)
1310 {
1311 _filterHolder=(FilterHolder)LazyList.get(filters, 0);
1312 filters=LazyList.remove(filters,0);
1313 _next=new CachedChain(filters,servletHolder);
1314 }
1315 else
1316 _servletHolder=servletHolder;
1317 }
1318
1319
1320 public void doFilter(ServletRequest request, ServletResponse response)
1321 throws IOException, ServletException
1322 {
1323
1324 if (_filterHolder!=null)
1325 {
1326 if (Log.isDebugEnabled())
1327 Log.debug("call filter " + _filterHolder);
1328 Filter filter= _filterHolder.getFilter();
1329 if (_filterHolder.isAsyncSupported())
1330 filter.doFilter(request, response, _next);
1331 else
1332 {
1333 final Request baseRequest=(request instanceof Request)?((Request)request):HttpConnection.getCurrentConnection().getRequest();
1334 final boolean suspendable=baseRequest.isAsyncSupported();
1335 if (suspendable)
1336 {
1337 try
1338 {
1339 baseRequest.setAsyncSupported(false);
1340 filter.doFilter(request, response, _next);
1341 }
1342 finally
1343 {
1344 baseRequest.setAsyncSupported(true);
1345 }
1346 }
1347 else
1348 filter.doFilter(request, response, _next);
1349 }
1350 return;
1351 }
1352
1353
1354 if (_servletHolder != null)
1355 {
1356 if (Log.isDebugEnabled())
1357 Log.debug("call servlet " + _servletHolder);
1358 final Request baseRequest=(request instanceof Request)?((Request)request):HttpConnection.getCurrentConnection().getRequest();
1359 _servletHolder.handle(baseRequest,request, response);
1360 }
1361 else
1362 notFound((HttpServletRequest)request, (HttpServletResponse)response);
1363 }
1364
1365 public String toString()
1366 {
1367 if (_filterHolder!=null)
1368 return _filterHolder+"->"+_next.toString();
1369 if (_servletHolder!=null)
1370 return _servletHolder.toString();
1371 return "null";
1372 }
1373 }
1374
1375
1376
1377 private class Chain implements FilterChain
1378 {
1379 final Request _baseRequest;
1380 final Object _chain;
1381 final ServletHolder _servletHolder;
1382 int _filter= 0;
1383
1384
1385 Chain(Request baseRequest, Object filters, ServletHolder servletHolder)
1386 {
1387 _baseRequest=baseRequest;
1388 _chain= filters;
1389 _servletHolder= servletHolder;
1390 }
1391
1392
1393 public void doFilter(ServletRequest request, ServletResponse response)
1394 throws IOException, ServletException
1395 {
1396 if (Log.isDebugEnabled()) Log.debug("doFilter " + _filter);
1397
1398
1399 if (_filter < LazyList.size(_chain))
1400 {
1401 FilterHolder holder= (FilterHolder)LazyList.get(_chain, _filter++);
1402 if (Log.isDebugEnabled()) Log.debug("call filter " + holder);
1403 Filter filter= holder.getFilter();
1404
1405 if (holder.isAsyncSupported() || !_baseRequest.isAsyncSupported())
1406 {
1407 filter.doFilter(request, response, this);
1408 }
1409 else
1410 {
1411 try
1412 {
1413 _baseRequest.setAsyncSupported(false);
1414 filter.doFilter(request, response, this);
1415 }
1416 finally
1417 {
1418 _baseRequest.setAsyncSupported(true);
1419 }
1420 }
1421
1422 return;
1423 }
1424
1425
1426 if (_servletHolder != null)
1427 {
1428 if (Log.isDebugEnabled()) Log.debug("call servlet " + _servletHolder);
1429 _servletHolder.handle(_baseRequest,request, response);
1430 }
1431 else
1432 notFound((HttpServletRequest)request, (HttpServletResponse)response);
1433 }
1434
1435
1436 public String toString()
1437 {
1438 StringBuilder b = new StringBuilder();
1439 for (int i=0; i<LazyList.size(_chain);i++)
1440 {
1441 Object o=LazyList.get(_chain, i);
1442 b.append(o.toString());
1443 b.append("->");
1444 }
1445 b.append(_servletHolder);
1446 return b.toString();
1447 }
1448 }
1449
1450
1451
1452
1453
1454 public int getMaxFilterChainsCacheSize()
1455 {
1456 return _maxFilterChainsCacheSize;
1457 }
1458
1459
1460
1461
1462
1463
1464
1465
1466 public void setMaxFilterChainsCacheSize(int maxFilterChainsCacheSize)
1467 {
1468 _maxFilterChainsCacheSize = maxFilterChainsCacheSize;
1469 }
1470
1471
1472 void destroyServlet(Servlet servlet)
1473 {
1474 if (_contextHandler!=null)
1475 _contextHandler.destroyServlet(servlet);
1476 }
1477
1478
1479 void destroyFilter(Filter filter)
1480 {
1481 if (_contextHandler!=null)
1482 _contextHandler.destroyFilter(filter);
1483 }
1484
1485
1486 @Override
1487 public void dump(Appendable out,String indent) throws IOException
1488 {
1489 super.dumpThis(out);
1490 dump(out,indent,
1491 TypeUtil.asList(getHandlers()),
1492 getBeans(),
1493 TypeUtil.asList(getFilterMappings()),
1494 TypeUtil.asList(getFilters()),
1495 TypeUtil.asList(getServletMappings()),
1496 TypeUtil.asList(getServlets()));
1497 }
1498 }