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