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.List;
29 import java.util.ListIterator;
30 import java.util.Map;
31 import java.util.Queue;
32 import java.util.Set;
33 import java.util.concurrent.ConcurrentHashMap;
34 import java.util.concurrent.ConcurrentLinkedQueue;
35 import java.util.concurrent.ConcurrentMap;
36
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.HttpServlet;
50 import javax.servlet.http.HttpServletRequest;
51 import javax.servlet.http.HttpServletResponse;
52
53 import org.eclipse.jetty.http.HttpHeader;
54 import org.eclipse.jetty.http.HttpHeaderValue;
55 import org.eclipse.jetty.http.PathMap;
56 import org.eclipse.jetty.io.EofException;
57 import org.eclipse.jetty.io.RuntimeIOException;
58 import org.eclipse.jetty.security.IdentityService;
59 import org.eclipse.jetty.security.SecurityHandler;
60 import org.eclipse.jetty.server.QuietServletException;
61 import org.eclipse.jetty.server.Request;
62 import org.eclipse.jetty.server.ServletRequestHttpWrapper;
63 import org.eclipse.jetty.server.ServletResponseHttpWrapper;
64 import org.eclipse.jetty.server.UserIdentity;
65 import org.eclipse.jetty.server.handler.ContextHandler;
66 import org.eclipse.jetty.server.handler.ScopedHandler;
67 import org.eclipse.jetty.servlet.BaseHolder.Source;
68 import org.eclipse.jetty.util.ArrayUtil;
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.URIUtil;
73 import org.eclipse.jetty.util.annotation.ManagedAttribute;
74 import org.eclipse.jetty.util.annotation.ManagedObject;
75 import org.eclipse.jetty.util.component.LifeCycle;
76 import org.eclipse.jetty.util.log.Log;
77 import org.eclipse.jetty.util.log.Logger;
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92 @ManagedObject("Servlet Handler")
93 public class ServletHandler extends ScopedHandler
94 {
95 private static final Logger LOG = Log.getLogger(ServletHandler.class);
96
97
98 public static final String __DEFAULT_SERVLET="default";
99
100
101 private ServletContextHandler _contextHandler;
102 private ServletContext _servletContext;
103 private FilterHolder[] _filters=new FilterHolder[0];
104 private FilterMapping[] _filterMappings;
105 private int _matchBeforeIndex = -1;
106 private int _matchAfterIndex = -1;
107 private boolean _filterChainsCached=true;
108 private int _maxFilterChainsCacheSize=512;
109 private boolean _startWithUnavailable=false;
110 private boolean _ensureDefaultServlet=true;
111 private IdentityService _identityService;
112
113 private ServletHolder[] _servlets=new ServletHolder[0];
114 private ServletMapping[] _servletMappings;
115 private final Map<String,FilterHolder> _filterNameMap= new HashMap<>();
116 private List<FilterMapping> _filterPathMappings;
117 private MultiMap<FilterMapping> _filterNameMappings;
118
119 private final Map<String,ServletHolder> _servletNameMap=new HashMap<>();
120 private PathMap<ServletHolder> _servletPathMap;
121
122 private ListenerHolder[] _listeners=new ListenerHolder[0];
123
124 @SuppressWarnings("unchecked")
125 protected final ConcurrentMap<String, FilterChain> _chainCache[] = new ConcurrentMap[FilterMapping.ALL];
126
127 @SuppressWarnings("unchecked")
128 protected final Queue<String>[] _chainLRU = new Queue[FilterMapping.ALL];
129
130
131
132
133
134
135 public ServletHandler()
136 {
137 }
138
139
140 @Override
141 protected synchronized void doStart()
142 throws Exception
143 {
144 ContextHandler.Context context=ContextHandler.getCurrentContext();
145 _servletContext=context==null?new ContextHandler.StaticContext():context;
146 _contextHandler=(ServletContextHandler)(context==null?null:context.getContextHandler());
147
148 if (_contextHandler!=null)
149 {
150 SecurityHandler security_handler = _contextHandler.getChildHandlerByClass(SecurityHandler.class);
151 if (security_handler!=null)
152 _identityService=security_handler.getIdentityService();
153 }
154
155 updateNameMappings();
156 updateMappings();
157
158 if (getServletMapping("/")==null && _ensureDefaultServlet)
159 {
160 if (LOG.isDebugEnabled())
161 LOG.debug("Adding Default404Servlet to {}",this);
162 addServletWithMapping(Default404Servlet.class,"/");
163 updateMappings();
164 getServletMapping("/").setDefault(true);
165 }
166
167 if(_filterChainsCached)
168 {
169 _chainCache[FilterMapping.REQUEST]=new ConcurrentHashMap<String,FilterChain>();
170 _chainCache[FilterMapping.FORWARD]=new ConcurrentHashMap<String,FilterChain>();
171 _chainCache[FilterMapping.INCLUDE]=new ConcurrentHashMap<String,FilterChain>();
172 _chainCache[FilterMapping.ERROR]=new ConcurrentHashMap<String,FilterChain>();
173 _chainCache[FilterMapping.ASYNC]=new ConcurrentHashMap<String,FilterChain>();
174
175 _chainLRU[FilterMapping.REQUEST]=new ConcurrentLinkedQueue<String>();
176 _chainLRU[FilterMapping.FORWARD]=new ConcurrentLinkedQueue<String>();
177 _chainLRU[FilterMapping.INCLUDE]=new ConcurrentLinkedQueue<String>();
178 _chainLRU[FilterMapping.ERROR]=new ConcurrentLinkedQueue<String>();
179 _chainLRU[FilterMapping.ASYNC]=new ConcurrentLinkedQueue<String>();
180 }
181
182 if (_contextHandler==null)
183 initialize();
184
185 super.doStart();
186 }
187
188
189
190
191
192
193
194 public boolean isEnsureDefaultServlet()
195 {
196 return _ensureDefaultServlet;
197 }
198
199
200
201
202
203
204 public void setEnsureDefaultServlet(boolean ensureDefaultServlet)
205 {
206 _ensureDefaultServlet=ensureDefaultServlet;
207 }
208
209
210 @Override
211 protected void start(LifeCycle l) throws Exception
212 {
213
214
215
216
217 if (!(l instanceof Holder))
218 super.start(l);
219 }
220
221
222 @Override
223 protected synchronized void doStop()
224 throws Exception
225 {
226 super.doStop();
227
228
229 List<FilterHolder> filterHolders = new ArrayList<FilterHolder>();
230 List<FilterMapping> filterMappings = ArrayUtil.asMutableList(_filterMappings);
231 if (_filters!=null)
232 {
233 for (int i=_filters.length; i-->0;)
234 {
235 try
236 {
237 _filters[i].stop();
238 }
239 catch(Exception e)
240 {
241 LOG.warn(Log.EXCEPTION,e);
242 }
243 if (_filters[i].getSource() != Source.EMBEDDED)
244 {
245
246 _filterNameMap.remove(_filters[i].getName());
247
248 ListIterator<FilterMapping> fmitor = filterMappings.listIterator();
249 while (fmitor.hasNext())
250 {
251 FilterMapping fm = fmitor.next();
252 if (fm.getFilterName().equals(_filters[i].getName()))
253 fmitor.remove();
254 }
255 }
256 else
257 filterHolders.add(_filters[i]);
258 }
259 }
260
261
262 FilterHolder[] fhs = (FilterHolder[]) LazyList.toArray(filterHolders, FilterHolder.class);
263 updateBeans(_filters, fhs);
264 _filters = fhs;
265 FilterMapping[] fms = (FilterMapping[]) LazyList.toArray(filterMappings, FilterMapping.class);
266 updateBeans(_filterMappings, fms);
267 _filterMappings = fms;
268
269 _matchAfterIndex = (_filterMappings == null || _filterMappings.length == 0 ? -1 : _filterMappings.length-1);
270 _matchBeforeIndex = -1;
271
272
273 List<ServletHolder> servletHolders = new ArrayList<ServletHolder>();
274 List<ServletMapping> servletMappings = ArrayUtil.asMutableList(_servletMappings);
275 if (_servlets!=null)
276 {
277 for (int i=_servlets.length; i-->0;)
278 {
279 try
280 {
281 _servlets[i].stop();
282 }
283 catch(Exception e)
284 {
285 LOG.warn(Log.EXCEPTION,e);
286 }
287
288 if (_servlets[i].getSource() != Source.EMBEDDED)
289 {
290
291 _servletNameMap.remove(_servlets[i].getName());
292
293 ListIterator<ServletMapping> smitor = servletMappings.listIterator();
294 while (smitor.hasNext())
295 {
296 ServletMapping sm = smitor.next();
297 if (sm.getServletName().equals(_servlets[i].getName()))
298 smitor.remove();
299 }
300 }
301 else
302 servletHolders.add(_servlets[i]);
303 }
304 }
305
306
307 ServletHolder[] shs = (ServletHolder[]) LazyList.toArray(servletHolders, ServletHolder.class);
308 updateBeans(_servlets, shs);
309 _servlets = shs;
310 ServletMapping[] sms = (ServletMapping[])LazyList.toArray(servletMappings, ServletMapping.class);
311 updateBeans(_servletMappings, sms);
312 _servletMappings = sms;
313
314
315 List<ListenerHolder> listenerHolders = new ArrayList<ListenerHolder>();
316 if (_listeners != null)
317 {
318 for (int i=_listeners.length; i-->0;)
319 {
320 try
321 {
322 _listeners[i].stop();
323 }
324 catch(Exception e)
325 {
326 LOG.warn(Log.EXCEPTION,e);
327 }
328 if (_listeners[i].getSource() == Source.EMBEDDED)
329 listenerHolders.add(_listeners[i]);
330 }
331 }
332 ListenerHolder[] listeners = (ListenerHolder[])LazyList.toArray(listenerHolders, ListenerHolder.class);
333 updateBeans(_listeners, listeners);
334 _listeners = listeners;
335
336
337 _filterPathMappings=null;
338 _filterNameMappings=null;
339 _servletPathMap=null;
340 }
341
342
343 protected IdentityService getIdentityService()
344 {
345 return _identityService;
346 }
347
348
349
350
351
352 public Object getContextLog()
353 {
354 return null;
355 }
356
357
358
359
360
361 @ManagedAttribute(value="filters", readonly=true)
362 public FilterMapping[] getFilterMappings()
363 {
364 return _filterMappings;
365 }
366
367
368
369
370
371 @ManagedAttribute(value="filters", readonly=true)
372 public FilterHolder[] getFilters()
373 {
374 return _filters;
375 }
376
377
378
379
380
381
382 public PathMap.MappedEntry<ServletHolder> getHolderEntry(String pathInContext)
383 {
384 if (_servletPathMap==null)
385 return null;
386 return _servletPathMap.getMatch(pathInContext);
387 }
388
389
390 public ServletContext getServletContext()
391 {
392 return _servletContext;
393 }
394
395
396
397
398
399 @ManagedAttribute(value="mappings of servlets", readonly=true)
400 public ServletMapping[] getServletMappings()
401 {
402 return _servletMappings;
403 }
404
405
406
407
408
409
410
411
412 public ServletMapping getServletMapping(String pathSpec)
413 {
414 if (pathSpec == null || _servletMappings == null)
415 return null;
416
417 ServletMapping mapping = null;
418 for (int i=0; i<_servletMappings.length && mapping == null; i++)
419 {
420 ServletMapping m = _servletMappings[i];
421 if (m.getPathSpecs() != null)
422 {
423 for (String p:m.getPathSpecs())
424 {
425 if (pathSpec.equals(p))
426 {
427 mapping = m;
428 break;
429 }
430 }
431 }
432 }
433 return mapping;
434 }
435
436
437
438
439
440 @ManagedAttribute(value="servlets", readonly=true)
441 public ServletHolder[] getServlets()
442 {
443 return _servlets;
444 }
445
446
447 public ServletHolder getServlet(String name)
448 {
449 return _servletNameMap.get(name);
450 }
451
452
453 @Override
454 public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
455 {
456
457 final String old_servlet_path=baseRequest.getServletPath();
458 final String old_path_info=baseRequest.getPathInfo();
459
460 DispatcherType type = baseRequest.getDispatcherType();
461
462 ServletHolder servlet_holder=null;
463 UserIdentity.Scope old_scope=null;
464
465
466 if (target.startsWith("/"))
467 {
468
469 PathMap.MappedEntry<ServletHolder> entry=getHolderEntry(target);
470 if (entry!=null)
471 {
472 servlet_holder=entry.getValue();
473
474 String servlet_path_spec= entry.getKey();
475 String servlet_path=entry.getMapped()!=null?entry.getMapped():PathMap.pathMatch(servlet_path_spec,target);
476 String path_info=PathMap.pathInfo(servlet_path_spec,target);
477
478 if (DispatcherType.INCLUDE.equals(type))
479 {
480 baseRequest.setAttribute(RequestDispatcher.INCLUDE_SERVLET_PATH,servlet_path);
481 baseRequest.setAttribute(RequestDispatcher.INCLUDE_PATH_INFO, path_info);
482 }
483 else
484 {
485 baseRequest.setServletPath(servlet_path);
486 baseRequest.setPathInfo(path_info);
487 }
488 }
489 }
490 else
491 {
492
493 servlet_holder= _servletNameMap.get(target);
494 }
495
496 if (LOG.isDebugEnabled())
497 LOG.debug("servlet {}|{}|{} -> {}",baseRequest.getContextPath(),baseRequest.getServletPath(),baseRequest.getPathInfo(),servlet_holder);
498
499 try
500 {
501
502 old_scope=baseRequest.getUserIdentityScope();
503 baseRequest.setUserIdentityScope(servlet_holder);
504
505
506 if (never())
507 nextScope(target,baseRequest,request,response);
508 else if (_nextScope!=null)
509 _nextScope.doScope(target,baseRequest,request, response);
510 else if (_outerScope!=null)
511 _outerScope.doHandle(target,baseRequest,request, response);
512 else
513 doHandle(target,baseRequest,request, response);
514
515 }
516 finally
517 {
518 if (old_scope!=null)
519 baseRequest.setUserIdentityScope(old_scope);
520
521 if (!(DispatcherType.INCLUDE.equals(type)))
522 {
523 baseRequest.setServletPath(old_servlet_path);
524 baseRequest.setPathInfo(old_path_info);
525 }
526 }
527 }
528
529
530
531
532
533 @Override
534 public void doHandle(String target, Request baseRequest,HttpServletRequest request, HttpServletResponse response)
535 throws IOException, ServletException
536 {
537 DispatcherType type = baseRequest.getDispatcherType();
538
539 ServletHolder servlet_holder=(ServletHolder) baseRequest.getUserIdentityScope();
540 FilterChain chain=null;
541
542
543 if (target.startsWith("/"))
544 {
545 if (servlet_holder!=null && _filterMappings!=null && _filterMappings.length>0)
546 chain=getFilterChain(baseRequest, target, servlet_holder);
547 }
548 else
549 {
550 if (servlet_holder!=null)
551 {
552 if (_filterMappings!=null && _filterMappings.length>0)
553 {
554 chain=getFilterChain(baseRequest, null,servlet_holder);
555 }
556 }
557 }
558
559 if (LOG.isDebugEnabled())
560 LOG.debug("chain={}",chain);
561
562 Throwable th=null;
563 try
564 {
565 if (servlet_holder==null)
566 notFound(baseRequest,request, response);
567 else
568 {
569
570 ServletRequest req = request;
571 if (req instanceof ServletRequestHttpWrapper)
572 req = ((ServletRequestHttpWrapper)req).getRequest();
573 ServletResponse res = response;
574 if (res instanceof ServletResponseHttpWrapper)
575 res = ((ServletResponseHttpWrapper)res).getResponse();
576
577
578 servlet_holder.prepare(baseRequest, req, res);
579
580 if (chain!=null)
581 chain.doFilter(req, res);
582 else
583 servlet_holder.handle(baseRequest,req,res);
584 }
585 }
586 catch(EofException e)
587 {
588 throw e;
589 }
590 catch(RuntimeIOException e)
591 {
592 if (e.getCause() instanceof IOException)
593 {
594 LOG.debug(e);
595 throw (IOException)e.getCause();
596 }
597 throw e;
598 }
599 catch(Exception e)
600 {
601
602
603 if (baseRequest.isAsyncStarted() || !(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
604 {
605 if (e instanceof IOException)
606 throw (IOException)e;
607 if (e instanceof RuntimeException)
608 throw (RuntimeException)e;
609 if (e instanceof ServletException)
610 throw (ServletException)e;
611 }
612
613
614 th=e;
615 if (th instanceof ServletException)
616 {
617 if (th instanceof QuietServletException)
618 {
619 LOG.warn(th.toString());
620 LOG.debug(th);
621 }
622 else
623 LOG.warn(th);
624 }
625 else if (th instanceof EofException)
626 {
627 throw (EofException)th;
628 }
629 else
630 {
631 LOG.warn(request.getRequestURI(),th);
632 if (LOG.isDebugEnabled())
633 LOG.debug(request.toString());
634 }
635
636 request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,th.getClass());
637 request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,th);
638 if (!response.isCommitted())
639 {
640 baseRequest.getResponse().getHttpFields().put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
641 if (th instanceof UnavailableException)
642 {
643 UnavailableException ue = (UnavailableException)th;
644 if (ue.isPermanent())
645 response.sendError(HttpServletResponse.SC_NOT_FOUND);
646 else
647 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
648 }
649 else
650 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
651 }
652 else
653 {
654 if (th instanceof IOException)
655 throw (IOException)th;
656 if (th instanceof RuntimeException)
657 throw (RuntimeException)th;
658 if (th instanceof ServletException)
659 throw (ServletException)th;
660 throw new IllegalStateException("response already committed",th);
661 }
662 }
663 catch(Error e)
664 {
665 if ("ContinuationThrowable".equals(e.getClass().getSimpleName()))
666 throw e;
667 th=e;
668 if (!(DispatcherType.REQUEST.equals(type) || DispatcherType.ASYNC.equals(type)))
669 throw e;
670 LOG.warn("Error for "+request.getRequestURI(),e);
671 if(LOG.isDebugEnabled())
672 LOG.debug(request.toString());
673
674 request.setAttribute(RequestDispatcher.ERROR_EXCEPTION_TYPE,e.getClass());
675 request.setAttribute(RequestDispatcher.ERROR_EXCEPTION,e);
676 if (!response.isCommitted())
677 {
678 baseRequest.getResponse().getHttpFields().put(HttpHeader.CONNECTION,HttpHeaderValue.CLOSE);
679 response.sendError(HttpServletResponse.SC_INTERNAL_SERVER_ERROR);
680 }
681 else
682 LOG.debug("Response already committed for handling ",e);
683 }
684 finally
685 {
686
687 if (th!=null && request.isAsyncStarted())
688 baseRequest.getHttpChannelState().errorComplete();
689
690 if (servlet_holder!=null)
691 baseRequest.setHandled(true);
692 }
693 }
694
695
696 protected FilterChain getFilterChain(Request baseRequest, String pathInContext, ServletHolder servletHolder)
697 {
698 String key=pathInContext==null?servletHolder.getName():pathInContext;
699 int dispatch = FilterMapping.dispatch(baseRequest.getDispatcherType());
700
701 if (_filterChainsCached && _chainCache!=null)
702 {
703 FilterChain chain = (FilterChain)_chainCache[dispatch].get(key);
704 if (chain!=null)
705 return chain;
706 }
707
708
709 List<FilterHolder> filters = new ArrayList<>();
710
711
712 if (pathInContext!=null && _filterPathMappings!=null)
713 {
714 for (FilterMapping filterPathMapping : _filterPathMappings)
715 {
716 if (filterPathMapping.appliesTo(pathInContext, dispatch))
717 filters.add(filterPathMapping.getFilterHolder());
718 }
719 }
720
721
722 if (servletHolder != null && _filterNameMappings!=null && _filterNameMappings.size() > 0)
723 {
724
725 if (_filterNameMappings.size() > 0)
726 {
727 Object o= _filterNameMappings.get(servletHolder.getName());
728
729 for (int i=0; i<LazyList.size(o);i++)
730 {
731 FilterMapping mapping = (FilterMapping)LazyList.get(o,i);
732 if (mapping.appliesTo(dispatch))
733 filters.add(mapping.getFilterHolder());
734 }
735
736 o= _filterNameMappings.get("*");
737 for (int i=0; i<LazyList.size(o);i++)
738 {
739 FilterMapping mapping = (FilterMapping)LazyList.get(o,i);
740 if (mapping.appliesTo(dispatch))
741 filters.add(mapping.getFilterHolder());
742 }
743 }
744 }
745
746 if (filters.isEmpty())
747 return null;
748
749
750 FilterChain chain = null;
751 if (_filterChainsCached)
752 {
753 if (filters.size() > 0)
754 chain= new CachedChain(filters, servletHolder);
755
756 final Map<String,FilterChain> cache=_chainCache[dispatch];
757 final Queue<String> lru=_chainLRU[dispatch];
758
759
760 while (_maxFilterChainsCacheSize>0 && cache.size()>=_maxFilterChainsCacheSize)
761 {
762
763
764
765 String k=lru.poll();
766 if (k==null)
767 {
768 cache.clear();
769 break;
770 }
771 cache.remove(k);
772 }
773
774 cache.put(key,chain);
775 lru.add(key);
776 }
777 else if (filters.size() > 0)
778 chain = new Chain(baseRequest,filters, servletHolder);
779
780 return chain;
781 }
782
783
784 protected void invalidateChainsCache()
785 {
786 if (_chainLRU[FilterMapping.REQUEST]!=null)
787 {
788 _chainLRU[FilterMapping.REQUEST].clear();
789 _chainLRU[FilterMapping.FORWARD].clear();
790 _chainLRU[FilterMapping.INCLUDE].clear();
791 _chainLRU[FilterMapping.ERROR].clear();
792 _chainLRU[FilterMapping.ASYNC].clear();
793
794 _chainCache[FilterMapping.REQUEST].clear();
795 _chainCache[FilterMapping.FORWARD].clear();
796 _chainCache[FilterMapping.INCLUDE].clear();
797 _chainCache[FilterMapping.ERROR].clear();
798 _chainCache[FilterMapping.ASYNC].clear();
799 }
800 }
801
802
803
804
805
806 public boolean isAvailable()
807 {
808 if (!isStarted())
809 return false;
810 ServletHolder[] holders = getServlets();
811 for (ServletHolder holder : holders)
812 {
813 if (holder != null && !holder.isAvailable())
814 return false;
815 }
816 return true;
817 }
818
819
820
821
822
823 public void setStartWithUnavailable(boolean start)
824 {
825 _startWithUnavailable=start;
826 }
827
828
829
830
831
832 public boolean isStartWithUnavailable()
833 {
834 return _startWithUnavailable;
835 }
836
837
838
839
840
841
842
843 public void initialize()
844 throws Exception
845 {
846 MultiException mx = new MultiException();
847
848
849 if (_filters != null)
850 {
851 for (FilterHolder f: _filters)
852 {
853 try
854 {
855 f.start();
856 f.initialize();
857 }
858 catch (Exception e)
859 {
860 mx.add(e);
861 }
862 }
863 }
864
865
866 if (_servlets!=null)
867 {
868 ServletHolder[] servlets = _servlets.clone();
869 Arrays.sort(servlets);
870 for (ServletHolder servlet : servlets)
871 {
872 try
873 {
874 servlet.start();
875 servlet.initialize();
876 }
877 catch (Throwable e)
878 {
879 LOG.debug(Log.EXCEPTION, e);
880 mx.add(e);
881 }
882 }
883 }
884
885
886 for (Holder<?> h: getBeans(Holder.class))
887 {
888 try
889 {
890 if (!h.isStarted())
891 {
892 h.start();
893 h.initialize();
894 }
895 }
896 catch (Exception e)
897 {
898 mx.add(e);
899 }
900 }
901
902 mx.ifExceptionThrow();
903 }
904
905
906
907
908
909 public boolean isFilterChainsCached()
910 {
911 return _filterChainsCached;
912 }
913
914
915
916
917
918 public void addListener (ListenerHolder listener)
919 {
920 if (listener != null)
921 setListeners(ArrayUtil.addToArray(getListeners(), listener, ListenerHolder.class));
922 }
923
924
925
926 public ListenerHolder[] getListeners()
927 {
928 return _listeners;
929 }
930
931
932 public void setListeners(ListenerHolder[] listeners)
933 {
934 if (listeners!=null)
935 for (ListenerHolder holder:listeners)
936 holder.setServletHandler(this);
937
938 updateBeans(_listeners,listeners);
939 _listeners = listeners;
940 }
941
942
943 public ListenerHolder newListenerHolder(Holder.Source source)
944 {
945 return new ListenerHolder(source);
946 }
947
948
949
950
951
952
953
954 public ServletHolder newServletHolder(Holder.Source source)
955 {
956 return new ServletHolder(source);
957 }
958
959
960
961
962
963
964
965 public ServletHolder addServletWithMapping (String className,String pathSpec)
966 {
967 ServletHolder holder = newServletHolder(Source.EMBEDDED);
968 holder.setClassName(className);
969 addServletWithMapping(holder,pathSpec);
970 return holder;
971 }
972
973
974
975
976
977
978
979 public ServletHolder addServletWithMapping (Class<? extends Servlet> servlet,String pathSpec)
980 {
981 ServletHolder holder = newServletHolder(Source.EMBEDDED);
982 holder.setHeldClass(servlet);
983 addServletWithMapping(holder,pathSpec);
984
985 return holder;
986 }
987
988
989
990
991
992
993 public void addServletWithMapping (ServletHolder servlet,String pathSpec)
994 {
995 ServletHolder[] holders=getServlets();
996 if (holders!=null)
997 holders = holders.clone();
998
999 try
1000 {
1001 setServlets(ArrayUtil.addToArray(holders, servlet, ServletHolder.class));
1002
1003 ServletMapping mapping = new ServletMapping();
1004 mapping.setServletName(servlet.getName());
1005 mapping.setPathSpec(pathSpec);
1006 setServletMappings(ArrayUtil.addToArray(getServletMappings(), mapping, ServletMapping.class));
1007 }
1008 catch (Exception e)
1009 {
1010 setServlets(holders);
1011 if (e instanceof RuntimeException)
1012 throw (RuntimeException)e;
1013 throw new RuntimeException(e);
1014 }
1015 }
1016
1017
1018
1019
1020
1021
1022
1023 public void addServlet(ServletHolder holder)
1024 {
1025 setServlets(ArrayUtil.addToArray(getServlets(), holder, ServletHolder.class));
1026 }
1027
1028
1029
1030
1031
1032
1033 public void addServletMapping (ServletMapping mapping)
1034 {
1035 setServletMappings(ArrayUtil.addToArray(getServletMappings(), mapping, ServletMapping.class));
1036 }
1037
1038
1039 public Set<String> setServletSecurity(ServletRegistration.Dynamic registration, ServletSecurityElement servletSecurityElement)
1040 {
1041 if (_contextHandler != null)
1042 {
1043 return _contextHandler.setServletSecurity(registration, servletSecurityElement);
1044 }
1045 return Collections.emptySet();
1046 }
1047
1048
1049 public FilterHolder newFilterHolder(Holder.Source source)
1050 {
1051 return new FilterHolder(source);
1052 }
1053
1054
1055 public FilterHolder getFilter(String name)
1056 {
1057 return _filterNameMap.get(name);
1058 }
1059
1060
1061
1062
1063
1064
1065
1066
1067
1068 public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,EnumSet<DispatcherType> dispatches)
1069 {
1070 FilterHolder holder = newFilterHolder(Source.EMBEDDED);
1071 holder.setHeldClass(filter);
1072 addFilterWithMapping(holder,pathSpec,dispatches);
1073
1074 return holder;
1075 }
1076
1077
1078
1079
1080
1081
1082
1083
1084 public FilterHolder addFilterWithMapping (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
1085 {
1086 FilterHolder holder = newFilterHolder(Source.EMBEDDED);
1087 holder.setClassName(className);
1088
1089 addFilterWithMapping(holder,pathSpec,dispatches);
1090 return holder;
1091 }
1092
1093
1094
1095
1096
1097
1098
1099 public void addFilterWithMapping (FilterHolder holder,String pathSpec,EnumSet<DispatcherType> dispatches)
1100 {
1101 FilterHolder[] holders = getFilters();
1102 if (holders!=null)
1103 holders = holders.clone();
1104
1105 try
1106 {
1107 setFilters(ArrayUtil.addToArray(holders, holder, FilterHolder.class));
1108
1109 FilterMapping mapping = new FilterMapping();
1110 mapping.setFilterName(holder.getName());
1111 mapping.setPathSpec(pathSpec);
1112 mapping.setDispatcherTypes(dispatches);
1113 addFilterMapping(mapping);
1114
1115 }
1116 catch (RuntimeException e)
1117 {
1118 setFilters(holders);
1119 throw e;
1120 }
1121 catch (Error e)
1122 {
1123 setFilters(holders);
1124 throw e;
1125 }
1126
1127 }
1128
1129
1130
1131
1132
1133
1134
1135
1136 public FilterHolder addFilterWithMapping (Class<? extends Filter> filter,String pathSpec,int dispatches)
1137 {
1138 FilterHolder holder = newFilterHolder(Source.EMBEDDED);
1139 holder.setHeldClass(filter);
1140 addFilterWithMapping(holder,pathSpec,dispatches);
1141
1142 return holder;
1143 }
1144
1145
1146
1147
1148
1149
1150
1151
1152 public FilterHolder addFilterWithMapping (String className,String pathSpec,int dispatches)
1153 {
1154 FilterHolder holder = newFilterHolder(Source.EMBEDDED);
1155 holder.setClassName(className);
1156
1157 addFilterWithMapping(holder,pathSpec,dispatches);
1158 return holder;
1159 }
1160
1161
1162
1163
1164
1165
1166
1167 public void addFilterWithMapping (FilterHolder holder,String pathSpec,int dispatches)
1168 {
1169 FilterHolder[] holders = getFilters();
1170 if (holders!=null)
1171 holders = holders.clone();
1172
1173 try
1174 {
1175 setFilters(ArrayUtil.addToArray(holders, holder, FilterHolder.class));
1176
1177 FilterMapping mapping = new FilterMapping();
1178 mapping.setFilterName(holder.getName());
1179 mapping.setPathSpec(pathSpec);
1180 mapping.setDispatches(dispatches);
1181 addFilterMapping(mapping);
1182 }
1183 catch (RuntimeException e)
1184 {
1185 setFilters(holders);
1186 throw e;
1187 }
1188 catch (Error e)
1189 {
1190 setFilters(holders);
1191 throw e;
1192 }
1193
1194 }
1195
1196
1197
1198
1199
1200
1201
1202
1203
1204
1205 @Deprecated
1206 public FilterHolder addFilter (String className,String pathSpec,EnumSet<DispatcherType> dispatches)
1207 {
1208 return addFilterWithMapping(className, pathSpec, dispatches);
1209 }
1210
1211
1212
1213
1214
1215
1216
1217 public void addFilter (FilterHolder filter, FilterMapping filterMapping)
1218 {
1219 if (filter != null)
1220 setFilters(ArrayUtil.addToArray(getFilters(), filter, FilterHolder.class));
1221 if (filterMapping != null)
1222 addFilterMapping(filterMapping);
1223 }
1224
1225
1226
1227
1228
1229
1230 public void addFilter (FilterHolder filter)
1231 {
1232 if (filter != null)
1233 setFilters(ArrayUtil.addToArray(getFilters(), filter, FilterHolder.class));
1234 }
1235
1236
1237
1238
1239
1240
1241 public void addFilterMapping (FilterMapping mapping)
1242 {
1243 if (mapping != null)
1244 {
1245 Source source = (mapping.getFilterHolder()==null?null:mapping.getFilterHolder().getSource());
1246 FilterMapping[] mappings =getFilterMappings();
1247 if (mappings==null || mappings.length==0)
1248 {
1249 setFilterMappings(insertFilterMapping(mapping,0,false));
1250 if (source != null && source == Source.JAVAX_API)
1251 _matchAfterIndex = 0;
1252 }
1253 else
1254 {
1255
1256
1257
1258 if (source != null && Source.JAVAX_API == source)
1259 {
1260 setFilterMappings(insertFilterMapping(mapping,mappings.length-1, false));
1261 if (_matchAfterIndex < 0)
1262 _matchAfterIndex = getFilterMappings().length-1;
1263 }
1264 else
1265 {
1266
1267 if (_matchAfterIndex < 0)
1268 setFilterMappings(insertFilterMapping(mapping,mappings.length-1, false));
1269 else
1270 {
1271 FilterMapping[] new_mappings = insertFilterMapping(mapping, _matchAfterIndex, true);
1272 ++_matchAfterIndex;
1273 setFilterMappings(new_mappings);
1274 }
1275 }
1276 }
1277 }
1278 }
1279
1280
1281
1282
1283
1284
1285
1286 public void prependFilterMapping (FilterMapping mapping)
1287 {
1288 if (mapping != null)
1289 {
1290 Source source = (mapping.getFilterHolder()==null?null:mapping.getFilterHolder().getSource());
1291 FilterMapping[] mappings = getFilterMappings();
1292 if (mappings==null || mappings.length==0)
1293 {
1294 setFilterMappings(insertFilterMapping(mapping, 0, false));
1295 if (source != null && Source.JAVAX_API == source)
1296 _matchBeforeIndex = 0;
1297 }
1298 else
1299 {
1300 if (source != null && Source.JAVAX_API == source)
1301 {
1302
1303
1304
1305
1306 if (_matchBeforeIndex < 0)
1307 {
1308
1309 _matchBeforeIndex = 0;
1310 FilterMapping[] new_mappings = insertFilterMapping(mapping, 0, true);
1311 setFilterMappings(new_mappings);
1312 }
1313 else
1314 {
1315 FilterMapping[] new_mappings = insertFilterMapping(mapping,_matchBeforeIndex, false);
1316 ++_matchBeforeIndex;
1317 setFilterMappings(new_mappings);
1318 }
1319 }
1320 else
1321 {
1322
1323 FilterMapping[] new_mappings = insertFilterMapping(mapping, 0, true);
1324 setFilterMappings(new_mappings);
1325 }
1326
1327
1328 if (_matchAfterIndex >= 0)
1329 ++_matchAfterIndex;
1330 }
1331 }
1332 }
1333
1334
1335
1336
1337
1338
1339
1340
1341
1342
1343 protected FilterMapping[] insertFilterMapping (FilterMapping mapping, int pos, boolean before)
1344 {
1345 if (pos < 0)
1346 throw new IllegalArgumentException("FilterMapping insertion pos < 0");
1347 FilterMapping[] mappings = getFilterMappings();
1348
1349 if (mappings==null || mappings.length==0)
1350 {
1351 return new FilterMapping[] {mapping};
1352 }
1353 FilterMapping[] new_mappings = new FilterMapping[mappings.length+1];
1354
1355
1356 if (before)
1357 {
1358
1359 System.arraycopy(mappings,0,new_mappings,0,pos);
1360
1361
1362 new_mappings[pos] = mapping;
1363
1364
1365 System.arraycopy(mappings,pos,new_mappings,pos+1, mappings.length-pos);
1366
1367 }
1368 else
1369 {
1370
1371 System.arraycopy(mappings,0,new_mappings,0,pos+1);
1372
1373 new_mappings[pos+1] = mapping;
1374
1375
1376 if (mappings.length > pos+1)
1377 System.arraycopy(mappings,pos+1,new_mappings,pos+2, mappings.length-(pos+1));
1378 }
1379 return new_mappings;
1380 }
1381
1382
1383
1384 protected synchronized void updateNameMappings()
1385 {
1386
1387 _filterNameMap.clear();
1388 if (_filters!=null)
1389 {
1390 for (FilterHolder filter : _filters)
1391 {
1392 _filterNameMap.put(filter.getName(), filter);
1393 filter.setServletHandler(this);
1394 }
1395 }
1396
1397
1398 _servletNameMap.clear();
1399 if (_servlets!=null)
1400 {
1401
1402 for (ServletHolder servlet : _servlets)
1403 {
1404 _servletNameMap.put(servlet.getName(), servlet);
1405 servlet.setServletHandler(this);
1406 }
1407 }
1408 }
1409
1410
1411 protected synchronized void updateMappings()
1412 {
1413
1414 if (_filterMappings==null)
1415 {
1416 _filterPathMappings=null;
1417 _filterNameMappings=null;
1418 }
1419 else
1420 {
1421 _filterPathMappings=new ArrayList<>();
1422 _filterNameMappings=new MultiMap<FilterMapping>();
1423 for (FilterMapping filtermapping : _filterMappings)
1424 {
1425 FilterHolder filter_holder = _filterNameMap.get(filtermapping.getFilterName());
1426 if (filter_holder == null)
1427 throw new IllegalStateException("No filter named " + filtermapping.getFilterName());
1428 filtermapping.setFilterHolder(filter_holder);
1429 if (filtermapping.getPathSpecs() != null)
1430 _filterPathMappings.add(filtermapping);
1431
1432 if (filtermapping.getServletNames() != null)
1433 {
1434 String[] names = filtermapping.getServletNames();
1435 for (String name : names)
1436 {
1437 if (name != null)
1438 _filterNameMappings.add(name, filtermapping);
1439 }
1440 }
1441 }
1442 }
1443
1444
1445 if (_servletMappings==null || _servletNameMap==null)
1446 {
1447 _servletPathMap=null;
1448 }
1449 else
1450 {
1451 PathMap<ServletHolder> pm = new PathMap<>();
1452 Map<String,ServletMapping> servletPathMappings = new HashMap<String,ServletMapping>();
1453
1454
1455 HashMap<String, Set<ServletMapping>> sms = new HashMap<String, Set<ServletMapping>>();
1456 for (ServletMapping servletMapping : _servletMappings)
1457 {
1458 String[] pathSpecs = servletMapping.getPathSpecs();
1459 if (pathSpecs != null)
1460 {
1461 for (String pathSpec : pathSpecs)
1462 {
1463 Set<ServletMapping> mappings = sms.get(pathSpec);
1464 if (mappings == null)
1465 {
1466 mappings = new HashSet<ServletMapping>();
1467 sms.put(pathSpec, mappings);
1468 }
1469 mappings.add(servletMapping);
1470 }
1471 }
1472 }
1473
1474
1475 for (String pathSpec : sms.keySet())
1476 {
1477
1478
1479 Set<ServletMapping> mappings = sms.get(pathSpec);
1480
1481 ServletMapping finalMapping = null;
1482 for (ServletMapping mapping : mappings)
1483 {
1484
1485 ServletHolder servlet_holder = _servletNameMap.get(mapping.getServletName());
1486 if (servlet_holder == null)
1487 throw new IllegalStateException("No such servlet: " + mapping.getServletName());
1488
1489 if (!servlet_holder.isEnabled())
1490 continue;
1491
1492
1493 if (finalMapping == null)
1494 finalMapping = mapping;
1495 else
1496 {
1497
1498 if (finalMapping.isDefault())
1499 finalMapping = mapping;
1500 else
1501 {
1502
1503 if (!mapping.isDefault())
1504 throw new IllegalStateException("Multiple servlets map to path: "+pathSpec+": "+finalMapping.getServletName()+","+mapping.getServletName());
1505 }
1506 }
1507 }
1508 if (finalMapping == null)
1509 throw new IllegalStateException ("No acceptable servlet mappings for "+pathSpec);
1510
1511 if (LOG.isDebugEnabled()) LOG.debug("Chose path={} mapped to servlet={} from default={}", pathSpec, finalMapping.getServletName(), finalMapping.isDefault());
1512
1513 servletPathMappings.put(pathSpec, finalMapping);
1514 pm.put(pathSpec,_servletNameMap.get(finalMapping.getServletName()));
1515 }
1516
1517 _servletPathMap=pm;
1518 }
1519
1520
1521 if (_chainCache!=null)
1522 {
1523 for (int i=_chainCache.length;i-->0;)
1524 {
1525 if (_chainCache[i]!=null)
1526 _chainCache[i].clear();
1527 }
1528 }
1529
1530 if (LOG.isDebugEnabled())
1531 {
1532 LOG.debug("filterNameMap="+_filterNameMap);
1533 LOG.debug("pathFilters="+_filterPathMappings);
1534 LOG.debug("servletFilterMap="+_filterNameMappings);
1535 LOG.debug("servletPathMap="+_servletPathMap);
1536 LOG.debug("servletNameMap="+_servletNameMap);
1537 }
1538
1539 try
1540 {
1541 if (_contextHandler!=null && _contextHandler.isStarted() || _contextHandler==null && isStarted())
1542 initialize();
1543 }
1544 catch (Exception e)
1545 {
1546 throw new RuntimeException(e);
1547 }
1548 }
1549
1550
1551 protected void notFound(Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
1552 {
1553 if (LOG.isDebugEnabled())
1554 LOG.debug("Not Found {}",request.getRequestURI());
1555 if (getHandler()!=null)
1556 nextHandle(URIUtil.addPaths(request.getServletPath(),request.getPathInfo()),baseRequest,request,response);
1557 }
1558
1559
1560
1561
1562
1563 public void setFilterChainsCached(boolean filterChainsCached)
1564 {
1565 _filterChainsCached = filterChainsCached;
1566 }
1567
1568
1569
1570
1571
1572 public void setFilterMappings(FilterMapping[] filterMappings)
1573 {
1574 updateBeans(_filterMappings,filterMappings);
1575 _filterMappings = filterMappings;
1576 if (isStarted()) updateMappings();
1577 invalidateChainsCache();
1578 }
1579
1580
1581 public synchronized void setFilters(FilterHolder[] holders)
1582 {
1583 if (holders!=null)
1584 for (FilterHolder holder:holders)
1585 holder.setServletHandler(this);
1586
1587 updateBeans(_filters,holders);
1588 _filters=holders;
1589 updateNameMappings();
1590 invalidateChainsCache();
1591 }
1592
1593
1594
1595
1596
1597 public void setServletMappings(ServletMapping[] servletMappings)
1598 {
1599 updateBeans(_servletMappings,servletMappings);
1600 _servletMappings = servletMappings;
1601 if (isStarted()) updateMappings();
1602 invalidateChainsCache();
1603 }
1604
1605
1606
1607
1608
1609 public synchronized void setServlets(ServletHolder[] holders)
1610 {
1611 if (holders!=null)
1612 for (ServletHolder holder:holders)
1613 holder.setServletHandler(this);
1614
1615 updateBeans(_servlets,holders);
1616 _servlets=holders;
1617 updateNameMappings();
1618 invalidateChainsCache();
1619 }
1620
1621
1622
1623 private class CachedChain implements FilterChain
1624 {
1625 FilterHolder _filterHolder;
1626 CachedChain _next;
1627 ServletHolder _servletHolder;
1628
1629
1630
1631
1632
1633
1634 CachedChain(List<FilterHolder> filters, ServletHolder servletHolder)
1635 {
1636 if (filters.size()>0)
1637 {
1638 _filterHolder=filters.get(0);
1639 filters.remove(0);
1640 _next=new CachedChain(filters,servletHolder);
1641 }
1642 else
1643 _servletHolder=servletHolder;
1644 }
1645
1646
1647 @Override
1648 public void doFilter(ServletRequest request, ServletResponse response)
1649 throws IOException, ServletException
1650 {
1651 final Request baseRequest=Request.getBaseRequest(request);
1652
1653
1654 if (_filterHolder!=null)
1655 {
1656 if (LOG.isDebugEnabled())
1657 LOG.debug("call filter {}", _filterHolder);
1658 Filter filter= _filterHolder.getFilter();
1659
1660
1661
1662
1663 boolean requestAsyncSupported = baseRequest.isAsyncSupported();
1664 try
1665 {
1666 if (!_filterHolder.isAsyncSupported() && requestAsyncSupported)
1667 baseRequest.setAsyncSupported(false);
1668 filter.doFilter(request, response, _next);
1669 }
1670 finally
1671 {
1672 baseRequest.setAsyncSupported(requestAsyncSupported);
1673 }
1674 return;
1675 }
1676
1677
1678 HttpServletRequest srequest = (HttpServletRequest)request;
1679 if (_servletHolder == null)
1680 notFound(baseRequest, srequest, (HttpServletResponse)response);
1681 else
1682 {
1683 if (LOG.isDebugEnabled())
1684 LOG.debug("call servlet " + _servletHolder);
1685 _servletHolder.handle(baseRequest,request, response);
1686 }
1687 }
1688
1689 @Override
1690 public String toString()
1691 {
1692 if (_filterHolder!=null)
1693 return _filterHolder+"->"+_next.toString();
1694 if (_servletHolder!=null)
1695 return _servletHolder.toString();
1696 return "null";
1697 }
1698 }
1699
1700
1701
1702 private class Chain implements FilterChain
1703 {
1704 final Request _baseRequest;
1705 final List<FilterHolder> _chain;
1706 final ServletHolder _servletHolder;
1707 int _filter= 0;
1708
1709
1710 Chain(Request baseRequest, List<FilterHolder> filters, ServletHolder servletHolder)
1711 {
1712 _baseRequest=baseRequest;
1713 _chain= filters;
1714 _servletHolder= servletHolder;
1715 }
1716
1717
1718 @Override
1719 public void doFilter(ServletRequest request, ServletResponse response)
1720 throws IOException, ServletException
1721 {
1722 if (LOG.isDebugEnabled())
1723 LOG.debug("doFilter " + _filter);
1724
1725
1726 if (_filter < _chain.size())
1727 {
1728 FilterHolder holder= _chain.get(_filter++);
1729 if (LOG.isDebugEnabled())
1730 LOG.debug("call filter " + holder);
1731 Filter filter= holder.getFilter();
1732
1733
1734
1735
1736 boolean requestAsyncSupported = _baseRequest.isAsyncSupported();
1737 try
1738 {
1739 if (!holder.isAsyncSupported() && requestAsyncSupported)
1740 _baseRequest.setAsyncSupported(false);
1741 filter.doFilter(request, response, this);
1742 }
1743 finally
1744 {
1745 _baseRequest.setAsyncSupported(requestAsyncSupported);
1746 }
1747 return;
1748 }
1749
1750
1751 HttpServletRequest srequest = (HttpServletRequest)request;
1752 if (_servletHolder == null)
1753 notFound(Request.getBaseRequest(request), srequest, (HttpServletResponse)response);
1754 else
1755 {
1756 if (LOG.isDebugEnabled())
1757 LOG.debug("call servlet {}", _servletHolder);
1758 _servletHolder.handle(_baseRequest,request, response);
1759 }
1760 }
1761
1762
1763 @Override
1764 public String toString()
1765 {
1766 StringBuilder b = new StringBuilder();
1767 for(FilterHolder f: _chain)
1768 {
1769 b.append(f.toString());
1770 b.append("->");
1771 }
1772 b.append(_servletHolder);
1773 return b.toString();
1774 }
1775 }
1776
1777
1778
1779
1780
1781 public int getMaxFilterChainsCacheSize()
1782 {
1783 return _maxFilterChainsCacheSize;
1784 }
1785
1786
1787
1788
1789
1790
1791
1792
1793 public void setMaxFilterChainsCacheSize(int maxFilterChainsCacheSize)
1794 {
1795 _maxFilterChainsCacheSize = maxFilterChainsCacheSize;
1796 }
1797
1798
1799 void destroyServlet(Servlet servlet)
1800 {
1801 if (_contextHandler!=null)
1802 _contextHandler.destroyServlet(servlet);
1803 }
1804
1805
1806 void destroyFilter(Filter filter)
1807 {
1808 if (_contextHandler!=null)
1809 _contextHandler.destroyFilter(filter);
1810 }
1811
1812
1813
1814
1815 public static class Default404Servlet extends HttpServlet
1816 {
1817 @Override
1818 protected void doGet(HttpServletRequest req, HttpServletResponse resp)
1819 throws ServletException, IOException
1820 {
1821 resp.sendError(HttpServletResponse.SC_NOT_FOUND);
1822 }
1823 }
1824 }