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