Ensure JarFile created for nested entry InputStream is closed
Closes gh-17127
This commit is contained in:
parent
29d1cd3b2d
commit
048be1813e
|
@ -19,6 +19,7 @@ package org.springframework.boot.loader.jar;
|
|||
import java.io.ByteArrayOutputStream;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.FilePermission;
|
||||
import java.io.FilterInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.UnsupportedEncodingException;
|
||||
|
@ -80,14 +81,18 @@ final class JarURLConnection extends java.net.JarURLConnection {
|
|||
|
||||
private final JarEntryName jarEntryName;
|
||||
|
||||
private final CloseAction closeAction;
|
||||
|
||||
private JarEntry jarEntry;
|
||||
|
||||
private JarURLConnection(URL url, JarFile jarFile, JarEntryName jarEntryName) throws IOException {
|
||||
private JarURLConnection(URL url, JarFile jarFile, JarEntryName jarEntryName, CloseAction closeAction)
|
||||
throws IOException {
|
||||
// What we pass to super is ultimately ignored
|
||||
super(EMPTY_JAR_URL);
|
||||
this.url = url;
|
||||
this.jarFile = jarFile;
|
||||
this.jarEntryName = jarEntryName;
|
||||
this.closeAction = closeAction;
|
||||
}
|
||||
|
||||
@Override
|
||||
|
@ -168,7 +173,17 @@ final class JarURLConnection extends java.net.JarURLConnection {
|
|||
if (inputStream == null) {
|
||||
throwFileNotFound(this.jarEntryName, this.jarFile);
|
||||
}
|
||||
return inputStream;
|
||||
return new FilterInputStream(inputStream) {
|
||||
|
||||
@Override
|
||||
public void close() throws IOException {
|
||||
super.close();
|
||||
if (JarURLConnection.this.closeAction != null) {
|
||||
JarURLConnection.this.closeAction.perform();
|
||||
}
|
||||
}
|
||||
|
||||
};
|
||||
}
|
||||
|
||||
private void throwFileNotFound(Object entry, JarFile jarFile) throws FileNotFoundException {
|
||||
|
@ -249,24 +264,30 @@ final class JarURLConnection extends java.net.JarURLConnection {
|
|||
int index = indexOfRootSpec(spec, jarFile.getPathFromRoot());
|
||||
if (index == -1) {
|
||||
return (Boolean.TRUE.equals(useFastExceptions.get()) ? NOT_FOUND_CONNECTION
|
||||
: new JarURLConnection(url, null, EMPTY_JAR_ENTRY_NAME));
|
||||
: new JarURLConnection(url, null, EMPTY_JAR_ENTRY_NAME, null));
|
||||
}
|
||||
int separator;
|
||||
JarFile connectionJarFile = jarFile;
|
||||
while ((separator = spec.indexOf(SEPARATOR, index)) > 0) {
|
||||
JarEntryName entryName = JarEntryName.get(spec.subSequence(index, separator));
|
||||
JarEntry jarEntry = jarFile.getJarEntry(entryName.toCharSequence());
|
||||
if (jarEntry == null) {
|
||||
return JarURLConnection.notFound(jarFile, entryName);
|
||||
return JarURLConnection.notFound(connectionJarFile, entryName,
|
||||
(connectionJarFile != jarFile) ? connectionJarFile::close : null);
|
||||
}
|
||||
jarFile = jarFile.getNestedJarFile(jarEntry);
|
||||
connectionJarFile = connectionJarFile.getNestedJarFile(jarEntry);
|
||||
index = separator + SEPARATOR.length();
|
||||
}
|
||||
JarEntryName jarEntryName = JarEntryName.get(spec, index);
|
||||
if (Boolean.TRUE.equals(useFastExceptions.get()) && !jarEntryName.isEmpty()
|
||||
&& !jarFile.containsEntry(jarEntryName.toString())) {
|
||||
&& !connectionJarFile.containsEntry(jarEntryName.toString())) {
|
||||
if (connectionJarFile != jarFile) {
|
||||
connectionJarFile.close();
|
||||
}
|
||||
return NOT_FOUND_CONNECTION;
|
||||
}
|
||||
return new JarURLConnection(url, jarFile, jarEntryName);
|
||||
return new JarURLConnection(url, connectionJarFile, jarEntryName,
|
||||
(connectionJarFile != jarFile) ? connectionJarFile::close : null);
|
||||
}
|
||||
|
||||
private static int indexOfRootSpec(StringSequence file, String pathFromRoot) {
|
||||
|
@ -279,18 +300,22 @@ final class JarURLConnection extends java.net.JarURLConnection {
|
|||
|
||||
private static JarURLConnection notFound() {
|
||||
try {
|
||||
return notFound(null, null);
|
||||
return notFound(null, null, null);
|
||||
}
|
||||
catch (IOException ex) {
|
||||
throw new IllegalStateException(ex);
|
||||
}
|
||||
}
|
||||
|
||||
private static JarURLConnection notFound(JarFile jarFile, JarEntryName jarEntryName) throws IOException {
|
||||
private static JarURLConnection notFound(JarFile jarFile, JarEntryName jarEntryName, CloseAction closeAction)
|
||||
throws IOException {
|
||||
if (Boolean.TRUE.equals(useFastExceptions.get())) {
|
||||
if (closeAction != null) {
|
||||
closeAction.perform();
|
||||
}
|
||||
return NOT_FOUND_CONNECTION;
|
||||
}
|
||||
return new JarURLConnection(null, jarFile, jarEntryName);
|
||||
return new JarURLConnection(null, jarFile, jarEntryName, closeAction);
|
||||
}
|
||||
|
||||
/**
|
||||
|
@ -393,4 +418,15 @@ final class JarURLConnection extends java.net.JarURLConnection {
|
|||
|
||||
}
|
||||
|
||||
/**
|
||||
* An action to be taken when the connection is being "closed" and its underlying
|
||||
* resources are no longer needed.
|
||||
*/
|
||||
@FunctionalInterface
|
||||
private interface CloseAction {
|
||||
|
||||
void perform() throws IOException;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue