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