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