From 503aae8c7c9727df5c77d9b71dba75845161cffa Mon Sep 17 00:00:00 2001 From: shartte Date: Sun, 2 Jun 2024 23:44:14 +0200 Subject: [PATCH] Add close() methods throughout the SecureJar->JarContents chain to allow closing the backing file systems (#68) --- .../java/cpw/mods/jarhandling/JarContents.java | 4 +++- .../java/cpw/mods/jarhandling/SecureJar.java | 10 ++++++---- .../java/cpw/mods/jarhandling/VirtualJar.java | 6 ++++++ .../java/cpw/mods/jarhandling/impl/Jar.java | 7 ++++++- .../mods/jarhandling/impl/JarContentsImpl.java | 6 +++++- .../cpw/mods/niofs/union/UnionFileSystem.java | 17 ++++++++++++++++- .../jarhandling/impl/TestDummyJarProvider.java | 6 ++++-- .../cpw/mods/jarhandling/impl/TestMetadata.java | 4 ++++ 8 files changed, 50 insertions(+), 10 deletions(-) diff --git a/src/main/java/cpw/mods/jarhandling/JarContents.java b/src/main/java/cpw/mods/jarhandling/JarContents.java index a9bf818..da4366c 100644 --- a/src/main/java/cpw/mods/jarhandling/JarContents.java +++ b/src/main/java/cpw/mods/jarhandling/JarContents.java @@ -2,6 +2,8 @@ import org.jetbrains.annotations.ApiStatus; +import java.io.Closeable; +import java.io.IOException; import java.net.URI; import java.nio.file.Path; import java.util.Collection; @@ -18,7 +20,7 @@ * Convert to a full jar with {@link SecureJar#from(JarContents)}. */ @ApiStatus.NonExtendable -public interface JarContents { +public interface JarContents extends Closeable { /** * @see SecureJar#getPrimaryPath() */ diff --git a/src/main/java/cpw/mods/jarhandling/SecureJar.java b/src/main/java/cpw/mods/jarhandling/SecureJar.java index 75d443e..40cfcad 100644 --- a/src/main/java/cpw/mods/jarhandling/SecureJar.java +++ b/src/main/java/cpw/mods/jarhandling/SecureJar.java @@ -17,10 +17,6 @@ import java.security.CodeSigner; import java.util.List; import java.util.Optional; -import java.util.Set; -import java.util.function.BiPredicate; -import java.util.function.Function; -import java.util.function.Supplier; import java.util.jar.Attributes; import java.util.jar.Manifest; @@ -86,6 +82,12 @@ static SecureJar from(JarContents contents, JarMetadata metadata) { */ Path getRootPath(); + /** + * Closes the underlying file system resources (if any). + * Renders this object unusable. + */ + void close() throws IOException; + /** * All the functions that are necessary to turn a {@link SecureJar} into a module. */ diff --git a/src/main/java/cpw/mods/jarhandling/VirtualJar.java b/src/main/java/cpw/mods/jarhandling/VirtualJar.java index f6fc84c..5b22482 100644 --- a/src/main/java/cpw/mods/jarhandling/VirtualJar.java +++ b/src/main/java/cpw/mods/jarhandling/VirtualJar.java @@ -4,6 +4,7 @@ import cpw.mods.niofs.union.UnionFileSystemProvider; import org.jetbrains.annotations.Nullable; +import java.io.IOException; import java.io.InputStream; import java.lang.module.ModuleDescriptor; import java.net.URI; @@ -106,6 +107,11 @@ public Path getRootPath() { return dummyFileSystem.getRoot(); } + @Override + public void close() throws IOException { + dummyFileSystem.close(); + } + private class VirtualJarModuleDataProvider implements ModuleDataProvider { @Override public String name() { diff --git a/src/main/java/cpw/mods/jarhandling/impl/Jar.java b/src/main/java/cpw/mods/jarhandling/impl/Jar.java index 7ec50eb..c970e4e 100644 --- a/src/main/java/cpw/mods/jarhandling/impl/Jar.java +++ b/src/main/java/cpw/mods/jarhandling/impl/Jar.java @@ -3,10 +3,10 @@ import cpw.mods.jarhandling.JarMetadata; import cpw.mods.jarhandling.SecureJar; import cpw.mods.niofs.union.UnionFileSystem; -import cpw.mods.niofs.union.UnionPathFilter; import cpw.mods.util.LambdaExceptionUtils; import org.jetbrains.annotations.Nullable; +import java.io.IOException; import java.io.InputStream; import java.lang.module.ModuleDescriptor; import java.net.URI; @@ -104,6 +104,11 @@ public Path getRootPath() { return filesystem.getPath(""); } + @Override + public void close() throws IOException { + contents.close(); + } + @Override public String toString() { return "Jar[" + getURI() + "]"; diff --git a/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java b/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java index 2100d12..d198444 100644 --- a/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java +++ b/src/main/java/cpw/mods/jarhandling/impl/JarContentsImpl.java @@ -23,7 +23,6 @@ import java.util.Map; import java.util.Optional; import java.util.Set; -import java.util.function.BiPredicate; import java.util.function.Supplier; import java.util.jar.JarFile; import java.util.jar.JarInputStream; @@ -218,4 +217,9 @@ public List getMetaInfServices() { } return this.providers; } + + @Override + public void close() throws IOException { + filesystem.close(); + } } diff --git a/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java b/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java index a89da3e..4db42d7 100644 --- a/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java +++ b/src/main/java/cpw/mods/niofs/union/UnionFileSystem.java @@ -155,8 +155,23 @@ public UnionFileSystemProvider provider() { } @Override - public void close() { + public void close() throws IOException { provider().removeFileSystem(this); + IOException closeException = null; + for (var embeddedFs : embeddedFileSystems.values()) { + try { + embeddedFs.fs.close(); + } catch (IOException e) { + if (closeException != null) { + closeException.addSuppressed(e); + } else { + closeException = e; + } + } + } + if (closeException != null) { + throw closeException; + } } @Override diff --git a/src/test/java/cpw/mods/jarhandling/impl/TestDummyJarProvider.java b/src/test/java/cpw/mods/jarhandling/impl/TestDummyJarProvider.java index e67909b..ccba0c9 100644 --- a/src/test/java/cpw/mods/jarhandling/impl/TestDummyJarProvider.java +++ b/src/test/java/cpw/mods/jarhandling/impl/TestDummyJarProvider.java @@ -13,11 +13,9 @@ import java.lang.module.Configuration; import java.lang.module.ModuleDescriptor; import java.lang.module.ModuleFinder; -import java.lang.module.ResolvedModule; import java.net.URI; import java.nio.file.Path; import java.security.CodeSigner; -import java.util.Arrays; import java.util.List; import java.util.Optional; import java.util.Set; @@ -133,5 +131,9 @@ public Path getPath(final String first, final String... rest) { public Path getRootPath() { return null; } + + @Override + public void close() { + } } } diff --git a/src/test/java/cpw/mods/jarhandling/impl/TestMetadata.java b/src/test/java/cpw/mods/jarhandling/impl/TestMetadata.java index 2eb4d76..c762629 100644 --- a/src/test/java/cpw/mods/jarhandling/impl/TestMetadata.java +++ b/src/test/java/cpw/mods/jarhandling/impl/TestMetadata.java @@ -70,5 +70,9 @@ public Set getPackagesExcluding(String... excludedRootPackages) { public List getMetaInfServices() { return List.of(); } + + @Override + public void close() { + } } }