From 6dc8e6815d792160b9b7bd27c0916b690a6e57d4 Mon Sep 17 00:00:00 2001 From: Andy Wilkinson Date: Thu, 24 Sep 2020 17:51:38 +0100 Subject: [PATCH] Align default tldScanPatterns with Tomcat's Previously, we configured embedded Tomcat in such a way that no TLD scan patterns were configured. This differed from a standalone Tomcat installation where 4 patterns are configured that take precedence over some of the skip patterns. The missing scan patterns resulted in the skip patterns preventing the discovery of Log4j2's TLDs. This commit updates TomcatServletWebServerFactory to configure the same four scan patterns as standalone Tomcat configures by default. Fixes gh-23302 --- .../boot/web/embedded/tomcat/TldPatterns.java | 160 ++++++++++++++++++ .../web/embedded/tomcat/TldSkipPatterns.java | 140 --------------- .../tomcat/TomcatServletWebServerFactory.java | 9 +- .../TomcatServletWebServerFactoryTests.java | 13 ++ 4 files changed, 179 insertions(+), 143 deletions(-) create mode 100644 spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TldPatterns.java delete mode 100644 spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TldSkipPatterns.java diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TldPatterns.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TldPatterns.java new file mode 100644 index 00000000000..04f5ea587ee --- /dev/null +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TldPatterns.java @@ -0,0 +1,160 @@ +/* + * Copyright 2012-2020 the original author or authors. + * + * Licensed 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 + * + * https://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.springframework.boot.web.embedded.tomcat; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; + +/** + * TLD skip and scan patterns used by Spring Boot. + * + * @author Phillip Webb + * @author Andy Wilkinson + */ +final class TldPatterns { + + private static final Set TOMCAT_SKIP; + + static { + // Same as Tomcat + Set skipPatterns = new LinkedHashSet<>(); + skipPatterns.add("ant-*.jar"); + skipPatterns.add("aspectj*.jar"); + skipPatterns.add("commons-beanutils*.jar"); + skipPatterns.add("commons-codec*.jar"); + skipPatterns.add("commons-collections*.jar"); + skipPatterns.add("commons-dbcp*.jar"); + skipPatterns.add("commons-digester*.jar"); + skipPatterns.add("commons-fileupload*.jar"); + skipPatterns.add("commons-httpclient*.jar"); + skipPatterns.add("commons-io*.jar"); + skipPatterns.add("commons-lang*.jar"); + skipPatterns.add("commons-logging*.jar"); + skipPatterns.add("commons-math*.jar"); + skipPatterns.add("commons-pool*.jar"); + skipPatterns.add("geronimo-spec-jaxrpc*.jar"); + skipPatterns.add("h2*.jar"); + skipPatterns.add("hamcrest*.jar"); + skipPatterns.add("hibernate*.jar"); + skipPatterns.add("jaxb-runtime-*.jar"); + skipPatterns.add("jmx*.jar"); + skipPatterns.add("jmx-tools-*.jar"); + skipPatterns.add("jta*.jar"); + skipPatterns.add("junit-*.jar"); + skipPatterns.add("httpclient*.jar"); + skipPatterns.add("log4j-*.jar"); + skipPatterns.add("mail*.jar"); + skipPatterns.add("org.hamcrest*.jar"); + skipPatterns.add("slf4j*.jar"); + skipPatterns.add("tomcat-embed-core-*.jar"); + skipPatterns.add("tomcat-embed-logging-*.jar"); + skipPatterns.add("tomcat-jdbc-*.jar"); + skipPatterns.add("tomcat-juli-*.jar"); + skipPatterns.add("tools.jar"); + skipPatterns.add("wsdl4j*.jar"); + skipPatterns.add("xercesImpl-*.jar"); + skipPatterns.add("xmlParserAPIs-*.jar"); + skipPatterns.add("xml-apis-*.jar"); + TOMCAT_SKIP = Collections.unmodifiableSet(skipPatterns); + } + + private static final Set ADDITIONAL_SKIP; + + static { + // Additional typical for Spring Boot applications + Set skipPatterns = new LinkedHashSet<>(); + skipPatterns.add("antlr-*.jar"); + skipPatterns.add("aopalliance-*.jar"); + skipPatterns.add("aspectjrt-*.jar"); + skipPatterns.add("aspectjweaver-*.jar"); + skipPatterns.add("classmate-*.jar"); + skipPatterns.add("dom4j-*.jar"); + skipPatterns.add("ecj-*.jar"); + skipPatterns.add("ehcache-core-*.jar"); + skipPatterns.add("hibernate-core-*.jar"); + skipPatterns.add("hibernate-commons-annotations-*.jar"); + skipPatterns.add("hibernate-entitymanager-*.jar"); + skipPatterns.add("hibernate-jpa-2.1-api-*.jar"); + skipPatterns.add("hibernate-validator-*.jar"); + skipPatterns.add("hsqldb-*.jar"); + skipPatterns.add("jackson-annotations-*.jar"); + skipPatterns.add("jackson-core-*.jar"); + skipPatterns.add("jackson-databind-*.jar"); + skipPatterns.add("jandex-*.jar"); + skipPatterns.add("javassist-*.jar"); + skipPatterns.add("jboss-logging-*.jar"); + skipPatterns.add("jboss-transaction-api_*.jar"); + skipPatterns.add("jcl-over-slf4j-*.jar"); + skipPatterns.add("jdom-*.jar"); + skipPatterns.add("jul-to-slf4j-*.jar"); + skipPatterns.add("log4j-over-slf4j-*.jar"); + skipPatterns.add("logback-classic-*.jar"); + skipPatterns.add("logback-core-*.jar"); + skipPatterns.add("rome-*.jar"); + skipPatterns.add("slf4j-api-*.jar"); + skipPatterns.add("spring-aop-*.jar"); + skipPatterns.add("spring-aspects-*.jar"); + skipPatterns.add("spring-beans-*.jar"); + skipPatterns.add("spring-boot-*.jar"); + skipPatterns.add("spring-core-*.jar"); + skipPatterns.add("spring-context-*.jar"); + skipPatterns.add("spring-data-*.jar"); + skipPatterns.add("spring-expression-*.jar"); + skipPatterns.add("spring-jdbc-*.jar,"); + skipPatterns.add("spring-orm-*.jar"); + skipPatterns.add("spring-oxm-*.jar"); + skipPatterns.add("spring-tx-*.jar"); + skipPatterns.add("snakeyaml-*.jar"); + skipPatterns.add("tomcat-embed-el-*.jar"); + skipPatterns.add("validation-api-*.jar"); + skipPatterns.add("xml-apis-*.jar"); + ADDITIONAL_SKIP = Collections.unmodifiableSet(skipPatterns); + } + + static final Set DEFAULT_SKIP; + + static { + Set skipPatterns = new LinkedHashSet<>(); + skipPatterns.addAll(TOMCAT_SKIP); + skipPatterns.addAll(ADDITIONAL_SKIP); + DEFAULT_SKIP = Collections.unmodifiableSet(skipPatterns); + } + + private static final Set TOMCAT_SCAN; + + static { + Set scanPatterns = new LinkedHashSet<>(); + scanPatterns.add("log4j-taglib*.jar"); + scanPatterns.add("log4j-web*.jar"); + scanPatterns.add("log4javascript*.jar"); + scanPatterns.add("slf4j-taglib*.jar"); + TOMCAT_SCAN = Collections.unmodifiableSet(scanPatterns); + } + + static final Set DEFAULT_SCAN; + + static { + Set scanPatterns = new LinkedHashSet<>(); + scanPatterns.addAll(TOMCAT_SCAN); + DEFAULT_SCAN = Collections.unmodifiableSet(scanPatterns); + } + + private TldPatterns() { + } + +} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TldSkipPatterns.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TldSkipPatterns.java deleted file mode 100644 index dbb0db33435..00000000000 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TldSkipPatterns.java +++ /dev/null @@ -1,140 +0,0 @@ -/* - * Copyright 2012-2019 the original author or authors. - * - * Licensed 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 - * - * https://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.springframework.boot.web.embedded.tomcat; - -import java.util.Collections; -import java.util.LinkedHashSet; -import java.util.Set; - -/** - * TLD Skip Patterns used by Spring Boot. - * - * @author Phillip Webb - */ -final class TldSkipPatterns { - - private static final Set TOMCAT; - - static { - // Same as Tomcat - Set patterns = new LinkedHashSet<>(); - patterns.add("ant-*.jar"); - patterns.add("aspectj*.jar"); - patterns.add("commons-beanutils*.jar"); - patterns.add("commons-codec*.jar"); - patterns.add("commons-collections*.jar"); - patterns.add("commons-dbcp*.jar"); - patterns.add("commons-digester*.jar"); - patterns.add("commons-fileupload*.jar"); - patterns.add("commons-httpclient*.jar"); - patterns.add("commons-io*.jar"); - patterns.add("commons-lang*.jar"); - patterns.add("commons-logging*.jar"); - patterns.add("commons-math*.jar"); - patterns.add("commons-pool*.jar"); - patterns.add("geronimo-spec-jaxrpc*.jar"); - patterns.add("h2*.jar"); - patterns.add("hamcrest*.jar"); - patterns.add("hibernate*.jar"); - patterns.add("jaxb-runtime-*.jar"); - patterns.add("jmx*.jar"); - patterns.add("jmx-tools-*.jar"); - patterns.add("jta*.jar"); - patterns.add("junit-*.jar"); - patterns.add("httpclient*.jar"); - patterns.add("log4j-*.jar"); - patterns.add("mail*.jar"); - patterns.add("org.hamcrest*.jar"); - patterns.add("slf4j*.jar"); - patterns.add("tomcat-embed-core-*.jar"); - patterns.add("tomcat-embed-logging-*.jar"); - patterns.add("tomcat-jdbc-*.jar"); - patterns.add("tomcat-juli-*.jar"); - patterns.add("tools.jar"); - patterns.add("wsdl4j*.jar"); - patterns.add("xercesImpl-*.jar"); - patterns.add("xmlParserAPIs-*.jar"); - patterns.add("xml-apis-*.jar"); - TOMCAT = Collections.unmodifiableSet(patterns); - } - - private static final Set ADDITIONAL; - - static { - // Additional typical for Spring Boot applications - Set patterns = new LinkedHashSet<>(); - patterns.add("antlr-*.jar"); - patterns.add("aopalliance-*.jar"); - patterns.add("aspectjrt-*.jar"); - patterns.add("aspectjweaver-*.jar"); - patterns.add("classmate-*.jar"); - patterns.add("dom4j-*.jar"); - patterns.add("ecj-*.jar"); - patterns.add("ehcache-core-*.jar"); - patterns.add("hibernate-core-*.jar"); - patterns.add("hibernate-commons-annotations-*.jar"); - patterns.add("hibernate-entitymanager-*.jar"); - patterns.add("hibernate-jpa-2.1-api-*.jar"); - patterns.add("hibernate-validator-*.jar"); - patterns.add("hsqldb-*.jar"); - patterns.add("jackson-annotations-*.jar"); - patterns.add("jackson-core-*.jar"); - patterns.add("jackson-databind-*.jar"); - patterns.add("jandex-*.jar"); - patterns.add("javassist-*.jar"); - patterns.add("jboss-logging-*.jar"); - patterns.add("jboss-transaction-api_*.jar"); - patterns.add("jcl-over-slf4j-*.jar"); - patterns.add("jdom-*.jar"); - patterns.add("jul-to-slf4j-*.jar"); - patterns.add("log4j-over-slf4j-*.jar"); - patterns.add("logback-classic-*.jar"); - patterns.add("logback-core-*.jar"); - patterns.add("rome-*.jar"); - patterns.add("slf4j-api-*.jar"); - patterns.add("spring-aop-*.jar"); - patterns.add("spring-aspects-*.jar"); - patterns.add("spring-beans-*.jar"); - patterns.add("spring-boot-*.jar"); - patterns.add("spring-core-*.jar"); - patterns.add("spring-context-*.jar"); - patterns.add("spring-data-*.jar"); - patterns.add("spring-expression-*.jar"); - patterns.add("spring-jdbc-*.jar,"); - patterns.add("spring-orm-*.jar"); - patterns.add("spring-oxm-*.jar"); - patterns.add("spring-tx-*.jar"); - patterns.add("snakeyaml-*.jar"); - patterns.add("tomcat-embed-el-*.jar"); - patterns.add("validation-api-*.jar"); - patterns.add("xml-apis-*.jar"); - ADDITIONAL = Collections.unmodifiableSet(patterns); - } - - static final Set DEFAULT; - - static { - Set patterns = new LinkedHashSet<>(); - patterns.addAll(TOMCAT); - patterns.addAll(ADDITIONAL); - DEFAULT = Collections.unmodifiableSet(patterns); - } - - private TldSkipPatterns() { - } - -} diff --git a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java index 3c6fbedf297..600c7c68c20 100644 --- a/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java +++ b/spring-boot-project/spring-boot/src/main/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactory.java @@ -130,7 +130,9 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto private String protocol = DEFAULT_PROTOCOL; - private Set tldSkipPatterns = new LinkedHashSet<>(TldSkipPatterns.DEFAULT); + private Set tldSkipPatterns = new LinkedHashSet<>(TldPatterns.DEFAULT_SKIP); + + private Set tldScanPatterns = new LinkedHashSet<>(TldPatterns.DEFAULT_SCAN); private Charset uriEncoding = DEFAULT_CHARSET; @@ -220,7 +222,7 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto catch (NoSuchMethodError ex) { // Tomcat is < 8.5.39. Continue. } - configureTldSkipPatterns(context); + configureTldPatterns(context); WebappLoader loader = new WebappLoader(); loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName()); loader.setDelegate(true); @@ -254,9 +256,10 @@ public class TomcatServletWebServerFactory extends AbstractServletWebServerFacto (locale, charset) -> context.addLocaleEncodingMappingParameter(locale.toString(), charset.toString())); } - private void configureTldSkipPatterns(TomcatEmbeddedContext context) { + private void configureTldPatterns(TomcatEmbeddedContext context) { StandardJarScanFilter filter = new StandardJarScanFilter(); filter.setTldSkip(StringUtils.collectionToCommaDelimitedString(this.tldSkipPatterns)); + filter.setTldScan(StringUtils.collectionToCommaDelimitedString(this.tldScanPatterns)); context.getJarScanner().setJarScanFilter(filter); } diff --git a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java index c35b590c7e2..ad126171d71 100644 --- a/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java +++ b/spring-boot-project/spring-boot/src/test/java/org/springframework/boot/web/embedded/tomcat/TomcatServletWebServerFactoryTests.java @@ -58,6 +58,7 @@ import org.apache.coyote.http11.AbstractHttp11Protocol; import org.apache.jasper.servlet.JspServlet; import org.apache.tomcat.JarScanFilter; import org.apache.tomcat.JarScanType; +import org.apache.tomcat.util.scan.StandardJarScanFilter; import org.junit.jupiter.api.AfterEach; import org.junit.jupiter.api.Test; import org.mockito.ArgumentCaptor; @@ -438,6 +439,18 @@ class TomcatServletWebServerFactoryTests extends AbstractServletWebServerFactory assertThat(jarScanFilter.check(JarScanType.TLD, "test.jar")).isTrue(); } + @Test + void tldScanPatternsShouldBeAppliedToContextJarScanner() { + TomcatServletWebServerFactory factory = getFactory(); + this.webServer = factory.getWebServer(); + this.webServer.start(); + Tomcat tomcat = ((TomcatWebServer) this.webServer).getTomcat(); + Context context = (Context) tomcat.getHost().findChildren()[0]; + JarScanFilter jarScanFilter = context.getJarScanner().getJarScanFilter(); + String tldScan = ((StandardJarScanFilter) jarScanFilter).getTldScan(); + assertThat(tldScan).isEqualTo("log4j-taglib*.jar,log4j-web*.jar,log4javascript*.jar,slf4j-taglib*.jar"); + } + @Test void customTomcatHttpOnlyCookie() { TomcatServletWebServerFactory factory = getFactory();