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