1
17 package org.apache.catalina.core;
18
19 import java.io.InputStream;
20 import java.lang.reflect.InvocationTargetException;
21 import java.net.MalformedURLException;
22 import java.net.URL;
23 import java.nio.charset.StandardCharsets;
24 import java.util.ArrayList;
25 import java.util.Collections;
26 import java.util.EnumSet;
27 import java.util.Enumeration;
28 import java.util.EventListener;
29 import java.util.HashMap;
30 import java.util.HashSet;
31 import java.util.List;
32 import java.util.Map;
33 import java.util.Set;
34 import java.util.concurrent.ConcurrentHashMap;
35
36 import javax.naming.NamingException;
37 import javax.servlet.Filter;
38 import javax.servlet.FilterRegistration;
39 import javax.servlet.RequestDispatcher;
40 import javax.servlet.Servlet;
41 import javax.servlet.ServletContext;
42 import javax.servlet.ServletContextAttributeEvent;
43 import javax.servlet.ServletContextAttributeListener;
44 import javax.servlet.ServletContextListener;
45 import javax.servlet.ServletException;
46 import javax.servlet.ServletRegistration;
47 import javax.servlet.ServletRegistration.Dynamic;
48 import javax.servlet.ServletRequestAttributeListener;
49 import javax.servlet.ServletRequestListener;
50 import javax.servlet.ServletSecurityElement;
51 import javax.servlet.SessionCookieConfig;
52 import javax.servlet.SessionTrackingMode;
53 import javax.servlet.annotation.ServletSecurity;
54 import javax.servlet.descriptor.JspConfigDescriptor;
55 import javax.servlet.http.HttpServletMapping;
56 import javax.servlet.http.HttpSessionAttributeListener;
57 import javax.servlet.http.HttpSessionIdListener;
58 import javax.servlet.http.HttpSessionListener;
59
60 import org.apache.catalina.Container;
61 import org.apache.catalina.Context;
62 import org.apache.catalina.Engine;
63 import org.apache.catalina.Globals;
64 import org.apache.catalina.LifecycleState;
65 import org.apache.catalina.Service;
66 import org.apache.catalina.WebResourceRoot;
67 import org.apache.catalina.Wrapper;
68 import org.apache.catalina.connector.Connector;
69 import org.apache.catalina.mapper.MappingData;
70 import org.apache.catalina.util.Introspection;
71 import org.apache.catalina.util.ServerInfo;
72 import org.apache.catalina.util.URLEncoder;
73 import org.apache.tomcat.util.ExceptionUtils;
74 import org.apache.tomcat.util.buf.CharChunk;
75 import org.apache.tomcat.util.buf.MessageBytes;
76 import org.apache.tomcat.util.buf.UDecoder;
77 import org.apache.tomcat.util.descriptor.web.FilterDef;
78 import org.apache.tomcat.util.http.RequestUtil;
79 import org.apache.tomcat.util.res.StringManager;
80
81
82
90 public class ApplicationContext implements ServletContext {
91
92 protected static final boolean STRICT_SERVLET_COMPLIANCE;
93
94 protected static final boolean GET_RESOURCE_REQUIRE_SLASH;
95
96
97 static {
98 STRICT_SERVLET_COMPLIANCE = Globals.STRICT_SERVLET_COMPLIANCE;
99
100 String requireSlash = System.getProperty(
101 "org.apache.catalina.core.ApplicationContext.GET_RESOURCE_REQUIRE_SLASH");
102 if (requireSlash == null) {
103 GET_RESOURCE_REQUIRE_SLASH = STRICT_SERVLET_COMPLIANCE;
104 } else {
105 GET_RESOURCE_REQUIRE_SLASH = Boolean.parseBoolean(requireSlash);
106 }
107 }
108
109
110
111
112
118 public ApplicationContext(StandardContext context) {
119 super();
120 this.context = context;
121 this.service = ((Engine) context.getParent().getParent()).getService();
122 this.sessionCookieConfig = new ApplicationSessionCookieConfig(context);
123
124
125 populateSessionTrackingModes();
126 }
127
128
129
130
131
132
135 protected Map<String,Object> attributes = new ConcurrentHashMap<>();
136
137
138
141 private final Map<String,String> readOnlyAttributes = new ConcurrentHashMap<>();
142
143
144
147 private final StandardContext context;
148
149
150
153 private final Service service;
154
155
156
159 private static final List<String> emptyString = Collections.emptyList();
160
161
162
165 private static final List<Servlet> emptyServlet = Collections.emptyList();
166
167
168
171 private final ServletContext facade = new ApplicationContextFacade(this);
172
173
174
177 private final Map<String,String> parameters = new ConcurrentHashMap<>();
178
179
180
183 private static final StringManager sm = StringManager.getManager(Constants.Package);
184
185
186
189 private final ThreadLocal<DispatchData> dispatchData = new ThreadLocal<>();
190
191
192
195 private SessionCookieConfig sessionCookieConfig;
196
197
200 private Set<SessionTrackingMode> sessionTrackingModes = null;
201 private Set<SessionTrackingMode> defaultSessionTrackingModes = null;
202 private Set<SessionTrackingMode> supportedSessionTrackingModes = null;
203
204
209 private boolean newServletContextListenerAllowed = true;
210
211
212
213
214 @Override
215 public Object getAttribute(String name) {
216 return attributes.get(name);
217 }
218
219
220 @Override
221 public Enumeration<String> getAttributeNames() {
222 Set<String> names = new HashSet<>();
223 names.addAll(attributes.keySet());
224 return Collections.enumeration(names);
225 }
226
227
228 @Override
229 public ServletContext getContext(String uri) {
230
231
232 if (uri == null || !uri.startsWith("/")) {
233 return null;
234 }
235
236 Context child = null;
237 try {
238
239 Container host = context.getParent();
240 child = (Context) host.findChild(uri);
241
242
243 if (child != null && !child.getState().isAvailable()) {
244 child = null;
245 }
246
247
248 if (child == null) {
249 int i = uri.indexOf("##");
250 if (i > -1) {
251 uri = uri.substring(0, i);
252 }
253
254
255
256
257 MessageBytes hostMB = MessageBytes.newInstance();
258 hostMB.setString(host.getName());
259
260 MessageBytes pathMB = MessageBytes.newInstance();
261 pathMB.setString(uri);
262
263 MappingData mappingData = new MappingData();
264 service.getMapper().map(hostMB, pathMB, null, mappingData);
265 child = mappingData.context;
266 }
267 } catch (Throwable t) {
268 ExceptionUtils.handleThrowable(t);
269 return null;
270 }
271
272 if (child == null) {
273 return null;
274 }
275
276 if (context.getCrossContext()) {
277
278 return child.getServletContext();
279 } else if (child == context) {
280
281 return context.getServletContext();
282 } else {
283
284 return null;
285 }
286 }
287
288
289 @Override
290 public String getContextPath() {
291 return context.getPath();
292 }
293
294
295 @Override
296 public String getInitParameter(final String name) {
297
298
299 if (Globals.JASPER_XML_VALIDATION_TLD_INIT_PARAM.equals(name) &&
300 context.getTldValidation()) {
301 return "true";
302 }
303 if (Globals.JASPER_XML_BLOCK_EXTERNAL_INIT_PARAM.equals(name)) {
304 if (!context.getXmlBlockExternal()) {
305
306 return "false";
307 }
308 }
309 return parameters.get(name);
310 }
311
312
313 @Override
314 public Enumeration<String> getInitParameterNames() {
315 Set<String> names = new HashSet<>();
316 names.addAll(parameters.keySet());
317
318
319 if (context.getTldValidation()) {
320 names.add(Globals.JASPER_XML_VALIDATION_TLD_INIT_PARAM);
321 }
322 if (!context.getXmlBlockExternal()) {
323 names.add(Globals.JASPER_XML_BLOCK_EXTERNAL_INIT_PARAM);
324 }
325 return Collections.enumeration(names);
326 }
327
328
329 @Override
330 public int getMajorVersion() {
331 return Constants.MAJOR_VERSION;
332 }
333
334
335 @Override
336 public int getMinorVersion() {
337 return Constants.MINOR_VERSION;
338 }
339
340
341
347 @Override
348 public String getMimeType(String file) {
349
350 if (file == null)
351 return null;
352 int period = file.lastIndexOf('.');
353 if (period < 0)
354 return null;
355 String extension = file.substring(period + 1);
356 if (extension.length() < 1)
357 return null;
358 return context.findMimeMapping(extension);
359
360 }
361
362
363
369 @Override
370 public RequestDispatcher getNamedDispatcher(String name) {
371
372
373 if (name == null)
374 return null;
375
376
377 Wrapper wrapper = (Wrapper) context.findChild(name);
378 if (wrapper == null)
379 return null;
380
381 return new ApplicationDispatcher(wrapper, null, null, null, null, null, name);
382
383 }
384
385
386 @Override
387 public String getRealPath(String path) {
388 String validatedPath = validateResourcePath(path, true);
389 return context.getRealPath(validatedPath);
390 }
391
392
393 @Override
394 public RequestDispatcher getRequestDispatcher(final String path) {
395
396
397 if (path == null) {
398 return null;
399 }
400 if (!path.startsWith("/")) {
401 throw new IllegalArgumentException(
402 sm.getString("applicationContext.requestDispatcher.iae", path));
403 }
404
405
406
407 String uri;
408 String queryString;
409 int pos = path.indexOf('?');
410 if (pos >= 0) {
411 uri = path.substring(0, pos);
412 queryString = path.substring(pos + 1);
413 } else {
414 uri = path;
415 queryString = null;
416 }
417
418
419 String uriNoParams = stripPathParams(uri);
420
421
422 String normalizedUri = RequestUtil.normalize(uriNoParams);
423 if (normalizedUri == null) {
424 return null;
425 }
426
427
428
429 if (getContext().getDispatchersUseEncodedPaths()) {
430
431 String decodedUri = UDecoder.URLDecode(normalizedUri);
432
433
434 normalizedUri = RequestUtil.normalize(decodedUri);
435 if (!decodedUri.equals(normalizedUri)) {
436 getContext().getLogger().warn(
437 sm.getString("applicationContext.illegalDispatchPath", path),
438 new IllegalArgumentException());
439 return null;
440 }
441
442
443 uri = URLEncoder.DEFAULT.encode(getContextPath(), StandardCharsets.UTF_8) + uri;
444 } else {
445
446
447
448
449 uri = URLEncoder.DEFAULT.encode(getContextPath() + uri, StandardCharsets.UTF_8);
450 }
451
452
453 DispatchData dd = dispatchData.get();
454 if (dd == null) {
455 dd = new DispatchData();
456 dispatchData.set(dd);
457 }
458
459 MessageBytes uriMB = dd.uriMB;
460 uriMB.recycle();
461
462
463 MappingData mappingData = dd.mappingData;
464
465 try {
466
467 CharChunk uriCC = uriMB.getCharChunk();
468 try {
469 uriCC.append(context.getPath());
470 uriCC.append(normalizedUri);
471 service.getMapper().map(context, uriMB, mappingData);
472 if (mappingData.wrapper == null) {
473 return null;
474 }
475 } catch (Exception e) {
476
477 log(sm.getString("applicationContext.mapping.error"), e);
478 return null;
479 }
480
481 Wrapper wrapper = mappingData.wrapper;
482 String wrapperPath = mappingData.wrapperPath.toString();
483 String pathInfo = mappingData.pathInfo.toString();
484 HttpServletMapping mapping = new ApplicationMapping(mappingData).getHttpServletMapping();
485
486
487 return new ApplicationDispatcher(wrapper, uri, wrapperPath, pathInfo,
488 queryString, mapping, null);
489 } finally {
490
491
492
493 mappingData.recycle();
494 }
495 }
496
497
498
499 static String stripPathParams(String input) {
500
501 if (input.indexOf(';') < 0) {
502 return input;
503 }
504
505 StringBuilder sb = new StringBuilder(input.length());
506 int pos = 0;
507 int limit = input.length();
508 while (pos < limit) {
509 int nextSemiColon = input.indexOf(';', pos);
510 if (nextSemiColon < 0) {
511 nextSemiColon = limit;
512 }
513 sb.append(input.substring(pos, nextSemiColon));
514 int followingSlash = input.indexOf('/', nextSemiColon);
515 if (followingSlash < 0) {
516 pos = limit;
517 } else {
518 pos = followingSlash;
519 }
520 }
521
522 return sb.toString();
523 }
524
525
526 @Override
527 public URL getResource(String path) throws MalformedURLException {
528
529 String validatedPath = validateResourcePath(path, false);
530
531 if (validatedPath == null) {
532 throw new MalformedURLException(
533 sm.getString("applicationContext.requestDispatcher.iae", path));
534 }
535
536 WebResourceRoot resources = context.getResources();
537 if (resources != null) {
538 return resources.getResource(validatedPath).getURL();
539 }
540
541 return null;
542 }
543
544
545 @Override
546 public InputStream getResourceAsStream(String path) {
547
548 String validatedPath = validateResourcePath(path, false);
549
550 if (validatedPath == null) {
551 return null;
552 }
553
554 WebResourceRoot resources = context.getResources();
555 if (resources != null) {
556 return resources.getResource(validatedPath).getInputStream();
557 }
558
559 return null;
560 }
561
562
563
567 private String validateResourcePath(String path, boolean allowEmptyPath) {
568 if (path == null) {
569 return null;
570 }
571
572 if (path.length() == 0 && allowEmptyPath) {
573 return path;
574 }
575
576 if (!path.startsWith("/")) {
577 if (GET_RESOURCE_REQUIRE_SLASH) {
578 return null;
579 } else {
580 return "/" + path;
581 }
582 }
583
584 return path;
585 }
586
587
588 @Override
589 public Set<String> getResourcePaths(String path) {
590
591
592 if (path == null) {
593 return null;
594 }
595 if (!path.startsWith("/")) {
596 throw new IllegalArgumentException (sm.getString("applicationContext.resourcePaths.iae", path));
597 }
598
599 WebResourceRoot resources = context.getResources();
600 if (resources != null) {
601 return resources.listWebAppPaths(path);
602 }
603
604 return null;
605 }
606
607
608 @Override
609 public String getServerInfo() {
610 return ServerInfo.getServerInfo();
611 }
612
613
614 @Override
615 @Deprecated
616 public Servlet getServlet(String name) {
617 return null;
618 }
619
620
621 @Override
622 public String getServletContextName() {
623 return context.getDisplayName();
624 }
625
626
627 @Override
628 @Deprecated
629 public Enumeration<String> getServletNames() {
630 return Collections.enumeration(emptyString);
631 }
632
633
634 @Override
635 @Deprecated
636 public Enumeration<Servlet> getServlets() {
637 return Collections.enumeration(emptyServlet);
638 }
639
640
641 @Override
642 public void log(String message) {
643 context.getLogger().info(message);
644 }
645
646
647 @Override
648 @Deprecated
649 public void log(Exception exception, String message) {
650 context.getLogger().error(message, exception);
651 }
652
653
654 @Override
655 public void log(String message, Throwable throwable) {
656 context.getLogger().error(message, throwable);
657 }
658
659
660 @Override
661 public void removeAttribute(String name) {
662
663 Object value = null;
664
665
666
667 if (readOnlyAttributes.containsKey(name)){
668 return;
669 }
670 value = attributes.remove(name);
671 if (value == null) {
672 return;
673 }
674
675
676 Object listeners[] = context.getApplicationEventListeners();
677 if ((listeners == null) || (listeners.length == 0)) {
678 return;
679 }
680 ServletContextAttributeEvent event = new ServletContextAttributeEvent(
681 context.getServletContext(), name, value);
682 for (Object obj : listeners) {
683 if (!(obj instanceof ServletContextAttributeListener)) {
684 continue;
685 }
686 ServletContextAttributeListener listener = (ServletContextAttributeListener) obj;
687 try {
688 context.fireContainerEvent("beforeContextAttributeRemoved", listener);
689 listener.attributeRemoved(event);
690 context.fireContainerEvent("afterContextAttributeRemoved", listener);
691 } catch (Throwable t) {
692 ExceptionUtils.handleThrowable(t);
693 context.fireContainerEvent("afterContextAttributeRemoved", listener);
694
695 log(sm.getString("applicationContext.attributeEvent"), t);
696 }
697 }
698 }
699
700
701 @Override
702 public void setAttribute(String name, Object value) {
703
704 if (name == null) {
705 throw new NullPointerException(sm.getString("applicationContext.setAttribute.namenull"));
706 }
707
708
709 if (value == null) {
710 removeAttribute(name);
711 return;
712 }
713
714
715
716 if (readOnlyAttributes.containsKey(name)) {
717 return;
718 }
719
720 Object oldValue = attributes.put(name, value);
721 boolean replaced = oldValue != null;
722
723
724 Object listeners[] = context.getApplicationEventListeners();
725 if ((listeners == null) || (listeners.length == 0)) {
726 return;
727 }
728 ServletContextAttributeEvent event = null;
729 if (replaced) {
730 event = new ServletContextAttributeEvent(context.getServletContext(), name, oldValue);
731 } else {
732 event = new ServletContextAttributeEvent(context.getServletContext(), name, value);
733 }
734
735 for (Object obj : listeners) {
736 if (!(obj instanceof ServletContextAttributeListener)) {
737 continue;
738 }
739 ServletContextAttributeListener listener = (ServletContextAttributeListener) obj;
740 try {
741 if (replaced) {
742 context.fireContainerEvent("beforeContextAttributeReplaced", listener);
743 listener.attributeReplaced(event);
744 context.fireContainerEvent("afterContextAttributeReplaced", listener);
745 } else {
746 context.fireContainerEvent("beforeContextAttributeAdded", listener);
747 listener.attributeAdded(event);
748 context.fireContainerEvent("afterContextAttributeAdded", listener);
749 }
750 } catch (Throwable t) {
751 ExceptionUtils.handleThrowable(t);
752 if (replaced) {
753 context.fireContainerEvent("afterContextAttributeReplaced", listener);
754 } else {
755 context.fireContainerEvent("afterContextAttributeAdded", listener);
756 }
757
758 log(sm.getString("applicationContext.attributeEvent"), t);
759 }
760 }
761 }
762
763
764 @Override
765 public FilterRegistration.Dynamic addFilter(String filterName, String className) {
766 return addFilter(filterName, className, null);
767 }
768
769
770 @Override
771 public FilterRegistration.Dynamic addFilter(String filterName, Filter filter) {
772 return addFilter(filterName, null, filter);
773 }
774
775
776 @Override
777 public FilterRegistration.Dynamic addFilter(String filterName,
778 Class<? extends Filter> filterClass) {
779 return addFilter(filterName, filterClass.getName(), null);
780 }
781
782
783 private FilterRegistration.Dynamic addFilter(String filterName,
784 String filterClass, Filter filter) throws IllegalStateException {
785
786 if (filterName == null || filterName.equals("")) {
787 throw new IllegalArgumentException(sm.getString(
788 "applicationContext.invalidFilterName", filterName));
789 }
790
791 if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
792
793 throw new IllegalStateException(
794 sm.getString("applicationContext.addFilter.ise",
795 getContextPath()));
796 }
797
798 FilterDef filterDef = context.findFilterDef(filterName);
799
800
801
802 if (filterDef == null) {
803 filterDef = new FilterDef();
804 filterDef.setFilterName(filterName);
805 context.addFilterDef(filterDef);
806 } else {
807 if (filterDef.getFilterName() != null &&
808 filterDef.getFilterClass() != null) {
809 return null;
810 }
811 }
812
813 if (filter == null) {
814 filterDef.setFilterClass(filterClass);
815 } else {
816 filterDef.setFilterClass(filter.getClass().getName());
817 filterDef.setFilter(filter);
818 }
819
820 return new ApplicationFilterRegistration(filterDef, context);
821 }
822
823
824 @Override
825 public <T extends Filter> T createFilter(Class<T> c) throws ServletException {
826 try {
827 @SuppressWarnings("unchecked")
828 T filter = (T) context.getInstanceManager().newInstance(c.getName());
829 return filter;
830 } catch (InvocationTargetException e) {
831 ExceptionUtils.handleThrowable(e.getCause());
832 throw new ServletException(e);
833 } catch (ReflectiveOperationException | NamingException e) {
834 throw new ServletException(e);
835 }
836 }
837
838
839 @Override
840 public FilterRegistration getFilterRegistration(String filterName) {
841 FilterDef filterDef = context.findFilterDef(filterName);
842 if (filterDef == null) {
843 return null;
844 }
845 return new ApplicationFilterRegistration(filterDef, context);
846 }
847
848
849 @Override
850 public ServletRegistration.Dynamic addServlet(String servletName, String className) {
851 return addServlet(servletName, className, null, null);
852 }
853
854
855 @Override
856 public ServletRegistration.Dynamic addServlet(String servletName, Servlet servlet) {
857 return addServlet(servletName, null, servlet, null);
858 }
859
860
861 @Override
862 public ServletRegistration.Dynamic addServlet(String servletName,
863 Class<? extends Servlet> servletClass) {
864 return addServlet(servletName, servletClass.getName(), null, null);
865 }
866
867
868 @Override
869 public Dynamic addJspFile(String jspName, String jspFile) {
870
871
872 if (jspFile == null || !jspFile.startsWith("/")) {
873 throw new IllegalArgumentException(
874 sm.getString("applicationContext.addJspFile.iae", jspFile));
875 }
876
877 String jspServletClassName = null;
878 Map<String,String> jspFileInitParams = new HashMap<>();
879
880 Wrapper jspServlet = (Wrapper) context.findChild("jsp");
881
882 if (jspServlet == null) {
883
884
885 jspServletClassName = Constants.JSP_SERVLET_CLASS;
886 } else {
887
888
889 jspServletClassName = jspServlet.getServletClass();
890
891 String[] params = jspServlet.findInitParameters();
892 for (String param : params) {
893 jspFileInitParams.put(param, jspServlet.findInitParameter(param));
894 }
895 }
896
897
898 jspFileInitParams.put("jspFile", jspFile);
899
900 return addServlet(jspName, jspServletClassName, null, jspFileInitParams);
901 }
902
903
904 private ServletRegistration.Dynamic addServlet(String servletName, String servletClass,
905 Servlet servlet, Map<String,String> initParams) throws IllegalStateException {
906
907 if (servletName == null || servletName.equals("")) {
908 throw new IllegalArgumentException(sm.getString(
909 "applicationContext.invalidServletName", servletName));
910 }
911
912 if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
913
914 throw new IllegalStateException(
915 sm.getString("applicationContext.addServlet.ise",
916 getContextPath()));
917 }
918
919 Wrapper wrapper = (Wrapper) context.findChild(servletName);
920
921
922
923 if (wrapper == null) {
924 wrapper = context.createWrapper();
925 wrapper.setName(servletName);
926 context.addChild(wrapper);
927 } else {
928 if (wrapper.getName() != null &&
929 wrapper.getServletClass() != null) {
930 if (wrapper.isOverridable()) {
931 wrapper.setOverridable(false);
932 } else {
933 return null;
934 }
935 }
936 }
937
938 ServletSecurity annotation = null;
939 if (servlet == null) {
940 wrapper.setServletClass(servletClass);
941 Class<?> clazz = Introspection.loadClass(context, servletClass);
942 if (clazz != null) {
943 annotation = clazz.getAnnotation(ServletSecurity.class);
944 }
945 } else {
946 wrapper.setServletClass(servlet.getClass().getName());
947 wrapper.setServlet(servlet);
948 if (context.wasCreatedDynamicServlet(servlet)) {
949 annotation = servlet.getClass().getAnnotation(ServletSecurity.class);
950 }
951 }
952
953 if (initParams != null) {
954 for (Map.Entry<String, String> initParam: initParams.entrySet()) {
955 wrapper.addInitParameter(initParam.getKey(), initParam.getValue());
956 }
957 }
958
959 ServletRegistration.Dynamic registration =
960 new ApplicationServletRegistration(wrapper, context);
961 if (annotation != null) {
962 registration.setServletSecurity(new ServletSecurityElement(annotation));
963 }
964 return registration;
965 }
966
967
968 @Override
969 public <T extends Servlet> T createServlet(Class<T> c) throws ServletException {
970 try {
971 @SuppressWarnings("unchecked")
972 T servlet = (T) context.getInstanceManager().newInstance(c.getName());
973 context.dynamicServletCreated(servlet);
974 return servlet;
975 } catch (InvocationTargetException e) {
976 ExceptionUtils.handleThrowable(e.getCause());
977 throw new ServletException(e);
978 } catch (ReflectiveOperationException | NamingException e) {
979 throw new ServletException(e);
980 }
981 }
982
983
984 @Override
985 public ServletRegistration getServletRegistration(String servletName) {
986 Wrapper wrapper = (Wrapper) context.findChild(servletName);
987 if (wrapper == null) {
988 return null;
989 }
990
991 return new ApplicationServletRegistration(wrapper, context);
992 }
993
994
995 @Override
996 public Set<SessionTrackingMode> getDefaultSessionTrackingModes() {
997 return defaultSessionTrackingModes;
998 }
999
1000
1001 private void populateSessionTrackingModes() {
1002
1003 defaultSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
1004 supportedSessionTrackingModes = EnumSet.of(SessionTrackingMode.URL);
1005
1006 if (context.getCookies()) {
1007 defaultSessionTrackingModes.add(SessionTrackingMode.COOKIE);
1008 supportedSessionTrackingModes.add(SessionTrackingMode.COOKIE);
1009 }
1010
1011
1012
1013 Connector[] connectors = service.findConnectors();
1014
1015 for (Connector connector : connectors) {
1016 if (Boolean.TRUE.equals(connector.getProperty("SSLEnabled"))) {
1017 supportedSessionTrackingModes.add(SessionTrackingMode.SSL);
1018 break;
1019 }
1020 }
1021 }
1022
1023
1024 @Override
1025 public Set<SessionTrackingMode> getEffectiveSessionTrackingModes() {
1026 if (sessionTrackingModes != null) {
1027 return sessionTrackingModes;
1028 }
1029 return defaultSessionTrackingModes;
1030 }
1031
1032
1033 @Override
1034 public SessionCookieConfig getSessionCookieConfig() {
1035 return sessionCookieConfig;
1036 }
1037
1038
1039 @Override
1040 public void setSessionTrackingModes(Set<SessionTrackingMode> sessionTrackingModes) {
1041
1042 if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
1043 throw new IllegalStateException(
1044 sm.getString("applicationContext.setSessionTracking.ise",
1045 getContextPath()));
1046 }
1047
1048
1049 for (SessionTrackingMode sessionTrackingMode : sessionTrackingModes) {
1050 if (!supportedSessionTrackingModes.contains(sessionTrackingMode)) {
1051 throw new IllegalArgumentException(sm.getString(
1052 "applicationContext.setSessionTracking.iae.invalid",
1053 sessionTrackingMode.toString(), getContextPath()));
1054 }
1055 }
1056
1057
1058 if (sessionTrackingModes.contains(SessionTrackingMode.SSL)) {
1059 if (sessionTrackingModes.size() > 1) {
1060 throw new IllegalArgumentException(sm.getString(
1061 "applicationContext.setSessionTracking.iae.ssl",
1062 getContextPath()));
1063 }
1064 }
1065
1066 this.sessionTrackingModes = sessionTrackingModes;
1067 }
1068
1069
1070 @Override
1071 public boolean setInitParameter(String name, String value) {
1072
1073 if (name == null) {
1074 throw new NullPointerException(sm.getString("applicationContext.setAttribute.namenull"));
1075 }
1076 if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
1077 throw new IllegalStateException(
1078 sm.getString("applicationContext.setInitParam.ise",
1079 getContextPath()));
1080 }
1081
1082 return parameters.putIfAbsent(name, value) == null;
1083 }
1084
1085
1086 @Override
1087 public void addListener(Class<? extends EventListener> listenerClass) {
1088 EventListener listener;
1089 try {
1090 listener = createListener(listenerClass);
1091 } catch (ServletException e) {
1092 throw new IllegalArgumentException(sm.getString(
1093 "applicationContext.addListener.iae.init",
1094 listenerClass.getName()), e);
1095 }
1096 addListener(listener);
1097 }
1098
1099
1100 @Override
1101 public void addListener(String className) {
1102
1103 try {
1104 if (context.getInstanceManager() != null) {
1105 Object obj = context.getInstanceManager().newInstance(className);
1106
1107 if (!(obj instanceof EventListener)) {
1108 throw new IllegalArgumentException(sm.getString(
1109 "applicationContext.addListener.iae.wrongType",
1110 className));
1111 }
1112
1113 EventListener listener = (EventListener) obj;
1114 addListener(listener);
1115 }
1116 } catch (InvocationTargetException e) {
1117 ExceptionUtils.handleThrowable(e.getCause());
1118 throw new IllegalArgumentException(sm.getString(
1119 "applicationContext.addListener.iae.cnfe", className),
1120 e);
1121 } catch (ReflectiveOperationException| NamingException e) {
1122 throw new IllegalArgumentException(sm.getString(
1123 "applicationContext.addListener.iae.cnfe", className),
1124 e);
1125 }
1126
1127 }
1128
1129
1130 @Override
1131 public <T extends EventListener> void addListener(T t) {
1132 if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
1133 throw new IllegalStateException(
1134 sm.getString("applicationContext.addListener.ise",
1135 getContextPath()));
1136 }
1137
1138 boolean match = false;
1139 if (t instanceof ServletContextAttributeListener ||
1140 t instanceof ServletRequestListener ||
1141 t instanceof ServletRequestAttributeListener ||
1142 t instanceof HttpSessionIdListener ||
1143 t instanceof HttpSessionAttributeListener) {
1144 context.addApplicationEventListener(t);
1145 match = true;
1146 }
1147
1148 if (t instanceof HttpSessionListener ||
1149 (t instanceof ServletContextListener && newServletContextListenerAllowed)) {
1150
1151
1152 context.addApplicationLifecycleListener(t);
1153 match = true;
1154 }
1155
1156 if (match) return;
1157
1158 if (t instanceof ServletContextListener) {
1159 throw new IllegalArgumentException(sm.getString(
1160 "applicationContext.addListener.iae.sclNotAllowed",
1161 t.getClass().getName()));
1162 } else {
1163 throw new IllegalArgumentException(sm.getString(
1164 "applicationContext.addListener.iae.wrongType",
1165 t.getClass().getName()));
1166 }
1167 }
1168
1169
1170 @Override
1171 public <T extends EventListener> T createListener(Class<T> c)
1172 throws ServletException {
1173 try {
1174 @SuppressWarnings("unchecked")
1175 T listener = (T) context.getInstanceManager().newInstance(c);
1176 if (listener instanceof ServletContextListener ||
1177 listener instanceof ServletContextAttributeListener ||
1178 listener instanceof ServletRequestListener ||
1179 listener instanceof ServletRequestAttributeListener ||
1180 listener instanceof HttpSessionListener ||
1181 listener instanceof HttpSessionIdListener ||
1182 listener instanceof HttpSessionAttributeListener) {
1183 return listener;
1184 }
1185 throw new IllegalArgumentException(sm.getString(
1186 "applicationContext.addListener.iae.wrongType",
1187 listener.getClass().getName()));
1188 } catch (InvocationTargetException e) {
1189 ExceptionUtils.handleThrowable(e.getCause());
1190 throw new ServletException(e);
1191 } catch (ReflectiveOperationException | NamingException e) {
1192 throw new ServletException(e);
1193 }
1194 }
1195
1196
1197 @Override
1198 public void declareRoles(String... roleNames) {
1199
1200 if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
1201
1202 throw new IllegalStateException(
1203 sm.getString("applicationContext.addRole.ise",
1204 getContextPath()));
1205 }
1206
1207 if (roleNames == null) {
1208 throw new IllegalArgumentException(
1209 sm.getString("applicationContext.roles.iae",
1210 getContextPath()));
1211 }
1212
1213 for (String role : roleNames) {
1214 if (role == null || "".equals(role)) {
1215 throw new IllegalArgumentException(
1216 sm.getString("applicationContext.role.iae",
1217 getContextPath()));
1218 }
1219 context.addSecurityRole(role);
1220 }
1221 }
1222
1223
1224 @Override
1225 public ClassLoader getClassLoader() {
1226 ClassLoader result = context.getLoader().getClassLoader();
1227 if (Globals.IS_SECURITY_ENABLED) {
1228 ClassLoader tccl = Thread.currentThread().getContextClassLoader();
1229 ClassLoader parent = result;
1230 while (parent != null) {
1231 if (parent == tccl) {
1232 break;
1233 }
1234 parent = parent.getParent();
1235 }
1236 if (parent == null) {
1237 System.getSecurityManager().checkPermission(
1238 new RuntimePermission("getClassLoader"));
1239 }
1240 }
1241
1242 return result;
1243 }
1244
1245
1246 @Override
1247 public int getEffectiveMajorVersion() {
1248 return context.getEffectiveMajorVersion();
1249 }
1250
1251
1252 @Override
1253 public int getEffectiveMinorVersion() {
1254 return context.getEffectiveMinorVersion();
1255 }
1256
1257
1258 @Override
1259 public Map<String, ? extends FilterRegistration> getFilterRegistrations() {
1260 Map<String, ApplicationFilterRegistration> result = new HashMap<>();
1261
1262 FilterDef[] filterDefs = context.findFilterDefs();
1263 for (FilterDef filterDef : filterDefs) {
1264 result.put(filterDef.getFilterName(),
1265 new ApplicationFilterRegistration(filterDef, context));
1266 }
1267
1268 return result;
1269 }
1270
1271
1272 @Override
1273 public JspConfigDescriptor getJspConfigDescriptor() {
1274 return context.getJspConfigDescriptor();
1275 }
1276
1277
1278 @Override
1279 public Map<String, ? extends ServletRegistration> getServletRegistrations() {
1280 Map<String, ApplicationServletRegistration> result = new HashMap<>();
1281
1282 Container[] wrappers = context.findChildren();
1283 for (Container wrapper : wrappers) {
1284 result.put(wrapper.getName(),
1285 new ApplicationServletRegistration(
1286 (Wrapper) wrapper, context));
1287 }
1288
1289 return result;
1290 }
1291
1292
1293 @Override
1294 public String getVirtualServerName() {
1295
1296 Container host = context.getParent();
1297 Container engine = host.getParent();
1298 return engine.getName() + "/" + host.getName();
1299 }
1300
1301
1302 @Override
1303 public int getSessionTimeout() {
1304 return context.getSessionTimeout();
1305 }
1306
1307
1308 @Override
1309 public void setSessionTimeout(int sessionTimeout) {
1310 if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
1311 throw new IllegalStateException(
1312 sm.getString("applicationContext.setSessionTimeout.ise",
1313 getContextPath()));
1314 }
1315
1316 context.setSessionTimeout(sessionTimeout);
1317 }
1318
1319
1320 @Override
1321 public String getRequestCharacterEncoding() {
1322 return context.getRequestCharacterEncoding();
1323 }
1324
1325
1326 @Override
1327 public void setRequestCharacterEncoding(String encoding) {
1328 if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
1329 throw new IllegalStateException(
1330 sm.getString("applicationContext.setRequestEncoding.ise",
1331 getContextPath()));
1332 }
1333
1334 context.setRequestCharacterEncoding(encoding);
1335 }
1336
1337
1338 @Override
1339 public String getResponseCharacterEncoding() {
1340 return context.getResponseCharacterEncoding();
1341 }
1342
1343
1344 @Override
1345 public void setResponseCharacterEncoding(String encoding) {
1346 if (!context.getState().equals(LifecycleState.STARTING_PREP)) {
1347 throw new IllegalStateException(
1348 sm.getString("applicationContext.setResponseEncoding.ise",
1349 getContextPath()));
1350 }
1351
1352 context.setResponseCharacterEncoding(encoding);
1353 }
1354
1355
1356
1357 protected StandardContext getContext() {
1358 return this.context;
1359 }
1360
1361
1364 protected void clearAttributes() {
1365
1366
1367 List<String> list = new ArrayList<>();
1368 for (String s : attributes.keySet()) {
1369 list.add(s);
1370 }
1371
1372
1373
1374 for (String key : list) {
1375 removeAttribute(key);
1376 }
1377
1378 }
1379
1380
1381
1384 protected ServletContext getFacade() {
1385 return this.facade;
1386 }
1387
1388
1389
1392 void setAttributeReadOnly(String name) {
1393
1394 if (attributes.containsKey(name))
1395 readOnlyAttributes.put(name, name);
1396
1397 }
1398
1399
1400 protected void setNewServletContextListenerAllowed(boolean allowed) {
1401 this.newServletContextListenerAllowed = allowed;
1402 }
1403
1404
1408 private static final class DispatchData {
1409
1410 public MessageBytes uriMB;
1411 public MappingData mappingData;
1412
1413 public DispatchData() {
1414 uriMB = MessageBytes.newInstance();
1415 CharChunk uriCC = uriMB.getCharChunk();
1416 uriCC.setLimit(-1);
1417 mappingData = new MappingData();
1418 }
1419 }
1420 }
1421