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 gh-29175
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2021 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
@@ -265,8 +265,8 @@ public abstract class AbstractJarWriter implements LoaderClassesWriter {
|
||||
private void writeEntry(JarArchiveEntry entry, Library library, EntryWriter entryWriter,
|
||||
UnpackHandler unpackHandler) throws IOException {
|
||||
String name = entry.getName();
|
||||
writeParentDirectoryEntries(name);
|
||||
if (this.writtenEntries.add(name)) {
|
||||
writeParentDirectoryEntries(name);
|
||||
entry.setUnixMode(name.endsWith("/") ? UNIX_DIR_MODE : UNIX_FILE_MODE);
|
||||
entry.getGeneralPurposeBit().useUTF8ForNames(true);
|
||||
if (!entry.isDirectory() && entry.getSize() == -1) {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2012-2020 the original author or authors.
|
||||
* Copyright 2012-2022 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.
|
||||
@@ -38,6 +38,7 @@ import org.junit.jupiter.api.Test;
|
||||
|
||||
import org.springframework.boot.loader.tools.sample.ClassWithMainMethod;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.StopWatch;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
import static org.assertj.core.api.Assertions.assertThat;
|
||||
@@ -198,6 +199,18 @@ class RepackagerTests extends AbstractPackagerTests<Repackager> {
|
||||
}
|
||||
}
|
||||
|
||||
@Test
|
||||
void repackagingDeeplyNestedPackageIsNotProhibitivelySlow() throws IOException {
|
||||
StopWatch stopWatch = new StopWatch();
|
||||
stopWatch.start();
|
||||
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",
|
||||
ClassWithMainMethod.class);
|
||||
Repackager repackager = createRepackager(this.testJarFile.getFile(), true);
|
||||
repackager.repackage(this.destination, NO_LIBRARIES, null, null);
|
||||
stopWatch.stop();
|
||||
assertThat(stopWatch.getTotalTimeMillis()).isLessThan(5000);
|
||||
}
|
||||
|
||||
private boolean hasLauncherClasses(File file) throws IOException {
|
||||
return hasEntry(file, "org/springframework/boot/")
|
||||
&& hasEntry(file, "org/springframework/boot/loader/JarLauncher.class");
|
||||
|
||||
Reference in New Issue
Block a user