Skip to content

Commit

Permalink
Only include zips in BOOT-INF/lib, WEB-INF/lib, and WEB-INF/lib-provided
Browse files Browse the repository at this point in the history
  • Loading branch information
wilkinsona committed Feb 20, 2019
1 parent e922cba commit 59430a2
Show file tree
Hide file tree
Showing 6 changed files with 98 additions and 26 deletions.
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* 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.
Expand All @@ -16,6 +16,10 @@

package org.springframework.boot.gradle.tasks.bundling;

import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.InputStream;
import java.util.Collections;
import java.util.HashSet;
import java.util.Map;
Expand Down Expand Up @@ -43,6 +47,8 @@
*/
class BootArchiveSupport {

private static final byte[] ZIP_FILE_HEADER = new byte[] { 'P', 'K', 3, 4 };

private static final Set<String> DEFAULT_LAUNCHER_CLASSES;

static {
Expand Down Expand Up @@ -120,6 +126,26 @@ void setExcludeDevtools(boolean excludeDevtools) {
configureExclusions();
}

boolean isZip(File file) {
try {
try (FileInputStream fileInputStream = new FileInputStream(file)) {
return isZip(fileInputStream);
}
}
catch (IOException ex) {
return false;
}
}

private boolean isZip(InputStream inputStream) throws IOException {
for (int i = 0; i < ZIP_FILE_HEADER.length; i++) {
if (inputStream.read() != ZIP_FILE_HEADER[i]) {
return false;
}
}
return true;
}

private void configureExclusions() {
Set<String> excludes = new HashSet<>();
if (this.excludeDevtools) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -58,6 +58,13 @@ public BootJar() {
this.bootInf.filesMatching("module-info.class", (details) -> {
details.setRelativePath(details.getRelativeSourcePath());
});
getRootSpec().eachFile((details) -> {
String pathString = details.getRelativePath().getPathString();
if (pathString.startsWith("BOOT-INF/lib/")
&& !this.support.isZip(details.getFile())) {
details.exclude();
}
});
}

private Action<CopySpec> classpathFiles(Spec<File> filter) {
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -57,6 +57,14 @@ public BootWar() {
getRootSpec().filesMatching("module-info.class", (details) -> {
details.setRelativePath(details.getRelativeSourcePath());
});
getRootSpec().eachFile((details) -> {
String pathString = details.getRelativePath().getPathString();
if ((pathString.startsWith("WEB-INF/lib/")
|| pathString.startsWith("WEB-INF/lib-provided/"))
&& !this.support.isZip(details.getFile())) {
details.exclude();
}
});
}

@Override
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -17,11 +17,15 @@
package org.springframework.boot.gradle.docs;

import java.io.File;
import java.io.FileOutputStream;
import java.io.FileReader;
import java.io.FileWriter;
import java.io.IOException;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;

import org.junit.Rule;
import org.junit.Test;
Expand Down Expand Up @@ -108,8 +112,8 @@ public void springBootDslMainClass() throws IOException {

@Test
public void bootWarIncludeDevtools() throws IOException {
new File(this.gradleBuild.getProjectDir(),
"spring-boot-devtools-1.2.3.RELEASE.jar").createNewFile();
jarFile(new File(this.gradleBuild.getProjectDir(),
"spring-boot-devtools-1.2.3.RELEASE.jar"));
this.gradleBuild.script("src/main/gradle/packaging/boot-war-include-devtools")
.build("bootWar");
File file = new File(this.gradleBuild.getProjectDir(),
Expand Down Expand Up @@ -196,7 +200,14 @@ public void bootJarAndJar() {
File bootJar = new File(this.gradleBuild.getProjectDir(),
"build/libs/" + this.gradleBuild.getProjectDir().getName() + "-boot.jar");
assertThat(bootJar).isFile();
}

protected void jarFile(File file) throws IOException {
try (JarOutputStream jar = new JarOutputStream(new FileOutputStream(file))) {
jar.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
new Manifest().write(jar);
jar.closeEntry();
}
}

}
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
package org.springframework.boot.gradle.tasks.bundling;

import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.nio.file.Files;
import java.nio.file.StandardOpenOption;
Expand All @@ -30,6 +31,9 @@
import java.util.Set;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
import java.util.jar.JarOutputStream;
import java.util.jar.Manifest;
import java.util.zip.ZipEntry;

import org.apache.commons.compress.archivers.zip.ZipArchiveEntry;
import org.apache.commons.compress.archivers.zip.ZipFile;
Expand Down Expand Up @@ -108,7 +112,7 @@ public void basicArchiveCreation() throws IOException {
@Test
public void classpathJarsArePackagedBeneathLibPath() throws IOException {
this.task.setMainClassName("com.example.Main");
this.task.classpath(this.temp.newFile("one.jar"), this.temp.newFile("two.jar"));
this.task.classpath(jarFile("one.jar"), jarFile("two.jar"));
this.task.execute();
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
assertThat(jarFile.getEntry(this.libPath + "/one.jar")).isNotNull();
Expand Down Expand Up @@ -160,9 +164,8 @@ public void moduleInfoClassIsPackagedInTheRootOfTheArchive() throws IOException
@Test
public void classpathCanBeSetUsingAFileCollection() throws IOException {
this.task.setMainClassName("com.example.Main");
this.task.classpath(this.temp.newFile("one.jar"));
this.task
.setClasspath(this.task.getProject().files(this.temp.newFile("two.jar")));
this.task.classpath(jarFile("one.jar"));
this.task.setClasspath(this.task.getProject().files(jarFile("two.jar")));
this.task.execute();
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
assertThat(jarFile.getEntry(this.libPath + "/one.jar")).isNull();
Expand All @@ -173,15 +176,25 @@ public void classpathCanBeSetUsingAFileCollection() throws IOException {
@Test
public void classpathCanBeSetUsingAnObject() throws IOException {
this.task.setMainClassName("com.example.Main");
this.task.classpath(this.temp.newFile("one.jar"));
this.task.setClasspath(this.temp.newFile("two.jar"));
this.task.classpath(jarFile("one.jar"));
this.task.setClasspath(jarFile("two.jar"));
this.task.execute();
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
assertThat(jarFile.getEntry(this.libPath + "/one.jar")).isNull();
assertThat(jarFile.getEntry(this.libPath + "/two.jar")).isNotNull();
}
}

@Test
public void filesOnTheClasspathThatAreNotZipFilesAreSkipped() throws IOException {
this.task.setMainClassName("com.example.Main");
this.task.classpath(this.temp.newFile("test.pom"));
this.task.execute();
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
assertThat(jarFile.getEntry(this.libPath + "/test.pom")).isNull();
}
}

@Test
public void loaderIsWrittenToTheRootOfTheJar() throws IOException {
this.task.setMainClassName("com.example.Main");
Expand Down Expand Up @@ -212,7 +225,7 @@ public void loaderIsWrittenToTheRootOfTheJarWhenUsingThePropertiesLauncher()
@Test
public void unpackCommentIsAddedToEntryIdentifiedByAPattern() throws IOException {
this.task.setMainClassName("com.example.Main");
this.task.classpath(this.temp.newFile("one.jar"), this.temp.newFile("two.jar"));
this.task.classpath(jarFile("one.jar"), jarFile("two.jar"));
this.task.requiresUnpack("**/one.jar");
this.task.execute();
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
Expand All @@ -225,7 +238,7 @@ public void unpackCommentIsAddedToEntryIdentifiedByAPattern() throws IOException
@Test
public void unpackCommentIsAddedToEntryIdentifiedByASpec() throws IOException {
this.task.setMainClassName("com.example.Main");
this.task.classpath(this.temp.newFile("one.jar"), this.temp.newFile("two.jar"));
this.task.classpath(jarFile("one.jar"), jarFile("two.jar"));
this.task.requiresUnpack((element) -> element.getName().endsWith("two.jar"));
this.task.execute();
try (JarFile jarFile = new JarFile(this.task.getArchivePath())) {
Expand Down Expand Up @@ -370,7 +383,7 @@ public void devtoolsJarIsExcludedByDefault() throws IOException {
@Test
public void devtoolsJarCanBeIncluded() throws IOException {
this.task.setMainClassName("com.example.Main");
this.task.classpath(this.temp.newFile("spring-boot-devtools-0.1.2.jar"));
this.task.classpath(jarFile("spring-boot-devtools-0.1.2.jar"));
this.task.setExcludeDevtools(false);
this.task.execute();
assertThat(this.task.getArchivePath()).exists();
Expand Down Expand Up @@ -410,9 +423,8 @@ public void loaderIsWrittenFirstThenApplicationClassesThenLibraries()
"com/example/Application.class");
applicationClass.getParentFile().mkdirs();
applicationClass.createNewFile();
this.task.classpath(classpathFolder, this.temp.newFile("first-library.jar"),
this.temp.newFile("second-library.jar"),
this.temp.newFile("third-library.jar"));
this.task.classpath(classpathFolder, jarFile("first-library.jar"),
jarFile("second-library.jar"), jarFile("third-library.jar"));
this.task.requiresUnpack("second-library.jar");
this.task.execute();
assertThat(getEntryNames(this.task.getArchivePath())).containsSubsequence(
Expand All @@ -422,6 +434,16 @@ public void loaderIsWrittenFirstThenApplicationClassesThenLibraries()
this.libPath + "/third-library.jar");
}

protected File jarFile(String name) throws IOException {
File file = this.temp.newFile(name);
try (JarOutputStream jar = new JarOutputStream(new FileOutputStream(file))) {
jar.putNextEntry(new ZipEntry("META-INF/MANIFEST.MF"));
new Manifest().write(jar);
jar.closeEntry();
}
return file;
}

private T configure(T task) throws IOException {
AbstractArchiveTask archiveTask = task;
archiveTask.setBaseName("test");
Expand Down
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/*
* Copyright 2012-2018 the original author or authors.
* 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.
Expand Down Expand Up @@ -39,8 +39,7 @@ public BootWarTests() {
@Test
public void providedClasspathJarsArePackagedInWebInfLibProvided() throws IOException {
getTask().setMainClassName("com.example.Main");
getTask().providedClasspath(this.temp.newFile("one.jar"),
this.temp.newFile("two.jar"));
getTask().providedClasspath(jarFile("one.jar"), jarFile("two.jar"));
getTask().execute();
try (JarFile jarFile = new JarFile(getTask().getArchivePath())) {
assertThat(jarFile.getEntry("WEB-INF/lib-provided/one.jar")).isNotNull();
Expand All @@ -51,9 +50,8 @@ public void providedClasspathJarsArePackagedInWebInfLibProvided() throws IOExcep
@Test
public void providedClasspathCanBeSetUsingAFileCollection() throws IOException {
getTask().setMainClassName("com.example.Main");
getTask().providedClasspath(this.temp.newFile("one.jar"));
getTask().setProvidedClasspath(
getTask().getProject().files(this.temp.newFile("two.jar")));
getTask().providedClasspath(jarFile("one.jar"));
getTask().setProvidedClasspath(getTask().getProject().files(jarFile("two.jar")));
getTask().execute();
try (JarFile jarFile = new JarFile(getTask().getArchivePath())) {
assertThat(jarFile.getEntry("WEB-INF/lib-provided/one.jar")).isNull();
Expand All @@ -64,8 +62,8 @@ public void providedClasspathCanBeSetUsingAFileCollection() throws IOException {
@Test
public void providedClasspathCanBeSetUsingAnObject() throws IOException {
getTask().setMainClassName("com.example.Main");
getTask().providedClasspath(this.temp.newFile("one.jar"));
getTask().setProvidedClasspath(this.temp.newFile("two.jar"));
getTask().providedClasspath(jarFile("one.jar"));
getTask().setProvidedClasspath(jarFile("two.jar"));
getTask().execute();
try (JarFile jarFile = new JarFile(getTask().getArchivePath())) {
assertThat(jarFile.getEntry("WEB-INF/lib-provided/one.jar")).isNull();
Expand All @@ -91,7 +89,7 @@ public void devtoolsJarIsExcludedByDefaultWhenItsOnTheProvidedClasspath()
public void devtoolsJarCanBeIncludedWhenItsOnTheProvidedClasspath()
throws IOException {
getTask().setMainClassName("com.example.Main");
getTask().providedClasspath(this.temp.newFile("spring-boot-devtools-0.1.2.jar"));
getTask().providedClasspath(jarFile("spring-boot-devtools-0.1.2.jar"));
getTask().setExcludeDevtools(false);
getTask().execute();
assertThat(getTask().getArchivePath()).exists();
Expand Down Expand Up @@ -122,8 +120,8 @@ public void webappResourcesInDirectoriesThatOverlapWithLoaderCanBePackaged()
@Test
public void libProvidedEntriesAreWrittenAfterLibEntries() throws IOException {
getTask().setMainClassName("com.example.Main");
getTask().classpath(this.temp.newFile("library.jar"));
getTask().providedClasspath(this.temp.newFile("provided-library.jar"));
getTask().classpath(jarFile("library.jar"));
getTask().providedClasspath(jarFile("provided-library.jar"));
getTask().execute();
assertThat(getEntryNames(getTask().getArchivePath())).containsSubsequence(
"WEB-INF/lib/library.jar", "WEB-INF/lib-provided/provided-library.jar");
Expand Down

0 comments on commit 59430a2

Please sign in to comment.