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