diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/CustomSkipPatternJarScanner.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/CustomSkipPatternJarScanner.java new file mode 100644 index 0000000000..ad083a9fc4 --- /dev/null +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/CustomSkipPatternJarScanner.java @@ -0,0 +1,128 @@ +/* + * Copyright 2012-2014 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 + * + * 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.springframework.boot.context.embedded.tomcat; + +import java.util.Collections; +import java.util.LinkedHashSet; +import java.util.Set; +import java.util.StringTokenizer; + +import javax.servlet.ServletContext; + +import org.apache.tomcat.JarScanner; +import org.apache.tomcat.JarScannerCallback; +import org.springframework.util.Assert; + +/** + * {@link JarScanner} decorator allowing alternative default jar pattern matching. + * + * @author Phillip Webb + * @see #apply(TomcatEmbeddedContext, String) + */ +class SkipPatternJarScanner implements JarScanner { + + private final JarScanner jarScanner; + + private final SkipPattern pattern; + + SkipPatternJarScanner(JarScanner jarScanner, String pattern) { + Assert.notNull(jarScanner, "JarScanner must not be null"); + this.jarScanner = jarScanner; + this.pattern = (pattern == null ? new SkipPattern() : new SkipPattern(pattern)); + } + + @Override + public void scan(ServletContext context, ClassLoader classloader, + JarScannerCallback callback, Set jarsToSkip) { + this.jarScanner.scan(context, classloader, callback, + (jarsToSkip == null ? this.pattern.asSet() : jarsToSkip)); + } + + /** + * Apply this decorator the specified context. + * @param context the context to apply to + * @param pattern the jar skip pattern or {@code null} for defaults + */ + public static void apply(TomcatEmbeddedContext context, String pattern) { + context.setJarScanner(new SkipPatternJarScanner(context.getJarScanner(), pattern)); + } + + private static class SkipPattern { + + private Set patterns = new LinkedHashSet(); + + protected SkipPattern() { + add("ant-*.jar"); + add("aspectj*.jar"); + add("commons-beanutils*.jar"); + add("commons-codec*.jar"); + add("commons-collections*.jar"); + add("commons-dbcp*.jar"); + add("commons-digester*.jar"); + add("commons-fileupload*.jar"); + add("commons-httpclient*.jar"); + add("commons-io*.jar"); + add("commons-lang*.jar"); + add("commons-logging*.jar"); + add("commons-math*.jar"); + add("commons-pool*.jar"); + add("geronimo-spec-jaxrpc*.jar"); + add("h2*.jar"); + add("hamcrest*.jar"); + add("hibernate*.jar"); + add("jmx*.jar"); + add("jmx-tools-*.jar"); + add("jta*.jar"); + add("junit-*.jar"); + add("httpclient*.jar"); + add("log4j-*.jar"); + add("mail*.jar"); + add("org.hamcrest*.jar"); + add("slf4j*.jar"); + add("tomcat-embed-core-*.jar"); + add("tomcat-embed-logging-*.jar"); + add("tomcat-jdbc-*.jar"); + add("tomcat-juli-*.jar"); + add("tools.jar"); + add("wsdl4j*.jar"); + add("xercesImpl-*.jar"); + add("xmlParserAPIs-*.jar"); + add("xml-apis-*.jar"); + } + + public SkipPattern(String patterns) { + StringTokenizer tokenizer = new StringTokenizer(patterns, ","); + while (tokenizer.hasMoreElements()) { + add(tokenizer.nextToken()); + } + } + + protected void add(String patterns) { + Assert.notNull(patterns, "Patterns must not be null"); + if (patterns.length() > 0 && !patterns.trim().startsWith(",")) { + this.patterns.add(","); + } + this.patterns.add(patterns); + } + + public Set asSet() { + return Collections.unmodifiableSet(this.patterns); + } + + } + +} diff --git a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java index f7d005f584..03da368ccb 100644 --- a/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java +++ b/spring-boot/src/main/java/org/springframework/boot/context/embedded/tomcat/TomcatEmbeddedServletContainerFactory.java @@ -89,14 +89,7 @@ public class TomcatEmbeddedServletContainerFactory extends private String protocol = DEFAULT_PROTOCOL; - private static String DEFAULT_SKIP_JARS = "tomcat-embed-core-*.jar,tomcat-embed-logging-*.jar,tomcat-juli-*.jar,tomcat-jdbc-*.jar," - + "tools.jar,commons-beanutils*.jar,commons-codec*.jar,commons-collections*.jar," - + "commons-dbcp*.jar,commons-digester*.jar,commons-fileupload*.jar,commons-httpclient*.jar,commons-io*.jar,commons-lang*.jar," - + "commons-logging*.jar,commons-math*.jar,commons-pool*.jar,geronimo-spec-jaxrpc*.jar,wsdl4j*.jar,ant-*.jar," - + "aspectj*.jar,jmx*.jar,h2*.jar,hibernate*.jar,httpclient*.jar,jmx-tools-*.jar,jta*.jar,log4j-*.jar,mail*.jar,slf4j*.jar," - + "xercesImpl-*.jar,xmlParserAPIs-*.jar,xml-apis-*.jar,junit-*.jar,hamcrest*.jar,org.hamcrest*.jar"; - - private String skipJars = DEFAULT_SKIP_JARS; + private String tldSkip; /** * Create a new {@link TomcatEmbeddedServletContainerFactory} instance. @@ -146,7 +139,6 @@ public class TomcatEmbeddedServletContainerFactory extends protected void prepareContext(Host host, ServletContextInitializer[] initializers) { File docBase = getValidDocumentRoot(); docBase = (docBase != null ? docBase : createTempDir("tomcat-docbase")); - applySkipJars(); TomcatEmbeddedContext context = new TomcatEmbeddedContext(); context.setName(getContextPath()); context.setPath(getContextPath()); @@ -154,6 +146,7 @@ public class TomcatEmbeddedServletContainerFactory extends context.addLifecycleListener(new FixContextListener()); context.setParentClassLoader(this.resourceLoader != null ? this.resourceLoader .getClassLoader() : ClassUtils.getDefaultClassLoader()); + SkipPatternJarScanner.apply(context, this.tldSkip); WebappLoader loader = new WebappLoader(context.getParentClassLoader()); loader.setLoaderClass(TomcatEmbeddedWebappClassLoader.class.getName()); loader.setDelegate(true); @@ -173,14 +166,6 @@ public class TomcatEmbeddedServletContainerFactory extends postProcessContext(context); } - private void applySkipJars() { - // Tomcat 8.0 - System.setProperty("tomcat.util.scan.StandardJarScanFilter.jarsToSkip", - this.skipJars); - // Tomcat 7.0 - System.setProperty("tomcat.util.scan.DefaultJarScanner.jarsToSkip", this.skipJars); - } - private void addDefaultServlet(Context context) { Wrapper defaultServlet = context.createWrapper(); defaultServlet.setName("default"); @@ -302,11 +287,11 @@ public class TomcatEmbeddedServletContainerFactory extends /** * A comma-separated list of jars to ignore for TLD scanning. See Tomcat's * catalina.properties for typical values. Defaults to a list drawn from that source. - * - * @param skipJars the jars to skip when scanning for tlds etc + * @param tldSkip the jars to skip when scanning for TLDs etc */ - public void setSkipJars(String skipJars) { - this.skipJars = skipJars; + public void setTldSkip(String tldSkip) { + Assert.notNull(tldSkip, "TldSkip must not be null"); + this.tldSkip = tldSkip; } /**