1
2
3
4
5
6
7
8
9
10
11
12
13
14 package org.eclipse.jetty.server.handler;
15
16 import java.io.File;
17 import java.io.IOException;
18 import java.io.InputStream;
19 import java.net.MalformedURLException;
20 import java.net.URL;
21 import java.net.URLClassLoader;
22 import java.util.ArrayList;
23 import java.util.Arrays;
24 import java.util.Collections;
25 import java.util.Enumeration;
26 import java.util.EventListener;
27 import java.util.HashMap;
28 import java.util.HashSet;
29 import java.util.List;
30 import java.util.Locale;
31 import java.util.Map;
32 import java.util.Set;
33
34 import javax.servlet.RequestDispatcher;
35 import javax.servlet.Servlet;
36 import javax.servlet.ServletContext;
37 import javax.servlet.ServletContextAttributeEvent;
38 import javax.servlet.ServletContextAttributeListener;
39 import javax.servlet.ServletContextEvent;
40 import javax.servlet.ServletContextListener;
41 import javax.servlet.ServletException;
42 import javax.servlet.ServletRequestAttributeListener;
43 import javax.servlet.ServletRequestEvent;
44 import javax.servlet.ServletRequestListener;
45 import javax.servlet.http.HttpServletRequest;
46 import javax.servlet.http.HttpServletResponse;
47
48 import org.eclipse.jetty.http.HttpException;
49 import org.eclipse.jetty.http.MimeTypes;
50 import org.eclipse.jetty.io.Buffer;
51 import org.eclipse.jetty.server.AbstractHttpConnection;
52 import org.eclipse.jetty.server.Dispatcher;
53 import org.eclipse.jetty.server.DispatcherType;
54 import org.eclipse.jetty.server.Handler;
55 import org.eclipse.jetty.server.HandlerContainer;
56 import org.eclipse.jetty.server.Request;
57 import org.eclipse.jetty.server.Server;
58 import org.eclipse.jetty.util.Attributes;
59 import org.eclipse.jetty.util.AttributesMap;
60 import org.eclipse.jetty.util.LazyList;
61 import org.eclipse.jetty.util.Loader;
62 import org.eclipse.jetty.util.TypeUtil;
63 import org.eclipse.jetty.util.URIUtil;
64 import org.eclipse.jetty.util.component.AggregateLifeCycle;
65 import org.eclipse.jetty.util.component.Dumpable;
66 import org.eclipse.jetty.util.log.Log;
67 import org.eclipse.jetty.util.log.Logger;
68 import org.eclipse.jetty.util.resource.Resource;
69
70
71
72
73
74
75
76
77
78
79
80
81
82 public class ContextHandler extends ScopedHandler implements Attributes, Server.Graceful
83 {
84 private static final Logger LOG = Log.getLogger(ContextHandler.class);
85
86 private static final ThreadLocal<Context> __context = new ThreadLocal<Context>();
87
88
89
90
91
92
93 public static final String MANAGED_ATTRIBUTES = "org.eclipse.jetty.server.context.ManagedAttributes";
94
95
96
97
98
99
100
101 public static Context getCurrentContext()
102 {
103 return __context.get();
104 }
105
106 protected Context _scontext;
107
108 private final AttributesMap _attributes;
109 private final AttributesMap _contextAttributes;
110 private final Map<String, String> _initParams;
111 private ClassLoader _classLoader;
112 private String _contextPath = "/";
113 private String _displayName;
114 private Resource _baseResource;
115 private MimeTypes _mimeTypes;
116 private Map<String, String> _localeEncodingMap;
117 private String[] _welcomeFiles;
118 private ErrorHandler _errorHandler;
119 private String[] _vhosts;
120 private Set<String> _connectors;
121 private EventListener[] _eventListeners;
122 private Logger _logger;
123 private boolean _allowNullPathInfo;
124 private int _maxFormContentSize = Integer.getInteger("org.eclipse.jetty.server.Request.maxFormContentSize",200000).intValue();
125 private boolean _compactPath = false;
126 private boolean _aliases = false;
127
128 private Object _contextListeners;
129 private Object _contextAttributeListeners;
130 private Object _requestListeners;
131 private Object _requestAttributeListeners;
132 private Map<String, Object> _managedAttributes;
133
134 private boolean _shutdown = false;
135 private boolean _available = true;
136 private volatile int _availability;
137
138 private final static int __STOPPED = 0, __AVAILABLE = 1, __SHUTDOWN = 2, __UNAVAILABLE = 3;
139
140
141
142
143
144 public ContextHandler()
145 {
146 super();
147 _scontext = new Context();
148 _attributes = new AttributesMap();
149 _contextAttributes = new AttributesMap();
150 _initParams = new HashMap<String, String>();
151 }
152
153
154
155
156
157 protected ContextHandler(Context context)
158 {
159 super();
160 _scontext = context;
161 _attributes = new AttributesMap();
162 _contextAttributes = new AttributesMap();
163 _initParams = new HashMap<String, String>();
164 }
165
166
167
168
169
170 public ContextHandler(String contextPath)
171 {
172 this();
173 setContextPath(contextPath);
174 }
175
176
177
178
179
180 public ContextHandler(HandlerContainer parent, String contextPath)
181 {
182 this();
183 setContextPath(contextPath);
184 if (parent instanceof HandlerWrapper)
185 ((HandlerWrapper)parent).setHandler(this);
186 else if (parent instanceof HandlerCollection)
187 ((HandlerCollection)parent).addHandler(this);
188 }
189
190
191 @Override
192 public void dump(Appendable out, String indent) throws IOException
193 {
194 dumpThis(out);
195 dump(out,indent,Collections.singletonList(new CLDump(getClassLoader())),TypeUtil.asList(getHandlers()),getBeans(),_initParams.entrySet(),
196 _attributes.getAttributeEntrySet(),_contextAttributes.getAttributeEntrySet());
197 }
198
199
200 public Context getServletContext()
201 {
202 return _scontext;
203 }
204
205
206
207
208
209 public boolean getAllowNullPathInfo()
210 {
211 return _allowNullPathInfo;
212 }
213
214
215
216
217
218
219 public void setAllowNullPathInfo(boolean allowNullPathInfo)
220 {
221 _allowNullPathInfo = allowNullPathInfo;
222 }
223
224
225 @Override
226 public void setServer(Server server)
227 {
228 if (_errorHandler != null)
229 {
230 Server old_server = getServer();
231 if (old_server != null && old_server != server)
232 old_server.getContainer().update(this,_errorHandler,null,"error",true);
233 super.setServer(server);
234 if (server != null && server != old_server)
235 server.getContainer().update(this,null,_errorHandler,"error",true);
236 _errorHandler.setServer(server);
237 }
238 else
239 super.setServer(server);
240 }
241
242
243
244
245
246
247
248
249
250
251
252 public void setVirtualHosts(String[] vhosts)
253 {
254 if (vhosts == null)
255 {
256 _vhosts = vhosts;
257 }
258 else
259 {
260 _vhosts = new String[vhosts.length];
261 for (int i = 0; i < vhosts.length; i++)
262 _vhosts[i] = normalizeHostname(vhosts[i]);
263 }
264 }
265
266
267
268
269
270
271
272
273 public void addVirtualHosts(String[] virtualHosts)
274 {
275 if (virtualHosts == null)
276 {
277 return;
278 }
279 else
280 {
281 List<String> currentVirtualHosts = null;
282 if (_vhosts != null)
283 {
284 currentVirtualHosts = new ArrayList<String>(Arrays.asList(_vhosts));
285 }
286 else
287 {
288 currentVirtualHosts = new ArrayList<String>();
289 }
290
291 for (int i = 0; i < virtualHosts.length; i++)
292 {
293 String normVhost = normalizeHostname(virtualHosts[i]);
294 if (!currentVirtualHosts.contains(normVhost))
295 {
296 currentVirtualHosts.add(normVhost);
297 }
298 }
299 _vhosts = currentVirtualHosts.toArray(new String[0]);
300 }
301 }
302
303
304
305
306
307
308
309
310
311 public void removeVirtualHosts(String[] virtualHosts)
312 {
313 if (virtualHosts == null)
314 {
315 return;
316 }
317 else if ( _vhosts == null || _vhosts.length == 0)
318 {
319 return;
320 }
321 else
322 {
323 List<String> existingVirtualHosts = new ArrayList<String>(Arrays.asList(_vhosts));
324
325 for (int i = 0; i < virtualHosts.length; i++)
326 {
327 String toRemoveVirtualHost = normalizeHostname(virtualHosts[i]);
328 if (existingVirtualHosts.contains(toRemoveVirtualHost))
329 {
330 existingVirtualHosts.remove(toRemoveVirtualHost);
331 }
332 }
333
334 if (existingVirtualHosts.isEmpty())
335 {
336 _vhosts = null;
337 }
338 else
339 {
340 _vhosts = existingVirtualHosts.toArray(new String[0]);
341 }
342 }
343 }
344
345
346
347
348
349
350
351
352
353
354 public String[] getVirtualHosts()
355 {
356 return _vhosts;
357 }
358
359
360
361
362
363 public String[] getConnectorNames()
364 {
365 if (_connectors == null || _connectors.size() == 0)
366 return null;
367
368 return _connectors.toArray(new String[_connectors.size()]);
369 }
370
371
372
373
374
375
376
377
378
379
380 public void setConnectorNames(String[] connectors)
381 {
382 if (connectors == null || connectors.length == 0)
383 _connectors = null;
384 else
385 _connectors = new HashSet<String>(Arrays.asList(connectors));
386 }
387
388
389
390
391
392 public Object getAttribute(String name)
393 {
394 return _attributes.getAttribute(name);
395 }
396
397
398
399
400
401 @SuppressWarnings("unchecked")
402 public Enumeration getAttributeNames()
403 {
404 return AttributesMap.getAttributeNamesCopy(_attributes);
405 }
406
407
408
409
410
411 public Attributes getAttributes()
412 {
413 return _attributes;
414 }
415
416
417
418
419
420 public ClassLoader getClassLoader()
421 {
422 return _classLoader;
423 }
424
425
426
427
428
429
430
431 public String getClassPath()
432 {
433 if (_classLoader == null || !(_classLoader instanceof URLClassLoader))
434 return null;
435 URLClassLoader loader = (URLClassLoader)_classLoader;
436 URL[] urls = loader.getURLs();
437 StringBuilder classpath = new StringBuilder();
438 for (int i = 0; i < urls.length; i++)
439 {
440 try
441 {
442 Resource resource = newResource(urls[i]);
443 File file = resource.getFile();
444 if (file != null && file.exists())
445 {
446 if (classpath.length() > 0)
447 classpath.append(File.pathSeparatorChar);
448 classpath.append(file.getAbsolutePath());
449 }
450 }
451 catch (IOException e)
452 {
453 LOG.debug(e);
454 }
455 }
456 if (classpath.length() == 0)
457 return null;
458 return classpath.toString();
459 }
460
461
462
463
464
465 public String getContextPath()
466 {
467 return _contextPath;
468 }
469
470
471
472
473
474 public String getInitParameter(String name)
475 {
476 return _initParams.get(name);
477 }
478
479
480
481
482 public String setInitParameter(String name, String value)
483 {
484 return _initParams.put(name,value);
485 }
486
487
488
489
490
491 @SuppressWarnings("rawtypes")
492 public Enumeration getInitParameterNames()
493 {
494 return Collections.enumeration(_initParams.keySet());
495 }
496
497
498
499
500
501 public Map<String, String> getInitParams()
502 {
503 return _initParams;
504 }
505
506
507
508
509
510 public String getDisplayName()
511 {
512 return _displayName;
513 }
514
515
516 public EventListener[] getEventListeners()
517 {
518 return _eventListeners;
519 }
520
521
522
523
524
525
526
527
528
529
530
531
532 public void setEventListeners(EventListener[] eventListeners)
533 {
534 _contextListeners = null;
535 _contextAttributeListeners = null;
536 _requestListeners = null;
537 _requestAttributeListeners = null;
538
539 _eventListeners = eventListeners;
540
541 for (int i = 0; eventListeners != null && i < eventListeners.length; i++)
542 {
543 EventListener listener = _eventListeners[i];
544
545 if (listener instanceof ServletContextListener)
546 _contextListeners = LazyList.add(_contextListeners,listener);
547
548 if (listener instanceof ServletContextAttributeListener)
549 _contextAttributeListeners = LazyList.add(_contextAttributeListeners,listener);
550
551 if (listener instanceof ServletRequestListener)
552 _requestListeners = LazyList.add(_requestListeners,listener);
553
554 if (listener instanceof ServletRequestAttributeListener)
555 _requestAttributeListeners = LazyList.add(_requestAttributeListeners,listener);
556 }
557 }
558
559
560
561
562
563
564
565
566
567
568 public void addEventListener(EventListener listener)
569 {
570 setEventListeners((EventListener[])LazyList.addToArray(getEventListeners(),listener,EventListener.class));
571 }
572
573
574
575
576
577 public boolean isShutdown()
578 {
579 synchronized (this)
580 {
581 return !_shutdown;
582 }
583 }
584
585
586
587
588
589
590
591
592
593 public void setShutdown(boolean shutdown)
594 {
595 synchronized (this)
596 {
597 _shutdown = shutdown;
598 _availability = isRunning()?(_shutdown?__SHUTDOWN:_available?__AVAILABLE:__UNAVAILABLE):__STOPPED;
599 }
600 }
601
602
603
604
605
606 public boolean isAvailable()
607 {
608 synchronized (this)
609 {
610 return _available;
611 }
612 }
613
614
615
616
617
618 public void setAvailable(boolean available)
619 {
620 synchronized (this)
621 {
622 _available = available;
623 _availability = isRunning()?(_shutdown?__SHUTDOWN:_available?__AVAILABLE:__UNAVAILABLE):__STOPPED;
624 }
625 }
626
627
628 public Logger getLogger()
629 {
630 return _logger;
631 }
632
633
634 public void setLogger(Logger logger)
635 {
636 _logger = logger;
637 }
638
639
640
641
642
643 @Override
644 protected void doStart() throws Exception
645 {
646 _availability = __STOPPED;
647
648 if (_contextPath == null)
649 throw new IllegalStateException("Null contextPath");
650
651 _logger = Log.getLogger(getDisplayName() == null?getContextPath():getDisplayName());
652 ClassLoader old_classloader = null;
653 Thread current_thread = null;
654 Context old_context = null;
655
656 try
657 {
658
659 if (_classLoader != null)
660 {
661 current_thread = Thread.currentThread();
662 old_classloader = current_thread.getContextClassLoader();
663 current_thread.setContextClassLoader(_classLoader);
664 }
665
666 if (_mimeTypes == null)
667 _mimeTypes = new MimeTypes();
668
669 old_context = __context.get();
670 __context.set(_scontext);
671
672
673 startContext();
674
675 synchronized(this)
676 {
677 _availability = _shutdown?__SHUTDOWN:_available?__AVAILABLE:__UNAVAILABLE;
678 }
679 }
680 finally
681 {
682 __context.set(old_context);
683
684
685 if (_classLoader != null)
686 {
687 current_thread.setContextClassLoader(old_classloader);
688 }
689
690 }
691 }
692
693
694
695
696
697
698
699
700 protected void startContext() throws Exception
701 {
702 String managedAttributes = _initParams.get(MANAGED_ATTRIBUTES);
703 if (managedAttributes != null)
704 {
705 _managedAttributes = new HashMap<String, Object>();
706 String[] attributes = managedAttributes.split(",");
707 for (String attribute : attributes)
708 _managedAttributes.put(attribute,null);
709
710 Enumeration e = _scontext.getAttributeNames();
711 while (e.hasMoreElements())
712 {
713 String name = (String)e.nextElement();
714 Object value = _scontext.getAttribute(name);
715 checkManagedAttribute(name,value);
716 }
717 }
718
719 super.doStart();
720
721 if (_errorHandler != null)
722 _errorHandler.start();
723
724
725 if (_contextListeners != null)
726 {
727 ServletContextEvent event = new ServletContextEvent(_scontext);
728 for (int i = 0; i < LazyList.size(_contextListeners); i++)
729 {
730 ((ServletContextListener)LazyList.get(_contextListeners,i)).contextInitialized(event);
731 }
732 }
733
734 LOG.info("started {}",this);
735 }
736
737
738
739
740
741 @Override
742 protected void doStop() throws Exception
743 {
744 _availability = __STOPPED;
745
746 ClassLoader old_classloader = null;
747 Thread current_thread = null;
748
749 Context old_context = __context.get();
750 __context.set(_scontext);
751 try
752 {
753
754 if (_classLoader != null)
755 {
756 current_thread = Thread.currentThread();
757 old_classloader = current_thread.getContextClassLoader();
758 current_thread.setContextClassLoader(_classLoader);
759 }
760
761 super.doStop();
762
763
764 if (_contextListeners != null)
765 {
766 ServletContextEvent event = new ServletContextEvent(_scontext);
767 for (int i = LazyList.size(_contextListeners); i-- > 0;)
768 {
769 ((ServletContextListener)LazyList.get(_contextListeners,i)).contextDestroyed(event);
770 }
771 }
772
773 if (_errorHandler != null)
774 _errorHandler.stop();
775
776 Enumeration e = _scontext.getAttributeNames();
777 while (e.hasMoreElements())
778 {
779 String name = (String)e.nextElement();
780 checkManagedAttribute(name,null);
781 }
782 }
783 finally
784 {
785 LOG.info("stopped {}",this);
786 __context.set(old_context);
787
788 if (_classLoader != null)
789 current_thread.setContextClassLoader(old_classloader);
790 }
791
792 _contextAttributes.clearAttributes();
793 }
794
795
796
797
798
799 public boolean checkContext(final String target, final Request baseRequest, final HttpServletResponse response) throws IOException, ServletException
800 {
801 DispatcherType dispatch = baseRequest.getDispatcherType();
802
803 switch (_availability)
804 {
805 case __STOPPED:
806 case __SHUTDOWN:
807 return false;
808 case __UNAVAILABLE:
809 baseRequest.setHandled(true);
810 response.sendError(HttpServletResponse.SC_SERVICE_UNAVAILABLE);
811 return false;
812 default:
813 if ((DispatcherType.REQUEST.equals(dispatch) && baseRequest.isHandled()))
814 return false;
815 }
816
817
818 if (_vhosts != null && _vhosts.length > 0)
819 {
820 String vhost = normalizeHostname(baseRequest.getServerName());
821
822 boolean match = false;
823
824
825 for (int i = 0; !match && i < _vhosts.length; i++)
826 {
827 String contextVhost = _vhosts[i];
828 if (contextVhost == null)
829 continue;
830 if (contextVhost.startsWith("*."))
831 {
832
833 match = contextVhost.regionMatches(true,2,vhost,vhost.indexOf(".") + 1,contextVhost.length() - 2);
834 }
835 else
836 match = contextVhost.equalsIgnoreCase(vhost);
837 }
838 if (!match)
839 return false;
840 }
841
842
843 if (_connectors != null && _connectors.size() > 0)
844 {
845 String connector = AbstractHttpConnection.getCurrentConnection().getConnector().getName();
846 if (connector == null || !_connectors.contains(connector))
847 return false;
848 }
849
850
851 if (_contextPath.length() > 1)
852 {
853
854 if (!target.startsWith(_contextPath))
855 return false;
856 if (target.length() > _contextPath.length() && target.charAt(_contextPath.length()) != '/')
857 return false;
858
859
860 if (!_allowNullPathInfo && _contextPath.length() == target.length())
861 {
862
863 baseRequest.setHandled(true);
864 if (baseRequest.getQueryString() != null)
865 response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH) + "?" + baseRequest.getQueryString());
866 else
867 response.sendRedirect(URIUtil.addPaths(baseRequest.getRequestURI(),URIUtil.SLASH));
868 return false;
869 }
870 }
871
872 return true;
873 }
874
875
876
877
878
879
880 @Override
881 public void doScope(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
882 {
883 if (LOG.isDebugEnabled())
884 LOG.debug("scope {}|{}|{} @ {}",baseRequest.getContextPath(),baseRequest.getServletPath(),baseRequest.getPathInfo(),this);
885
886 Context old_context = null;
887 String old_context_path = null;
888 String old_servlet_path = null;
889 String old_path_info = null;
890 ClassLoader old_classloader = null;
891 Thread current_thread = null;
892 String pathInfo = target;
893
894 DispatcherType dispatch = baseRequest.getDispatcherType();
895
896 old_context = baseRequest.getContext();
897
898
899 if (old_context != _scontext)
900 {
901
902 if (DispatcherType.REQUEST.equals(dispatch) || DispatcherType.ASYNC.equals(dispatch))
903 {
904 if (_compactPath)
905 target = URIUtil.compactPath(target);
906 if (!checkContext(target,baseRequest,response))
907 return;
908
909 if (target.length() > _contextPath.length())
910 {
911 if (_contextPath.length() > 1)
912 target = target.substring(_contextPath.length());
913 pathInfo = target;
914 }
915 else if (_contextPath.length() == 1)
916 {
917 target = URIUtil.SLASH;
918 pathInfo = URIUtil.SLASH;
919 }
920 else
921 {
922 target = URIUtil.SLASH;
923 pathInfo = null;
924 }
925 }
926
927
928 if (_classLoader != null)
929 {
930 current_thread = Thread.currentThread();
931 old_classloader = current_thread.getContextClassLoader();
932 current_thread.setContextClassLoader(_classLoader);
933 }
934 }
935
936 try
937 {
938 old_context_path = baseRequest.getContextPath();
939 old_servlet_path = baseRequest.getServletPath();
940 old_path_info = baseRequest.getPathInfo();
941
942
943 baseRequest.setContext(_scontext);
944 __context.set(_scontext);
945 if (!DispatcherType.INCLUDE.equals(dispatch) && target.startsWith("/"))
946 {
947 if (_contextPath.length() == 1)
948 baseRequest.setContextPath("");
949 else
950 baseRequest.setContextPath(_contextPath);
951 baseRequest.setServletPath(null);
952 baseRequest.setPathInfo(pathInfo);
953 }
954
955 if (LOG.isDebugEnabled())
956 LOG.debug("context={}|{}|{} @ {}",baseRequest.getContextPath(),baseRequest.getServletPath(), baseRequest.getPathInfo(),this);
957
958
959 if (never())
960 nextScope(target,baseRequest,request,response);
961 else if (_nextScope != null)
962 _nextScope.doScope(target,baseRequest,request,response);
963 else if (_outerScope != null)
964 _outerScope.doHandle(target,baseRequest,request,response);
965 else
966 doHandle(target,baseRequest,request,response);
967
968 }
969 finally
970 {
971 if (old_context != _scontext)
972 {
973
974 if (_classLoader != null)
975 {
976 current_thread.setContextClassLoader(old_classloader);
977 }
978
979
980 baseRequest.setContext(old_context);
981 __context.set(old_context);
982 baseRequest.setContextPath(old_context_path);
983 baseRequest.setServletPath(old_servlet_path);
984 baseRequest.setPathInfo(old_path_info);
985 }
986 }
987 }
988
989
990
991
992
993
994 @Override
995 public void doHandle(String target, Request baseRequest, HttpServletRequest request, HttpServletResponse response) throws IOException, ServletException
996 {
997 final DispatcherType dispatch = baseRequest.getDispatcherType();
998 final boolean new_context = baseRequest.takeNewContext();
999 try
1000 {
1001 if (new_context)
1002 {
1003
1004 if (_requestAttributeListeners != null)
1005 {
1006 final int s = LazyList.size(_requestAttributeListeners);
1007 for (int i = 0; i < s; i++)
1008 baseRequest.addEventListener(((EventListener)LazyList.get(_requestAttributeListeners,i)));
1009 }
1010
1011 if (_requestListeners != null)
1012 {
1013 final int s = LazyList.size(_requestListeners);
1014 final ServletRequestEvent sre = new ServletRequestEvent(_scontext,request);
1015 for (int i = 0; i < s; i++)
1016 ((ServletRequestListener)LazyList.get(_requestListeners,i)).requestInitialized(sre);
1017 }
1018 }
1019
1020 if (DispatcherType.REQUEST.equals(dispatch) && isProtectedTarget(target))
1021 throw new HttpException(HttpServletResponse.SC_NOT_FOUND);
1022
1023
1024
1025 if (never())
1026 nextHandle(target,baseRequest,request,response);
1027 else if (_nextScope != null && _nextScope == _handler)
1028 _nextScope.doHandle(target,baseRequest,request,response);
1029 else if (_handler != null)
1030 _handler.handle(target,baseRequest,request,response);
1031
1032 }
1033 catch (HttpException e)
1034 {
1035 LOG.debug(e);
1036 baseRequest.setHandled(true);
1037 response.sendError(e.getStatus(),e.getReason());
1038 }
1039 finally
1040 {
1041
1042 if (new_context)
1043 {
1044 if (_requestListeners != null)
1045 {
1046 final ServletRequestEvent sre = new ServletRequestEvent(_scontext,request);
1047 for (int i = LazyList.size(_requestListeners); i-- > 0;)
1048 ((ServletRequestListener)LazyList.get(_requestListeners,i)).requestDestroyed(sre);
1049 }
1050
1051 if (_requestAttributeListeners != null)
1052 {
1053 for (int i = LazyList.size(_requestAttributeListeners); i-- > 0;)
1054 baseRequest.removeEventListener(((EventListener)LazyList.get(_requestAttributeListeners,i)));
1055 }
1056 }
1057 }
1058 }
1059
1060
1061
1062
1063
1064 public void handle(Runnable runnable)
1065 {
1066 ClassLoader old_classloader = null;
1067 Thread current_thread = null;
1068 Context old_context = null;
1069 try
1070 {
1071 old_context = __context.get();
1072 __context.set(_scontext);
1073
1074
1075 if (_classLoader != null)
1076 {
1077 current_thread = Thread.currentThread();
1078 old_classloader = current_thread.getContextClassLoader();
1079 current_thread.setContextClassLoader(_classLoader);
1080 }
1081
1082 runnable.run();
1083 }
1084 finally
1085 {
1086 __context.set(old_context);
1087 if (old_classloader != null)
1088 {
1089 current_thread.setContextClassLoader(old_classloader);
1090 }
1091 }
1092 }
1093
1094
1095
1096
1097
1098
1099
1100 protected boolean isProtectedTarget(String target)
1101 {
1102 return false;
1103 }
1104
1105
1106
1107
1108
1109 public void removeAttribute(String name)
1110 {
1111 checkManagedAttribute(name,null);
1112 _attributes.removeAttribute(name);
1113 }
1114
1115
1116
1117
1118
1119
1120
1121
1122 public void setAttribute(String name, Object value)
1123 {
1124 checkManagedAttribute(name,value);
1125 _attributes.setAttribute(name,value);
1126 }
1127
1128
1129
1130
1131
1132
1133 public void setAttributes(Attributes attributes)
1134 {
1135 _attributes.clearAttributes();
1136 _attributes.addAll(attributes);
1137 Enumeration e = _attributes.getAttributeNames();
1138 while (e.hasMoreElements())
1139 {
1140 String name = (String)e.nextElement();
1141 checkManagedAttribute(name,attributes.getAttribute(name));
1142 }
1143 }
1144
1145
1146 public void clearAttributes()
1147 {
1148 Enumeration e = _attributes.getAttributeNames();
1149 while (e.hasMoreElements())
1150 {
1151 String name = (String)e.nextElement();
1152 checkManagedAttribute(name,null);
1153 }
1154 _attributes.clearAttributes();
1155 }
1156
1157
1158 public void checkManagedAttribute(String name, Object value)
1159 {
1160 if (_managedAttributes != null && _managedAttributes.containsKey(name))
1161 {
1162 setManagedAttribute(name,value);
1163 }
1164 }
1165
1166
1167 public void setManagedAttribute(String name, Object value)
1168 {
1169 Object old = _managedAttributes.put(name,value);
1170 getServer().getContainer().update(this,old,value,name,true);
1171 }
1172
1173
1174
1175
1176
1177
1178 public void setClassLoader(ClassLoader classLoader)
1179 {
1180 _classLoader = classLoader;
1181 }
1182
1183
1184
1185
1186
1187
1188 public void setContextPath(String contextPath)
1189 {
1190 if (contextPath != null && contextPath.length() > 1 && contextPath.endsWith("/"))
1191 throw new IllegalArgumentException("ends with /");
1192 _contextPath = contextPath;
1193
1194 if (getServer() != null && (getServer().isStarting() || getServer().isStarted()))
1195 {
1196 Handler[] contextCollections = getServer().getChildHandlersByClass(ContextHandlerCollection.class);
1197 for (int h = 0; contextCollections != null && h < contextCollections.length; h++)
1198 ((ContextHandlerCollection)contextCollections[h]).mapContexts();
1199 }
1200 }
1201
1202
1203
1204
1205
1206
1207 public void setDisplayName(String servletContextName)
1208 {
1209 _displayName = servletContextName;
1210 }
1211
1212
1213
1214
1215
1216 public Resource getBaseResource()
1217 {
1218 if (_baseResource == null)
1219 return null;
1220 return _baseResource;
1221 }
1222
1223
1224
1225
1226
1227 public String getResourceBase()
1228 {
1229 if (_baseResource == null)
1230 return null;
1231 return _baseResource.toString();
1232 }
1233
1234
1235
1236
1237
1238
1239 public void setBaseResource(Resource base)
1240 {
1241 _baseResource = base;
1242 }
1243
1244
1245
1246
1247
1248
1249 public void setResourceBase(String resourceBase)
1250 {
1251 try
1252 {
1253 setBaseResource(newResource(resourceBase));
1254 }
1255 catch (Exception e)
1256 {
1257 LOG.warn(e.toString());
1258 LOG.debug(e);
1259 throw new IllegalArgumentException(resourceBase);
1260 }
1261 }
1262
1263
1264
1265
1266
1267 public boolean isAliases()
1268 {
1269 return _aliases;
1270 }
1271
1272
1273
1274
1275
1276
1277 public void setAliases(boolean aliases)
1278 {
1279 _aliases = aliases;
1280 }
1281
1282
1283
1284
1285
1286 public MimeTypes getMimeTypes()
1287 {
1288 if (_mimeTypes == null)
1289 _mimeTypes = new MimeTypes();
1290 return _mimeTypes;
1291 }
1292
1293
1294
1295
1296
1297
1298 public void setMimeTypes(MimeTypes mimeTypes)
1299 {
1300 _mimeTypes = mimeTypes;
1301 }
1302
1303
1304
1305
1306 public void setWelcomeFiles(String[] files)
1307 {
1308 _welcomeFiles = files;
1309 }
1310
1311
1312
1313
1314
1315
1316
1317 public String[] getWelcomeFiles()
1318 {
1319 return _welcomeFiles;
1320 }
1321
1322
1323
1324
1325
1326 public ErrorHandler getErrorHandler()
1327 {
1328 return _errorHandler;
1329 }
1330
1331
1332
1333
1334
1335
1336 public void setErrorHandler(ErrorHandler errorHandler)
1337 {
1338 if (errorHandler != null)
1339 errorHandler.setServer(getServer());
1340 if (getServer() != null)
1341 getServer().getContainer().update(this,_errorHandler,errorHandler,"errorHandler",true);
1342 _errorHandler = errorHandler;
1343 }
1344
1345
1346 public int getMaxFormContentSize()
1347 {
1348 return _maxFormContentSize;
1349 }
1350
1351
1352 public void setMaxFormContentSize(int maxSize)
1353 {
1354 _maxFormContentSize = maxSize;
1355 }
1356
1357
1358
1359
1360
1361 public boolean isCompactPath()
1362 {
1363 return _compactPath;
1364 }
1365
1366
1367
1368
1369
1370
1371 public void setCompactPath(boolean compactPath)
1372 {
1373 _compactPath = compactPath;
1374 }
1375
1376
1377 @Override
1378 public String toString()
1379 {
1380 String[] vhosts = getVirtualHosts();
1381
1382 StringBuilder b = new StringBuilder();
1383
1384 String p = getClass().getPackage().getName();
1385 if (p != null && p.length() > 0)
1386 {
1387 String[] ss = p.split("\\.");
1388 for (String s : ss)
1389 b.append(s.charAt(0)).append('.');
1390 }
1391
1392 b.append(getClass().getSimpleName());
1393 b.append('{').append(getContextPath()).append(',').append(getBaseResource());
1394
1395 if (vhosts != null && vhosts.length > 0)
1396 b.append(',').append(vhosts[0]);
1397 b.append('}');
1398
1399 return b.toString();
1400 }
1401
1402
1403 public synchronized Class<?> loadClass(String className) throws ClassNotFoundException
1404 {
1405 if (className == null)
1406 return null;
1407
1408 if (_classLoader == null)
1409 return Loader.loadClass(this.getClass(),className);
1410
1411 return _classLoader.loadClass(className);
1412 }
1413
1414
1415 public void addLocaleEncoding(String locale, String encoding)
1416 {
1417 if (_localeEncodingMap == null)
1418 _localeEncodingMap = new HashMap<String, String>();
1419 _localeEncodingMap.put(locale,encoding);
1420 }
1421
1422 public String getLocaleEncoding(String locale)
1423 {
1424 if (_localeEncodingMap == null)
1425 return null;
1426 String encoding = _localeEncodingMap.get(locale);
1427 return encoding;
1428 }
1429
1430
1431
1432
1433
1434
1435
1436
1437
1438
1439 public String getLocaleEncoding(Locale locale)
1440 {
1441 if (_localeEncodingMap == null)
1442 return null;
1443 String encoding = _localeEncodingMap.get(locale.toString());
1444 if (encoding == null)
1445 encoding = _localeEncodingMap.get(locale.getLanguage());
1446 return encoding;
1447 }
1448
1449
1450
1451
1452 public Resource getResource(String path) throws MalformedURLException
1453 {
1454 if (path == null || !path.startsWith(URIUtil.SLASH))
1455 throw new MalformedURLException(path);
1456
1457 if (_baseResource == null)
1458 return null;
1459
1460 try
1461 {
1462 path = URIUtil.canonicalPath(path);
1463 Resource resource = _baseResource.addPath(path);
1464
1465 if (!_aliases && resource.getAlias() != null)
1466 {
1467 if (resource.exists())
1468 LOG.warn("Aliased resource: " + resource + "~=" + resource.getAlias());
1469 else if (path.endsWith("/") && resource.getAlias().toString().endsWith(path))
1470 return resource;
1471 else if (LOG.isDebugEnabled())
1472 LOG.debug("Aliased resource: " + resource + "~=" + resource.getAlias());
1473 return null;
1474 }
1475
1476 return resource;
1477 }
1478 catch (Exception e)
1479 {
1480 LOG.ignore(e);
1481 }
1482
1483 return null;
1484 }
1485
1486
1487
1488
1489
1490 public Resource newResource(URL url) throws IOException
1491 {
1492 return Resource.newResource(url);
1493 }
1494
1495
1496
1497
1498
1499
1500
1501
1502
1503
1504
1505 public Resource newResource(String urlOrPath) throws IOException
1506 {
1507 return Resource.newResource(urlOrPath);
1508 }
1509
1510
1511
1512
1513 public Set<String> getResourcePaths(String path)
1514 {
1515 try
1516 {
1517 path = URIUtil.canonicalPath(path);
1518 Resource resource = getResource(path);
1519
1520 if (resource != null && resource.exists())
1521 {
1522 if (!path.endsWith(URIUtil.SLASH))
1523 path = path + URIUtil.SLASH;
1524
1525 String[] l = resource.list();
1526 if (l != null)
1527 {
1528 HashSet<String> set = new HashSet<String>();
1529 for (int i = 0; i < l.length; i++)
1530 set.add(path + l[i]);
1531 return set;
1532 }
1533 }
1534 }
1535 catch (Exception e)
1536 {
1537 LOG.ignore(e);
1538 }
1539 return Collections.emptySet();
1540 }
1541
1542
1543 private String normalizeHostname(String host)
1544 {
1545 if (host == null)
1546 return null;
1547
1548 if (host.endsWith("."))
1549 return host.substring(0,host.length() - 1);
1550
1551 return host;
1552 }
1553
1554
1555
1556
1557
1558
1559
1560
1561
1562
1563 public class Context implements ServletContext
1564 {
1565
1566 protected Context()
1567 {
1568 }
1569
1570
1571 public ContextHandler getContextHandler()
1572 {
1573
1574 return ContextHandler.this;
1575 }
1576
1577
1578
1579
1580
1581 public ServletContext getContext(String uripath)
1582 {
1583 List<ContextHandler> contexts = new ArrayList<ContextHandler>();
1584 Handler[] handlers = getServer().getChildHandlersByClass(ContextHandler.class);
1585 String matched_path = null;
1586
1587 for (Handler handler : handlers)
1588 {
1589 if (handler == null)
1590 continue;
1591 ContextHandler ch = (ContextHandler)handler;
1592 String context_path = ch.getContextPath();
1593
1594 if (uripath.equals(context_path) || (uripath.startsWith(context_path) && uripath.charAt(context_path.length()) == '/')
1595 || "/".equals(context_path))
1596 {
1597
1598 if (getVirtualHosts() != null && getVirtualHosts().length > 0)
1599 {
1600 if (ch.getVirtualHosts() != null && ch.getVirtualHosts().length > 0)
1601 {
1602 for (String h1 : getVirtualHosts())
1603 for (String h2 : ch.getVirtualHosts())
1604 if (h1.equals(h2))
1605 {
1606 if (matched_path == null || context_path.length() > matched_path.length())
1607 {
1608 contexts.clear();
1609 matched_path = context_path;
1610 }
1611
1612 if (matched_path.equals(context_path))
1613 contexts.add(ch);
1614 }
1615 }
1616 }
1617 else
1618 {
1619 if (matched_path == null || context_path.length() > matched_path.length())
1620 {
1621 contexts.clear();
1622 matched_path = context_path;
1623 }
1624
1625 if (matched_path.equals(context_path))
1626 contexts.add(ch);
1627 }
1628 }
1629 }
1630
1631 if (contexts.size() > 0)
1632 return contexts.get(0)._scontext;
1633
1634
1635 matched_path = null;
1636 for (Handler handler : handlers)
1637 {
1638 if (handler == null)
1639 continue;
1640 ContextHandler ch = (ContextHandler)handler;
1641 String context_path = ch.getContextPath();
1642
1643 if (uripath.equals(context_path) || (uripath.startsWith(context_path) && uripath.charAt(context_path.length()) == '/')
1644 || "/".equals(context_path))
1645 {
1646 if (matched_path == null || context_path.length() > matched_path.length())
1647 {
1648 contexts.clear();
1649 matched_path = context_path;
1650 }
1651
1652 if (matched_path.equals(context_path))
1653 contexts.add(ch);
1654 }
1655 }
1656
1657 if (contexts.size() > 0)
1658 return contexts.get(0)._scontext;
1659 return null;
1660 }
1661
1662
1663
1664
1665
1666 public int getMajorVersion()
1667 {
1668 return 2;
1669 }
1670
1671
1672
1673
1674
1675 public String getMimeType(String file)
1676 {
1677 if (_mimeTypes == null)
1678 return null;
1679 Buffer mime = _mimeTypes.getMimeByExtension(file);
1680 if (mime != null)
1681 return mime.toString();
1682 return null;
1683 }
1684
1685
1686
1687
1688
1689 public int getMinorVersion()
1690 {
1691 return 5;
1692 }
1693
1694
1695
1696
1697
1698 public RequestDispatcher getNamedDispatcher(String name)
1699 {
1700 return null;
1701 }
1702
1703
1704
1705
1706
1707 public RequestDispatcher getRequestDispatcher(String uriInContext)
1708 {
1709 if (uriInContext == null)
1710 return null;
1711
1712 if (!uriInContext.startsWith("/"))
1713 return null;
1714
1715 try
1716 {
1717 String query = null;
1718 int q = 0;
1719 if ((q = uriInContext.indexOf('?')) > 0)
1720 {
1721 query = uriInContext.substring(q + 1);
1722 uriInContext = uriInContext.substring(0,q);
1723 }
1724 if ((q = uriInContext.indexOf(';')) > 0)
1725 uriInContext = uriInContext.substring(0,q);
1726
1727 String pathInContext = URIUtil.canonicalPath(URIUtil.decodePath(uriInContext));
1728 String uri = URIUtil.addPaths(getContextPath(),uriInContext);
1729 ContextHandler context = ContextHandler.this;
1730 return new Dispatcher(context,uri,pathInContext,query);
1731 }
1732 catch (Exception e)
1733 {
1734 LOG.ignore(e);
1735 }
1736 return null;
1737 }
1738
1739
1740
1741
1742
1743 public String getRealPath(String path)
1744 {
1745 if (path == null)
1746 return null;
1747 if (path.length() == 0)
1748 path = URIUtil.SLASH;
1749 else if (path.charAt(0) != '/')
1750 path = URIUtil.SLASH + path;
1751
1752 try
1753 {
1754 Resource resource = ContextHandler.this.getResource(path);
1755 if (resource != null)
1756 {
1757 File file = resource.getFile();
1758 if (file != null)
1759 return file.getCanonicalPath();
1760 }
1761 }
1762 catch (Exception e)
1763 {
1764 LOG.ignore(e);
1765 }
1766
1767 return null;
1768 }
1769
1770
1771 public URL getResource(String path) throws MalformedURLException
1772 {
1773 Resource resource = ContextHandler.this.getResource(path);
1774 if (resource != null && resource.exists())
1775 return resource.getURL();
1776 return null;
1777 }
1778
1779
1780
1781
1782
1783 public InputStream getResourceAsStream(String path)
1784 {
1785 try
1786 {
1787 URL url = getResource(path);
1788 if (url == null)
1789 return null;
1790 return url.openStream();
1791 }
1792 catch (Exception e)
1793 {
1794 LOG.ignore(e);
1795 return null;
1796 }
1797 }
1798
1799
1800
1801
1802
1803 public Set getResourcePaths(String path)
1804 {
1805 return ContextHandler.this.getResourcePaths(path);
1806 }
1807
1808
1809
1810
1811
1812 public String getServerInfo()
1813 {
1814 return "jetty/" + Server.getVersion();
1815 }
1816
1817
1818
1819
1820
1821 public Servlet getServlet(String name) throws ServletException
1822 {
1823 return null;
1824 }
1825
1826
1827
1828
1829
1830 @SuppressWarnings("unchecked")
1831 public Enumeration getServletNames()
1832 {
1833 return Collections.enumeration(Collections.EMPTY_LIST);
1834 }
1835
1836
1837
1838
1839
1840 @SuppressWarnings("unchecked")
1841 public Enumeration getServlets()
1842 {
1843 return Collections.enumeration(Collections.EMPTY_LIST);
1844 }
1845
1846
1847
1848
1849
1850 public void log(Exception exception, String msg)
1851 {
1852 _logger.warn(msg,exception);
1853 }
1854
1855
1856
1857
1858
1859 public void log(String msg)
1860 {
1861 _logger.info(msg);
1862 }
1863
1864
1865
1866
1867
1868 public void log(String message, Throwable throwable)
1869 {
1870 _logger.warn(message,throwable);
1871 }
1872
1873
1874
1875
1876
1877 public String getInitParameter(String name)
1878 {
1879 return ContextHandler.this.getInitParameter(name);
1880 }
1881
1882
1883
1884
1885
1886 @SuppressWarnings("unchecked")
1887 public Enumeration getInitParameterNames()
1888 {
1889 return ContextHandler.this.getInitParameterNames();
1890 }
1891
1892
1893
1894
1895
1896 public synchronized Object getAttribute(String name)
1897 {
1898 Object o = ContextHandler.this.getAttribute(name);
1899 if (o == null && _contextAttributes != null)
1900 o = _contextAttributes.getAttribute(name);
1901 return o;
1902 }
1903
1904
1905
1906
1907
1908 @SuppressWarnings("unchecked")
1909 public synchronized Enumeration getAttributeNames()
1910 {
1911 HashSet<String> set = new HashSet<String>();
1912 if (_contextAttributes != null)
1913 {
1914 Enumeration<String> e = _contextAttributes.getAttributeNames();
1915 while (e.hasMoreElements())
1916 set.add(e.nextElement());
1917 }
1918 Enumeration<String> e = _attributes.getAttributeNames();
1919 while (e.hasMoreElements())
1920 set.add(e.nextElement());
1921
1922 return Collections.enumeration(set);
1923 }
1924
1925
1926
1927
1928
1929 public synchronized void setAttribute(String name, Object value)
1930 {
1931 checkManagedAttribute(name,value);
1932 Object old_value = _contextAttributes.getAttribute(name);
1933
1934 if (value == null)
1935 _contextAttributes.removeAttribute(name);
1936 else
1937 _contextAttributes.setAttribute(name,value);
1938
1939 if (_contextAttributeListeners != null)
1940 {
1941 ServletContextAttributeEvent event = new ServletContextAttributeEvent(_scontext,name,old_value == null?value:old_value);
1942
1943 for (int i = 0; i < LazyList.size(_contextAttributeListeners); i++)
1944 {
1945 ServletContextAttributeListener l = (ServletContextAttributeListener)LazyList.get(_contextAttributeListeners,i);
1946
1947 if (old_value == null)
1948 l.attributeAdded(event);
1949 else if (value == null)
1950 l.attributeRemoved(event);
1951 else
1952 l.attributeReplaced(event);
1953 }
1954 }
1955 }
1956
1957
1958
1959
1960
1961 public synchronized void removeAttribute(String name)
1962 {
1963 checkManagedAttribute(name,null);
1964
1965 if (_contextAttributes == null)
1966 {
1967
1968 _attributes.removeAttribute(name);
1969 return;
1970 }
1971
1972 Object old_value = _contextAttributes.getAttribute(name);
1973 _contextAttributes.removeAttribute(name);
1974 if (old_value != null)
1975 {
1976 if (_contextAttributeListeners != null)
1977 {
1978 ServletContextAttributeEvent event = new ServletContextAttributeEvent(_scontext,name,old_value);
1979
1980 for (int i = 0; i < LazyList.size(_contextAttributeListeners); i++)
1981 ((ServletContextAttributeListener)LazyList.get(_contextAttributeListeners,i)).attributeRemoved(event);
1982 }
1983 }
1984 }
1985
1986
1987
1988
1989
1990 public String getServletContextName()
1991 {
1992 String name = ContextHandler.this.getDisplayName();
1993 if (name == null)
1994 name = ContextHandler.this.getContextPath();
1995 return name;
1996 }
1997
1998
1999 public String getContextPath()
2000 {
2001 if ((_contextPath != null) && _contextPath.equals(URIUtil.SLASH))
2002 return "";
2003
2004 return _contextPath;
2005 }
2006
2007
2008 @Override
2009 public String toString()
2010 {
2011 return "ServletContext@" + ContextHandler.this.toString();
2012 }
2013
2014
2015 public boolean setInitParameter(String name, String value)
2016 {
2017 if (ContextHandler.this.getInitParameter(name) != null)
2018 return false;
2019 ContextHandler.this.getInitParams().put(name,value);
2020 return true;
2021 }
2022
2023 }
2024
2025 private static class CLDump implements Dumpable
2026 {
2027 final ClassLoader _loader;
2028
2029 CLDump(ClassLoader loader)
2030 {
2031 _loader = loader;
2032 }
2033
2034 public String dump()
2035 {
2036 return AggregateLifeCycle.dump(this);
2037 }
2038
2039 public void dump(Appendable out, String indent) throws IOException
2040 {
2041 out.append(String.valueOf(_loader)).append("\n");
2042
2043 if (_loader != null)
2044 {
2045 Object parent = _loader.getParent();
2046 if (parent != null)
2047 {
2048 if (!(parent instanceof Dumpable))
2049 parent = new CLDump((ClassLoader)parent);
2050
2051 if (_loader instanceof URLClassLoader)
2052 AggregateLifeCycle.dump(out,indent,TypeUtil.asList(((URLClassLoader)_loader).getURLs()),Collections.singleton(parent));
2053 else
2054 AggregateLifeCycle.dump(out,indent,Collections.singleton(parent));
2055 }
2056 }
2057 }
2058
2059 }
2060 }