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 baseRequest.setHandled(true);
486 if (chain!=null)
487 chain.doFilter(req, res);
488 else
489 servlet_holder.handle(baseRequest,req,res);
490 }
491 }
492 catch(EofException e)
493 {
494 throw e;
495 }
496 catch(UncheckedIOException e)
497 {
498 throw e;
499 }
500 catch(ContinuationThrowable e)
501 {
502 throw e;
503 }
504 catch(Exception e)
505 {
506 if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
507 {
508 if (e instanceof IOException)
509 throw (IOException)e;
510 if (e instanceof RuntimeException)
511 throw (RuntimeException)e;
512 if (e instanceof ServletException)
513 throw (ServletException)e;
514 }
515
516
517 Throwable th=e;
518 if (th instanceof UnavailableException)
519 {
520 LOG.debug(th);
521 }
522 else if (th instanceof ServletException)
523 {
524 LOG.debug(th);
525 Throwable cause=((ServletException)th).getRootCause();
526 if (cause!=null)
527 th=cause;
528 }
529 else if (th instanceof UncheckedIOException)
530 {
531 LOG.debug(th);
532 Throwable cause=(IOException)((UncheckedIOException)th).getCause();
533 if (cause!=null)
534 th=cause;
535 }
536
537
538 if (th instanceof HttpException)
539 throw (HttpException)th;
540 else if (th instanceof UncheckedIOException)
541 throw (UncheckedIOException)th;
542 else if (th instanceof EofException)
543 throw (EofException)th;
544
545 else if (LOG.isDebugEnabled())
546 {
547 LOG.warn(request.getRequestURI(), th);
548 LOG.debug(request.toString());
549 }
550 else if (th instanceof IOException || th instanceof UnavailableException)
551 {
552 LOG.debug(request.getRequestURI(),th);
553 }
554 else
555 {
556 LOG.warn(request.getRequestURI(),th);
557 }
558
559 if (!response.isCommitted())
560 {
561 request.setAttribute(Dispatcher.ERROR_EXCEPTION_TYPE,th.getClass());
562 request.setAttribute(Dispatcher.ERROR_EXCEPTION,th);
563 if (th instanceof UnavailableException)
564 {
565 UnavailableException ue = (UnavailableException)th;
566 if (ue.isPermanent())
567 response.sendError(HttpServletResponse.SC_NOT_FOUND,th.getMessage());
568 else
569 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,th.getMessage());
570 }
571 else
572 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,th.getMessage());
573 }
574 else
575 LOG.debug("Response already committed for handling "+th);
576 }
577 catch(Error e)
578 {
579 if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
580 throw e;
581 LOG.warn("Error for "+request.getRequestURI(),e);
582 if(LOG.isDebugEnabled())LOG.debug(request.toString());
583
584
585 if (!response.isCommitted())
586 {
587 request.setAttribute(Dispatcher.ERROR_EXCEPTION_TYPE,e.getClass());
588 request.setAttribute(Dispatcher.ERROR_EXCEPTION,e);
589 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,e.getMessage());
590 }
591 else
592 LOG.debug("Response already committed for handling ",e);
593 }
594 }
595
596
597 private FilterChain getFilterChain(Request baseRequest, String pathInContext, ServletHolder servletHolder)
598 {
599 String key=pathInContext==null?servletHolder.getName():pathInContext;
600 int dispatch = FilterMapping.dispatch(baseRequest.getDispatcherType());
601
602 if (_filterChainsCached && _chainCache!=null)
603 {
604 FilterChain chain = (FilterChain)_chainCache[dispatch].get(key);
605 if (chain!=null)
606 return chain;
607 }
608
609
610 Object filters= null;
611
612 if (pathInContext!=null && _filterPathMappings!=null)
613 {
614 for (int i= 0; i < _filterPathMappings.size(); i++)
615 {
616 FilterMapping mapping = (FilterMapping)_filterPathMappings.get(i);
617 if (mapping.appliesTo(pathInContext, dispatch))
618 filters= LazyList.add(filters, mapping.getFilterHolder());
619 }
620 }
621
622
623 if (servletHolder != null && _filterNameMappings!=null && _filterNameMappings.size() > 0)
624 {
625
626 if (_filterNameMappings.size() > 0)
627 {
628 Object o= _filterNameMappings.get(servletHolder.getName());
629 for (int i=0; i<LazyList.size(o);i++)
630 {
631 FilterMapping mapping = (FilterMapping)LazyList.get(o,i);
632 if (mapping.appliesTo(dispatch))
633 filters=LazyList.add(filters,mapping.getFilterHolder());
634 }
635
636 o= _filterNameMappings.get("*");
637 for (int i=0; i<LazyList.size(o);i++)
638 {
639 FilterMapping mapping = (FilterMapping)LazyList.get(o,i);
640 if (mapping.appliesTo(dispatch))
641 filters=LazyList.add(filters,mapping.getFilterHolder());
642 }
643 }
644 }
645
646 if (filters==null)
647 return null;
648
649
650 FilterChain chain = null;
651 if (_filterChainsCached)
652 {
653 if (LazyList.size(filters) > 0)
654 chain= new CachedChain(filters, servletHolder);
655
656 final Map<String,FilterChain> cache=_chainCache[dispatch];
657 final Queue<String> lru=_chainLRU[dispatch];
658
659
660 while (_maxFilterChainsCacheSize>0 && cache.size()>=_maxFilterChainsCacheSize)
661 {
662
663
664
665 String k=lru.poll();
666 if (k==null)
667 {
668 cache.clear();
669 break;
670 }
671 cache.remove(k);
672 }
673
674 cache.put(key,chain);
675 lru.add(key);
676 }
677 else if (LazyList.size(filters) > 0)
678 chain = new Chain(baseRequest,filters, servletHolder);
679
680 return chain;
681 }
682
683
684 private void invalidateChainsCache()
685 {
686 if (_chainLRU[FilterMapping.REQUEST]!=null)
687 {
688 _chainLRU[FilterMapping.REQUEST].clear();
689 _chainLRU[FilterMapping.FORWARD].clear();
690 _chainLRU[FilterMapping.INCLUDE].clear();
691 _chainLRU[FilterMapping.ERROR].clear();
692 _chainLRU[FilterMapping.ASYNC].clear();
693
694 _chainCache[FilterMapping.REQUEST].clear();
695 _chainCache[FilterMapping.FORWARD].clear();
696 _chainCache[FilterMapping.INCLUDE].clear();
697 _chainCache[FilterMapping.ERROR].clear();
698 _chainCache[FilterMapping.ASYNC].clear();
699 }
700 }
701
702
703
704
705
706 public boolean isAvailable()
707 {
708 if (!isStarted())
709 return false;
710 ServletHolder[] holders = getServlets();
711 for (int i=0;i<holders.length;i++)
712 {
713 ServletHolder holder = holders[i];
714 if (holder!=null && !holder.isAvailable())
715 return false;
716 }
717 return true;
718 }
719
720
721
722
723
724 public void setStartWithUnavailable(boolean start)
725 {
726 _startWithUnavailable=start;
727 }
728
729
730
731
732
733 public boolean isStartWithUnavailable()
734 {
735 return _startWithUnavailable;
736 }
737
738
739
740
741
742
743
744 public void initialize()
745 throws Exception
746 {
747 MultiException mx = new MultiException();
748
749
750 if (_filters!=null)
751 {
752 for (int i=0;i<_filters.length; i++)
753 _filters[i].start();
754 }
755
756 if (_servlets!=null)
757 {
758
759 ServletHolder[] servlets = (ServletHolder[])_servlets.clone();
760 Arrays.sort(servlets);
761 for (int i=0; i<servlets.length; i++)
762 {
763 try
764 {
765 if (servlets[i].getClassName()==null && servlets[i].getForcedPath()!=null)
766 {
767 ServletHolder forced_holder = (ServletHolder)_servletPathMap.match(servlets[i].getForcedPath());
768 if (forced_holder==null || forced_holder.getClassName()==null)
769 {
770 mx.add(new IllegalStateException("No forced path servlet for "+servlets[i].getForcedPath()));
771 continue;
772 }
773 servlets[i].setClassName(forced_holder.getClassName());
774 }
775
776 servlets[i].start();
777 }
778 catch(Throwable e)
779 {
780 LOG.debug(Log.EXCEPTION,e);
781 mx.add(e);
782 }
783 }
784 mx.ifExceptionThrow();
785 }
786 }
787
788
789
790
791
792 public boolean isFilterChainsCached()
793 {
794 return _filterChainsCached;
795 }
796
797
798
799
800
801 public ServletHolder newServletHolder(Holder.Source source)
802 {
803 return new ServletHolder(source);
804 }
805
806
807
808
809
810
811
812
813
814
815
816
817 public ServletHolder addServletWithMapping (String className,String pathSpec)
818 {
819 ServletHolder holder = newServletHolder(null);
820 holder.setName(className+"-"+LazyList.size(_servlets));
821 holder.setClassName(className);
822 addServletWithMapping(holder,pathSpec);
823 return holder;
824 }
825
826
827
828
829
830 public ServletHolder addServletWithMapping (Class<? extends Servlet> servlet,String pathSpec)
831 {
832 ServletHolder holder = newServletHolder(Holder.Source.EMBEDDED);
833 holder.setHeldClass(servlet);
834 setServlets((ServletHolder[])LazyList.addToArray(getServlets(), holder, ServletHolder.class));
835 addServletWithMapping(holder,pathSpec);
836
837 return holder;
838 }
839
840
841
842
843
844
845 public void addServletWithMapping (ServletHolder servlet,String pathSpec)
846 {
847 ServletHolder[] holders=getServlets();
848 if (holders!=null)
849 holders = holders.clone();
850
851 try
852 {
853 setServlets((ServletHolder[])LazyList.addToArray(holders, servlet, ServletHolder.class));
854
855 ServletMapping mapping = new ServletMapping();
856 mapping.setServletName(servlet.getName());
857 mapping.setPathSpec(pathSpec);
858 setServletMappings((ServletMapping[])LazyList.addToArray(getServletMappings(), mapping, ServletMapping.class));
859 }
860 catch (Exception e)
861 {
862 setServlets(holders);
863 if (e instanceof RuntimeException)
864 throw (RuntimeException)e;
865 throw new RuntimeException(e);
866 }
867 }
868
869
870
871
872
873
874 public void addServlet(ServletHolder holder)
875 {
876 setServlets((ServletHolder[])LazyList.addToArray(getServlets(), holder, ServletHolder.class));
877 }
878
879
880
881
882
883 public void addServletMapping (ServletMapping mapping)
884 {
885 setServletMappings((ServletMapping[])LazyList.addToArray(getServletMappings(), mapping, ServletMapping.class));
886 }
887
888 public Set<String> setServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement) {
889 if (_contextHandler != null) {
890 return _contextHandler.setServletSecurity(registration, servletSecurityElement);
891 }
892 return Collections.emptySet();
893 }
894
895
896
897
898
899 public FilterHolder newFilterHolder(Holder.Source source)
900 {
901 return new FilterHolder(source);
902 }
903
904
905 public FilterHolder getFilter(String name)
906 {
907 return (FilterHolder)_filterNameMap.get(name);
908 }
909
910
911
912
913
914
915
916
917
918 public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,EnumSet<DispatcherType> dispatches)
919 {
920 FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
921 holder.setHeldClass(filter);
922 addFilterWithMapping(holder,pathSpec,dispatches);
923
924 return holder;
925 }
926
927
928
929
930
931
932
933
934 public FilterHolder addFilterWithMapping (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
935 {
936 FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
937 holder.setName(className+"-"+_filters.length);
938 holder.setClassName(className);
939
940 addFilterWithMapping(holder,pathSpec,dispatches);
941 return holder;
942 }
943
944
945
946
947
948
949
950 public void addFilterWithMapping (FilterHolder holder,String pathSpec,EnumSet<DispatcherType> dispatches)
951 {
952 FilterHolder[] holders = getFilters();
953 if (holders!=null)
954 holders = (FilterHolder[])holders.clone();
955
956 try
957 {
958 setFilters((FilterHolder[])LazyList.addToArray(holders, holder, FilterHolder.class));
959
960 FilterMapping mapping = new FilterMapping();
961 mapping.setFilterName(holder.getName());
962 mapping.setPathSpec(pathSpec);
963 mapping.setDispatcherTypes(dispatches);
964 setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), mapping, FilterMapping.class));
965 }
966 catch (RuntimeException e)
967 {
968 setFilters(holders);
969 throw e;
970 }
971 catch (Error e)
972 {
973 setFilters(holders);
974 throw e;
975 }
976
977 }
978
979
980
981
982
983
984
985
986 public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,int dispatches)
987 {
988 FilterHolder holder = newFilterHolder(Holder.Source.EMBEDDED);
989 holder.setHeldClass(filter);
990 addFilterWithMapping(holder,pathSpec,dispatches);
991
992 return holder;
993 }
994
995
996
997
998
999
1000
1001
1002 public FilterHolder addFilterWithMapping (String className,String pathSpec,int dispatches)
1003 {
1004 FilterHolder holder = newFilterHolder(null);
1005 holder.setName(className+"-"+_filters.length);
1006 holder.setClassName(className);
1007
1008 addFilterWithMapping(holder,pathSpec,dispatches);
1009 return holder;
1010 }
1011
1012
1013
1014
1015
1016
1017
1018 public void addFilterWithMapping (FilterHolder holder,String pathSpec,int dispatches)
1019 {
1020 FilterHolder[] holders = getFilters();
1021 if (holders!=null)
1022 holders = (FilterHolder[])holders.clone();
1023
1024 try
1025 {
1026 setFilters((FilterHolder[])LazyList.addToArray(holders, holder, FilterHolder.class));
1027
1028 FilterMapping mapping = new FilterMapping();
1029 mapping.setFilterName(holder.getName());
1030 mapping.setPathSpec(pathSpec);
1031 mapping.setDispatches(dispatches);
1032 setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), mapping, FilterMapping.class));
1033 }
1034 catch (RuntimeException e)
1035 {
1036 setFilters(holders);
1037 throw e;
1038 }
1039 catch (Error e)
1040 {
1041 setFilters(holders);
1042 throw e;
1043 }
1044
1045 }
1046
1047
1048
1049
1050
1051
1052
1053
1054
1055 public FilterHolder addFilter (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
1056 {
1057 return addFilterWithMapping(className, pathSpec, dispatches);
1058 }
1059
1060
1061
1062
1063
1064
1065
1066 public void addFilter (FilterHolder filter, FilterMapping filterMapping)
1067 {
1068 if (filter != null)
1069 setFilters((FilterHolder[])LazyList.addToArray(getFilters(), filter, FilterHolder.class));
1070 if (filterMapping != null)
1071 setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), filterMapping, FilterMapping.class));
1072 }
1073
1074
1075
1076
1077
1078 public void addFilter (FilterHolder filter)
1079 {
1080 if (filter != null)
1081 setFilters((FilterHolder[])LazyList.addToArray(getFilters(), filter, FilterHolder.class));
1082 }
1083
1084
1085
1086
1087
1088 public void addFilterMapping (FilterMapping mapping)
1089 {
1090 if (mapping != null)
1091 setFilterMappings((FilterMapping[])LazyList.addToArray(getFilterMappings(), mapping, FilterMapping.class));
1092 }
1093
1094
1095
1096
1097
1098 public void prependFilterMapping (FilterMapping mapping)
1099 {
1100 if (mapping != null)
1101 {
1102 FilterMapping[] mappings =getFilterMappings();
1103 if (mappings==null || mappings.length==0)
1104 setFilterMappings(new FilterMapping[] {mapping});
1105 else
1106 {
1107
1108 FilterMapping[] new_mappings=new FilterMapping[mappings.length+1];
1109 System.arraycopy(mappings,0,new_mappings,1,mappings.length);
1110 new_mappings[0]=mapping;
1111 setFilterMappings(new_mappings);
1112 }
1113 }
1114 }
1115
1116
1117 protected synchronized void updateNameMappings()
1118 {
1119
1120 _filterNameMap.clear();
1121 if (_filters!=null)
1122 {
1123 for (int i=0;i<_filters.length;i++)
1124 {
1125 _filterNameMap.put(_filters[i].getName(),_filters[i]);
1126 _filters[i].setServletHandler(this);
1127 }
1128 }
1129
1130
1131 _servletNameMap.clear();
1132 if (_servlets!=null)
1133 {
1134
1135 for (int i=0;i<_servlets.length;i++)
1136 {
1137 _servletNameMap.put(_servlets[i].getName(),_servlets[i]);
1138 _servlets[i].setServletHandler(this);
1139 }
1140 }
1141 }
1142
1143
1144 protected synchronized void updateMappings()
1145 {
1146
1147 if (_filterMappings==null)
1148 {
1149 _filterPathMappings=null;
1150 _filterNameMappings=null;
1151 }
1152 else
1153 {
1154 _filterPathMappings=new ArrayList();
1155 _filterNameMappings=new MultiMap();
1156 for (int i=0;i<_filterMappings.length;i++)
1157 {
1158 FilterHolder filter_holder = (FilterHolder)_filterNameMap.get(_filterMappings[i].getFilterName());
1159 if (filter_holder==null)
1160 throw new IllegalStateException("No filter named "+_filterMappings[i].getFilterName());
1161 _filterMappings[i].setFilterHolder(filter_holder);
1162 if (_filterMappings[i].getPathSpecs()!=null)
1163 _filterPathMappings.add(_filterMappings[i]);
1164
1165 if (_filterMappings[i].getServletNames()!=null)
1166 {
1167 String[] names=_filterMappings[i].getServletNames();
1168 for (int j=0;j<names.length;j++)
1169 {
1170 if (names[j]!=null)
1171 _filterNameMappings.add(names[j], _filterMappings[i]);
1172 }
1173 }
1174 }
1175 }
1176
1177
1178 if (_servletMappings==null || _servletNameMap==null)
1179 {
1180 _servletPathMap=null;
1181 }
1182 else
1183 {
1184 PathMap pm = new PathMap();
1185
1186
1187 for (int i=0;i<_servletMappings.length;i++)
1188 {
1189 ServletHolder servlet_holder = (ServletHolder)_servletNameMap.get(_servletMappings[i].getServletName());
1190 if (servlet_holder==null)
1191 throw new IllegalStateException("No such servlet: "+_servletMappings[i].getServletName());
1192 else if (_servletMappings[i].getPathSpecs()!=null)
1193 {
1194 String[] pathSpecs = _servletMappings[i].getPathSpecs();
1195 for (int j=0;j<pathSpecs.length;j++)
1196 if (pathSpecs[j]!=null)
1197 pm.put(pathSpecs[j],servlet_holder);
1198 }
1199 }
1200
1201 _servletPathMap=pm;
1202 }
1203
1204
1205 if (_chainCache!=null)
1206 {
1207 for (int i=_chainCache.length;i-->0;)
1208 {
1209 if (_chainCache[i]!=null)
1210 _chainCache[i].clear();
1211 }
1212 }
1213
1214 if (LOG.isDebugEnabled())
1215 {
1216 LOG.debug("filterNameMap="+_filterNameMap);
1217 LOG.debug("pathFilters="+_filterPathMappings);
1218 LOG.debug("servletFilterMap="+_filterNameMappings);
1219 LOG.debug("servletPathMap="+_servletPathMap);
1220 LOG.debug("servletNameMap="+_servletNameMap);
1221 }
1222
1223 try
1224 {
1225 if (isStarted())
1226 initialize();
1227 }
1228 catch (Exception e)
1229 {
1230 throw new RuntimeException(e);
1231 }
1232 }
1233
1234
1235 protected void notFound(HttpServletRequest request,
1236 HttpServletResponse response)
1237 throws IOException
1238 {
1239 if(LOG.isDebugEnabled())LOG.debug("Not Found "+request.getRequestURI());
1240 response.sendError(HttpServletResponse.SC_NOT_FOUND);
1241 }
1242
1243
1244
1245
1246
1247 public void setFilterChainsCached(boolean filterChainsCached)
1248 {
1249 _filterChainsCached = filterChainsCached;
1250 }
1251
1252
1253
1254
1255
1256 public void setFilterMappings(FilterMapping[] filterMappings)
1257 {
1258 if (getServer()!=null)
1259 getServer().getContainer().update(this,_filterMappings,filterMappings,"filterMapping",true);
1260 _filterMappings = filterMappings;
1261 updateMappings();
1262 invalidateChainsCache();
1263 }
1264
1265
1266 public synchronized void setFilters(FilterHolder[] holders)
1267 {
1268 if (getServer()!=null)
1269 getServer().getContainer().update(this,_filters,holders,"filter",true);
1270 _filters=holders;
1271 updateNameMappings();
1272 invalidateChainsCache();
1273 }
1274
1275
1276
1277
1278
1279 public void setServletMappings(ServletMapping[] servletMappings)
1280 {
1281 if (getServer()!=null)
1282 getServer().getContainer().update(this,_servletMappings,servletMappings,"servletMapping",true);
1283 _servletMappings = servletMappings;
1284 updateMappings();
1285 invalidateChainsCache();
1286 }
1287
1288
1289
1290
1291
1292 public synchronized void setServlets(ServletHolder[] holders)
1293 {
1294 if (getServer()!=null)
1295 getServer().getContainer().update(this,_servlets,holders,"servlet",true);
1296 _servlets=holders;
1297 updateNameMappings();
1298 invalidateChainsCache();
1299 }
1300
1301
1302
1303 private class CachedChain implements FilterChain
1304 {
1305 FilterHolder _filterHolder;
1306 CachedChain _next;
1307 ServletHolder _servletHolder;
1308
1309
1310 CachedChain(Object filters, ServletHolder servletHolder)
1311 {
1312 if (LazyList.size(filters)>0)
1313 {
1314 _filterHolder=(FilterHolder)LazyList.get(filters, 0);
1315 filters=LazyList.remove(filters,0);
1316 _next=new CachedChain(filters,servletHolder);
1317 }
1318 else
1319 _servletHolder=servletHolder;
1320 }
1321
1322
1323 public void doFilter(ServletRequest request, ServletResponse response)
1324 throws IOException, ServletException
1325 {
1326
1327 if (_filterHolder!=null)
1328 {
1329 if (LOG.isDebugEnabled())
1330 LOG.debug("call filter " + _filterHolder);
1331 Filter filter= _filterHolder.getFilter();
1332 if (_filterHolder.isAsyncSupported())
1333 filter.doFilter(request, response, _next);
1334 else
1335 {
1336 final Request baseRequest=(request instanceof Request)?((Request)request):HttpConnection.getCurrentConnection().getRequest();
1337 final boolean suspendable=baseRequest.isAsyncSupported();
1338 if (suspendable)
1339 {
1340 try
1341 {
1342 baseRequest.setAsyncSupported(false);
1343 filter.doFilter(request, response, _next);
1344 }
1345 finally
1346 {
1347 baseRequest.setAsyncSupported(true);
1348 }
1349 }
1350 else
1351 filter.doFilter(request, response, _next);
1352 }
1353 return;
1354 }
1355
1356
1357 if (_servletHolder != null)
1358 {
1359 if (LOG.isDebugEnabled())
1360 LOG.debug("call servlet " + _servletHolder);
1361 final Request baseRequest=(request instanceof Request)?((Request)request):HttpConnection.getCurrentConnection().getRequest();
1362 _servletHolder.handle(baseRequest,request, response);
1363 }
1364 else
1365 notFound((HttpServletRequest)request, (HttpServletResponse)response);
1366 }
1367
1368 public String toString()
1369 {
1370 if (_filterHolder!=null)
1371 return _filterHolder+"->"+_next.toString();
1372 if (_servletHolder!=null)
1373 return _servletHolder.toString();
1374 return "null";
1375 }
1376 }
1377
1378
1379
1380 private class Chain implements FilterChain
1381 {
1382 final Request _baseRequest;
1383 final Object _chain;
1384 final ServletHolder _servletHolder;
1385 int _filter= 0;
1386
1387
1388 Chain(Request baseRequest, Object filters, ServletHolder servletHolder)
1389 {
1390 _baseRequest=baseRequest;
1391 _chain= filters;
1392 _servletHolder= servletHolder;
1393 }
1394
1395
1396 public void doFilter(ServletRequest request, ServletResponse response)
1397 throws IOException, ServletException
1398 {
1399 if (LOG.isDebugEnabled()) LOG.debug("doFilter " + _filter);
1400
1401
1402 if (_filter < LazyList.size(_chain))
1403 {
1404 FilterHolder holder= (FilterHolder)LazyList.get(_chain, _filter++);
1405 if (LOG.isDebugEnabled()) LOG.debug("call filter " + holder);
1406 Filter filter= holder.getFilter();
1407
1408 if (holder.isAsyncSupported() || !_baseRequest.isAsyncSupported())
1409 {
1410 filter.doFilter(request, response, this);
1411 }
1412 else
1413 {
1414 try
1415 {
1416 _baseRequest.setAsyncSupported(false);
1417 filter.doFilter(request, response, this);
1418 }
1419 finally
1420 {
1421 _baseRequest.setAsyncSupported(true);
1422 }
1423 }
1424
1425 return;
1426 }
1427
1428
1429 if (_servletHolder != null)
1430 {
1431 if (LOG.isDebugEnabled()) LOG.debug("call servlet " + _servletHolder);
1432 _servletHolder.handle(_baseRequest,request, response);
1433 }
1434 else
1435 notFound((HttpServletRequest)request, (HttpServletResponse)response);
1436 }
1437
1438
1439 public String toString()
1440 {
1441 StringBuilder b = new StringBuilder();
1442 for (int i=0; i<LazyList.size(_chain);i++)
1443 {
1444 Object o=LazyList.get(_chain, i);
1445 b.append(o.toString());
1446 b.append("->");
1447 }
1448 b.append(_servletHolder);
1449 return b.toString();
1450 }
1451 }
1452
1453
1454
1455
1456
1457 public int getMaxFilterChainsCacheSize()
1458 {
1459 return _maxFilterChainsCacheSize;
1460 }
1461
1462
1463
1464
1465
1466
1467
1468
1469 public void setMaxFilterChainsCacheSize(int maxFilterChainsCacheSize)
1470 {
1471 _maxFilterChainsCacheSize = maxFilterChainsCacheSize;
1472 }
1473
1474
1475 void destroyServlet(Servlet servlet)
1476 {
1477 if (_contextHandler!=null)
1478 _contextHandler.destroyServlet(servlet);
1479 }
1480
1481
1482 void destroyFilter(Filter filter)
1483 {
1484 if (_contextHandler!=null)
1485 _contextHandler.destroyFilter(filter);
1486 }
1487
1488
1489 @Override
1490 public void dump(Appendable out,String indent) throws IOException
1491 {
1492 super.dumpThis(out);
1493 dump(out,indent,
1494 TypeUtil.asList(getHandlers()),
1495 getBeans(),
1496 TypeUtil.asList(getFilterMappings()),
1497 TypeUtil.asList(getFilters()),
1498 TypeUtil.asList(getServletMappings()),
1499 TypeUtil.asList(getServlets()));
1500 }
1501 }