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 import org.eclipse.jetty.util.log.Logger;
65
66
67
68
69
70
71
72
73
74
75
76
77
78 public class ServletHandler extends ScopedHandler
79 {
80 private static final Logger LOG = Log.getLogger(ServletHandler.class);
81
82
83 public static final String __DEFAULT_SERVLET="default";
84
85
86 private ServletContextHandler _contextHandler;
87 private ContextHandler.Context _servletContext;
88 private FilterHolder[] _filters=new FilterHolder[0];
89 private FilterMapping[] _filterMappings;
90 private boolean _filterChainsCached=true;
91 private int _maxFilterChainsCacheSize=512;
92 private boolean _startWithUnavailable=true;
93 private IdentityService _identityService;
94
95 private ServletHolder[] _servlets=new ServletHolder[0];
96 private ServletMapping[] _servletMappings;
97
98 private final Map<String,FilterHolder> _filterNameMap= new HashMap<String,FilterHolder>();
99 private List<FilterMapping> _filterPathMappings;
100 private MultiMap<String> _filterNameMappings;
101
102 private final Map<String,ServletHolder> _servletNameMap=new HashMap<String,ServletHolder>();
103 private PathMap _servletPathMap;
104
105 protected final ConcurrentMap<String,FilterChain> _chainCache[] = new ConcurrentMap[FilterMapping.ALL];
106 protected final Queue<String>[] _chainLRU = new Queue[FilterMapping.ALL];
107
108
109
110
111
112 public ServletHandler()
113 {
114 }
115
116
117
118
119
120 public void setServer(Server server)
121 {
122 Server old=getServer();
123 if (old!=null && old!=server)
124 {
125 getServer().getContainer().update(this, _filters, null, "filter",true);
126 getServer().getContainer().update(this, _filterMappings, null, "filterMapping",true);
127 getServer().getContainer().update(this, _servlets, null, "servlet",true);
128 getServer().getContainer().update(this, _servletMappings, null, "servletMapping",true);
129 }
130
131 super.setServer(server);
132
133 if (server!=null && old!=server)
134 {
135 server.getContainer().update(this, null, _filters, "filter",true);
136 server.getContainer().update(this, null, _filterMappings, "filterMapping",true);
137 server.getContainer().update(this, null, _servlets, "servlet",true);
138 server.getContainer().update(this, null, _servletMappings, "servletMapping",true);
139 }
140 }
141
142
143 @Override
144 protected synchronized void doStart()
145 throws Exception
146 {
147 _servletContext=ContextHandler.getCurrentContext();
148 _contextHandler=(ServletContextHandler)(_servletContext==null?null:_servletContext.getContextHandler());
149
150 if (_contextHandler!=null)
151 {
152 SecurityHandler security_handler = (SecurityHandler)_contextHandler.getChildHandlerByClass(SecurityHandler.class);
153 if (security_handler!=null)
154 _identityService=security_handler.getIdentityService();
155 }
156
157 updateNameMappings();
158 updateMappings();
159
160 if(_filterChainsCached)
161 {
162 _chainCache[FilterMapping.REQUEST]=new ConcurrentHashMap<String,FilterChain>();
163 _chainCache[FilterMapping.FORWARD]=new ConcurrentHashMap<String,FilterChain>();
164 _chainCache[FilterMapping.INCLUDE]=new ConcurrentHashMap<String,FilterChain>();
165 _chainCache[FilterMapping.ERROR]=new ConcurrentHashMap<String,FilterChain>();
166 _chainCache[FilterMapping.ASYNC]=new ConcurrentHashMap<String,FilterChain>();
167
168 _chainLRU[FilterMapping.REQUEST]=new ConcurrentLinkedQueue<String>();
169 _chainLRU[FilterMapping.FORWARD]=new ConcurrentLinkedQueue<String>();
170 _chainLRU[FilterMapping.INCLUDE]=new ConcurrentLinkedQueue<String>();
171 _chainLRU[FilterMapping.ERROR]=new ConcurrentLinkedQueue<String>();
172 _chainLRU[FilterMapping.ASYNC]=new ConcurrentLinkedQueue<String>();
173 }
174
175 super.doStart();
176
177 if (_contextHandler==null || !(_contextHandler instanceof ServletContextHandler))
178 initialize();
179 }
180
181
182 @Override
183 protected synchronized void doStop()
184 throws Exception
185 {
186 super.doStop();
187
188
189 if (_filters!=null)
190 {
191 for (int i=_filters.length; i-->0;)
192 {
193 try { _filters[i].stop(); }catch(Exception e){LOG.warn(Log.EXCEPTION,e);}
194 }
195 }
196
197
198 if (_servlets!=null)
199 {
200 for (int i=_servlets.length; i-->0;)
201 {
202 try { _servlets[i].stop(); }catch(Exception e){LOG.warn(Log.EXCEPTION,e);}
203 }
204 }
205
206 _filterPathMappings=null;
207 _filterNameMappings=null;
208
209 _servletPathMap=null;
210 }
211
212
213 IdentityService getIdentityService()
214 {
215 return _identityService;
216 }
217
218
219
220
221
222 public Object getContextLog()
223 {
224 return null;
225 }
226
227
228
229
230
231 public FilterMapping[] getFilterMappings()
232 {
233 return _filterMappings;
234 }
235
236
237
238
239
240 public FilterHolder[] getFilters()
241 {
242 return _filters;
243 }
244
245
246
247
248
249
250 public PathMap.Entry getHolderEntry(String pathInContext)
251 {
252 if (_servletPathMap==null)
253 return null;
254 return _servletPathMap.getMatch(pathInContext);
255 }
256
257
258
259
260
261
262
263 public RequestDispatcher getRequestDispatcher(String uriInContext)
264 {
265 if (uriInContext == null || _contextHandler==null)
266 return null;
267
268 if (!uriInContext.startsWith("/"))
269 return null;
270
271 try
272 {
273 String query=null;
274 int q;
275 if ((q=uriInContext.indexOf('?'))>0)
276 {
277 query=uriInContext.substring(q+1);
278 uriInContext=uriInContext.substring(0,q);
279 }
280 if ((q=uriInContext.indexOf(';'))>0)
281 uriInContext=uriInContext.substring(0,q);
282
283 String pathInContext=URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
284 String uri=URIUtil.addPaths(_contextHandler.getContextPath(), uriInContext);
285 return new Dispatcher(_contextHandler, uri, pathInContext, query);
286 }
287 catch(Exception e)
288 {
289 LOG.ignore(e);
290 }
291 return null;
292 }
293
294
295 public ServletContext getServletContext()
296 {
297 return _servletContext;
298 }
299
300
301
302
303
304 public ServletMapping[] getServletMappings()
305 {
306 return _servletMappings;
307 }
308
309
310
311
312
313 public ServletMapping getServletMapping(String pattern)
314 {
315 if (_servletMappings!=null)
316 {
317 for (ServletMapping m:_servletMappings)
318 {
319 String[] paths=m.getPathSpecs();
320 if (paths!=null)
321 {
322 for (String path:paths)
323 {
324 if (pattern.equals(path))
325 return m;
326 }
327 }
328 }
329 }
330 return null;
331 }
332
333
334
335
336
337 public ServletHolder[] getServlets()
338 {
339 return _servlets;
340 }
341
342
343 public ServletHolder getServlet(String name)
344 {
345 return (ServletHolder)_servletNameMap.get(name);
346 }
347
348
349 @Override
350 public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
351 {
352
353 final String old_servlet_path=baseRequest.getServletPath();
354 final String old_path_info=baseRequest.getPathInfo();
355
356 DispatcherType type = baseRequest.getDispatcherType();
357
358 ServletHolder servlet_holder=null;
359 UserIdentity.Scope old_scope=null;
360
361
362 if (target.startsWith("/"))
363 {
364
365 PathMap.Entry entry=getHolderEntry(target);
366 if (entry!=null)
367 {
368 servlet_holder=(ServletHolder)entry.getValue();
369
370 String servlet_path_spec=(String)entry.getKey();
371 String servlet_path=entry.getMapped()!=null?entry.getMapped():PathMap.pathMatch(servlet_path_spec,target);
372 String path_info=PathMap.pathInfo(servlet_path_spec,target);
373
374 if (DispatcherType.INCLUDE.equals(type))
375 {
376 baseRequest.setAttribute(Dispatcher.INCLUDE_SERVLET_PATH,servlet_path);
377 baseRequest.setAttribute(Dispatcher.INCLUDE_PATH_INFO, path_info);
378 }
379 else
380 {
381 baseRequest.setServletPath(servlet_path);
382 baseRequest.setPathInfo(path_info);
383 }
384 }
385 }
386 else
387 {
388
389 servlet_holder=(ServletHolder)_servletNameMap.get(target);
390 }
391
392 if (LOG.isDebugEnabled())
393 LOG.debug("servlet {} -> {}",baseRequest.getContextPath()+"|"+baseRequest.getServletPath()+"|"+baseRequest.getPathInfo(),servlet_holder);
394
395 try
396 {
397
398 if (servlet_holder!=null)
399 {
400 old_scope=baseRequest.getUserIdentityScope();
401 baseRequest.setUserIdentityScope(servlet_holder);
402
403
404 if (never())
405 nextScope(target,baseRequest,request,response);
406 else if (_nextScope!=null)
407 _nextScope.doScope(target,baseRequest,request, response);
408 else if (_outerScope!=null)
409 _outerScope.doHandle(target,baseRequest,request, response);
410 else
411 doHandle(target,baseRequest,request, response);
412
413 }
414 }
415 finally
416 {
417 if (old_scope!=null)
418 baseRequest.setUserIdentityScope(old_scope);
419
420 if (!(DispatcherType.INCLUDE.equals(type)))
421 {
422 baseRequest.setServletPath(old_servlet_path);
423 baseRequest.setPathInfo(old_path_info);
424 }
425 }
426 }
427
428
429
430
431
432 @Override
433 public void doHandle(String target, Request baseRequest,HttpServletRequest request, HttpServletResponse response)
434 throws IOException, ServletException
435 {
436 DispatcherType type = baseRequest.getDispatcherType();
437
438 ServletHolder servlet_holder=(ServletHolder) baseRequest.getUserIdentityScope();
439 FilterChain chain=null;
440
441
442 if (target.startsWith("/"))
443 {
444 if (servlet_holder!=null && _filterMappings!=null && _filterMappings.length>0)
445 chain=getFilterChain(baseRequest, target, servlet_holder);
446 }
447 else
448 {
449 if (servlet_holder!=null)
450 {
451 if (_filterMappings!=null && _filterMappings.length>0)
452 {
453 chain=getFilterChain(baseRequest, null,servlet_holder);
454 }
455 }
456 }
457
458 LOG.debug("chain=",chain);
459
460 try
461 {
462 if (servlet_holder==null)
463 {
464 notFound(request, response);
465 }
466 else
467 {
468
469 ServletRequest req = request;
470 if (req instanceof ServletRequestHttpWrapper)
471 req = ((ServletRequestHttpWrapper)req).getRequest();
472 ServletResponse res = response;
473 if (res instanceof ServletResponseHttpWrapper)
474 res = ((ServletResponseHttpWrapper)res).getResponse();
475
476
477 if (chain!=null)
478 chain.doFilter(req, res);
479 else
480 servlet_holder.handle(baseRequest,req,res);
481 }
482 }
483 catch(EofException e)
484 {
485 throw e;
486 }
487 catch(RuntimeIOException e)
488 {
489 throw e;
490 }
491 catch(ContinuationThrowable e)
492 {
493 throw e;
494 }
495 catch(Exception e)
496 {
497 if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
498 {
499 if (e instanceof IOException)
500 throw (IOException)e;
501 if (e instanceof RuntimeException)
502 throw (RuntimeException)e;
503 if (e instanceof ServletException)
504 throw (ServletException)e;
505 }
506
507
508 Throwable th=e;
509 if (th instanceof UnavailableException)
510 {
511 LOG.debug(th);
512 }
513 else if (th instanceof ServletException)
514 {
515 LOG.debug(th);
516 Throwable cause=((ServletException)th).getRootCause();
517 if (cause!=null)
518 th=cause;
519 }
520 else if (th instanceof RuntimeIOException)
521 {
522 LOG.debug(th);
523 Throwable cause=(IOException)((RuntimeIOException)th).getCause();
524 if (cause!=null)
525 th=cause;
526 }
527
528
529 if (th instanceof HttpException)
530 throw (HttpException)th;
531 else if (th instanceof RuntimeIOException)
532 throw (RuntimeIOException)th;
533 else if (th instanceof EofException)
534 throw (EofException)th;
535
536 else if (LOG.isDebugEnabled())
537 {
538 LOG.warn(request.getRequestURI(), th);
539 LOG.debug(request.toString());
540 }
541 else if (th instanceof IOException || th instanceof UnavailableException)
542 {
543 LOG.debug(request.getRequestURI(),th);
544 }
545 else
546 {
547 LOG.warn(request.getRequestURI(),th);
548 }
549
550 if (!response.isCommitted())
551 {
552 request.setAttribute(Dispatcher.ERROR_EXCEPTION_TYPE,th.getClass());
553 request.setAttribute(Dispatcher.ERROR_EXCEPTION,th);
554 if (th instanceof UnavailableException)
555 {
556 UnavailableException ue = (UnavailableException)th;
557 if (ue.isPermanent())
558 response.sendError(HttpServletResponse.SC_NOT_FOUND,th.getMessage());
559 else
560 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE,th.getMessage());
561 }
562 else
563 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,th.getMessage());
564 }
565 else
566 LOG.debug("Response already committed for handling "+th);
567 }
568 catch(Error e)
569 {
570 if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
571 throw e;
572 LOG.warn("Error for "+request.getRequestURI(),e);
573 if(LOG.isDebugEnabled())LOG.debug(request.toString());
574
575
576 if (!response.isCommitted())
577 {
578 request.setAttribute(Dispatcher.ERROR_EXCEPTION_TYPE,e.getClass());
579 request.setAttribute(Dispatcher.ERROR_EXCEPTION,e);
580 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR,e.getMessage());
581 }
582 else
583 LOG.debug("Response already committed for handling ",e);
584 }
585 finally
586 {
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())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):HttpConnection.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):HttpConnection.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()) LOG.debug("doFilter " + _filter);
1396
1397
1398 if (_filter < LazyList.size(_chain))
1399 {
1400 FilterHolder holder= (FilterHolder)LazyList.get(_chain, _filter++);
1401 if (LOG.isDebugEnabled()) LOG.debug("call filter " + holder);
1402 Filter filter= holder.getFilter();
1403
1404 if (holder.isAsyncSupported() || !_baseRequest.isAsyncSupported())
1405 {
1406 filter.doFilter(request, response, this);
1407 }
1408 else
1409 {
1410 try
1411 {
1412 _baseRequest.setAsyncSupported(false);
1413 filter.doFilter(request, response, this);
1414 }
1415 finally
1416 {
1417 _baseRequest.setAsyncSupported(true);
1418 }
1419 }
1420
1421 return;
1422 }
1423
1424
1425 if (_servletHolder != null)
1426 {
1427 if (LOG.isDebugEnabled()) LOG.debug("call servlet " + _servletHolder);
1428 _servletHolder.handle(_baseRequest,request, response);
1429 }
1430 else
1431 notFound((HttpServletRequest)request, (HttpServletResponse)response);
1432 }
1433
1434
1435 public String toString()
1436 {
1437 StringBuilder b = new StringBuilder();
1438 for (int i=0; i<LazyList.size(_chain);i++)
1439 {
1440 Object o=LazyList.get(_chain, i);
1441 b.append(o.toString());
1442 b.append("->");
1443 }
1444 b.append(_servletHolder);
1445 return b.toString();
1446 }
1447 }
1448
1449
1450
1451
1452
1453 public int getMaxFilterChainsCacheSize()
1454 {
1455 return _maxFilterChainsCacheSize;
1456 }
1457
1458
1459
1460
1461
1462
1463
1464
1465 public void setMaxFilterChainsCacheSize(int maxFilterChainsCacheSize)
1466 {
1467 _maxFilterChainsCacheSize = maxFilterChainsCacheSize;
1468 }
1469
1470
1471 void destroyServlet(Servlet servlet)
1472 {
1473 if (_contextHandler!=null)
1474 _contextHandler.destroyServlet(servlet);
1475 }
1476
1477
1478 void destroyFilter(Filter filter)
1479 {
1480 if (_contextHandler!=null)
1481 _contextHandler.destroyFilter(filter);
1482 }
1483
1484
1485 @Override
1486 public void dump(Appendable out,String indent) throws IOException
1487 {
1488 super.dumpThis(out);
1489 dump(out,indent,
1490 TypeUtil.asList(getHandlers()),
1491 getBeans(),
1492 TypeUtil.asList(getFilterMappings()),
1493 TypeUtil.asList(getFilters()),
1494 TypeUtil.asList(getServletMappings()),
1495 TypeUtil.asList(getServlets()));
1496 }
1497 }