Don't close jar files early

Update `JarFile` and related classes so that `close()` is not longer
called early.

Prior to this commit, we would always immediately close the underlying
jar file to prevent file locking issues with our build. This causes
issues on certain JVMs when they attempt to verify a signed jar.

The file lock issues have now been solved by returning a custom input
stream from `JarUrlConnection` which captures and delegates the close
method.

Fixes gh-29356
This commit is contained in:
Phillip Webb
2022-06-14 20:46:51 -07:00
parent 49b71005de
commit b42f056ddb
9 changed files with 158 additions and 28 deletions

View File

@@ -51,7 +51,7 @@ class LoaderIntegrationTests {
@ParameterizedTest
@MethodSource("javaRuntimes")
void readUrlsWithoutWarning(JavaRuntime javaRuntime) {
try (GenericContainer<?> container = createContainer(javaRuntime)) {
try (GenericContainer<?> container = createContainer(javaRuntime, "spring-boot-loader-tests-app")) {
container.start();
System.out.println(this.output.toUtf8String());
assertThat(this.output.toUtf8String()).contains(">>>>> 287649 BYTES from").doesNotContain("WARNING:")
@@ -59,17 +59,32 @@ class LoaderIntegrationTests {
}
}
private GenericContainer<?> createContainer(JavaRuntime javaRuntime) {
@ParameterizedTest
@MethodSource("javaRuntimes")
void runSignedJarWhenUnpacked(JavaRuntime javaRuntime) {
try (GenericContainer<?> container = createContainer(javaRuntime,
"spring-boot-loader-tests-signed-jar-unpack-app")) {
container.start();
System.out.println(this.output.toUtf8String());
assertThat(this.output.toUtf8String()).contains("Legion of the Bouncy Castle");
}
}
private GenericContainer<?> createContainer(JavaRuntime javaRuntime, String name) {
return javaRuntime.getContainer().withLogConsumer(this.output)
.withCopyFileToContainer(MountableFile.forHostPath(findApplication().toPath()), "/app.jar")
.withCopyFileToContainer(findApplication(name), "/app.jar")
.withStartupCheckStrategy(new OneShotStartupCheckStrategy().withTimeout(Duration.ofMinutes(5)))
.withCommand("java", "-jar", "app.jar");
}
private File findApplication() {
String name = String.format("build/%1$s/build/libs/%1$s.jar", "spring-boot-loader-tests-app");
File jar = new File(name);
Assert.state(jar.isFile(), () -> "Could not find " + name + ". Have you built it?");
private MountableFile findApplication(String name) {
return MountableFile.forHostPath(findJarFile(name).toPath());
}
private File findJarFile(String name) {
String path = String.format("build/%1$s/build/libs/%1$s.jar", name);
File jar = new File(path);
Assert.state(jar.isFile(), () -> "Could not find " + path + ". Have you built it?");
return jar;
}