1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19 package org.eclipse.jetty.server.handler;
20
21 import java.io.File;
22 import java.io.IOException;
23 import java.io.InputStream;
24 import java.net.MalformedURLException;
25 import java.net.URL;
26 import java.net.URLClassLoader;
27 import java.security.AccessController;
28 import java.util.ArrayList;
29 import java.util.Arrays;
30 import java.util.Collections;
31 import java.util.Enumeration;
32 import java.util.EventListener;
33 import java.util.HashMap;
34 import java.util.HashSet;
35 import java.util.Iterator;
36 import java.util.List;
37 import java.util.ListIterator;
38 import java.util.Locale;
39 import java.util.Map;
40 import java.util.Set;
41 import java.util.concurrent.CopyOnWriteArrayList;
42 import java.util.concurrent.Future;
43
44 import javax.servlet.DispatcherType;
45 import javax.servlet.Filter;
46 import javax.servlet.FilterRegistration;
47 import javax.servlet.FilterRegistration.Dynamic;
48 import javax.servlet.RequestDispatcher;
49 import javax.servlet.Servlet;
50 import javax.servlet.ServletContext;
51 import javax.servlet.ServletContextAttributeEvent;
52 import javax.servlet.ServletContextAttributeListener;
53 import javax.servlet.ServletContextEvent;
54 import javax.servlet.ServletContextListener;
55 import javax.servlet.ServletException;
56 import javax.servlet.ServletRegistration;
57 import javax.servlet.ServletRequestAttributeListener;
58 import javax.servlet.ServletRequestEvent;
59 import javax.servlet.ServletRequestListener;
60 import javax.servlet.SessionCookieConfig;
61 import javax.servlet.SessionTrackingMode;
62 import javax.servlet.descriptor.JspConfigDescriptor;
63 import javax.servlet.http.HttpServletRequest;
64 import javax.servlet.http.HttpServletResponse;
65
66 import org.eclipse.jetty.http.MimeTypes;
67 import org.eclipse.jetty.server.ClassLoaderDump;
68 import org.eclipse.jetty.server.Connector;
69 import org.eclipse.jetty.server.Dispatcher;
70 import org.eclipse.jetty.server.Handler;
71 import org.eclipse.jetty.server.HandlerContainer;
72 import org.eclipse.jetty.server.Request;
73 import org.eclipse.jetty.server.Server;
74 import org.eclipse.jetty.util.Attributes;
75 import org.eclipse.jetty.util.AttributesMap;
76 import org.eclipse.jetty.util.FutureCallback;
77 import org.eclipse.jetty.util.Loader;
78 import org.eclipse.jetty.util.StringUtil;
79 import org.eclipse.jetty.util.URIUtil;
80 import org.eclipse.jetty.util.annotation.ManagedAttribute;
81 import org.eclipse.jetty.util.annotation.ManagedObject;
82 import org.eclipse.jetty.util.component.Graceful;
83 import org.eclipse.jetty.util.log.Log;
84 import org.eclipse.jetty.util.log.Logger;
85 import org.eclipse.jetty.util.resource.Resource;
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102 @ManagedObject("URI Context")
103 public class ContextHandler extends ScopedHandler implements Attributes, Graceful
104 {
105 public final static int SERVLET_MAJOR_VERSION=3;
106 public final static int SERVLET_MINOR_VERSION=0;
107
108 final private static String __unimplmented="Unimplemented - use org.eclipse.jetty.servlet.ServletContextHandler";
109
110
111
112 private static final Logger LOG = Log.getLogger(ContextHandler.class);
113
114 private static final ThreadLocal<Context> __context = new ThreadLocal<Context>();
115
116
117
118
119
120
121 public static final String MANAGED_ATTRIBUTES = "org.eclipse.jetty.server.context.ManagedAttributes";
122
123
124
125
126
127
128
129 public static Context getCurrentContext()
130 {
131 return __context.get();
132 }
133
134
135 public static ContextHandler getContextHandler(ServletContext context)
136 {
137 if(context instanceof ContextHandler.Context)
138 return ((ContextHandler.Context)context).getContextHandler();
139 Context c= getCurrentContext();
140 if (c!=null)
141 return c.getContextHandler();
142 return null;
143 }
144
145
146 protected Context _scontext;
147 private final AttributesMap _attributes;
148 private final Map<String, String> _initParams;
149 private ClassLoader _classLoader;
150 private String _contextPath = "/";
151
152 private String _displayName;
153
154 private Resource _baseResource;
155 private MimeTypes _mimeTypes;
156 private Map<String, String> _localeEncodingMap;
157 private String[] _welcomeFiles;
158 private ErrorHandler _errorHandler;
159 private String[] _vhosts;
160
161 private Logger _logger;
162 private boolean _allowNullPathInfo;
163 private int _maxFormKeys = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormKeys",-1).intValue();
164 private int _maxFormContentSize = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormContentSize",-1).intValue();
165 private boolean _compactPath = false;
166
167 private final List<EventListener> _eventListeners=new CopyOnWriteArrayList<>();
168 private final List<EventListener> _programmaticListeners=new CopyOnWriteArrayList<>();
169 private final List<ServletContextListener> _contextListeners=new CopyOnWriteArrayList<>();
170 private final List<ServletContextAttributeListener> _contextAttributeListeners=new CopyOnWriteArrayList<>();
171 private final List<ServletRequestListener> _requestListeners=new CopyOnWriteArrayList<>();
172 private final List<ServletRequestAttributeListener> _requestAttributeListeners=new CopyOnWriteArrayList<>();
173 private final List<EventListener> _durableListeners = new CopyOnWriteArrayList<>();
174 private Map<String, Object> _managedAttributes;
175 private String[] _protectedTargets;
176 private final CopyOnWriteArrayList<AliasCheck> _aliasChecks = new CopyOnWriteArrayList<ContextHandler.AliasCheck>();
177
178 public enum Availability { UNAVAILABLE,STARTING,AVAILABLE,SHUTDOWN,};
179 private volatile Availability _availability;
180
181
182
183
184
185 public ContextHandler()
186 {
187 super();
188 _scontext = new Context();
189 _attributes = new AttributesMap();
190 _initParams = new HashMap<String, String>();
191 addAliasCheck(new ApproveNonExistentDirectoryAliases());
192 }
193
194
195
196
197
198 protected ContextHandler(Context context)
199 {
200 super();
201 _scontext = context;
202 _attributes = new AttributesMap();
203 _initParams = new HashMap<String, String>();
204 addAliasCheck(new ApproveNonExistentDirectoryAliases());
205 }
206
207
208
209
210
211 public ContextHandler(String contextPath)
212 {
213 this();
214 setContextPath(contextPath);
215 }
216
217
218
219
220
221 public ContextHandler(HandlerContainer parent, String contextPath)
222 {
223 this();
224 setContextPath(contextPath);
225 if (parent instanceof HandlerWrapper)
226 ((HandlerWrapper)parent).setHandler(this);
227 else if (parent instanceof HandlerCollection)
228 ((HandlerCollection)parent).addHandler(this);
229 }
230
231
232 @Override
233 public void dump(Appendable out, String indent) throws IOException
234 {
235 dumpBeans(out,indent,
236 Collections.singletonList(new ClassLoaderDump(getClassLoader())),
237 _initParams.entrySet(),
238 _attributes.getAttributeEntrySet(),
239 _scontext.getAttributeEntrySet());
240 }
241
242
243 public Context getServletContext()
244 {
245 return _scontext;
246 }
247
248
249
250
251
252 @ManagedAttribute("Checks if the /context is not redirected to /context/")
253 public boolean getAllowNullPathInfo()
254 {
255 return _allowNullPathInfo;
256 }
257
258
259
260
261
262
263 public void setAllowNullPathInfo(boolean allowNullPathInfo)
264 {
265 _allowNullPathInfo = allowNullPathInfo;
266 }
267
268
269 @Override
270 public void setServer(Server server)
271 {
272 super.setServer(server);
273 if (_errorHandler != null)
274 _errorHandler.setServer(server);
275 }
276
277
278
279
280
281
282
283
284
285
286
287
288 public void setVirtualHosts(String[] vhosts)
289 {
290 if (vhosts == null)
291 {
292 _vhosts = vhosts;
293 }
294 else
295 {
296 _vhosts = new String[vhosts.length];
297 for (int i = 0; i < vhosts.length; i++)
298 _vhosts[i] = normalizeHostname(vhosts[i]);
299 }
300 }
301
302
303
304
305
306
307
308
309
310 public void addVirtualHosts(String[] virtualHosts)
311 {
312 if (virtualHosts == null)
313 {
314 return;
315 }
316 else
317 {
318 List<String> currentVirtualHosts = null;
319 if (_vhosts != null)
320 {
321 currentVirtualHosts = new ArrayList<String>(Arrays.asList(_vhosts));
322 }
323 else
324 {
325 currentVirtualHosts = new ArrayList<String>();
326 }
327
328 for (int i = 0; i < virtualHosts.length; i++)
329 {
330 String normVhost = normalizeHostname(virtualHosts[i]);
331 if (!currentVirtualHosts.contains(normVhost))
332 {
333 currentVirtualHosts.add(normVhost);
334 }
335 }
336 _vhosts = currentVirtualHosts.toArray(new String[0]);
337 }
338 }
339
340
341
342
343
344
345
346
347
348 public void removeVirtualHosts(String[] virtualHosts)
349 {
350 if (virtualHosts == null)
351 {
352 return;
353 }
354 else if ( _vhosts == null || _vhosts.length == 0)
355 {
356 return;
357 }
358 else
359 {
360 List<String> existingVirtualHosts = new ArrayList<String>(Arrays.asList(_vhosts));
361
362 for (int i = 0; i < virtualHosts.length; i++)
363 {
364 String toRemoveVirtualHost = normalizeHostname(virtualHosts[i]);
365 if (existingVirtualHosts.contains(toRemoveVirtualHost))
366 {
367 existingVirtualHosts.remove(toRemoveVirtualHost);
368 }
369 }
370
371 if (existingVirtualHosts.isEmpty())
372 {
373 _vhosts = null;
374 }
375 else
376 {
377 _vhosts = existingVirtualHosts.toArray(new String[0]);
378 }
379 }
380 }
381
382
383
384
385
386
387
388
389
390
391 @ManagedAttribute(value="Virtual hosts accepted by the context", readonly=true)
392 public String[] getVirtualHosts()
393 {
394 return _vhosts;
395 }
396
397
398
399
400
401 @Override
402 public Object getAttribute(String name)
403 {
404 return _attributes.getAttribute(name);
405 }
406
407
408
409
410
411 @Override
412 public Enumeration<String> getAttributeNames()
413 {
414 return AttributesMap.getAttributeNamesCopy(_attributes);
415 }
416
417
418
419
420
421 public Attributes getAttributes()
422 {
423 return _attributes;
424 }
425
426
427
428
429
430 public ClassLoader getClassLoader()
431 {
432 return _classLoader;
433 }
434
435
436
437
438
439
440
441 @ManagedAttribute("The file classpath")
442 public String getClassPath()
443 {
444 if (_classLoader == null || !(_classLoader instanceof URLClassLoader))
445 return null;
446 URLClassLoader loader = (URLClassLoader)_classLoader;
447 URL[] urls = loader.getURLs();
448 StringBuilder classpath = new StringBuilder();
449 for (int i = 0; i < urls.length; i++)
450 {
451 try
452 {
453 Resource resource = newResource(urls[i]);
454 File file = resource.getFile();
455 if (file != null && file.exists())
456 {
457 if (classpath.length() > 0)
458 classpath.append(File.pathSeparatorChar);
459 classpath.append(file.getAbsolutePath());
460 }
461 }
462 catch (IOException e)
463 {
464 LOG.debug(e);
465 }
466 }
467 if (classpath.length() == 0)
468 return null;
469 return classpath.toString();
470 }
471
472
473
474
475
476 @ManagedAttribute("True if URLs are compacted to replace the multiple '/'s with a single '/'")
477 public String getContextPath()
478 {
479 return _contextPath;
480 }
481
482
483
484
485
486 public String getInitParameter(String name)
487 {
488 return _initParams.get(name);
489 }
490
491
492
493
494 public String setInitParameter(String name, String value)
495 {
496 return _initParams.put(name,value);
497 }
498
499
500
501
502
503 @SuppressWarnings("rawtypes")
504 public Enumeration getInitParameterNames()
505 {
506 return Collections.enumeration(_initParams.keySet());
507 }
508
509
510
511
512
513 @ManagedAttribute("Initial Parameter map for the context")
514 public Map<String, String> getInitParams()
515 {
516 return _initParams;
517 }
518
519
520
521
522
523 @ManagedAttribute(value="Display name of the Context", readonly=true)
524 public String getDisplayName()
525 {
526 return _displayName;
527 }
528
529
530 public EventListener[] getEventListeners()
531 {
532 return _eventListeners.toArray(new EventListener[_eventListeners.size()]);
533 }
534
535
536
537
538
539
540
541
542
543
544
545
546 public void setEventListeners(EventListener[] eventListeners)
547 {
548 _contextListeners.clear();
549 _contextAttributeListeners.clear();
550 _requestListeners.clear();
551 _requestAttributeListeners.clear();
552 _eventListeners.clear();
553
554 if (eventListeners!=null)
555 for (EventListener listener : eventListeners)
556 addEventListener(listener);
557 }
558
559
560
561
562
563
564
565
566
567
568 public void addEventListener(EventListener listener)
569 {
570 _eventListeners.add(listener);
571
572 if (!(isStarted() || isStarting()))
573 _durableListeners.add(listener);
574
575 if (listener instanceof ServletContextListener)
576 _contextListeners.add((ServletContextListener)listener);
577
578 if (listener instanceof ServletContextAttributeListener)
579 _contextAttributeListeners.add((ServletContextAttributeListener)listener);
580
581 if (listener instanceof ServletRequestListener)
582 _requestListeners.add((ServletRequestListener)listener);
583
584 if (listener instanceof ServletRequestAttributeListener)
585 _requestAttributeListeners.add((ServletRequestAttributeListener)listener);
586 }
587
588
589
590
591
592
593
594
595
596
597 public void removeEventListener(EventListener listener)
598 {
599 _eventListeners.remove(listener);
600
601 if (listener instanceof ServletContextListener)
602 _contextListeners.remove(listener);
603
604 if (listener instanceof ServletContextAttributeListener)
605 _contextAttributeListeners.remove(listener);
606
607 if (listener instanceof ServletRequestListener)
608 _requestListeners.remove(listener);
609
610 if (listener instanceof ServletRequestAttributeListener)
611 _requestAttributeListeners.remove(listener);
612 }
613
614
615
616
617
618
619
620 protected void addProgrammaticListener (EventListener listener)
621 {
622 _programmaticListeners.add(listener);
623 }
624
625
626 protected boolean isProgrammaticListener(EventListener listener)
627 {
628 return _programmaticListeners.contains(listener);
629 }
630
631
632
633
634
635
636
637 @ManagedAttribute("true for graceful shutdown, which allows existing requests to complete")
638 public boolean isShutdown()
639 {
640 switch(_availability)
641 {
642 case SHUTDOWN:
643 return true;
644 default:
645 return false;
646 }
647 }
648
649
650
651
652
653
654
655 @Override
656 public Future<Void> shutdown()
657 {
658 _availability = isRunning() ? Availability.SHUTDOWN : Availability.UNAVAILABLE;
659 return new FutureCallback(true);
660 }
661
662
663
664
665
666 public boolean isAvailable()
667 {
668 return _availability==Availability.AVAILABLE;
669 }
670
671
672
673
674
675 public void setAvailable(boolean available)
676 {
677 synchronized (this)
678 {
679 if (available && isRunning())
680 _availability = Availability.AVAILABLE;
681 else if (!available || !isRunning())
682 _availability = Availability.UNAVAILABLE;
683 }
684 }
685
686
687 public Logger getLogger()
688 {
689 return _logger;
690 }
691
692
693 public void setLogger(Logger logger)
694 {
695 _logger = logger;
696 }
697
698
699
700
701
702 @Override
703 protected void doStart() throws Exception
704 {
705 _availability = Availability.STARTING;
706
707 if (_contextPath == null)
708 throw new IllegalStateException("Null contextPath");
709
710 _logger = Log.getLogger(getDisplayName() == null?getContextPath():getDisplayName());
711 ClassLoader old_classloader = null;
712 Thread current_thread = null;
713 Context old_context = null;
714
715 try
716 {
717
718 if (_classLoader != null)
719 {
720 current_thread = Thread.currentThread();
721 old_classloader = current_thread.getContextClassLoader();
722 current_thread.setContextClassLoader(_classLoader);
723 }
724
725 if (_mimeTypes == null)
726 _mimeTypes = new MimeTypes();
727
728 old_context = __context.get();
729 __context.set(_scontext);
730
731
732 startContext();
733
734 _availability = Availability.AVAILABLE;
735 LOG.info("Started {}", this);
736 }
737 finally
738 {
739 __context.set(old_context);
740
741
742 if (_classLoader != null && current_thread!=null)
743 current_thread.setContextClassLoader(old_classloader);
744 }
745 }
746
747
748
749
750
751
752
753
754 protected void startContext() throws Exception
755 {
756 String managedAttributes = _initParams.get(MANAGED_ATTRIBUTES);
757 if (managedAttributes != null)
758 {
759 _managedAttributes = new HashMap<String, Object>();
760 String[] attributes = managedAttributes.split(",");
761 for (String attribute : attributes)
762 _managedAttributes.put(attribute,null);
763
764 Enumeration<String> e = _scontext.getAttributeNames();
765 while (e.hasMoreElements())
766 {
767 String name = e.nextElement();
768 Object value = _scontext.getAttribute(name);
769 checkManagedAttribute(name,value);
770 }
771 }
772
773 super.doStart();
774
775
776 if (!_contextListeners.isEmpty())
777 {
778 ServletContextEvent event = new ServletContextEvent(_scontext);
779 for (ServletContextListener listener:_contextListeners)
780 callContextInitialized(listener, event);
781 }
782 }
783
784
785 protected void callContextInitialized (ServletContextListener l, ServletContextEvent e)
786 {
787 LOG.debug("contextInitialized: {}->{}",e,l);
788 l.contextInitialized(e);
789 }
790
791
792 protected void callContextDestroyed (ServletContextListener l, ServletContextEvent e)
793 {
794 LOG.debug("contextDestroyed: {}->{}",e,l);
795 l.contextDestroyed(e);
796 }
797
798
799
800
801
802 @Override
803 protected void doStop() throws Exception
804 {
805 _availability = Availability.UNAVAILABLE;
806
807 ClassLoader old_classloader = null;
808 Thread current_thread = null;
809
810 Context old_context = __context.get();
811 __context.set(_scontext);
812 try
813 {
814
815 if (_classLoader != null)
816 {
817 current_thread = Thread.currentThread();
818 old_classloader = current_thread.getContextClassLoader();
819 current_thread.setContextClassLoader(_classLoader);
820 }
821
822 super.doStop();
823
824
825 if (!_contextListeners.isEmpty())
826 {
827 ServletContextEvent event = new ServletContextEvent(_scontext);
828 for (int i = _contextListeners.size(); i-->0;)
829 callContextDestroyed(_contextListeners.get(i),event);
830 }
831
832
833 setEventListeners(_durableListeners.toArray(new EventListener[_durableListeners.size()]));
834 _durableListeners.clear();
835
836 if (_errorHandler != null)
837 _errorHandler.stop();
838
839 Enumeration<String> e = _scontext.getAttributeNames();
840 while (e.hasMoreElements())
841 {
842 String name = e.nextElement();
843 checkManagedAttribute(name,null);
844 }
845
846 for (EventListener l : _programmaticListeners)
847 removeEventListener(l);
848 _programmaticListeners.clear();
849 }
850 finally
851 {
852 LOG.info("Stopped {}", this);
853 __context.set(old_context);
854
855 if (_classLoader != null && current_thread!=null)
856 current_thread.setContextClassLoader(old_classloader);
857 }
858
859 _scontext.clearAttributes();
860 }
861
862
863
864
865
866 public boolean checkContext(final String target, final Request baseRequest, final HttpServletResponse response) throws IOException
867 {
868 DispatcherType dispatch = baseRequest.getDispatcherType();
869
870 switch (_availability)
871 {
872 case SHUTDOWN:
873 case UNAVAILABLE:
874 baseRequest.setHandled(true);
875 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
876 return false;
877 default:
878 if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled()))
879 return false;
880 }
881
882
883 if (_vhosts != null && _vhosts.length > 0)
884 {
885 String vhost = normalizeHostname(baseRequest.getServerName());
886
887 boolean match = false;
888 boolean connectorName = false;
889 boolean connectorMatch = false;
890
891 for (String contextVhost:_vhosts)
892 {
893 if (contextVhost == null || contextVhost.length()==0)
894 continue;
895 char c=contextVhost.charAt(0);
896 switch (c)
897 {
898 case '*':
899 if (contextVhost.startsWith("*."))
900
901 match = match || contextVhost.regionMatches(true,2,vhost,vhost.indexOf(".") + 1,contextVhost.length() - 2);
902 break;
903 case '@':
904 connectorName=true;
905 String name=baseRequest.getHttpChannel().getConnector().getName();
906 boolean m=name!=null && contextVhost.length()==name.length()+1 && contextVhost.endsWith(name);
907 match = match || m;
908 connectorMatch = connectorMatch || m;
909 break;
910 default:
911 match = match || contextVhost.equalsIgnoreCase(vhost);
912 }
913
914 }
915 if (!match || connectorName && !connectorMatch)
916 return false;
917 }
918
919
920 if (_contextPath.length() > 1)
921 {
922
923 if (!target.startsWith(_contextPath))
924 return false;
925 if (target.length() > _contextPath.length() && target.charAt(_contextPath.length()) != '/')
926 return false;
927
928
929 if (!_allowNullPathInfo && _contextPath.length() == target.length())
930 {
931
932 baseRequest.setHandled(true);
933 if (baseRequest.getQueryString() != null)
934 response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH) + "?" + baseRequest.getQueryString());
935 else
936 response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH));
937 return false;
938 }
939 }
940
941 return true;
942 }
943
944
945
946
947
948
949 @Override
950 public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
951 {
952 if (LOG.isDebugEnabled())
953 LOG.debug("scope {}|{}|{} @ {}",baseRequest.getContextPath(),baseRequest.getServletPath(),baseRequest.getPathInfo(),this);
954
955 Context old_context = null;
956 String old_context_path = null;
957 String old_servlet_path = null;
958 String old_path_info = null;
959 ClassLoader old_classloader = null;
960 Thread current_thread = null;
961 String pathInfo = target;
962
963 DispatcherType dispatch = baseRequest.getDispatcherType();
964
965 old_context = baseRequest.getContext();
966
967
968 if (old_context != _scontext)
969 {
970
971 if (DispatcherType.REQUEST.equals(dispatch) || DispatcherType.ASYNC.equals(dispatch) || (DispatcherType.ERROR.equals(dispatch) && baseRequest.getHttpChannelState().isExpired()))
972 {
973 if (_compactPath)
974 target = URIUtil.compactPath(target);
975 if (!checkContext(target,baseRequest,response))
976 return;
977
978 if (target.length() > _contextPath.length())
979 {
980 if (_contextPath.length() > 1)
981 target = target.substring(_contextPath.length());
982 pathInfo = target;
983 }
984 else if (_contextPath.length() == 1)
985 {
986 target = URIUtil.SLASH;
987 pathInfo = URIUtil.SLASH;
988 }
989 else
990 {
991 target = URIUtil.SLASH;
992 pathInfo = null;
993 }
994 }
995
996
997 if (_classLoader != null)
998 {
999 current_thread = Thread.currentThread();
1000 old_classloader = current_thread.getContextClassLoader();
1001 current_thread.setContextClassLoader(_classLoader);
1002 }
1003 }
1004
1005 try
1006 {
1007 old_context_path = baseRequest.getContextPath();
1008 old_servlet_path = baseRequest.getServletPath();
1009 old_path_info = baseRequest.getPathInfo();
1010
1011
1012 baseRequest.setContext(_scontext);
1013 __context.set(_scontext);
1014 if (!DispatcherType.INCLUDE.equals(dispatch) && target.startsWith("/"))
1015 {
1016 if (_contextPath.length() == 1)
1017 baseRequest.setContextPath("");
1018 else
1019 baseRequest.setContextPath(_contextPath);
1020 baseRequest.setServletPath(null);
1021 baseRequest.setPathInfo(pathInfo);
1022 }
1023
1024 if (LOG.isDebugEnabled())
1025 LOG.debug("context={}|{}|{} @ {}",baseRequest.getContextPath(),baseRequest.getServletPath(), baseRequest.getPathInfo(),this);
1026
1027
1028 if (never())
1029 nextScope(target,baseRequest,request,response);
1030 else if (_nextScope != null)
1031 _nextScope.doScope(target,baseRequest,request,response);
1032 else if (_outerScope != null)
1033 _outerScope.doHandle(target,baseRequest,request,response);
1034 else
1035 doHandle(target,baseRequest,request,response);
1036
1037 }
1038 finally
1039 {
1040 if (old_context != _scontext)
1041 {
1042
1043 if (_classLoader != null && current_thread!=null)
1044 {
1045 current_thread.setContextClassLoader(old_classloader);
1046 }
1047
1048
1049 baseRequest.setContext(old_context);
1050 __context.set(old_context);
1051 baseRequest.setContextPath(old_context_path);
1052 baseRequest.setServletPath(old_servlet_path);
1053 baseRequest.setPathInfo(old_path_info);
1054 }
1055 }
1056 }
1057
1058
1059
1060
1061
1062
1063 @Override
1064 public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
1065 {
1066 final DispatcherType dispatch = baseRequest.getDispatcherType();
1067 final boolean new_context = baseRequest.takeNewContext();
1068 try
1069 {
1070 if (new_context)
1071 {
1072
1073 if (!_requestAttributeListeners.isEmpty())
1074 for (ServletRequestAttributeListener l :_requestAttributeListeners)
1075 baseRequest.addEventListener(l);
1076
1077 if (!_requestListeners.isEmpty())
1078 {
1079 final ServletRequestEvent sre = new ServletRequestEvent(_scontext,request);
1080 for (ServletRequestListener l : _requestListeners)
1081 l.requestInitialized(sre);
1082 }
1083 }
1084
1085 if (DispatcherType.REQUEST.equals(dispatch) && isProtectedTarget(target))
1086 {
1087 response.sendError(HttpServletResponse.SC_NOT_FOUND);
1088 baseRequest.setHandled(true);
1089 return;
1090 }
1091
1092
1093
1094 if (never())
1095 nextHandle(target,baseRequest,request,response);
1096 else if (_nextScope != null && _nextScope == _handler)
1097 _nextScope.doHandle(target,baseRequest,request,response);
1098 else if (_handler != null)
1099 _handler.handle(target,baseRequest,request,response);
1100
1101 }
1102 finally
1103 {
1104
1105 if (new_context)
1106 {
1107 if (!_requestListeners.isEmpty())
1108 {
1109 final ServletRequestEvent sre = new ServletRequestEvent(_scontext,request);
1110 for (int i=_requestListeners.size();i-->0;)
1111 _requestListeners.get(i).requestDestroyed(sre);
1112 }
1113
1114 if (!_requestAttributeListeners.isEmpty())
1115 {
1116 ListIterator<ServletRequestAttributeListener> iter = _requestAttributeListeners.listIterator(_requestAttributeListeners.size());
1117 for (int i=_requestAttributeListeners.size();i-->0;)
1118 baseRequest.removeEventListener(_requestAttributeListeners.get(i));
1119 }
1120 }
1121 }
1122 }
1123
1124
1125
1126
1127
1128 public void handle(Runnable runnable)
1129 {
1130 ClassLoader old_classloader = null;
1131 Thread current_thread = null;
1132 Context old_context = null;
1133 try
1134 {
1135 old_context = __context.get();
1136 __context.set(_scontext);
1137
1138
1139 if (_classLoader != null)
1140 {
1141 current_thread = Thread.currentThread();
1142 old_classloader = current_thread.getContextClassLoader();
1143 current_thread.setContextClassLoader(_classLoader);
1144 }
1145
1146 runnable.run();
1147 }
1148 finally
1149 {
1150 __context.set(old_context);
1151 if (old_classloader != null && current_thread!=null)
1152 {
1153 current_thread.setContextClassLoader(old_classloader);
1154 }
1155 }
1156 }
1157
1158
1159
1160
1161
1162
1163
1164 public boolean isProtectedTarget(String target)
1165 {
1166 if (target == null || _protectedTargets == null)
1167 return false;
1168
1169 while (target.startsWith("//"))
1170 target=URIUtil.compactPath(target);
1171
1172 for (int i=0; i<_protectedTargets.length; i++)
1173 {
1174 String t=_protectedTargets[i];
1175 if (StringUtil.startsWithIgnoreCase(target,t))
1176 {
1177 if (target.length()==t.length())
1178 return true;
1179
1180
1181
1182 char c=target.charAt(t.length());
1183 if (c=='/'||c=='?'||c=='#'||c==';')
1184 return true;
1185 }
1186 }
1187 return false;
1188 }
1189
1190
1191
1192
1193
1194
1195
1196 public void setProtectedTargets (String[] targets)
1197 {
1198 if (targets == null)
1199 {
1200 _protectedTargets = null;
1201 return;
1202 }
1203
1204 _protectedTargets = new String[targets.length];
1205 System.arraycopy(targets, 0, _protectedTargets, 0, targets.length);
1206 }
1207
1208
1209 public String[] getProtectedTargets ()
1210 {
1211 if (_protectedTargets == null)
1212 return null;
1213
1214 String[] tmp = new String[_protectedTargets.length];
1215 System.arraycopy(_protectedTargets, 0, tmp, 0, _protectedTargets.length);
1216 return tmp;
1217 }
1218
1219
1220
1221
1222
1223
1224 @Override
1225 public void removeAttribute(String name)
1226 {
1227 checkManagedAttribute(name,null);
1228 _attributes.removeAttribute(name);
1229 }
1230
1231
1232
1233
1234
1235
1236
1237
1238 @Override
1239 public void setAttribute( String name, Object value)
1240 {
1241 checkManagedAttribute(name,value);
1242 _attributes.setAttribute(name,value);
1243 }
1244
1245
1246
1247
1248
1249
1250 public void setAttributes(Attributes attributes)
1251 {
1252 _attributes.clearAttributes();
1253 _attributes.addAll(attributes);
1254 Enumeration<String> e = _attributes.getAttributeNames();
1255 while (e.hasMoreElements())
1256 {
1257 String name = e.nextElement();
1258 checkManagedAttribute(name,attributes.getAttribute(name));
1259 }
1260 }
1261
1262
1263 @Override
1264 public void clearAttributes()
1265 {
1266 Enumeration<String> e = _attributes.getAttributeNames();
1267 while (e.hasMoreElements())
1268 {
1269 String name = e.nextElement();
1270 checkManagedAttribute(name,null);
1271 }
1272 _attributes.clearAttributes();
1273 }
1274
1275
1276 public void checkManagedAttribute(String name, Object value)
1277 {
1278 if (_managedAttributes != null && _managedAttributes.containsKey(name))
1279 {
1280 setManagedAttribute(name,value);
1281 }
1282 }
1283
1284
1285 public void setManagedAttribute(String name, Object value)
1286 {
1287 Object old = _managedAttributes.put(name,value);
1288 updateBean(old,value);
1289 }
1290
1291
1292
1293
1294
1295
1296 public void setClassLoader(ClassLoader classLoader)
1297 {
1298 _classLoader = classLoader;
1299 }
1300
1301
1302
1303
1304
1305
1306 public void setContextPath(String contextPath)
1307 {
1308 if (contextPath == null)
1309 throw new IllegalArgumentException("null contextPath");
1310
1311 if (contextPath.endsWith("/*"))
1312 {
1313 LOG.warn(this+" contextPath ends with /*");
1314 contextPath=contextPath.substring(0,contextPath.length()-2);
1315 }
1316 else if (contextPath.length()>1 && contextPath.endsWith("/"))
1317 {
1318 LOG.warn(this+" contextPath ends with /");
1319 contextPath=contextPath.substring(0,contextPath.length()-1);
1320 }
1321
1322 if (contextPath.length()==0)
1323 {
1324 LOG.warn("Empty contextPath");
1325 contextPath="/";
1326 }
1327
1328 _contextPath = contextPath;
1329
1330 if (getServer() != null && (getServer().isStarting() || getServer().isStarted()))
1331 {
1332 Handler[] contextCollections = getServer().getChildHandlersByClass(ContextHandlerCollection.class);
1333 for (int h = 0; contextCollections != null && h < contextCollections.length; h++)
1334 ((ContextHandlerCollection)contextCollections[h]).mapContexts();
1335 }
1336 }
1337
1338
1339
1340
1341
1342
1343 public void setDisplayName(String servletContextName)
1344 {
1345 _displayName = servletContextName;
1346 }
1347
1348
1349
1350
1351
1352 public Resource getBaseResource()
1353 {
1354 if (_baseResource == null)
1355 return null;
1356 return _baseResource;
1357 }
1358
1359
1360
1361
1362
1363 @ManagedAttribute("document root for context")
1364 public String getResourceBase()
1365 {
1366 if (_baseResource == null)
1367 return null;
1368 return _baseResource.toString();
1369 }
1370
1371
1372
1373
1374
1375
1376 public void setBaseResource(Resource base)
1377 {
1378 _baseResource = base;
1379 }
1380
1381
1382
1383
1384
1385
1386 public void setResourceBase(String resourceBase)
1387 {
1388 try
1389 {
1390 setBaseResource(newResource(resourceBase));
1391 }
1392 catch (Exception e)
1393 {
1394 LOG.warn(e.toString());
1395 LOG.debug(e);
1396 throw new IllegalArgumentException(resourceBase);
1397 }
1398 }
1399
1400
1401
1402
1403
1404 public MimeTypes getMimeTypes()
1405 {
1406 if (_mimeTypes == null)
1407 _mimeTypes = new MimeTypes();
1408 return _mimeTypes;
1409 }
1410
1411
1412
1413
1414
1415
1416 public void setMimeTypes(MimeTypes mimeTypes)
1417 {
1418 _mimeTypes = mimeTypes;
1419 }
1420
1421
1422
1423
1424 public void setWelcomeFiles(String[] files)
1425 {
1426 _welcomeFiles = files;
1427 }
1428
1429
1430
1431
1432
1433
1434
1435 @ManagedAttribute(value="Partial URIs of directory welcome files", readonly=true)
1436 public String[] getWelcomeFiles()
1437 {
1438 return _welcomeFiles;
1439 }
1440
1441
1442
1443
1444
1445 @ManagedAttribute("The error handler to use for the context")
1446 public ErrorHandler getErrorHandler()
1447 {
1448 return _errorHandler;
1449 }
1450
1451
1452
1453
1454
1455
1456 public void setErrorHandler(ErrorHandler errorHandler)
1457 {
1458 if (errorHandler != null)
1459 errorHandler.setServer(getServer());
1460 updateBean(_errorHandler,errorHandler);
1461 _errorHandler = errorHandler;
1462 }
1463
1464
1465 @ManagedAttribute("The maximum content size")
1466 public int getMaxFormContentSize()
1467 {
1468 return _maxFormContentSize;
1469 }
1470
1471
1472
1473
1474
1475
1476 public void setMaxFormContentSize(int maxSize)
1477 {
1478 _maxFormContentSize = maxSize;
1479 }
1480
1481
1482 public int getMaxFormKeys()
1483 {
1484 return _maxFormKeys;
1485 }
1486
1487
1488
1489
1490
1491
1492 public void setMaxFormKeys(int max)
1493 {
1494 _maxFormKeys = max;
1495 }
1496
1497
1498
1499
1500
1501 public boolean isCompactPath()
1502 {
1503 return _compactPath;
1504 }
1505
1506
1507
1508
1509
1510
1511 public void setCompactPath(boolean compactPath)
1512 {
1513 _compactPath = compactPath;
1514 }
1515
1516
1517 @Override
1518 public String toString()
1519 {
1520 String[] vhosts = getVirtualHosts();
1521
1522 StringBuilder b = new StringBuilder();
1523
1524 Package pkg = getClass().getPackage();
1525 if (pkg != null)
1526 {
1527 String p = pkg.getName();
1528 if (p != null && p.length() > 0)
1529 {
1530 String[] ss = p.split("\\.");
1531 for (String s : ss)
1532 b.append(s.charAt(0)).append('.');
1533 }
1534 }
1535 b.append(getClass().getSimpleName()).append('@').append(Integer.toString(hashCode(),16));
1536 b.append('{').append(getContextPath()).append(',').append(getBaseResource()).append(',').append(_availability);
1537
1538 if (vhosts != null && vhosts.length > 0)
1539 b.append(',').append(vhosts[0]);
1540 b.append('}');
1541
1542 return b.toString();
1543 }
1544
1545
1546 public synchronized Class<?> loadClass(String className) throws ClassNotFoundException
1547 {
1548 if (className == null)
1549 return null;
1550
1551 if (_classLoader == null)
1552 return Loader.loadClass(this.getClass(),className);
1553
1554 return _classLoader.loadClass(className);
1555 }
1556
1557
1558 public void addLocaleEncoding(String locale, String encoding)
1559 {
1560 if (_localeEncodingMap == null)
1561 _localeEncodingMap = new HashMap<String, String>();
1562 _localeEncodingMap.put(locale,encoding);
1563 }
1564
1565
1566 public String getLocaleEncoding(String locale)
1567 {
1568 if (_localeEncodingMap == null)
1569 return null;
1570 String encoding = _localeEncodingMap.get(locale);
1571 return encoding;
1572 }
1573
1574
1575
1576
1577
1578
1579
1580
1581
1582
1583 public String getLocaleEncoding(Locale locale)
1584 {
1585 if (_localeEncodingMap == null)
1586 return null;
1587 String encoding = _localeEncodingMap.get(locale.toString());
1588 if (encoding == null)
1589 encoding = _localeEncodingMap.get(locale.getLanguage());
1590 return encoding;
1591 }
1592
1593
1594
1595
1596 public Resource getResource(String path) throws MalformedURLException
1597 {
1598 if (path == null || !path.startsWith(URIUtil.SLASH))
1599 throw new MalformedURLException(path);
1600
1601 if (_baseResource == null)
1602 return null;
1603
1604 try
1605 {
1606 path = URIUtil.canonicalPath(path);
1607 Resource resource = _baseResource.addPath(path);
1608
1609 if (checkAlias(path,resource))
1610 return resource;
1611 return null;
1612 }
1613 catch (Exception e)
1614 {
1615 LOG.ignore(e);
1616 }
1617
1618 return null;
1619 }
1620
1621
1622 public boolean checkAlias(String path, Resource resource)
1623 {
1624
1625 if (resource.getAlias() != null)
1626 {
1627 if (LOG.isDebugEnabled())
1628 LOG.debug("Aliased resource: " + resource + "~=" + resource.getAlias());
1629
1630
1631 for (Iterator<AliasCheck> i=_aliasChecks.iterator();i.hasNext();)
1632 {
1633 AliasCheck check = i.next();
1634 if (check.check(path,resource))
1635 {
1636 if (LOG.isDebugEnabled())
1637 LOG.debug("Aliased resource: " + resource + " approved by " + check);
1638 return true;
1639 }
1640 }
1641 return false;
1642 }
1643 return true;
1644 }
1645
1646
1647
1648
1649
1650 public Resource newResource(URL url) throws IOException
1651 {
1652 return Resource.newResource(url);
1653 }
1654
1655
1656
1657
1658
1659
1660
1661
1662
1663
1664
1665 public Resource newResource(String urlOrPath) throws IOException
1666 {
1667 return Resource.newResource(urlOrPath);
1668 }
1669
1670
1671
1672
1673 public Set<String> getResourcePaths(String path)
1674 {
1675 try
1676 {
1677 path = URIUtil.canonicalPath(path);
1678 Resource resource = getResource(path);
1679
1680 if (resource != null && resource.exists())
1681 {
1682 if (!path.endsWith(URIUtil.SLASH))
1683 path = path + URIUtil.SLASH;
1684
1685 String[] l = resource.list();
1686 if (l != null)
1687 {
1688 HashSet<String> set = new HashSet<String>();
1689 for (int i = 0; i < l.length; i++)
1690 set.add(path + l[i]);
1691 return set;
1692 }
1693 }
1694 }
1695 catch (Exception e)
1696 {
1697 LOG.ignore(e);
1698 }
1699 return Collections.emptySet();
1700 }
1701
1702
1703 private String normalizeHostname(String host)
1704 {
1705 if (host == null)
1706 return null;
1707
1708 if (host.endsWith("."))
1709 return host.substring(0,host.length() - 1);
1710
1711 return host;
1712 }
1713
1714
1715
1716
1717
1718
1719 public void addAliasCheck(AliasCheck check)
1720 {
1721 _aliasChecks.add(check);
1722 }
1723
1724
1725
1726
1727
1728 public List<AliasCheck> getAliasChecks()
1729 {
1730 return _aliasChecks;
1731 }
1732
1733
1734
1735
1736
1737 public void setAliasChecks(List<AliasCheck> checks)
1738 {
1739 _aliasChecks.clear();
1740 _aliasChecks.addAll(checks);
1741 }
1742
1743
1744
1745
1746
1747
1748
1749
1750
1751
1752 public class Context extends NoContext
1753 {
1754 protected boolean _enabled = true;
1755
1756
1757 protected Context()
1758 {
1759 }
1760
1761
1762 public ContextHandler getContextHandler()
1763 {
1764 return ContextHandler.this;
1765 }
1766
1767
1768
1769
1770
1771 @Override
1772 public ServletContext getContext(String uripath)
1773 {
1774 List<ContextHandler> contexts = new ArrayList<ContextHandler>();
1775 Handler[] handlers = getServer().getChildHandlersByClass(ContextHandler.class);
1776 String matched_path = null;
1777
1778 for (Handler handler : handlers)
1779 {
1780 if (handler == null)
1781 continue;
1782 ContextHandler ch = (ContextHandler)handler;
1783 String context_path = ch.getContextPath();
1784
1785 if (uripath.equals(context_path) || (uripath.startsWith(context_path) && uripath.charAt(context_path.length()) == '/')
1786 || "/".equals(context_path))
1787 {
1788
1789 if (getVirtualHosts() != null && getVirtualHosts().length > 0)
1790 {
1791 if (ch.getVirtualHosts() != null && ch.getVirtualHosts().length > 0)
1792 {
1793 for (String h1 : getVirtualHosts())
1794 for (String h2 : ch.getVirtualHosts())
1795 if (h1.equals(h2))
1796 {
1797 if (matched_path == null || context_path.length() > matched_path.length())
1798 {
1799 contexts.clear();
1800 matched_path = context_path;
1801 }
1802
1803 if (matched_path.equals(context_path))
1804 contexts.add(ch);
1805 }
1806 }
1807 }
1808 else
1809 {
1810 if (matched_path == null || context_path.length() > matched_path.length())
1811 {
1812 contexts.clear();
1813 matched_path = context_path;
1814 }
1815
1816 if (matched_path.equals(context_path))
1817 contexts.add(ch);
1818 }
1819 }
1820 }
1821
1822 if (contexts.size() > 0)
1823 return contexts.get(0)._scontext;
1824
1825
1826 matched_path = null;
1827 for (Handler handler : handlers)
1828 {
1829 if (handler == null)
1830 continue;
1831 ContextHandler ch = (ContextHandler)handler;
1832 String context_path = ch.getContextPath();
1833
1834 if (uripath.equals(context_path) || (uripath.startsWith(context_path) && uripath.charAt(context_path.length()) == '/')
1835 || "/".equals(context_path))
1836 {
1837 if (matched_path == null || context_path.length() > matched_path.length())
1838 {
1839 contexts.clear();
1840 matched_path = context_path;
1841 }
1842
1843 if (matched_path.equals(context_path))
1844 contexts.add(ch);
1845 }
1846 }
1847
1848 if (contexts.size() > 0)
1849 return contexts.get(0)._scontext;
1850 return null;
1851 }
1852
1853
1854
1855
1856
1857 @Override
1858 public String getMimeType(String file)
1859 {
1860 if (_mimeTypes == null)
1861 return null;
1862 return _mimeTypes.getMimeByExtension(file);
1863 }
1864
1865
1866
1867
1868
1869 @Override
1870 public RequestDispatcher getRequestDispatcher(String uriInContext)
1871 {
1872 if (uriInContext == null)
1873 return null;
1874
1875 if (!uriInContext.startsWith("/"))
1876 return null;
1877
1878 try
1879 {
1880 String query = null;
1881 int q = 0;
1882 if ((q = uriInContext.indexOf('?')) > 0)
1883 {
1884 query = uriInContext.substring(q + 1);
1885 uriInContext = uriInContext.substring(0,q);
1886 }
1887
1888 String pathInContext = URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
1889 if (pathInContext!=null)
1890 {
1891 String uri = URIUtil.addPaths(getContextPath(),uriInContext);
1892 ContextHandler context = ContextHandler.this;
1893 return new Dispatcher(context,uri,pathInContext,query);
1894 }
1895 }
1896 catch (Exception e)
1897 {
1898 LOG.ignore(e);
1899 }
1900 return null;
1901 }
1902
1903
1904
1905
1906
1907 @Override
1908 public String getRealPath(String path)
1909 {
1910 if (path == null)
1911 return null;
1912 if (path.length() == 0)
1913 path = URIUtil.SLASH;
1914 else if (path.charAt(0) != '/')
1915 path = URIUtil.SLASH + path;
1916
1917 try
1918 {
1919 Resource resource = ContextHandler.this.getResource(path);
1920 if (resource != null)
1921 {
1922 File file = resource.getFile();
1923 if (file != null)
1924 return file.getCanonicalPath();
1925 }
1926 }
1927 catch (Exception e)
1928 {
1929 LOG.ignore(e);
1930 }
1931
1932 return null;
1933 }
1934
1935
1936 @Override
1937 public URL getResource(String path) throws MalformedURLException
1938 {
1939 Resource resource = ContextHandler.this.getResource(path);
1940 if (resource != null && resource.exists())
1941 return resource.getURL();
1942 return null;
1943 }
1944
1945
1946
1947
1948
1949 @Override
1950 public InputStream getResourceAsStream(String path)
1951 {
1952 try
1953 {
1954 URL url = getResource(path);
1955 if (url == null)
1956 return null;
1957 Resource r = Resource.newResource(url);
1958 return r.getInputStream();
1959 }
1960 catch (Exception e)
1961 {
1962 LOG.ignore(e);
1963 return null;
1964 }
1965 }
1966
1967
1968
1969
1970
1971 @Override
1972 public Set<String> getResourcePaths(String path)
1973 {
1974 return ContextHandler.this.getResourcePaths(path);
1975 }
1976
1977
1978
1979
1980
1981 @Override
1982 public void log(Exception exception, String msg)
1983 {
1984 _logger.warn(msg,exception);
1985 }
1986
1987
1988
1989
1990
1991 @Override
1992 public void log(String msg)
1993 {
1994 _logger.info(msg);
1995 }
1996
1997
1998
1999
2000
2001 @Override
2002 public void log(String message, Throwable throwable)
2003 {
2004 _logger.warn(message,throwable);
2005 }
2006
2007
2008
2009
2010
2011 @Override
2012 public String getInitParameter(String name)
2013 {
2014 return ContextHandler.this.getInitParameter(name);
2015 }
2016
2017
2018
2019
2020
2021 @SuppressWarnings("unchecked")
2022 @Override
2023 public Enumeration<String> getInitParameterNames()
2024 {
2025 return ContextHandler.this.getInitParameterNames();
2026 }
2027
2028
2029
2030
2031
2032 @Override
2033 public synchronized Object getAttribute(String name)
2034 {
2035 Object o = ContextHandler.this.getAttribute(name);
2036 if (o == null)
2037 o = super.getAttribute(name);
2038 return o;
2039 }
2040
2041
2042
2043
2044
2045 @Override
2046 public synchronized Enumeration<String> getAttributeNames()
2047 {
2048 HashSet<String> set = new HashSet<String>();
2049 Enumeration<String> e = super.getAttributeNames();
2050 while (e.hasMoreElements())
2051 set.add(e.nextElement());
2052 e = _attributes.getAttributeNames();
2053 while (e.hasMoreElements())
2054 set.add(e.nextElement());
2055
2056 return Collections.enumeration(set);
2057 }
2058
2059
2060
2061
2062
2063 @Override
2064 public synchronized void setAttribute(String name, Object value)
2065 {
2066 checkManagedAttribute(name,value);
2067 Object old_value = super.getAttribute(name);
2068
2069 if (value == null)
2070 super.removeAttribute(name);
2071 else
2072 super.setAttribute(name,value);
2073
2074 if (!_contextAttributeListeners.isEmpty())
2075 {
2076 ServletContextAttributeEvent event = new ServletContextAttributeEvent(_scontext,name,old_value == null?value:old_value);
2077
2078 for (ServletContextAttributeListener l : _contextAttributeListeners)
2079 {
2080 if (old_value == null)
2081 l.attributeAdded(event);
2082 else if (value == null)
2083 l.attributeRemoved(event);
2084 else
2085 l.attributeReplaced(event);
2086 }
2087 }
2088 }
2089
2090
2091
2092
2093
2094 @Override
2095 public synchronized void removeAttribute(String name)
2096 {
2097 checkManagedAttribute(name,null);
2098
2099 Object old_value = super.getAttribute(name);
2100 super.removeAttribute(name);
2101 if (old_value != null &&!_contextAttributeListeners.isEmpty())
2102 {
2103 ServletContextAttributeEvent event = new ServletContextAttributeEvent(_scontext,name,old_value);
2104
2105 for (ServletContextAttributeListener l : _contextAttributeListeners)
2106 l.attributeRemoved(event);
2107 }
2108 }
2109
2110
2111
2112
2113
2114 @Override
2115 public String getServletContextName()
2116 {
2117 String name = ContextHandler.this.getDisplayName();
2118 if (name == null)
2119 name = ContextHandler.this.getContextPath();
2120 return name;
2121 }
2122
2123
2124 @Override
2125 public String getContextPath()
2126 {
2127 if ((_contextPath != null) && _contextPath.equals(URIUtil.SLASH))
2128 return "";
2129
2130 return _contextPath;
2131 }
2132
2133
2134 @Override
2135 public String toString()
2136 {
2137 return "ServletContext@" + ContextHandler.this.toString();
2138 }
2139
2140
2141 @Override
2142 public boolean setInitParameter(String name, String value)
2143 {
2144 if (ContextHandler.this.getInitParameter(name) != null)
2145 return false;
2146 ContextHandler.this.getInitParams().put(name,value);
2147 return true;
2148 }
2149
2150 @Override
2151 public void addListener(String className)
2152 {
2153 if (!_enabled)
2154 throw new UnsupportedOperationException();
2155
2156 try
2157 {
2158 Class<? extends EventListener> clazz = _classLoader==null?Loader.loadClass(ContextHandler.class,className):_classLoader.loadClass(className);
2159 addListener(clazz);
2160 }
2161 catch (ClassNotFoundException e)
2162 {
2163 throw new IllegalArgumentException(e);
2164 }
2165 }
2166
2167 @Override
2168 public <T extends EventListener> void addListener(T t)
2169 {
2170 if (!_enabled)
2171 throw new UnsupportedOperationException();
2172 ContextHandler.this.addEventListener(t);
2173 ContextHandler.this.addProgrammaticListener(t);
2174 }
2175
2176 @Override
2177 public void addListener(Class<? extends EventListener> listenerClass)
2178 {
2179 if (!_enabled)
2180 throw new UnsupportedOperationException();
2181
2182 try
2183 {
2184 EventListener e = createListener(listenerClass);
2185 ContextHandler.this.addEventListener(e);
2186 ContextHandler.this.addProgrammaticListener(e);
2187 }
2188 catch (ServletException e)
2189 {
2190 throw new IllegalArgumentException(e);
2191 }
2192 }
2193
2194 @Override
2195 public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException
2196 {
2197 try
2198 {
2199 return clazz.newInstance();
2200 }
2201 catch (InstantiationException e)
2202 {
2203 throw new ServletException(e);
2204 }
2205 catch (IllegalAccessException e)
2206 {
2207 throw new ServletException(e);
2208 }
2209 }
2210
2211 @Override
2212 public ClassLoader getClassLoader()
2213 {
2214 AccessController.checkPermission(new RuntimePermission("getClassLoader"));
2215 return _classLoader;
2216 }
2217
2218 @Override
2219 public JspConfigDescriptor getJspConfigDescriptor()
2220 {
2221 LOG.warn(__unimplmented);
2222 return null;
2223 }
2224
2225 public void setJspConfigDescriptor(JspConfigDescriptor d)
2226 {
2227
2228 }
2229
2230 @Override
2231 public void declareRoles(String... roleNames)
2232 {
2233 if (!isStarting())
2234 throw new IllegalStateException ();
2235 if (!_enabled)
2236 throw new UnsupportedOperationException();
2237 }
2238
2239 public void setEnabled(boolean enabled)
2240 {
2241 _enabled = enabled;
2242 }
2243
2244 public boolean isEnabled()
2245 {
2246 return _enabled;
2247 }
2248 }
2249
2250
2251 public static class NoContext extends AttributesMap implements ServletContext
2252 {
2253 private int _effectiveMajorVersion = SERVLET_MAJOR_VERSION;
2254 private int _effectiveMinorVersion = SERVLET_MINOR_VERSION;
2255
2256
2257 public NoContext()
2258 {
2259 }
2260
2261 @Override
2262 public ServletContext getContext(String uripath)
2263 {
2264 return null;
2265 }
2266
2267 @Override
2268 public int getMajorVersion()
2269 {
2270 return SERVLET_MAJOR_VERSION;
2271 }
2272
2273 @Override
2274 public String getMimeType(String file)
2275 {
2276 return null;
2277 }
2278
2279 @Override
2280 public int getMinorVersion()
2281 {
2282 return SERVLET_MINOR_VERSION;
2283 }
2284
2285 @Override
2286 public RequestDispatcher getNamedDispatcher(String name)
2287 {
2288 return null;
2289 }
2290
2291 @Override
2292 public RequestDispatcher getRequestDispatcher(String uriInContext)
2293 {
2294 return null;
2295 }
2296
2297 @Override
2298 public String getRealPath(String path)
2299 {
2300 return null;
2301 }
2302
2303 @Override
2304 public URL getResource(String path) throws MalformedURLException
2305 {
2306 return null;
2307 }
2308
2309 @Override
2310 public InputStream getResourceAsStream(String path)
2311 {
2312 return null;
2313 }
2314
2315 @Override
2316 public Set<String> getResourcePaths(String path)
2317 {
2318 return null;
2319 }
2320
2321 @Override
2322 public String getServerInfo()
2323 {
2324 return "jetty/" + Server.getVersion();
2325 }
2326
2327 @Override
2328 @Deprecated
2329 public Servlet getServlet(String name) throws ServletException
2330 {
2331 return null;
2332 }
2333
2334 @SuppressWarnings("unchecked")
2335 @Override
2336 @Deprecated
2337 public Enumeration<String> getServletNames()
2338 {
2339 return Collections.enumeration(Collections.EMPTY_LIST);
2340 }
2341
2342 @SuppressWarnings("unchecked")
2343 @Override
2344 @Deprecated
2345 public Enumeration<Servlet> getServlets()
2346 {
2347 return Collections.enumeration(Collections.EMPTY_LIST);
2348 }
2349
2350 @Override
2351 public void log(Exception exception, String msg)
2352 {
2353 LOG.warn(msg,exception);
2354 }
2355
2356 @Override
2357 public void log(String msg)
2358 {
2359 LOG.info(msg);
2360 }
2361
2362 @Override
2363 public void log(String message, Throwable throwable)
2364 {
2365 LOG.warn(message,throwable);
2366 }
2367
2368 @Override
2369 public String getInitParameter(String name)
2370 {
2371 return null;
2372 }
2373
2374 @SuppressWarnings("unchecked")
2375 @Override
2376 public Enumeration<String> getInitParameterNames()
2377 {
2378 return Collections.enumeration(Collections.EMPTY_LIST);
2379 }
2380
2381
2382 @Override
2383 public String getServletContextName()
2384 {
2385 return "No Context";
2386 }
2387
2388 @Override
2389 public String getContextPath()
2390 {
2391 return null;
2392 }
2393
2394
2395 @Override
2396 public boolean setInitParameter(String name, String value)
2397 {
2398 return false;
2399 }
2400
2401 @Override
2402 public Dynamic addFilter(String filterName, Class<? extends Filter> filterClass)
2403 {
2404 LOG.warn(__unimplmented);
2405 return null;
2406 }
2407
2408 @Override
2409 public Dynamic addFilter(String filterName, Filter filter)
2410 {
2411 LOG.warn(__unimplmented);
2412 return null;
2413 }
2414
2415 @Override
2416 public Dynamic addFilter(String filterName, String className)
2417 {
2418 LOG.warn(__unimplmented);
2419 return null;
2420 }
2421
2422 @Override
2423 public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass)
2424 {
2425 LOG.warn(__unimplmented);
2426 return null;
2427 }
2428
2429 @Override
2430 public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
2431 {
2432 LOG.warn(__unimplmented);
2433 return null;
2434 }
2435
2436 @Override
2437 public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, String className)
2438 {
2439 LOG.warn(__unimplmented);
2440 return null;
2441 }
2442
2443 @Override
2444 public <T extends Filter> T createFilter(Class<T> c) throws ServletException
2445 {
2446 LOG.warn(__unimplmented);
2447 return null;
2448 }
2449
2450 @Override
2451 public <T extends Servlet> T createServlet(Class<T> c) throws ServletException
2452 {
2453 LOG.warn(__unimplmented);
2454 return null;
2455 }
2456
2457 @Override
2458 public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
2459 {
2460 LOG.warn(__unimplmented);
2461 return null;
2462 }
2463
2464 @Override
2465 public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
2466 {
2467 LOG.warn(__unimplmented);
2468 return null;
2469 }
2470
2471 @Override
2472 public FilterRegistration getFilterRegistration(String filterName)
2473 {
2474 LOG.warn(__unimplmented);
2475 return null;
2476 }
2477
2478 @Override
2479 public Map<String, ? extends FilterRegistration> getFilterRegistrations()
2480 {
2481 LOG.warn(__unimplmented);
2482 return null;
2483 }
2484
2485 @Override
2486 public ServletRegistration getServletRegistration(String servletName)
2487 {
2488 LOG.warn(__unimplmented);
2489 return null;
2490 }
2491
2492 @Override
2493 public Map<String, ? extends ServletRegistration> getServletRegistrations()
2494 {
2495 LOG.warn(__unimplmented);
2496 return null;
2497 }
2498
2499 @Override
2500 public SessionCookieConfig getSessionCookieConfig()
2501 {
2502 LOG.warn(__unimplmented);
2503 return null;
2504 }
2505
2506 @Override
2507 public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
2508 {
2509 LOG.warn(__unimplmented);
2510 }
2511
2512 @Override
2513 public void addListener(String className)
2514 {
2515 LOG.warn(__unimplmented);
2516 }
2517
2518 @Override
2519 public <T extends EventListener> void addListener(T t)
2520 {
2521 LOG.warn(__unimplmented);
2522 }
2523
2524 @Override
2525 public void addListener(Class<? extends EventListener> listenerClass)
2526 {
2527 LOG.warn(__unimplmented);
2528 }
2529
2530 @Override
2531 public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException
2532 {
2533 try
2534 {
2535 return clazz.newInstance();
2536 }
2537 catch (InstantiationException e)
2538 {
2539 throw new ServletException(e);
2540 }
2541 catch (IllegalAccessException e)
2542 {
2543 throw new ServletException(e);
2544 }
2545 }
2546
2547 @Override
2548 public ClassLoader getClassLoader()
2549 {
2550 AccessController.checkPermission(new RuntimePermission("getClassLoader"));
2551 return ContextHandler.class.getClassLoader();
2552 }
2553
2554 @Override
2555 public int getEffectiveMajorVersion()
2556 {
2557 return _effectiveMajorVersion;
2558 }
2559
2560 @Override
2561 public int getEffectiveMinorVersion()
2562 {
2563 return _effectiveMinorVersion;
2564 }
2565
2566 public void setEffectiveMajorVersion (int v)
2567 {
2568 _effectiveMajorVersion = v;
2569 }
2570
2571 public void setEffectiveMinorVersion (int v)
2572 {
2573 _effectiveMinorVersion = v;
2574 }
2575
2576 @Override
2577 public JspConfigDescriptor getJspConfigDescriptor()
2578 {
2579 LOG.warn(__unimplmented);
2580 return null;
2581 }
2582
2583 @Override
2584 public void declareRoles(String... roleNames)
2585 {
2586 LOG.warn(__unimplmented);
2587 }
2588 }
2589
2590
2591
2592
2593
2594 public interface AliasCheck
2595 {
2596
2597
2598
2599
2600
2601
2602 boolean check(String path, Resource resource);
2603 }
2604
2605
2606
2607
2608
2609 public static class ApproveAliases implements AliasCheck
2610 {
2611 @Override
2612 public boolean check(String path, Resource resource)
2613 {
2614 return true;
2615 }
2616 }
2617
2618
2619
2620
2621
2622
2623 @Deprecated
2624 public static class ApproveSameSuffixAliases implements AliasCheck
2625 {
2626 {
2627 LOG.warn("ApproveSameSuffixAlias is not safe for production");
2628 }
2629
2630 @Override
2631 public boolean check(String path, Resource resource)
2632 {
2633 int dot = path.lastIndexOf('.');
2634 if (dot<0)
2635 return false;
2636 String suffix=path.substring(dot);
2637 return resource.toString().endsWith(suffix);
2638 }
2639 }
2640
2641
2642
2643
2644
2645
2646
2647 @Deprecated
2648 public static class ApprovePathPrefixAliases implements AliasCheck
2649 {
2650 {
2651 LOG.warn("ApprovePathPrefixAliases is not safe for production");
2652 }
2653
2654 @Override
2655 public boolean check(String path, Resource resource)
2656 {
2657 int slash = path.lastIndexOf('/');
2658 if (slash<0 || slash==path.length()-1)
2659 return false;
2660 String suffix=path.substring(slash);
2661 return resource.toString().endsWith(suffix);
2662 }
2663 }
2664
2665
2666
2667
2668
2669
2670 public static class ApproveNonExistentDirectoryAliases implements AliasCheck
2671 {
2672 @Override
2673 public boolean check(String path, Resource resource)
2674 {
2675 if (resource.exists())
2676 return false;
2677
2678 String a=resource.getAlias().toString();
2679 String r=resource.getURL().toString();
2680
2681 if (a.length()>r.length())
2682 return a.startsWith(r) && a.length()==r.length()+1 && a.endsWith("/");
2683 if (a.length()<r.length())
2684 return r.startsWith(a) && r.length()==a.length()+1 && r.endsWith("/");
2685
2686 return a.equals(r);
2687 }
2688 }
2689
2690 }