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