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 Thread current_thread = null;
857
858 Context old_context = __context.get();
859 __context.set(_scontext);
860 try
861 {
862
863 if (_classLoader != null)
864 {
865 current_thread = Thread.currentThread();
866 old_classloader = current_thread.getContextClassLoader();
867 current_thread.setContextClassLoader(_classLoader);
868 }
869
870 stopContext();
871
872
873 setEventListeners(_durableListeners.toArray(new EventListener[_durableListeners.size()]));
874 _durableListeners.clear();
875
876 if (_errorHandler != null)
877 _errorHandler.stop();
878
879 for (EventListener l : _programmaticListeners)
880 removeEventListener(l);
881 _programmaticListeners.clear();
882 }
883 finally
884 {
885 LOG.info("Stopped {}", this);
886 __context.set(old_context);
887
888 if (_classLoader != null && current_thread!=null)
889 current_thread.setContextClassLoader(old_classloader);
890 }
891
892 _scontext.clearAttributes();
893 }
894
895
896
897 public boolean checkVirtualHost(final Request baseRequest)
898 {
899 if (_vhosts != null && _vhosts.length > 0)
900 {
901 String vhost = normalizeHostname(baseRequest.getServerName());
902
903 boolean match = false;
904 boolean connectorName = false;
905 boolean connectorMatch = false;
906
907 for (String contextVhost:_vhosts)
908 {
909 if (contextVhost == null || contextVhost.length()==0)
910 continue;
911 char c=contextVhost.charAt(0);
912 switch (c)
913 {
914 case '*':
915 if (contextVhost.startsWith("*."))
916
917 match = match || contextVhost.regionMatches(true,2,vhost,vhost.indexOf(".") + 1,contextVhost.length() - 2);
918 break;
919 case '@':
920 connectorName=true;
921 String name=baseRequest.getHttpChannel().getConnector().getName();
922 boolean m=name!=null && contextVhost.length()==name.length()+1 && contextVhost.endsWith(name);
923 match = match || m;
924 connectorMatch = connectorMatch || m;
925 break;
926 default:
927 match = match || contextVhost.equalsIgnoreCase(vhost);
928 }
929
930 }
931 if (!match || connectorName && !connectorMatch)
932 return false;
933 }
934 return true;
935 }
936
937
938
939 public boolean checkContextPath(String uri)
940 {
941
942 if (_contextPath.length() > 1)
943 {
944
945 if (!uri.startsWith(_contextPath))
946 return false;
947 if (uri.length() > _contextPath.length() && uri.charAt(_contextPath.length()) != '/')
948 return false;
949 }
950 return true;
951 }
952
953
954
955
956
957 public boolean checkContext(final String target, final Request baseRequest, final HttpServletResponse response) throws IOException
958 {
959 DispatcherType dispatch = baseRequest.getDispatcherType();
960
961
962 if (!checkVirtualHost(baseRequest))
963 return false;
964
965 if (!checkContextPath(target))
966 return false;
967
968
969
970 if (!_allowNullPathInfo && _contextPath.length() == target.length() && _contextPath.length()>1)
971 {
972
973 baseRequest.setHandled(true);
974 if (baseRequest.getQueryString() != null)
975 response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH) + "?" + baseRequest.getQueryString());
976 else
977 response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH));
978 return false;
979 }
980
981 switch (_availability)
982 {
983 case SHUTDOWN:
984 case UNAVAILABLE:
985 baseRequest.setHandled(true);
986 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
987 return false;
988 default:
989 if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled()))
990 return false;
991 }
992
993 return true;
994 }
995
996
997
998
999
1000
1001 @Override
1002 public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
1003 {
1004 if (LOG.isDebugEnabled())
1005 LOG.debug("scope {}|{}|{} @ {}",baseRequest.getContextPath(),baseRequest.getServletPath(),baseRequest.getPathInfo(),this);
1006
1007 Context old_context = null;
1008 String old_context_path = null;
1009 String old_servlet_path = null;
1010 String old_path_info = null;
1011 ClassLoader old_classloader = null;
1012 Thread current_thread = null;
1013 String pathInfo = target;
1014
1015 DispatcherType dispatch = baseRequest.getDispatcherType();
1016
1017 old_context = baseRequest.getContext();
1018
1019
1020 if (old_context != _scontext)
1021 {
1022
1023 if (DispatcherType.REQUEST.equals(dispatch) ||
1024 DispatcherType.ASYNC.equals(dispatch) ||
1025 DispatcherType.ERROR.equals(dispatch) && baseRequest.getHttpChannelState().isAsync())
1026 {
1027 if (_compactPath)
1028 target = URIUtil.compactPath(target);
1029 if (!checkContext(target,baseRequest,response))
1030 return;
1031
1032 if (target.length() > _contextPath.length())
1033 {
1034 if (_contextPath.length() > 1)
1035 target = target.substring(_contextPath.length());
1036 pathInfo = target;
1037 }
1038 else if (_contextPath.length() == 1)
1039 {
1040 target = URIUtil.SLASH;
1041 pathInfo = URIUtil.SLASH;
1042 }
1043 else
1044 {
1045 target = URIUtil.SLASH;
1046 pathInfo = null;
1047 }
1048 }
1049
1050
1051 if (_classLoader != null)
1052 {
1053 current_thread = Thread.currentThread();
1054 old_classloader = current_thread.getContextClassLoader();
1055 current_thread.setContextClassLoader(_classLoader);
1056 }
1057 }
1058
1059 try
1060 {
1061 old_context_path = baseRequest.getContextPath();
1062 old_servlet_path = baseRequest.getServletPath();
1063 old_path_info = baseRequest.getPathInfo();
1064
1065
1066 baseRequest.setContext(_scontext);
1067 __context.set(_scontext);
1068 if (!DispatcherType.INCLUDE.equals(dispatch) && target.startsWith("/"))
1069 {
1070 if (_contextPath.length() == 1)
1071 baseRequest.setContextPath("");
1072 else
1073 baseRequest.setContextPath(_contextPath);
1074 baseRequest.setServletPath(null);
1075 baseRequest.setPathInfo(pathInfo);
1076 }
1077
1078 if (old_context != _scontext)
1079 enterScope(baseRequest);
1080
1081 if (LOG.isDebugEnabled())
1082 LOG.debug("context={}|{}|{} @ {}",baseRequest.getContextPath(),baseRequest.getServletPath(), baseRequest.getPathInfo(),this);
1083
1084
1085 if (never())
1086 nextScope(target,baseRequest,request,response);
1087 else if (_nextScope != null)
1088 _nextScope.doScope(target,baseRequest,request,response);
1089 else if (_outerScope != null)
1090 _outerScope.doHandle(target,baseRequest,request,response);
1091 else
1092 doHandle(target,baseRequest,request,response);
1093
1094 }
1095 finally
1096 {
1097 if (old_context != _scontext)
1098 {
1099 exitScope(baseRequest);
1100
1101
1102 if (_classLoader != null && current_thread!=null)
1103 {
1104 current_thread.setContextClassLoader(old_classloader);
1105 }
1106
1107
1108 baseRequest.setContext(old_context);
1109 __context.set(old_context);
1110 baseRequest.setContextPath(old_context_path);
1111 baseRequest.setServletPath(old_servlet_path);
1112 baseRequest.setPathInfo(old_path_info);
1113 }
1114 }
1115 }
1116
1117
1118
1119
1120
1121
1122 @Override
1123 public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
1124 {
1125 final DispatcherType dispatch = baseRequest.getDispatcherType();
1126 final boolean new_context = baseRequest.takeNewContext();
1127 try
1128 {
1129 if (new_context)
1130 {
1131
1132 if (!_servletRequestAttributeListeners.isEmpty())
1133 for (ServletRequestAttributeListener l :_servletRequestAttributeListeners)
1134 baseRequest.addEventListener(l);
1135
1136 if (!_servletRequestListeners.isEmpty())
1137 {
1138 final ServletRequestEvent sre = new ServletRequestEvent(_scontext,request);
1139 for (ServletRequestListener l : _servletRequestListeners)
1140 l.requestInitialized(sre);
1141 }
1142 }
1143
1144 if (DispatcherType.REQUEST.equals(dispatch) && isProtectedTarget(target))
1145 {
1146 response.sendError(HttpServletResponse.SC_NOT_FOUND);
1147 baseRequest.setHandled(true);
1148 return;
1149 }
1150
1151
1152
1153 if (never())
1154 nextHandle(target,baseRequest,request,response);
1155 else if (_nextScope != null && _nextScope == _handler)
1156 _nextScope.doHandle(target,baseRequest,request,response);
1157 else if (_handler != null)
1158 _handler.handle(target,baseRequest,request,response);
1159
1160 }
1161 finally
1162 {
1163
1164 if (new_context)
1165 {
1166 if (!_servletRequestListeners.isEmpty())
1167 {
1168 final ServletRequestEvent sre = new ServletRequestEvent(_scontext,request);
1169 for (int i=_servletRequestListeners.size();i-->0;)
1170 _servletRequestListeners.get(i).requestDestroyed(sre);
1171 }
1172
1173 if (!_servletRequestAttributeListeners.isEmpty())
1174 {
1175 for (int i=_servletRequestAttributeListeners.size();i-->0;)
1176 baseRequest.removeEventListener(_servletRequestAttributeListeners.get(i));
1177 }
1178 }
1179 }
1180 }
1181
1182
1183
1184
1185
1186
1187
1188 protected void enterScope(Request request)
1189 {
1190 if (!_contextListeners.isEmpty())
1191 {
1192 for (ContextScopeListener listener:_contextListeners)
1193 {
1194 try
1195 {
1196 listener.enterScope(_scontext,request);
1197 }
1198 catch(Throwable e)
1199 {
1200 LOG.warn(e);
1201 }
1202 }
1203 }
1204 }
1205
1206
1207
1208
1209
1210 protected void exitScope(Request request)
1211 {
1212 if (!_contextListeners.isEmpty())
1213 {
1214 for (int i = _contextListeners.size(); i-->0;)
1215 {
1216 try
1217 {
1218 _contextListeners.get(i).exitScope(_scontext,request);
1219 }
1220 catch(Throwable e)
1221 {
1222 LOG.warn(e);
1223 }
1224 }
1225 }
1226 }
1227
1228
1229
1230
1231
1232
1233
1234 public void handle(Request request, Runnable runnable)
1235 {
1236 ClassLoader old_classloader = null;
1237 Thread current_thread = null;
1238 Context old_context = null;
1239 try
1240 {
1241 old_context = __context.get();
1242 __context.set(_scontext);
1243
1244
1245 if (_classLoader != null)
1246 {
1247 current_thread = Thread.currentThread();
1248 old_classloader = current_thread.getContextClassLoader();
1249 current_thread.setContextClassLoader(_classLoader);
1250 }
1251
1252 enterScope(request);
1253 runnable.run();
1254 }
1255 finally
1256 {
1257 exitScope(request);
1258
1259 __context.set(old_context);
1260 if (old_classloader != null && current_thread!=null)
1261 {
1262 current_thread.setContextClassLoader(old_classloader);
1263 }
1264 }
1265 }
1266
1267
1268
1269
1270
1271 public void handle(Runnable runnable)
1272 {
1273 handle(null,runnable);
1274 }
1275
1276
1277
1278
1279
1280
1281
1282
1283 public boolean isProtectedTarget(String target)
1284 {
1285 if (target == null || _protectedTargets == null)
1286 return false;
1287
1288 while (target.startsWith("//"))
1289 target=URIUtil.compactPath(target);
1290
1291 for (int i=0; i<_protectedTargets.length; i++)
1292 {
1293 String t=_protectedTargets[i];
1294 if (StringUtil.startsWithIgnoreCase(target,t))
1295 {
1296 if (target.length()==t.length())
1297 return true;
1298
1299
1300
1301 char c=target.charAt(t.length());
1302 if (c=='/'||c=='?'||c=='#'||c==';')
1303 return true;
1304 }
1305 }
1306 return false;
1307 }
1308
1309
1310
1311
1312
1313
1314
1315 public void setProtectedTargets (String[] targets)
1316 {
1317 if (targets == null)
1318 {
1319 _protectedTargets = null;
1320 return;
1321 }
1322
1323 _protectedTargets = Arrays.copyOf(targets, targets.length);
1324 }
1325
1326
1327 public String[] getProtectedTargets()
1328 {
1329 if (_protectedTargets == null)
1330 return null;
1331
1332 return Arrays.copyOf(_protectedTargets, _protectedTargets.length);
1333 }
1334
1335
1336
1337
1338
1339
1340 @Override
1341 public void removeAttribute(String name)
1342 {
1343 _attributes.removeAttribute(name);
1344 }
1345
1346
1347
1348
1349
1350
1351
1352
1353 @Override
1354 public void setAttribute( String name, Object value)
1355 {
1356 _attributes.setAttribute(name,value);
1357 }
1358
1359
1360
1361
1362
1363
1364 public void setAttributes(Attributes attributes)
1365 {
1366 _attributes.clearAttributes();
1367 _attributes.addAll(attributes);
1368 }
1369
1370
1371 @Override
1372 public void clearAttributes()
1373 {
1374 _attributes.clearAttributes();
1375 }
1376
1377
1378 public void setManagedAttribute(String name, Object value)
1379 {
1380 Object old = _managedAttributes.put(name,value);
1381 updateBean(old,value);
1382 }
1383
1384
1385
1386
1387
1388
1389 public void setClassLoader(ClassLoader classLoader)
1390 {
1391 _classLoader = classLoader;
1392 }
1393
1394
1395
1396
1397
1398
1399 public void setContextPath(String contextPath)
1400 {
1401 if (contextPath == null)
1402 throw new IllegalArgumentException("null contextPath");
1403
1404 if (contextPath.endsWith("/*"))
1405 {
1406 LOG.warn(this+" contextPath ends with /*");
1407 contextPath=contextPath.substring(0,contextPath.length()-2);
1408 }
1409 else if (contextPath.length()>1 && contextPath.endsWith("/"))
1410 {
1411 LOG.warn(this+" contextPath ends with /");
1412 contextPath=contextPath.substring(0,contextPath.length()-1);
1413 }
1414
1415 if (contextPath.length()==0)
1416 {
1417 LOG.warn("Empty contextPath");
1418 contextPath="/";
1419 }
1420
1421 _contextPath = contextPath;
1422
1423 if (getServer() != null && (getServer().isStarting() || getServer().isStarted()))
1424 {
1425 Handler[] contextCollections = getServer().getChildHandlersByClass(ContextHandlerCollection.class);
1426 for (int h = 0; contextCollections != null && h < contextCollections.length; h++)
1427 ((ContextHandlerCollection)contextCollections[h]).mapContexts();
1428 }
1429 }
1430
1431
1432
1433
1434
1435
1436 public void setDisplayName(String servletContextName)
1437 {
1438 _displayName = servletContextName;
1439 }
1440
1441
1442
1443
1444
1445 public Resource getBaseResource()
1446 {
1447 if (_baseResource == null)
1448 return null;
1449 return _baseResource;
1450 }
1451
1452
1453
1454
1455
1456 @ManagedAttribute("document root for context")
1457 public String getResourceBase()
1458 {
1459 if (_baseResource == null)
1460 return null;
1461 return _baseResource.toString();
1462 }
1463
1464
1465
1466
1467
1468
1469
1470 public void setBaseResource(Resource base)
1471 {
1472 _baseResource = base;
1473 }
1474
1475
1476
1477
1478
1479
1480
1481
1482 public void setResourceBase(String resourceBase)
1483 {
1484 try
1485 {
1486 setBaseResource(newResource(resourceBase));
1487 }
1488 catch (Exception e)
1489 {
1490 LOG.warn(e.toString());
1491 LOG.debug(e);
1492 throw new IllegalArgumentException(resourceBase);
1493 }
1494 }
1495
1496
1497
1498
1499
1500 public MimeTypes getMimeTypes()
1501 {
1502 if (_mimeTypes == null)
1503 _mimeTypes = new MimeTypes();
1504 return _mimeTypes;
1505 }
1506
1507
1508
1509
1510
1511
1512 public void setMimeTypes(MimeTypes mimeTypes)
1513 {
1514 _mimeTypes = mimeTypes;
1515 }
1516
1517
1518 public void setWelcomeFiles(String[] files)
1519 {
1520 _welcomeFiles = files;
1521 }
1522
1523
1524
1525
1526
1527
1528
1529 @ManagedAttribute(value="Partial URIs of directory welcome files", readonly=true)
1530 public String[] getWelcomeFiles()
1531 {
1532 return _welcomeFiles;
1533 }
1534
1535
1536
1537
1538
1539 @ManagedAttribute("The error handler to use for the context")
1540 public ErrorHandler getErrorHandler()
1541 {
1542 return _errorHandler;
1543 }
1544
1545
1546
1547
1548
1549
1550 public void setErrorHandler(ErrorHandler errorHandler)
1551 {
1552 if (errorHandler != null)
1553 errorHandler.setServer(getServer());
1554 updateBean(_errorHandler,errorHandler,true);
1555 _errorHandler = errorHandler;
1556 }
1557
1558
1559 @ManagedAttribute("The maximum content size")
1560 public int getMaxFormContentSize()
1561 {
1562 return _maxFormContentSize;
1563 }
1564
1565
1566
1567
1568
1569
1570 public void setMaxFormContentSize(int maxSize)
1571 {
1572 _maxFormContentSize = maxSize;
1573 }
1574
1575
1576 public int getMaxFormKeys()
1577 {
1578 return _maxFormKeys;
1579 }
1580
1581
1582
1583
1584
1585
1586 public void setMaxFormKeys(int max)
1587 {
1588 _maxFormKeys = max;
1589 }
1590
1591
1592
1593
1594
1595 public boolean isCompactPath()
1596 {
1597 return _compactPath;
1598 }
1599
1600
1601
1602
1603
1604
1605 public void setCompactPath(boolean compactPath)
1606 {
1607 _compactPath = compactPath;
1608 }
1609
1610
1611 @Override
1612 public String toString()
1613 {
1614 String[] vhosts = getVirtualHosts();
1615
1616 StringBuilder b = new StringBuilder();
1617
1618 Package pkg = getClass().getPackage();
1619 if (pkg != null)
1620 {
1621 String p = pkg.getName();
1622 if (p != null && p.length() > 0)
1623 {
1624 String[] ss = p.split("\\.");
1625 for (String s : ss)
1626 b.append(s.charAt(0)).append('.');
1627 }
1628 }
1629 b.append(getClass().getSimpleName()).append('@').append(Integer.toString(hashCode(),16));
1630 b.append('{').append(getContextPath()).append(',').append(getBaseResource()).append(',').append(_availability);
1631
1632 if (vhosts != null && vhosts.length > 0)
1633 b.append(',').append(vhosts[0]);
1634 b.append('}');
1635
1636 return b.toString();
1637 }
1638
1639
1640 public synchronized Class<?> loadClass(String className) throws ClassNotFoundException
1641 {
1642 if (className == null)
1643 return null;
1644
1645 if (_classLoader == null)
1646 return Loader.loadClass(this.getClass(),className);
1647
1648 return _classLoader.loadClass(className);
1649 }
1650
1651
1652 public void addLocaleEncoding(String locale, String encoding)
1653 {
1654 if (_localeEncodingMap == null)
1655 _localeEncodingMap = new HashMap<String, String>();
1656 _localeEncodingMap.put(locale,encoding);
1657 }
1658
1659
1660 public String getLocaleEncoding(String locale)
1661 {
1662 if (_localeEncodingMap == null)
1663 return null;
1664 String encoding = _localeEncodingMap.get(locale);
1665 return encoding;
1666 }
1667
1668
1669
1670
1671
1672
1673
1674
1675
1676
1677 public String getLocaleEncoding(Locale locale)
1678 {
1679 if (_localeEncodingMap == null)
1680 return null;
1681 String encoding = _localeEncodingMap.get(locale.toString());
1682 if (encoding == null)
1683 encoding = _localeEncodingMap.get(locale.getLanguage());
1684 return encoding;
1685 }
1686
1687
1688
1689
1690
1691
1692
1693 public Map<String,String> getLocaleEncodings()
1694 {
1695 if (_localeEncodingMap == null)
1696 return null;
1697 return Collections.unmodifiableMap(_localeEncodingMap);
1698 }
1699
1700
1701
1702
1703 public Resource getResource(String path) throws MalformedURLException
1704 {
1705 if (path == null || !path.startsWith(URIUtil.SLASH))
1706 throw new MalformedURLException(path);
1707
1708 if (_baseResource == null)
1709 return null;
1710
1711 try
1712 {
1713 path = URIUtil.canonicalPath(path);
1714 Resource resource = _baseResource.addPath(path);
1715
1716 if (checkAlias(path,resource))
1717 return resource;
1718 return null;
1719 }
1720 catch (Exception e)
1721 {
1722 LOG.ignore(e);
1723 }
1724
1725 return null;
1726 }
1727
1728
1729
1730
1731
1732
1733
1734 public boolean checkAlias(String path, Resource resource)
1735 {
1736
1737 if (resource.isAlias())
1738 {
1739 if (LOG.isDebugEnabled())
1740 LOG.debug("Aliased resource: " + resource + "~=" + resource.getAlias());
1741
1742
1743 for (Iterator<AliasCheck> i=_aliasChecks.iterator();i.hasNext();)
1744 {
1745 AliasCheck check = i.next();
1746 if (check.check(path,resource))
1747 {
1748 if (LOG.isDebugEnabled())
1749 LOG.debug("Aliased resource: " + resource + " approved by " + check);
1750 return true;
1751 }
1752 }
1753 return false;
1754 }
1755 return true;
1756 }
1757
1758
1759
1760
1761
1762
1763
1764
1765 public Resource newResource(URL url) throws IOException
1766 {
1767 return Resource.newResource(url);
1768 }
1769
1770
1771
1772
1773
1774
1775
1776
1777 public Resource newResource(URI uri) throws IOException
1778 {
1779 return Resource.newResource(uri);
1780 }
1781
1782
1783
1784
1785
1786
1787
1788
1789
1790
1791
1792 public Resource newResource(String urlOrPath) throws IOException
1793 {
1794 return Resource.newResource(urlOrPath);
1795 }
1796
1797
1798
1799
1800 public Set<String> getResourcePaths(String path)
1801 {
1802 try
1803 {
1804 path = URIUtil.canonicalPath(path);
1805 Resource resource = getResource(path);
1806
1807 if (resource != null && resource.exists())
1808 {
1809 if (!path.endsWith(URIUtil.SLASH))
1810 path = path + URIUtil.SLASH;
1811
1812 String[] l = resource.list();
1813 if (l != null)
1814 {
1815 HashSet<String> set = new HashSet<String>();
1816 for (int i = 0; i < l.length; i++)
1817 set.add(path + l[i]);
1818 return set;
1819 }
1820 }
1821 }
1822 catch (Exception e)
1823 {
1824 LOG.ignore(e);
1825 }
1826 return Collections.emptySet();
1827 }
1828
1829
1830 private String normalizeHostname(String host)
1831 {
1832 if (host == null)
1833 return null;
1834
1835 if (host.endsWith("."))
1836 return host.substring(0,host.length() - 1);
1837
1838 return host;
1839 }
1840
1841
1842
1843
1844
1845
1846 public void addAliasCheck(AliasCheck check)
1847 {
1848 _aliasChecks.add(check);
1849 }
1850
1851
1852
1853
1854
1855 public List<AliasCheck> getAliasChecks()
1856 {
1857 return _aliasChecks;
1858 }
1859
1860
1861
1862
1863
1864 public void setAliasChecks(List<AliasCheck> checks)
1865 {
1866 _aliasChecks.clear();
1867 _aliasChecks.addAll(checks);
1868 }
1869
1870
1871
1872
1873
1874 public void clearAliasChecks()
1875 {
1876 _aliasChecks.clear();
1877 }
1878
1879
1880
1881
1882
1883
1884
1885
1886
1887
1888
1889 public class Context extends StaticContext
1890 {
1891 protected boolean _enabled = true;
1892 protected boolean _extendedListenerTypes = false;
1893
1894
1895
1896 protected Context()
1897 {
1898 }
1899
1900
1901 public ContextHandler getContextHandler()
1902 {
1903 return ContextHandler.this;
1904 }
1905
1906
1907
1908
1909
1910 @Override
1911 public ServletContext getContext(String uripath)
1912 {
1913 List<ContextHandler> contexts = new ArrayList<ContextHandler>();
1914 Handler[] handlers = getServer().getChildHandlersByClass(ContextHandler.class);
1915 String matched_path = null;
1916
1917 for (Handler handler : handlers)
1918 {
1919 if (handler == null)
1920 continue;
1921 ContextHandler ch = (ContextHandler)handler;
1922 String context_path = ch.getContextPath();
1923
1924 if (uripath.equals(context_path) || (uripath.startsWith(context_path) && uripath.charAt(context_path.length()) == '/')
1925 || "/".equals(context_path))
1926 {
1927
1928 if (getVirtualHosts() != null && getVirtualHosts().length > 0)
1929 {
1930 if (ch.getVirtualHosts() != null && ch.getVirtualHosts().length > 0)
1931 {
1932 for (String h1 : getVirtualHosts())
1933 for (String h2 : ch.getVirtualHosts())
1934 if (h1.equals(h2))
1935 {
1936 if (matched_path == null || context_path.length() > matched_path.length())
1937 {
1938 contexts.clear();
1939 matched_path = context_path;
1940 }
1941
1942 if (matched_path.equals(context_path))
1943 contexts.add(ch);
1944 }
1945 }
1946 }
1947 else
1948 {
1949 if (matched_path == null || context_path.length() > matched_path.length())
1950 {
1951 contexts.clear();
1952 matched_path = context_path;
1953 }
1954
1955 if (matched_path.equals(context_path))
1956 contexts.add(ch);
1957 }
1958 }
1959 }
1960
1961 if (contexts.size() > 0)
1962 return contexts.get(0)._scontext;
1963
1964
1965 matched_path = null;
1966 for (Handler handler : handlers)
1967 {
1968 if (handler == null)
1969 continue;
1970 ContextHandler ch = (ContextHandler)handler;
1971 String context_path = ch.getContextPath();
1972
1973 if (uripath.equals(context_path) || (uripath.startsWith(context_path) && uripath.charAt(context_path.length()) == '/')
1974 || "/".equals(context_path))
1975 {
1976 if (matched_path == null || context_path.length() > matched_path.length())
1977 {
1978 contexts.clear();
1979 matched_path = context_path;
1980 }
1981
1982 if (matched_path != null && matched_path.equals(context_path))
1983 contexts.add(ch);
1984 }
1985 }
1986
1987 if (contexts.size() > 0)
1988 return contexts.get(0)._scontext;
1989 return null;
1990 }
1991
1992
1993
1994
1995
1996 @Override
1997 public String getMimeType(String file)
1998 {
1999 if (_mimeTypes == null)
2000 return null;
2001 return _mimeTypes.getMimeByExtension(file);
2002 }
2003
2004
2005
2006
2007
2008 @Override
2009 public RequestDispatcher getRequestDispatcher(String uriInContext)
2010 {
2011 if (uriInContext == null)
2012 return null;
2013
2014 if (!uriInContext.startsWith("/"))
2015 return null;
2016
2017 try
2018 {
2019 HttpURI uri = new HttpURI(null,null,0,uriInContext);
2020
2021 String pathInfo=URIUtil.canonicalPath(uri.getDecodedPath());
2022 if (pathInfo==null)
2023 return null;
2024
2025 String contextPath=getContextPath();
2026 if (contextPath!=null && contextPath.length()>0)
2027 uri.setPath(URIUtil.addPaths(contextPath,uri.getPath()));
2028
2029 return new Dispatcher(ContextHandler.this,uri,pathInfo);
2030 }
2031 catch (Exception e)
2032 {
2033 LOG.ignore(e);
2034 }
2035 return null;
2036 }
2037
2038
2039
2040
2041
2042 @Override
2043 public String getRealPath(String path)
2044 {
2045 if (path == null)
2046 return null;
2047 if (path.length() == 0)
2048 path = URIUtil.SLASH;
2049 else if (path.charAt(0) != '/')
2050 path = URIUtil.SLASH + path;
2051
2052 try
2053 {
2054 Resource resource = ContextHandler.this.getResource(path);
2055 if (resource != null)
2056 {
2057 File file = resource.getFile();
2058 if (file != null)
2059 return file.getCanonicalPath();
2060 }
2061 }
2062 catch (Exception e)
2063 {
2064 LOG.ignore(e);
2065 }
2066
2067 return null;
2068 }
2069
2070
2071 @Override
2072 public URL getResource(String path) throws MalformedURLException
2073 {
2074 Resource resource = ContextHandler.this.getResource(path);
2075 if (resource != null && resource.exists())
2076 return resource.getURI().toURL();
2077 return null;
2078 }
2079
2080
2081
2082
2083
2084 @Override
2085 public InputStream getResourceAsStream(String path)
2086 {
2087 try
2088 {
2089 URL url = getResource(path);
2090 if (url == null)
2091 return null;
2092 Resource r = Resource.newResource(url);
2093 return r.getInputStream();
2094 }
2095 catch (Exception e)
2096 {
2097 LOG.ignore(e);
2098 return null;
2099 }
2100 }
2101
2102
2103
2104
2105
2106 @Override
2107 public Set<String> getResourcePaths(String path)
2108 {
2109 return ContextHandler.this.getResourcePaths(path);
2110 }
2111
2112
2113
2114
2115
2116 @Override
2117 public void log(Exception exception, String msg)
2118 {
2119 _logger.warn(msg,exception);
2120 }
2121
2122
2123
2124
2125
2126 @Override
2127 public void log(String msg)
2128 {
2129 _logger.info(msg);
2130 }
2131
2132
2133
2134
2135
2136 @Override
2137 public void log(String message, Throwable throwable)
2138 {
2139 _logger.warn(message,throwable);
2140 }
2141
2142
2143
2144
2145
2146 @Override
2147 public String getInitParameter(String name)
2148 {
2149 return ContextHandler.this.getInitParameter(name);
2150 }
2151
2152
2153
2154
2155
2156 @Override
2157 public Enumeration<String> getInitParameterNames()
2158 {
2159 return ContextHandler.this.getInitParameterNames();
2160 }
2161
2162
2163
2164
2165
2166 @Override
2167 public synchronized Object getAttribute(String name)
2168 {
2169 Object o = ContextHandler.this.getAttribute(name);
2170 if (o == null)
2171 o = super.getAttribute(name);
2172 return o;
2173 }
2174
2175
2176
2177
2178
2179 @Override
2180 public synchronized Enumeration<String> getAttributeNames()
2181 {
2182 HashSet<String> set = new HashSet<String>();
2183 Enumeration<String> e = super.getAttributeNames();
2184 while (e.hasMoreElements())
2185 set.add(e.nextElement());
2186 e = _attributes.getAttributeNames();
2187 while (e.hasMoreElements())
2188 set.add(e.nextElement());
2189
2190 return Collections.enumeration(set);
2191 }
2192
2193
2194
2195
2196
2197 @Override
2198 public synchronized void setAttribute(String name, Object value)
2199 {
2200 Object old_value = super.getAttribute(name);
2201
2202 if (value == null)
2203 super.removeAttribute(name);
2204 else
2205 super.setAttribute(name,value);
2206
2207 if (!_servletContextAttributeListeners.isEmpty())
2208 {
2209 ServletContextAttributeEvent event = new ServletContextAttributeEvent(_scontext,name,old_value == null?value:old_value);
2210
2211 for (ServletContextAttributeListener l : _servletContextAttributeListeners)
2212 {
2213 if (old_value == null)
2214 l.attributeAdded(event);
2215 else if (value == null)
2216 l.attributeRemoved(event);
2217 else
2218 l.attributeReplaced(event);
2219 }
2220 }
2221 }
2222
2223
2224
2225
2226
2227 @Override
2228 public synchronized void removeAttribute(String name)
2229 {
2230 Object old_value = super.getAttribute(name);
2231 super.removeAttribute(name);
2232 if (old_value != null &&!_servletContextAttributeListeners.isEmpty())
2233 {
2234 ServletContextAttributeEvent event = new ServletContextAttributeEvent(_scontext,name,old_value);
2235
2236 for (ServletContextAttributeListener l : _servletContextAttributeListeners)
2237 l.attributeRemoved(event);
2238 }
2239 }
2240
2241
2242
2243
2244
2245 @Override
2246 public String getServletContextName()
2247 {
2248 String name = ContextHandler.this.getDisplayName();
2249 if (name == null)
2250 name = ContextHandler.this.getContextPath();
2251 return name;
2252 }
2253
2254
2255 @Override
2256 public String getContextPath()
2257 {
2258 if ((_contextPath != null) && _contextPath.equals(URIUtil.SLASH))
2259 return "";
2260
2261 return _contextPath;
2262 }
2263
2264
2265 @Override
2266 public String toString()
2267 {
2268 return "ServletContext@" + ContextHandler.this.toString();
2269 }
2270
2271
2272 @Override
2273 public boolean setInitParameter(String name, String value)
2274 {
2275 if (ContextHandler.this.getInitParameter(name) != null)
2276 return false;
2277 ContextHandler.this.getInitParams().put(name,value);
2278 return true;
2279 }
2280
2281 @Override
2282 public void addListener(String className)
2283 {
2284 if (!_enabled)
2285 throw new UnsupportedOperationException();
2286
2287 try
2288 {
2289 @SuppressWarnings({ "unchecked", "rawtypes" })
2290 Class<? extends EventListener> clazz = _classLoader==null?Loader.loadClass(ContextHandler.class,className):(Class)_classLoader.loadClass(className);
2291 addListener(clazz);
2292 }
2293 catch (ClassNotFoundException e)
2294 {
2295 throw new IllegalArgumentException(e);
2296 }
2297 }
2298
2299 @Override
2300 public <T extends EventListener> void addListener(T t)
2301 {
2302 if (!_enabled)
2303 throw new UnsupportedOperationException();
2304
2305 checkListener(t.getClass());
2306
2307 ContextHandler.this.addEventListener(t);
2308 ContextHandler.this.addProgrammaticListener(t);
2309 }
2310
2311 @Override
2312 public void addListener(Class<? extends EventListener> listenerClass)
2313 {
2314 if (!_enabled)
2315 throw new UnsupportedOperationException();
2316
2317 try
2318 {
2319 EventListener e = createListener(listenerClass);
2320 addListener(e);
2321 }
2322 catch (ServletException e)
2323 {
2324 throw new IllegalArgumentException(e);
2325 }
2326 }
2327
2328 @Override
2329 public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException
2330 {
2331 try
2332 {
2333 return createInstance(clazz);
2334 }
2335 catch (Exception e)
2336 {
2337 throw new ServletException(e);
2338 }
2339 }
2340
2341
2342 public void checkListener (Class<? extends EventListener> listener) throws IllegalStateException
2343 {
2344 boolean ok = false;
2345 int startIndex = (isExtendedListenerTypes()?EXTENDED_LISTENER_TYPE_INDEX:DEFAULT_LISTENER_TYPE_INDEX);
2346 for (int i=startIndex;i<SERVLET_LISTENER_TYPES.length;i++)
2347 {
2348 if (SERVLET_LISTENER_TYPES[i].isAssignableFrom(listener))
2349 {
2350 ok = true;
2351 break;
2352 }
2353 }
2354 if (!ok)
2355 throw new IllegalArgumentException("Inappropriate listener class "+listener.getName());
2356 }
2357
2358 public void setExtendedListenerTypes (boolean extended)
2359 {
2360 _extendedListenerTypes = extended;
2361 }
2362
2363 public boolean isExtendedListenerTypes()
2364 {
2365 return _extendedListenerTypes;
2366 }
2367
2368 @Override
2369 public ClassLoader getClassLoader()
2370 {
2371 if (!_enabled)
2372 throw new UnsupportedOperationException();
2373
2374
2375 if (!_usingSecurityManager)
2376 return _classLoader;
2377 else
2378 {
2379
2380
2381 try
2382 {
2383 Class<?> reflect = Loader.loadClass(getClass(), "sun.reflect.Reflection");
2384 Method getCallerClass = reflect.getMethod("getCallerClass", Integer.TYPE);
2385 Class<?> caller = (Class<?>)getCallerClass.invoke(null, 2);
2386
2387 boolean ok = false;
2388 ClassLoader callerLoader = caller.getClassLoader();
2389 while (!ok && callerLoader != null)
2390 {
2391 if (callerLoader == _classLoader)
2392 ok = true;
2393 else
2394 callerLoader = callerLoader.getParent();
2395 }
2396
2397 if (ok)
2398 return _classLoader;
2399 }
2400 catch (Exception e)
2401 {
2402 LOG.warn("Unable to check classloader of caller",e);
2403 }
2404
2405 AccessController.checkPermission(new RuntimePermission("getClassLoader"));
2406 return _classLoader;
2407 }
2408 }
2409
2410 @Override
2411 public JspConfigDescriptor getJspConfigDescriptor()
2412 {
2413 LOG.warn(__unimplmented);
2414 return null;
2415 }
2416
2417 public void setJspConfigDescriptor(JspConfigDescriptor d)
2418 {
2419
2420 }
2421
2422 @Override
2423 public void declareRoles(String... roleNames)
2424 {
2425 if (!isStarting())
2426 throw new IllegalStateException ();
2427 if (!_enabled)
2428 throw new UnsupportedOperationException();
2429 }
2430
2431 public void setEnabled(boolean enabled)
2432 {
2433 _enabled = enabled;
2434 }
2435
2436 public boolean isEnabled()
2437 {
2438 return _enabled;
2439 }
2440
2441 public <T> T createInstance (Class<T> clazz) throws Exception
2442 {
2443 T o = clazz.newInstance();
2444 return o;
2445 }
2446
2447 @Override
2448 public String getVirtualServerName()
2449 {
2450 String[] hosts = getVirtualHosts();
2451 if (hosts!=null && hosts.length>0)
2452 return hosts[0];
2453 return null;
2454 }
2455 }
2456
2457 public static class StaticContext extends AttributesMap implements ServletContext
2458 {
2459 private int _effectiveMajorVersion = SERVLET_MAJOR_VERSION;
2460 private int _effectiveMinorVersion = SERVLET_MINOR_VERSION;
2461
2462
2463 public StaticContext()
2464 {
2465 }
2466
2467 @Override
2468 public ServletContext getContext(String uripath)
2469 {
2470 return null;
2471 }
2472
2473 @Override
2474 public int getMajorVersion()
2475 {
2476 return SERVLET_MAJOR_VERSION;
2477 }
2478
2479 @Override
2480 public String getMimeType(String file)
2481 {
2482 return null;
2483 }
2484
2485 @Override
2486 public int getMinorVersion()
2487 {
2488 return SERVLET_MINOR_VERSION;
2489 }
2490
2491 @Override
2492 public RequestDispatcher getNamedDispatcher(String name)
2493 {
2494 return null;
2495 }
2496
2497 @Override
2498 public RequestDispatcher getRequestDispatcher(String uriInContext)
2499 {
2500 return null;
2501 }
2502
2503 @Override
2504 public String getRealPath(String path)
2505 {
2506 return null;
2507 }
2508
2509 @Override
2510 public URL getResource(String path) throws MalformedURLException
2511 {
2512 return null;
2513 }
2514
2515 @Override
2516 public InputStream getResourceAsStream(String path)
2517 {
2518 return null;
2519 }
2520
2521 @Override
2522 public Set<String> getResourcePaths(String path)
2523 {
2524 return null;
2525 }
2526
2527 @Override
2528 public String getServerInfo()
2529 {
2530 return __serverInfo;
2531 }
2532
2533 @Override
2534 @Deprecated
2535 public Servlet getServlet(String name) throws ServletException
2536 {
2537 return null;
2538 }
2539
2540 @SuppressWarnings("unchecked")
2541 @Override
2542 @Deprecated
2543 public Enumeration<String> getServletNames()
2544 {
2545 return Collections.enumeration(Collections.EMPTY_LIST);
2546 }
2547
2548 @SuppressWarnings("unchecked")
2549 @Override
2550 @Deprecated
2551 public Enumeration<Servlet> getServlets()
2552 {
2553 return Collections.enumeration(Collections.EMPTY_LIST);
2554 }
2555
2556 @Override
2557 public void log(Exception exception, String msg)
2558 {
2559 LOG.warn(msg,exception);
2560 }
2561
2562 @Override
2563 public void log(String msg)
2564 {
2565 LOG.info(msg);
2566 }
2567
2568 @Override
2569 public void log(String message, Throwable throwable)
2570 {
2571 LOG.warn(message,throwable);
2572 }
2573
2574 @Override
2575 public String getInitParameter(String name)
2576 {
2577 return null;
2578 }
2579
2580 @SuppressWarnings("unchecked")
2581 @Override
2582 public Enumeration<String> getInitParameterNames()
2583 {
2584 return Collections.enumeration(Collections.EMPTY_LIST);
2585 }
2586
2587
2588 @Override
2589 public String getServletContextName()
2590 {
2591 return "No Context";
2592 }
2593
2594 @Override
2595 public String getContextPath()
2596 {
2597 return null;
2598 }
2599
2600 @Override
2601 public boolean setInitParameter(String name, String value)
2602 {
2603 return false;
2604 }
2605
2606 @Override
2607 public Dynamic addFilter(String filterName, Class<? extends Filter> filterClass)
2608 {
2609 LOG.warn(__unimplmented);
2610 return null;
2611 }
2612
2613 @Override
2614 public Dynamic addFilter(String filterName, Filter filter)
2615 {
2616 LOG.warn(__unimplmented);
2617 return null;
2618 }
2619
2620 @Override
2621 public Dynamic addFilter(String filterName, String className)
2622 {
2623 LOG.warn(__unimplmented);
2624 return null;
2625 }
2626
2627 @Override
2628 public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Class<? extends Servlet> servletClass)
2629 {
2630 LOG.warn(__unimplmented);
2631 return null;
2632 }
2633
2634 @Override
2635 public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet)
2636 {
2637 LOG.warn(__unimplmented);
2638 return null;
2639 }
2640
2641 @Override
2642 public javax.servlet.ServletRegistration.Dynamic addServlet(String servletName, String className)
2643 {
2644 LOG.warn(__unimplmented);
2645 return null;
2646 }
2647
2648 @Override
2649 public <T extends Filter> T createFilter(Class<T> c) throws ServletException
2650 {
2651 LOG.warn(__unimplmented);
2652 return null;
2653 }
2654
2655 @Override
2656 public <T extends Servlet> T createServlet(Class<T> c) throws ServletException
2657 {
2658 LOG.warn(__unimplmented);
2659 return null;
2660 }
2661
2662 @Override
2663 public Set<SessionTrackingMode> getDefaultSessionTrackingModes()
2664 {
2665 LOG.warn(__unimplmented);
2666 return null;
2667 }
2668
2669 @Override
2670 public Set<SessionTrackingMode> getEffectiveSessionTrackingModes()
2671 {
2672 LOG.warn(__unimplmented);
2673 return null;
2674 }
2675
2676 @Override
2677 public FilterRegistration getFilterRegistration(String filterName)
2678 {
2679 LOG.warn(__unimplmented);
2680 return null;
2681 }
2682
2683 @Override
2684 public Map<String, ? extends FilterRegistration> getFilterRegistrations()
2685 {
2686 LOG.warn(__unimplmented);
2687 return null;
2688 }
2689
2690 @Override
2691 public ServletRegistration getServletRegistration(String servletName)
2692 {
2693 LOG.warn(__unimplmented);
2694 return null;
2695 }
2696
2697 @Override
2698 public Map<String, ? extends ServletRegistration> getServletRegistrations()
2699 {
2700 LOG.warn(__unimplmented);
2701 return null;
2702 }
2703
2704 @Override
2705 public SessionCookieConfig getSessionCookieConfig()
2706 {
2707 LOG.warn(__unimplmented);
2708 return null;
2709 }
2710
2711 @Override
2712 public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes)
2713 {
2714 LOG.warn(__unimplmented);
2715 }
2716
2717 @Override
2718 public void addListener(String className)
2719 {
2720 LOG.warn(__unimplmented);
2721 }
2722
2723 @Override
2724 public <T extends EventListener> void addListener(T t)
2725 {
2726 LOG.warn(__unimplmented);
2727 }
2728
2729 @Override
2730 public void addListener(Class<? extends EventListener> listenerClass)
2731 {
2732 LOG.warn(__unimplmented);
2733 }
2734
2735 @Override
2736 public <T extends EventListener> T createListener(Class<T> clazz) throws ServletException
2737 {
2738 try
2739 {
2740 return clazz.newInstance();
2741 }
2742 catch (InstantiationException e)
2743 {
2744 throw new ServletException(e);
2745 }
2746 catch (IllegalAccessException e)
2747 {
2748 throw new ServletException(e);
2749 }
2750 }
2751
2752 @Override
2753 public ClassLoader getClassLoader()
2754 {
2755 return ContextHandler.class.getClassLoader();
2756 }
2757
2758 @Override
2759 public int getEffectiveMajorVersion()
2760 {
2761 return _effectiveMajorVersion;
2762 }
2763
2764 @Override
2765 public int getEffectiveMinorVersion()
2766 {
2767 return _effectiveMinorVersion;
2768 }
2769
2770 public void setEffectiveMajorVersion (int v)
2771 {
2772 _effectiveMajorVersion = v;
2773 }
2774
2775 public void setEffectiveMinorVersion (int v)
2776 {
2777 _effectiveMinorVersion = v;
2778 }
2779
2780 @Override
2781 public JspConfigDescriptor getJspConfigDescriptor()
2782 {
2783 LOG.warn(__unimplmented);
2784 return null;
2785 }
2786
2787 @Override
2788 public void declareRoles(String... roleNames)
2789 {
2790 LOG.warn(__unimplmented);
2791 }
2792
2793 @Override
2794 public String getVirtualServerName()
2795 {
2796 return null;
2797 }
2798 }
2799
2800
2801
2802
2803
2804 public interface AliasCheck
2805 {
2806
2807
2808
2809
2810
2811
2812 boolean check(String path, Resource resource);
2813 }
2814
2815
2816
2817
2818
2819 public static class ApproveAliases implements AliasCheck
2820 {
2821 @Override
2822 public boolean check(String path, Resource resource)
2823 {
2824 return true;
2825 }
2826 }
2827
2828
2829
2830
2831
2832
2833 public static class ApproveNonExistentDirectoryAliases implements AliasCheck
2834 {
2835 @Override
2836 public boolean check(String path, Resource resource)
2837 {
2838 if (resource.exists())
2839 return false;
2840
2841 String a=resource.getAlias().toString();
2842 String r=resource.getURI().toString();
2843
2844 if (a.length()>r.length())
2845 return a.startsWith(r) && a.length()==r.length()+1 && a.endsWith("/");
2846 if (a.length()<r.length())
2847 return r.startsWith(a) && r.length()==a.length()+1 && r.endsWith("/");
2848
2849 return a.equals(r);
2850 }
2851 }
2852
2853
2854
2855
2856 public static interface ContextScopeListener extends EventListener
2857 {
2858
2859
2860
2861
2862 void enterScope(Context context, Request request);
2863
2864
2865
2866
2867
2868
2869 void exitScope(Context context, Request request);
2870 }
2871 }