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