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