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