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