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