diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/ExecutableArchiveLauncher.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/ExecutableArchiveLauncher.java index d1a4beb707..ad6f14cbbb 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/ExecutableArchiveLauncher.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/ExecutableArchiveLauncher.java @@ -54,6 +54,11 @@ public abstract class ExecutableArchiveLauncher extends Launcher { this.javaAgentDetector = javaAgentDetector; } + ExecutableArchiveLauncher(Archive archive) { + this.javaAgentDetector = new InputArgumentsJavaAgentDetector(); + this.archive = archive; + } + protected final Archive getArchive() { return this.archive; } diff --git a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/WarLauncher.java b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/WarLauncher.java index cafda40b31..82a745aef7 100644 --- a/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/WarLauncher.java +++ b/spring-boot-tools/spring-boot-loader/src/main/java/org/springframework/boot/loader/WarLauncher.java @@ -16,9 +16,6 @@ package org.springframework.boot.loader; -import java.io.IOException; -import java.util.List; - import org.springframework.boot.loader.archive.Archive; import org.springframework.boot.loader.util.AsciiBytes; @@ -28,13 +25,12 @@ import org.springframework.boot.loader.util.AsciiBytes; * classes are loaded from {@code WEB-INF/classes}. * * @author Phillip Webb + * @author Andy Wilkinson */ public class WarLauncher extends ExecutableArchiveLauncher { private static final AsciiBytes WEB_INF = new AsciiBytes("WEB-INF/"); - private static final AsciiBytes META_INF = new AsciiBytes("META-INF/"); - private static final AsciiBytes WEB_INF_CLASSES = WEB_INF.append("classes/"); private static final AsciiBytes WEB_INF_LIB = WEB_INF.append("lib/"); @@ -42,6 +38,14 @@ public class WarLauncher extends ExecutableArchiveLauncher { private static final AsciiBytes WEB_INF_LIB_PROVIDED = WEB_INF .append("lib-provided/"); + public WarLauncher() { + super(); + } + + WarLauncher(Archive archive) { + super(archive); + } + @Override public boolean isNestedArchive(Archive.Entry entry) { if (entry.isDirectory()) { @@ -53,29 +57,6 @@ public class WarLauncher extends ExecutableArchiveLauncher { } } - @Override - protected void postProcessClassPathArchives(List archives) throws Exception { - archives.add(0, getFilteredArchive()); - } - - /** - * Filter the specified WAR file to exclude elements that should not appear on the - * classpath. - * @return the filtered archive - * @throws IOException on error - */ - protected Archive getFilteredArchive() throws IOException { - return getArchive().getFilteredArchive(new Archive.EntryRenameFilter() { - @Override - public AsciiBytes apply(AsciiBytes entryName, Archive.Entry entry) { - if (entryName.startsWith(META_INF) || entryName.startsWith(WEB_INF)) { - return null; - } - return entryName; - } - }); - } - public static void main(String[] args) { new WarLauncher().launch(args); } diff --git a/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/WarLauncherTests.java b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/WarLauncherTests.java new file mode 100644 index 0000000000..c5998c04a0 --- /dev/null +++ b/spring-boot-tools/spring-boot-loader/src/test/java/org/springframework/boot/loader/WarLauncherTests.java @@ -0,0 +1,124 @@ +/* + * 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.loader; + +import java.io.ByteArrayOutputStream; +import java.io.File; +import java.io.FileNotFoundException; +import java.io.FileOutputStream; +import java.io.IOException; +import java.net.MalformedURLException; +import java.net.URL; +import java.util.HashSet; +import java.util.List; +import java.util.Set; +import java.util.jar.JarEntry; +import java.util.jar.JarOutputStream; +import java.util.zip.CRC32; +import java.util.zip.ZipEntry; + +import org.junit.Test; +import org.springframework.boot.loader.archive.Archive; +import org.springframework.boot.loader.archive.ExplodedArchive; +import org.springframework.boot.loader.archive.JarFileArchive; +import org.springframework.util.FileSystemUtils; + +import static org.hamcrest.Matchers.hasItems; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertThat; + +/** + * Tests for {@link WarLauncher} + * + * @author Andy Wilkinson + */ +public class WarLauncherTests { + + @Test + public void explodedWarHasOnlyWebInfClassesAndContentsOfWebInfLibOnClasspath() + throws Exception { + File warRoot = new File("target/exploded-war"); + FileSystemUtils.deleteRecursively(warRoot); + warRoot.mkdirs(); + File webInfClasses = new File(warRoot, "WEB-INF/classes"); + webInfClasses.mkdirs(); + File webInfLib = new File(warRoot, "WEB-INF/lib"); + webInfLib.mkdirs(); + File webInfLibFoo = new File(webInfLib, "foo.jar"); + new JarOutputStream(new FileOutputStream(webInfLibFoo)).close(); + + WarLauncher launcher = new WarLauncher(new ExplodedArchive(warRoot, true)); + List archives = launcher.getClassPathArchives(); + assertEquals(2, archives.size()); + + assertThat( + getUrls(archives), + hasItems(webInfClasses.toURI().toURL(), new URL("jar:" + + webInfLibFoo.toURI().toURL() + "!/"))); + } + + @Test + public void archivedWarHasOnlyWebInfClassesAndContentsOfWebInfLibOnClasspath() + throws Exception { + File warRoot = createWarArchive(); + + WarLauncher launcher = new WarLauncher(new JarFileArchive(warRoot)); + List archives = launcher.getClassPathArchives(); + assertEquals(2, archives.size()); + + assertThat( + getUrls(archives), + hasItems( + new URL("jar:" + warRoot.toURI().toURL() + "!/WEB-INF/classes!/"), + new URL("jar:" + warRoot.toURI().toURL() + + "!/WEB-INF/lib/foo.jar!/"))); + } + + private Set getUrls(List archives) throws MalformedURLException { + Set urls = new HashSet(archives.size()); + for (Archive archive : archives) { + urls.add(archive.getUrl()); + } + return urls; + } + + private File createWarArchive() throws IOException, FileNotFoundException { + File warRoot = new File("target/archive.war"); + warRoot.delete(); + + JarOutputStream jarOutputStream = new JarOutputStream(new FileOutputStream( + warRoot)); + + jarOutputStream.putNextEntry(new JarEntry("WEB-INF/")); + jarOutputStream.putNextEntry(new JarEntry("WEB-INF/classes/")); + jarOutputStream.putNextEntry(new JarEntry("WEB-INF/lib/")); + + JarEntry webInfLibFoo = new JarEntry("WEB-INF/lib/foo.jar"); + webInfLibFoo.setMethod(ZipEntry.STORED); + ByteArrayOutputStream fooJarStream = new ByteArrayOutputStream(); + new JarOutputStream(fooJarStream).close(); + webInfLibFoo.setSize(fooJarStream.size()); + CRC32 crc32 = new CRC32(); + crc32.update(fooJarStream.toByteArray()); + webInfLibFoo.setCrc(crc32.getValue()); + jarOutputStream.putNextEntry(webInfLibFoo); + jarOutputStream.write(fooJarStream.toByteArray()); + + jarOutputStream.close(); + return warRoot; + } +}