diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java
index 3088613fe9..e249ff4e75 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java
+++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java
@@ -23,7 +23,10 @@ import java.io.StringWriter;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
+import java.util.Set;
import java.util.concurrent.Callable;
+import java.util.stream.Collectors;
+import java.util.stream.StreamSupport;
import org.gradle.api.Action;
import org.gradle.api.file.CopySpec;
@@ -282,18 +285,29 @@ public class BootJar extends Jar implements BootArchive {
* Returns the {@link ZipCompression} that should be used when adding the file
* represented by the given {@code details} to the jar.
*
- * By default, any file in {@code BOOT-INF/lib/} is stored and all other files are
- * deflated.
+ * By default, any file in {@code BOOT-INF/lib/} or
+ * {@code BOOT-INF/layers//lib} is stored and all other files are deflated.
* @param details the details
* @return the compression to use
*/
protected ZipCompression resolveZipCompression(FileCopyDetails details) {
- if (details.getRelativePath().getPathString().startsWith("BOOT-INF/lib/")) {
- return ZipCompression.STORED;
+ String path = details.getRelativePath().getPathString();
+ for (String prefix : getLibPathPrefixes()) {
+ if (path.startsWith(prefix)) {
+ return ZipCompression.STORED;
+ }
}
return ZipCompression.DEFLATED;
}
+ private Set getLibPathPrefixes() {
+ if (this.layers == null) {
+ return Collections.singleton("BOOT-INF/lib/");
+ }
+ return StreamSupport.stream(this.layers.spliterator(), false)
+ .map((layer) -> "BOOT-INF/layers/" + layer + "/lib/").collect(Collectors.toSet());
+ }
+
private LaunchScriptConfiguration enableLaunchScriptIfNecessary() {
LaunchScriptConfiguration launchScript = this.support.getLaunchScript();
if (launchScript == null) {
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java
index b5f7b0748a..ffffa2f585 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java
+++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java
@@ -110,13 +110,15 @@ abstract class AbstractBootArchiveTests {
}
@Test
- void classpathJarsArePackagedBeneathLibPath() throws IOException {
+ void classpathJarsArePackagedBeneathLibPathAndAreStored() throws IOException {
this.task.setMainClassName("com.example.Main");
this.task.classpath(jarFile("one.jar"), jarFile("two.jar"));
executeTask();
try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) {
- assertThat(jarFile.getEntry(this.libPath + "one.jar")).isNotNull();
- assertThat(jarFile.getEntry(this.libPath + "two.jar")).isNotNull();
+ assertThat(jarFile.getEntry(this.libPath + "one.jar")).isNotNull().extracting(ZipEntry::getMethod)
+ .isEqualTo(ZipEntry.STORED);
+ assertThat(jarFile.getEntry(this.libPath + "two.jar")).isNotNull().extracting(ZipEntry::getMethod)
+ .isEqualTo(ZipEntry.STORED);
}
}
@@ -409,6 +411,11 @@ abstract class AbstractBootArchiveTests {
this.libPath + "third-library.jar");
}
+ @Test
+ void libEntriesAreStored() throws IOException {
+
+ }
+
protected File jarFile(String name) throws IOException {
File file = newFile(name);
try (JarOutputStream jar = new JarOutputStream(new FileOutputStream(file))) {
diff --git a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarTests.java b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarTests.java
index 8738ad0d2d..4bb8dc037d 100644
--- a/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarTests.java
+++ b/spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarTests.java
@@ -23,6 +23,7 @@ import java.io.InputStreamReader;
import java.util.List;
import java.util.jar.JarFile;
import java.util.stream.Collectors;
+import java.util.zip.ZipEntry;
import org.junit.jupiter.api.Test;
@@ -100,6 +101,18 @@ class BootJarTests extends AbstractBootArchiveTests {
.contains("BOOT-INF/layers/resources/classes/static/test.css");
}
+ @Test
+ void whenJarIsLayeredJarsInLibAreStored() throws IOException {
+ try (JarFile jarFile = new JarFile(createLayeredJar())) {
+ assertThat(jarFile.getEntry("BOOT-INF/layers/dependencies/lib/first-library.jar").getMethod())
+ .isEqualTo(ZipEntry.STORED);
+ assertThat(jarFile.getEntry("BOOT-INF/layers/dependencies/lib/second-library.jar").getMethod())
+ .isEqualTo(ZipEntry.STORED);
+ assertThat(jarFile.getEntry("BOOT-INF/layers/snapshot-dependencies/lib/third-library-SNAPSHOT.jar")
+ .getMethod()).isEqualTo(ZipEntry.STORED);
+ }
+ }
+
@Test
void whenJarIsLayeredClasspathIndexPointsToLayeredLibs() throws IOException {
try (JarFile jarFile = new JarFile(createLayeredJar())) {