| /* |
| * Licensed to the Apache Software Foundation (ASF) under one or more |
| * contributor license agreements. See the NOTICE file distributed with |
| * this work for additional information regarding copyright ownership. |
| * The ASF licenses this file to You under the Apache License, Version 2.0 |
| * (the "License"); you may not use this file except in compliance with |
| * the License. You may obtain a copy of the License at |
| * |
| * http://www.apache.org/licenses/LICENSE-2.0 |
| * |
| * Unless required by applicable law or agreed to in writing, software |
| * distributed under the License is distributed on an "AS IS" BASIS, |
| * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
| * See the License for the specific language governing permissions and |
| * limitations under the License. |
| */ |
| package org.apache.tomcat.util.descriptor.web; |
| |
| import java.io.File; |
| import java.io.IOException; |
| import java.io.StringReader; |
| import java.util.HashSet; |
| import java.util.Map; |
| import java.util.Set; |
| |
| import org.junit.Assert; |
| import org.junit.Test; |
| |
| import org.apache.tomcat.util.descriptor.DigesterFactory; |
| import org.apache.tomcat.util.descriptor.XmlErrorHandler; |
| import org.apache.tomcat.util.descriptor.XmlIdentifiers; |
| import org.apache.tomcat.util.digester.Digester; |
| import org.xml.sax.InputSource; |
| import org.xml.sax.SAXException; |
| |
| /** |
| * Test case for {@link WebXml}. |
| */ |
| public class TestWebXml { |
| |
| @Test |
| public void testParseVersion() { |
| |
| WebXml webxml = new WebXml(); |
| |
| // Defaults |
| Assert.assertEquals(3, webxml.getMajorVersion()); |
| Assert.assertEquals(1, webxml.getMinorVersion()); |
| |
| // Both get changed |
| webxml.setVersion("2.5"); |
| Assert.assertEquals(2, webxml.getMajorVersion()); |
| Assert.assertEquals(5, webxml.getMinorVersion()); |
| |
| // unknown input should be ignored |
| webxml.setVersion("0.0"); |
| Assert.assertEquals(2, webxml.getMajorVersion()); |
| Assert.assertEquals(5, webxml.getMinorVersion()); |
| |
| // null input should be ignored |
| webxml.setVersion(null); |
| Assert.assertEquals(2, webxml.getMajorVersion()); |
| Assert.assertEquals(5, webxml.getMinorVersion()); |
| } |
| |
| @Test |
| public void testParsePublicIdVersion22() { |
| |
| WebXml webxml = new WebXml(); |
| |
| webxml.setPublicId(XmlIdentifiers.WEB_22_PUBLIC); |
| Assert.assertEquals(2, webxml.getMajorVersion()); |
| Assert.assertEquals(2, webxml.getMinorVersion()); |
| Assert.assertEquals("2.2", webxml.getVersion()); |
| } |
| |
| @Test |
| public void testParsePublicIdVersion23() { |
| |
| WebXml webxml = new WebXml(); |
| |
| webxml.setPublicId(XmlIdentifiers.WEB_23_PUBLIC); |
| Assert.assertEquals(2, webxml.getMajorVersion()); |
| Assert.assertEquals(3, webxml.getMinorVersion()); |
| Assert.assertEquals("2.3", webxml.getVersion()); |
| } |
| |
| @Test |
| public void testParseVersion24() { |
| |
| WebXml webxml = new WebXml(); |
| |
| webxml.setVersion("2.4"); |
| Assert.assertEquals(2, webxml.getMajorVersion()); |
| Assert.assertEquals(4, webxml.getMinorVersion()); |
| Assert.assertEquals("2.4", webxml.getVersion()); |
| } |
| |
| @Test |
| public void testParseVersion25() { |
| |
| WebXml webxml = new WebXml(); |
| |
| webxml.setVersion("2.5"); |
| Assert.assertEquals(2, webxml.getMajorVersion()); |
| Assert.assertEquals(5, webxml.getMinorVersion()); |
| Assert.assertEquals("2.5", webxml.getVersion()); |
| } |
| |
| @Test |
| public void testParseVersion30() { |
| |
| WebXml webxml = new WebXml(); |
| |
| webxml.setVersion("3.0"); |
| Assert.assertEquals(3, webxml.getMajorVersion()); |
| Assert.assertEquals(0, webxml.getMinorVersion()); |
| Assert.assertEquals("3.0", webxml.getVersion()); |
| } |
| |
| @Test |
| public void testParseVersion31() { |
| |
| WebXml webxml = new WebXml(); |
| |
| webxml.setVersion("3.1"); |
| Assert.assertEquals(3, webxml.getMajorVersion()); |
| Assert.assertEquals(1, webxml.getMinorVersion()); |
| Assert.assertEquals("3.1", webxml.getVersion()); |
| } |
| |
| @Test |
| public void testValidateVersion22() throws IOException, SAXException { |
| doTestValidateVersion("2.2"); |
| } |
| |
| @Test |
| public void testValidateVersion23() throws IOException, SAXException { |
| doTestValidateVersion("2.3"); |
| } |
| |
| @Test |
| public void testValidateVersion24() throws IOException, SAXException { |
| doTestValidateVersion("2.4"); |
| } |
| |
| @Test |
| public void testValidateVersion25() throws IOException, SAXException { |
| doTestValidateVersion("2.5"); |
| } |
| |
| @Test |
| public void testValidateVersion30() throws IOException, SAXException { |
| doTestValidateVersion("3.0"); |
| } |
| |
| @Test |
| public void testValidateVersion31() throws IOException, SAXException { |
| doTestValidateVersion("3.1"); |
| } |
| |
| private void doTestValidateVersion(String version) throws IOException, SAXException { |
| WebXml webxml = new WebXml(); |
| |
| // Special cases |
| if ("2.2".equals(version)) { |
| webxml.setPublicId(XmlIdentifiers.WEB_22_PUBLIC); |
| } else if ("2.3".equals(version)) { |
| webxml.setPublicId(XmlIdentifiers.WEB_23_PUBLIC); |
| } else { |
| webxml.setVersion(version); |
| } |
| |
| // Merged web.xml that is published as MERGED_WEB_XML context attribute |
| // in the simplest case consists of webapp's web.xml file |
| // plus the default conf/web.xml one. |
| Set<WebXml> defaults = new HashSet<>(); |
| defaults.add(getDefaultWebXmlFragment()); |
| webxml.merge(defaults); |
| |
| Digester digester = DigesterFactory.newDigester(true, true, new WebRuleSet(), true); |
| |
| XmlErrorHandler handler = new XmlErrorHandler(); |
| digester.setErrorHandler(handler); |
| |
| InputSource is = new InputSource(new StringReader(webxml.toXml())); |
| WebXml webxmlResult = new WebXml(); |
| digester.push(webxmlResult); |
| digester.parse(is); |
| |
| Assert.assertEquals(0, handler.getErrors().size()); |
| Assert.assertEquals(0, handler.getWarnings().size()); |
| |
| Assert.assertEquals(version, webxml.getVersion()); |
| Assert.assertEquals(version, webxmlResult.getVersion()); |
| } |
| |
| // A simplified copy of ContextConfig.getDefaultWebXmlFragment(). |
| // Assuming that global web.xml exists, host-specific web.xml does not exist. |
| private WebXml getDefaultWebXmlFragment() throws IOException, SAXException { |
| InputSource globalWebXml = new InputSource(new File("conf/web.xml") |
| .getAbsoluteFile().toURI().toString()); |
| |
| WebXml webXmlDefaultFragment = new WebXml(); |
| webXmlDefaultFragment.setOverridable(true); |
| webXmlDefaultFragment.setDistributable(true); |
| webXmlDefaultFragment.setAlwaysAddWelcomeFiles(false); |
| |
| Digester digester = DigesterFactory.newDigester(true, true, new WebRuleSet(), true); |
| XmlErrorHandler handler = new XmlErrorHandler(); |
| digester.setErrorHandler(handler); |
| digester.push(webXmlDefaultFragment); |
| digester.parse(globalWebXml); |
| Assert.assertEquals(0, handler.getErrors().size()); |
| Assert.assertEquals(0, handler.getWarnings().size()); |
| |
| webXmlDefaultFragment.setReplaceWelcomeFiles(true); |
| |
| // Assert that web.xml was parsed and is not empty. Default servlet is known to be there. |
| Assert.assertNotNull(webXmlDefaultFragment.getServlets().get("default")); |
| |
| // Manually add some version specific features to ensure that these do |
| // not cause problems for the merged web.xml |
| |
| // Filters were added in 2.3 so should be excluded in 2.2 |
| FilterDef filterDef = new FilterDef(); |
| filterDef.setFilterClass("org.apache.tomcat.DummyFilter"); |
| filterDef.setFilterName("Dummy"); |
| webXmlDefaultFragment.addFilter(filterDef); |
| |
| FilterMap filterMap = new FilterMap(); |
| filterMap.setFilterName("Dummy"); |
| filterMap.addURLPatternDecoded("/*"); |
| webXmlDefaultFragment.addFilterMapping(filterMap); |
| |
| // Listeners were added in 2.3 so should be excluded in 2.2 |
| webXmlDefaultFragment.addListener("org.apache.tomcat.DummyListener"); |
| |
| // resource-env-ref was added in 2.3 so should be excluded in 2.2 |
| ContextResourceEnvRef resourceEnvRef = new ContextResourceEnvRef(); |
| resourceEnvRef.setName("dummy"); |
| resourceEnvRef.setType("dummy"); |
| |
| webXmlDefaultFragment.addResourceEnvRef(resourceEnvRef); |
| |
| // ejb-local-ref was added in 2.3 so should be excluded in 2.2 |
| ContextLocalEjb ejbLocalRef = new ContextLocalEjb(); |
| ejbLocalRef.setName("dummy"); |
| ejbLocalRef.setType("Session"); |
| ejbLocalRef.setLocal("dummy"); |
| ejbLocalRef.setHome("dummy"); |
| webXmlDefaultFragment.addEjbLocalRef(ejbLocalRef); |
| |
| // Servlet/run-as was added in 2.3 so should be excluded in 2.2 |
| ServletDef servletDef = new ServletDef(); |
| servletDef.setServletName("Dummy"); |
| servletDef.setServletClass("org.apache.tomcat.DummyServlet"); |
| servletDef.setRunAs("dummy"); |
| webXmlDefaultFragment.addServlet(servletDef); |
| |
| webXmlDefaultFragment.addServletMapping("/dummy", "Dummy"); |
| |
| // resource-ref/res-sharing-scope was added in 2.3 so should be excluded |
| // in 2.2 |
| ContextResource contextResource = new ContextResource(); |
| contextResource.setName("dummy"); |
| contextResource.setType("dummy"); |
| contextResource.setAuth("Container"); |
| contextResource.setScope("Shareable"); |
| webXmlDefaultFragment.addResourceRef(contextResource); |
| |
| // security-constraint/display-name was added in 2.3 so should be |
| // excluded in 2.2 |
| SecurityConstraint sc = new SecurityConstraint(); |
| sc.setDisplayName("dummy"); |
| SecurityCollection collection = new SecurityCollection(); |
| collection.setName("dummy"); |
| collection.addPatternDecoded("/*"); |
| collection.addMethod("DELETE"); |
| sc.addCollection(collection); |
| webXmlDefaultFragment.addSecurityConstraint(sc); |
| |
| // service-ref was added in 2.4 so should be excluded in 2.3 and earlier |
| ContextService serviceRef = new ContextService(); |
| serviceRef.setName("dummy"); |
| serviceRef.setInterface("dummy"); |
| webXmlDefaultFragment.addServiceRef(serviceRef); |
| |
| // message-destination-ref was added in 2.4 so should be excluded in 2.3 |
| // and earlier |
| MessageDestinationRef mdRef = new MessageDestinationRef(); |
| mdRef.setName("dummy"); |
| mdRef.setType("dummy"); |
| mdRef.setUsage("Consumes"); |
| webXmlDefaultFragment.addMessageDestinationRef(mdRef); |
| |
| // message-destination was added in 2.4 so should be excluded in 2.3 |
| // and earlier |
| MessageDestination md = new MessageDestination(); |
| md.setName("dummy"); |
| webXmlDefaultFragment.addMessageDestination(md); |
| |
| // local-encoding-mapping-list was added in 2.4 so should be excluded in |
| // 2.3 and earlier |
| webXmlDefaultFragment.addLocaleEncodingMapping("en", "UTF-8"); |
| |
| // jsp-config was added in Servlet 2.4 |
| webXmlDefaultFragment.addTaglib("dummy", "dummy"); |
| |
| // filter-mapping/dispatcher added in Servlet 2.4 |
| filterMap.setDispatcher("REQUEST"); |
| |
| // listener-[description|display-name|icon] added in Servlet 2.4 |
| // None of these are supported in WebXml |
| |
| // filter-mapping/dispatcher/ASYNC added in Servlet 3.0 |
| filterMap.setDispatcher("ASYNC"); |
| |
| // error-page with just location allowed in Servlet 3.0+ |
| ErrorPage errorPage = new ErrorPage(); |
| errorPage.setLocation("/dummy"); |
| webXmlDefaultFragment.addErrorPage(errorPage); |
| |
| // async-supported added to Servlet and Filter in 3.0 |
| filterDef.setAsyncSupported("false"); |
| servletDef.setAsyncSupported("false"); |
| |
| // session-cookie-config added in 3.0 |
| SessionConfig sessionConfig = new SessionConfig(); |
| sessionConfig.setCookieDomain("dummy"); |
| webXmlDefaultFragment.setSessionConfig(sessionConfig); |
| |
| // http-method-omission added in Servlet 3.0 |
| // Let this trigger a validation error as dropping it silently could |
| // be a security concern |
| |
| // multi-part-config added in Servlet 3.0 |
| MultipartDef multiPart = new MultipartDef(); |
| servletDef.setMultipartDef(multiPart); |
| |
| // deny-uncovered-http-methods added in Servlet 3.1 |
| webXmlDefaultFragment.setDenyUncoveredHttpMethods(true); |
| |
| return webXmlDefaultFragment; |
| } |
| |
| @Test |
| public void testLifecycleMethodsWebXml() { |
| WebXml webxml = new WebXml(); |
| webxml.addPostConstructMethods("a", "a"); |
| webxml.addPreDestroyMethods("b", "b"); |
| |
| WebXml fragment = new WebXml(); |
| fragment.addPostConstructMethods("c", "c"); |
| fragment.addPreDestroyMethods("d", "d"); |
| |
| Set<WebXml> fragments = new HashSet<>(); |
| fragments.add(fragment); |
| |
| webxml.merge(fragments); |
| |
| Map<String, String> postConstructMethods = webxml.getPostConstructMethods(); |
| Map<String, String> preDestroyMethods = webxml.getPreDestroyMethods(); |
| Assert.assertEquals(1, postConstructMethods.size()); |
| Assert.assertEquals(1, preDestroyMethods.size()); |
| |
| Assert.assertEquals("a", postConstructMethods.get("a")); |
| Assert.assertEquals("b", preDestroyMethods.get("b")); |
| } |
| |
| @Test |
| public void testLifecycleMethodsWebFragments() { |
| WebXml webxml = new WebXml(); |
| |
| WebXml fragment1 = new WebXml(); |
| fragment1.addPostConstructMethods("a", "a"); |
| fragment1.addPreDestroyMethods("b", "b"); |
| |
| WebXml fragment2 = new WebXml(); |
| fragment2.addPostConstructMethods("c", "c"); |
| fragment2.addPreDestroyMethods("d", "d"); |
| |
| Set<WebXml> fragments = new HashSet<>(); |
| fragments.add(fragment1); |
| fragments.add(fragment2); |
| |
| webxml.merge(fragments); |
| |
| Map<String, String> postConstructMethods = webxml.getPostConstructMethods(); |
| Map<String, String> preDestroyMethods = webxml.getPreDestroyMethods(); |
| Assert.assertEquals(2, postConstructMethods.size()); |
| Assert.assertEquals(2, preDestroyMethods.size()); |
| |
| Assert.assertEquals("a", postConstructMethods.get("a")); |
| Assert.assertEquals("c", postConstructMethods.get("c")); |
| Assert.assertEquals("b", preDestroyMethods.get("b")); |
| Assert.assertEquals("d", preDestroyMethods.get("d")); |
| } |
| |
| @Test |
| public void testLifecycleMethodsWebFragmentsWithConflicts() { |
| WebXml webxml = new WebXml(); |
| |
| WebXml fragment1 = new WebXml(); |
| fragment1.addPostConstructMethods("a", "a"); |
| fragment1.addPreDestroyMethods("b", "a"); |
| |
| WebXml fragment2 = new WebXml(); |
| fragment2.addPostConstructMethods("a", "b"); |
| |
| Set<WebXml> fragments = new HashSet<>(); |
| fragments.add(fragment1); |
| fragments.add(fragment2); |
| |
| Assert.assertFalse(webxml.merge(fragments)); |
| |
| Assert.assertEquals(0, webxml.getPostConstructMethods().size()); |
| |
| WebXml fragment3 = new WebXml(); |
| fragment3.addPreDestroyMethods("b", "b"); |
| |
| fragments.remove(fragment2); |
| fragments.add(fragment3); |
| |
| Assert.assertFalse(webxml.merge(fragments)); |
| |
| Assert.assertEquals(0, webxml.getPreDestroyMethods().size()); |
| } |
| |
| @Test(expected=IllegalArgumentException.class) |
| public void testBug54387a() { |
| // Multiple servlets may not be mapped to the same url-pattern |
| WebXml webxml = new WebXml(); |
| webxml.addServletMapping("/foo", "a"); |
| webxml.addServletMapping("/foo", "b"); |
| } |
| |
| @Test(expected=IllegalArgumentException.class) |
| public void testBug54387b() { |
| // Multiple servlets may not be mapped to the same url-pattern |
| WebXml webxml = new WebXml(); |
| WebXml f1 = new WebXml(); |
| WebXml f2 = new WebXml(); |
| |
| HashSet<WebXml> fragments = new HashSet<>(); |
| fragments.add(f1); |
| fragments.add(f2); |
| |
| f1.addServletMapping("/foo", "a"); |
| f2.addServletMapping("/foo", "b"); |
| |
| webxml.merge(fragments); |
| } |
| |
| @Test |
| public void testBug54387c() { |
| // Multiple servlets may not be mapped to the same url-pattern but main |
| // web.xml takes priority |
| WebXml webxml = new WebXml(); |
| WebXml f1 = new WebXml(); |
| WebXml f2 = new WebXml(); |
| |
| HashSet<WebXml> fragments = new HashSet<>(); |
| fragments.add(f1); |
| fragments.add(f2); |
| |
| f1.addServletMapping("/foo", "a"); |
| f2.addServletMapping("/foo", "b"); |
| webxml.addServletMapping("/foo", "main"); |
| |
| webxml.merge(fragments); |
| } |
| } |