Skip to content

Commit 288f5ce

Browse files
committed
Fix zip compression of libs in layered jars
Closes gh-19792
1 parent 0bd0b2a commit 288f5ce

File tree

3 files changed

+41
-7
lines changed

3 files changed

+41
-7
lines changed

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/main/java/org/springframework/boot/gradle/tasks/bundling/BootJar.java

Lines changed: 18 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,10 @@
2323
import java.util.ArrayList;
2424
import java.util.Collections;
2525
import java.util.List;
26+
import java.util.Set;
2627
import java.util.concurrent.Callable;
28+
import java.util.stream.Collectors;
29+
import java.util.stream.StreamSupport;
2730

2831
import org.gradle.api.Action;
2932
import org.gradle.api.file.CopySpec;
@@ -282,18 +285,29 @@ public CopySpec bootInf(Action<CopySpec> action) {
282285
* Returns the {@link ZipCompression} that should be used when adding the file
283286
* represented by the given {@code details} to the jar.
284287
* <p>
285-
* By default, any file in {@code BOOT-INF/lib/} is stored and all other files are
286-
* deflated.
288+
* By default, any file in {@code BOOT-INF/lib/} or
289+
* {@code BOOT-INF/layers/<layer>/lib} is stored and all other files are deflated.
287290
* @param details the details
288291
* @return the compression to use
289292
*/
290293
protected ZipCompression resolveZipCompression(FileCopyDetails details) {
291-
if (details.getRelativePath().getPathString().startsWith("BOOT-INF/lib/")) {
292-
return ZipCompression.STORED;
294+
String path = details.getRelativePath().getPathString();
295+
for (String prefix : getLibPathPrefixes()) {
296+
if (path.startsWith(prefix)) {
297+
return ZipCompression.STORED;
298+
}
293299
}
294300
return ZipCompression.DEFLATED;
295301
}
296302

303+
private Set<String> getLibPathPrefixes() {
304+
if (this.layers == null) {
305+
return Collections.singleton("BOOT-INF/lib/");
306+
}
307+
return StreamSupport.stream(this.layers.spliterator(), false)
308+
.map((layer) -> "BOOT-INF/layers/" + layer + "/lib/").collect(Collectors.toSet());
309+
}
310+
297311
private LaunchScriptConfiguration enableLaunchScriptIfNecessary() {
298312
LaunchScriptConfiguration launchScript = this.support.getLaunchScript();
299313
if (launchScript == null) {

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/AbstractBootArchiveTests.java

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -110,13 +110,15 @@ void basicArchiveCreation() throws IOException {
110110
}
111111

112112
@Test
113-
void classpathJarsArePackagedBeneathLibPath() throws IOException {
113+
void classpathJarsArePackagedBeneathLibPathAndAreStored() throws IOException {
114114
this.task.setMainClassName("com.example.Main");
115115
this.task.classpath(jarFile("one.jar"), jarFile("two.jar"));
116116
executeTask();
117117
try (JarFile jarFile = new JarFile(this.task.getArchiveFile().get().getAsFile())) {
118-
assertThat(jarFile.getEntry(this.libPath + "one.jar")).isNotNull();
119-
assertThat(jarFile.getEntry(this.libPath + "two.jar")).isNotNull();
118+
assertThat(jarFile.getEntry(this.libPath + "one.jar")).isNotNull().extracting(ZipEntry::getMethod)
119+
.isEqualTo(ZipEntry.STORED);
120+
assertThat(jarFile.getEntry(this.libPath + "two.jar")).isNotNull().extracting(ZipEntry::getMethod)
121+
.isEqualTo(ZipEntry.STORED);
120122
}
121123
}
122124

@@ -409,6 +411,11 @@ void loaderIsWrittenFirstThenApplicationClassesThenLibraries() throws IOExceptio
409411
this.libPath + "third-library.jar");
410412
}
411413

414+
@Test
415+
void libEntriesAreStored() throws IOException {
416+
417+
}
418+
412419
protected File jarFile(String name) throws IOException {
413420
File file = newFile(name);
414421
try (JarOutputStream jar = new JarOutputStream(new FileOutputStream(file))) {

spring-boot-project/spring-boot-tools/spring-boot-gradle-plugin/src/test/java/org/springframework/boot/gradle/tasks/bundling/BootJarTests.java

Lines changed: 13 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@
2323
import java.util.List;
2424
import java.util.jar.JarFile;
2525
import java.util.stream.Collectors;
26+
import java.util.zip.ZipEntry;
2627

2728
import org.junit.jupiter.api.Test;
2829

@@ -100,6 +101,18 @@ void whenJarIsLayeredThenContentsAreMovedToLayerDirectories() throws IOException
100101
.contains("BOOT-INF/layers/resources/classes/static/test.css");
101102
}
102103

104+
@Test
105+
void whenJarIsLayeredJarsInLibAreStored() throws IOException {
106+
try (JarFile jarFile = new JarFile(createLayeredJar())) {
107+
assertThat(jarFile.getEntry("BOOT-INF/layers/dependencies/lib/first-library.jar").getMethod())
108+
.isEqualTo(ZipEntry.STORED);
109+
assertThat(jarFile.getEntry("BOOT-INF/layers/dependencies/lib/second-library.jar").getMethod())
110+
.isEqualTo(ZipEntry.STORED);
111+
assertThat(jarFile.getEntry("BOOT-INF/layers/snapshot-dependencies/lib/third-library-SNAPSHOT.jar")
112+
.getMethod()).isEqualTo(ZipEntry.STORED);
113+
}
114+
}
115+
103116
@Test
104117
void whenJarIsLayeredClasspathIndexPointsToLayeredLibs() throws IOException {
105118
try (JarFile jarFile = new JarFile(createLayeredJar())) {

0 commit comments

Comments
 (0)