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