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