Skip to content

Commit 41b01cc

Browse files
committed
Only write parent entries when entry is new
Previously, when writing a repackaged jar, an attempt to write all of an entry's parent directories would always be made, irrespective of whether or not the entry itself had already been written. This was inefficient as, due to the way that the jar is written, once an entry itself has been written, we know that all of its parent directories will also have been written. This commit updates the jar writer so that no attempt is made to write parent directory entries if the entry itself has already been written. Fixes spring-projectsgh-29175
1 parent 9a6f35c commit 41b01cc

File tree

2 files changed

+16
-3
lines changed

2 files changed

+16
-3
lines changed

spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/main/java/org/springframework/boot/loader/tools/AbstractJarWriter.java

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2021 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -265,8 +265,8 @@ private void writeEntry(JarArchiveEntry entry, EntryWriter entryWriter) throws I
265265
private void writeEntry(JarArchiveEntry entry, Library library, EntryWriter entryWriter,
266266
UnpackHandler unpackHandler) throws IOException {
267267
String name = entry.getName();
268-
writeParentDirectoryEntries(name);
269268
if (this.writtenEntries.add(name)) {
269+
writeParentDirectoryEntries(name);
270270
entry.setUnixMode(name.endsWith("/") ? UNIX_DIR_MODE : UNIX_FILE_MODE);
271271
entry.getGeneralPurposeBit().useUTF8ForNames(true);
272272
if (!entry.isDirectory() && entry.getSize() == -1) {

spring-boot-project/spring-boot-tools/spring-boot-loader-tools/src/test/java/org/springframework/boot/loader/tools/RepackagerTests.java

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2020 the original author or authors.
2+
* Copyright 2012-2022 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -38,6 +38,7 @@
3838

3939
import org.springframework.boot.loader.tools.sample.ClassWithMainMethod;
4040
import org.springframework.util.FileCopyUtils;
41+
import org.springframework.util.StopWatch;
4142
import org.springframework.util.StringUtils;
4243

4344
import static org.assertj.core.api.Assertions.assertThat;
@@ -198,6 +199,18 @@ void allEntriesUseProvidedTimestamp() throws IOException {
198199
}
199200
}
200201

202+
@Test
203+
void repackagingDeeplyNestedPackageIsNotProhibitivelySlow() throws IOException {
204+
StopWatch stopWatch = new StopWatch();
205+
stopWatch.start();
206+
this.testJarFile.addClass("a/b/c/d/e/f/g/h/i/j/k/l/m/n/o/p/q/r/s/t/u/v/w/x/y/z/Some.class",
207+
ClassWithMainMethod.class);
208+
Repackager repackager = createRepackager(this.testJarFile.getFile(), true);
209+
repackager.repackage(this.destination, NO_LIBRARIES, null, null);
210+
stopWatch.stop();
211+
assertThat(stopWatch.getTotalTimeMillis()).isLessThan(5000);
212+
}
213+
201214
private boolean hasLauncherClasses(File file) throws IOException {
202215
return hasEntry(file, "org/springframework/boot/")
203216
&& hasEntry(file, "org/springframework/boot/loader/JarLauncher.class");

0 commit comments

Comments
 (0)