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