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