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