From 8a88c00e371539d268a7d12eb959f4eacad97f7d Mon Sep 17 00:00:00 2001 From: Claus Stadler Date: Sun, 6 Oct 2024 19:52:42 +0200 Subject: [PATCH] Added improved FileSystem abstraction --- aksw-commons-bom/pom.xml | 4 +- .../org/aksw/commons/path/core/PathSys.java | 2 +- .../commons/path/nio/DirectoryStreams.java | 4 +- .../aksw/commons/path/nio/FileSystem2.java | 25 ++++ .../aksw/commons/path/nio/FileSystemSpec.java | 67 +++++++++ .../path/nio/FileSystemWithCloseShield.java | 21 +++ .../commons/path/nio/FileSystemWithSpec.java | 18 +++ .../commons/path/nio/FileSystemWrapper.java | 19 +++ .../path/nio/FileSystemWrapperBase.java | 105 ++++++++++++++ .../aksw/commons/path/nio/PathWrapper.java | 129 ++++++++++++++++++ .../commons/util/lifecycle/ResourceMgr.java | 1 - 11 files changed, 389 insertions(+), 6 deletions(-) create mode 100644 aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystem2.java create mode 100644 aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemSpec.java create mode 100644 aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWithCloseShield.java create mode 100644 aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWithSpec.java create mode 100644 aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWrapper.java create mode 100644 aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWrapperBase.java create mode 100644 aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/PathWrapper.java diff --git a/aksw-commons-bom/pom.xml b/aksw-commons-bom/pom.xml index cd4271ed..5ccba2ae 100644 --- a/aksw-commons-bom/pom.xml +++ b/aksw-commons-bom/pom.xml @@ -60,11 +60,11 @@ 3.1.8 1.7 1.16 - 2.15.0 + 2.17.0 0.0.9 5.6.0.201912101111-r - 3.3.6 + 3.4.0 2.15.2 0.8.2 diff --git a/aksw-commons-paths/src/main/java/org/aksw/commons/path/core/PathSys.java b/aksw-commons-paths/src/main/java/org/aksw/commons/path/core/PathSys.java index 33224be4..d7e69fde 100644 --- a/aksw-commons-paths/src/main/java/org/aksw/commons/path/core/PathSys.java +++ b/aksw-commons-paths/src/main/java/org/aksw/commons/path/core/PathSys.java @@ -3,6 +3,6 @@ public interface PathSys extends Path { - // @Override + @Override S getSystem(); } diff --git a/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/DirectoryStreams.java b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/DirectoryStreams.java index c960f3e3..5573b0b2 100644 --- a/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/DirectoryStreams.java +++ b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/DirectoryStreams.java @@ -41,7 +41,7 @@ public Iterator iterator() { public void close() throws IOException { base.close(); } - }; + } private static class DirectoryStreamFilter implements DirectoryStream @@ -74,5 +74,5 @@ public Iterator iterator() { public void close() throws IOException { base.close(); } - }; + } } diff --git a/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystem2.java b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystem2.java new file mode 100644 index 00000000..e656a2da --- /dev/null +++ b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystem2.java @@ -0,0 +1,25 @@ +package org.aksw.commons.path.nio; + +import java.io.IOException; +import java.nio.file.FileSystem; + +/** A nested file system. Closing the outer one also recursively closes the inner ones. */ +public class FileSystem2 + extends FileSystemWrapper +{ + protected FileSystem underlying; + + public FileSystem2(FileSystem delegate, FileSystem underlying) { + super(delegate); + this.underlying = underlying; + } + + @Override + public void close() throws IOException { + try { + super.close(); + } finally { + underlying.close(); + } + } +} diff --git a/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemSpec.java b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemSpec.java new file mode 100644 index 00000000..a7cda2c7 --- /dev/null +++ b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemSpec.java @@ -0,0 +1,67 @@ +package org.aksw.commons.path.nio; + +import java.io.IOException; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.FileSystems; +import java.nio.file.Path; +import java.util.List; +import java.util.Map; +import java.util.Objects; + +import org.aksw.commons.path.core.PathSys; + +public class FileSystemSpec { + protected Map env; + protected ClassLoader loader; + + protected URI uri; + protected PathSys basePath; + + protected FileSystemSpec(Map env, ClassLoader loader, PathSys basePath) { + super(); + this.env = env; + this.loader = loader; + this.basePath = Objects.requireNonNull(basePath); + } + + protected FileSystemSpec(Map env, ClassLoader loader, URI uri) { + super(); + this.env = env; + this.loader = loader; + this.uri = Objects.requireNonNull(uri); + } + + public static FileSystemSpec of(Map env, ClassLoader loader, URI uri) { + return new FileSystemSpec(env, loader, uri); + } + + public static FileSystemSpec of(Map env, ClassLoader loader, PathSys basePath) { + return new FileSystemSpec(env, loader, basePath); + } + + public boolean isUri() { + return uri != null; + } + + public boolean isPath() { + return basePath != null; + } + + public FileSystem resolve() throws IOException { + FileSystem result; + if (isUri()) { + result = new FileSystemWithSpec(FileSystems.newFileSystem(uri, env, loader), this); + } else { + FileSystemSpec baseSpec = basePath.getSystem(); + FileSystem baseFs = baseSpec.resolve(); + List segments = basePath.getSegments(); + String first = segments.isEmpty() ? "" : segments.get(0); + String[] rest = segments.isEmpty() ? new String[0] : segments.subList(1, segments.size()).toArray(new String[0]); + Path path = baseFs.getPath(first, rest); + FileSystem outer = new FileSystemWithSpec(FileSystems.newFileSystem(path, env, loader), this); + result = new FileSystem2(outer, baseFs); + } + return result; + } +} diff --git a/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWithCloseShield.java b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWithCloseShield.java new file mode 100644 index 00000000..7523d1b7 --- /dev/null +++ b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWithCloseShield.java @@ -0,0 +1,21 @@ +package org.aksw.commons.path.nio; + +import java.io.IOException; +import java.nio.file.FileSystem; + +public class FileSystemWithCloseShield + extends FileSystemWrapper +{ + protected FileSystemWithCloseShield(FileSystem delegate) { + super(delegate); + } + + public static FileSystem of(FileSystem delegate) { + return new FileSystemWithCloseShield(delegate); + } + + @Override + public void close() throws IOException { + // No op + } +} diff --git a/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWithSpec.java b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWithSpec.java new file mode 100644 index 00000000..0eb5cd8a --- /dev/null +++ b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWithSpec.java @@ -0,0 +1,18 @@ +package org.aksw.commons.path.nio; + +import java.nio.file.FileSystem; + +public class FileSystemWithSpec + extends FileSystemWrapper +{ + protected FileSystemSpec spec; + + public FileSystemWithSpec(FileSystem delegate, FileSystemSpec spec) { + super(delegate); + this.spec = spec; + } + + public FileSystemSpec getSpec() { + return spec; + } +} diff --git a/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWrapper.java b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWrapper.java new file mode 100644 index 00000000..74bc8fb0 --- /dev/null +++ b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWrapper.java @@ -0,0 +1,19 @@ +package org.aksw.commons.path.nio; + +import java.nio.file.FileSystem; + +public class FileSystemWrapper + extends FileSystemWrapperBase +{ + protected FileSystem delegate; + + public FileSystemWrapper(FileSystem delegate) { + super(); + this.delegate = delegate; + } + + @Override + protected FileSystem getDelegate() { + return delegate; + } +} diff --git a/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWrapperBase.java b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWrapperBase.java new file mode 100644 index 00000000..2693f30e --- /dev/null +++ b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/FileSystemWrapperBase.java @@ -0,0 +1,105 @@ +package org.aksw.commons.path.nio; + +import java.io.IOException; +import java.nio.file.FileStore; +import java.nio.file.FileSystem; +import java.nio.file.Path; +import java.nio.file.PathMatcher; +import java.nio.file.WatchService; +import java.nio.file.attribute.UserPrincipalLookupService; +import java.nio.file.spi.FileSystemProvider; +import java.util.Set; +import java.util.Spliterators; +import java.util.stream.StreamSupport; + +/** + * Base class for wrappers of file systems. + * Implementations need to implement {@link #getDelegate()}. + */ +public abstract class FileSystemWrapperBase + extends FileSystem +{ + protected abstract FileSystem getDelegate(); + + public Path wrap(Path path) { + return new PathWrapper<>(path, this); + } + + public Path unwrap(Path path) { + return unwrap(path, false); + } + + public static Path unwrap(Path path, boolean repeatedly) { + Path result = path; + while (result instanceof PathWrapper pw) { + result = pw.getDelegate(); + + if (!repeatedly) { + break; + } + } + return result; + } + + @Override + public FileSystemProvider provider() { + return getDelegate().provider(); + } + + @Override + public void close() throws IOException { + getDelegate().close(); + } + + @Override + public boolean isOpen() { + return getDelegate().isOpen(); + } + + @Override + public boolean isReadOnly() { + return getDelegate().isReadOnly(); + } + + @Override + public String getSeparator() { + return getDelegate().getSeparator(); + } + + @Override + public Iterable getRootDirectories() { + return () -> StreamSupport.stream(Spliterators.spliteratorUnknownSize(getDelegate().getRootDirectories().iterator(), 0), false) + .map(this::wrap) + .iterator(); + } + + @Override + public Iterable getFileStores() { + return getDelegate().getFileStores(); + } + + @Override + public Set supportedFileAttributeViews() { + return getDelegate().supportedFileAttributeViews(); + } + + @Override + public Path getPath(String first, String... more) { + return wrap(getDelegate().getPath(first, more)); + } + + @Override + public PathMatcher getPathMatcher(String syntaxAndPattern) { + return getDelegate().getPathMatcher(syntaxAndPattern); + } + + @Override + public UserPrincipalLookupService getUserPrincipalLookupService() { + return getDelegate().getUserPrincipalLookupService(); + } + + @Override + public WatchService newWatchService() throws IOException { + return getDelegate().newWatchService(); + } +} diff --git a/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/PathWrapper.java b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/PathWrapper.java new file mode 100644 index 00000000..b01d7c88 --- /dev/null +++ b/aksw-commons-paths/src/main/java/org/aksw/commons/path/nio/PathWrapper.java @@ -0,0 +1,129 @@ +package org.aksw.commons.path.nio; + +import java.io.IOException; +import java.net.URI; +import java.nio.file.FileSystem; +import java.nio.file.LinkOption; +import java.nio.file.Path; +import java.nio.file.WatchEvent.Kind; +import java.nio.file.WatchEvent.Modifier; +import java.nio.file.WatchKey; +import java.nio.file.WatchService; +import java.util.Objects; + +/** Wrapper for paths where the filesystem is a wrapper. */ +public class PathWrapper

+ implements Path +{ + protected Path delegate; + protected FS fileSystem; + + public PathWrapper(Path delegate, FS fileSystem) { + super(); + this.delegate = Objects.requireNonNull(delegate); + this.fileSystem = Objects.requireNonNull(fileSystem); + } + + public Path getDelegate() { + return delegate; + } + + @SuppressWarnings("unchecked") + protected P wrap(Path delegate) { + return (P)fileSystem.wrap(delegate); + } + + protected Path unwrap(Path delegate) { + return fileSystem.unwrap(delegate); + } + + @Override + public FileSystem getFileSystem() { + return fileSystem; + } + + @Override + public boolean isAbsolute() { + return getDelegate().isAbsolute(); + } + + @Override + public Path getRoot() { + return wrap(getDelegate().getRoot()); + } + + @Override + public Path getFileName() { + return wrap(getDelegate().getFileName()); + } + + @Override + public P getParent() { + return wrap(getDelegate().getParent()); + } + + @Override + public int getNameCount() { + return getDelegate().getNameCount(); + } + + @Override + public P getName(int index) { + return wrap(getDelegate().getName(index)); + } + + @Override + public P subpath(int beginIndex, int endIndex) { + return wrap(getDelegate().subpath(beginIndex, endIndex)); + } + + @Override + public boolean startsWith(Path other) { + return getDelegate().startsWith(unwrap(other)); + } + + @Override + public boolean endsWith(Path other) { + return getDelegate().endsWith(unwrap(other)); + } + + @Override + public P normalize() { + return wrap(getDelegate().normalize()); + } + + @Override + public P resolve(Path other) { + return wrap(getDelegate().resolve(unwrap(other))); + } + + @Override + public P relativize(Path other) { + return wrap(getDelegate().relativize(unwrap(other))); + } + + @Override + public URI toUri() { + return getDelegate().toUri(); + } + + @Override + public P toAbsolutePath() { + return wrap(getDelegate().toAbsolutePath()); + } + + @Override + public P toRealPath(LinkOption... options) throws IOException { + return wrap(getDelegate().toRealPath(options)); + } + + @Override + public WatchKey register(WatchService watcher, Kind[] events, Modifier... modifiers) throws IOException { + return getDelegate().register(watcher, events, modifiers); + } + + @Override + public int compareTo(Path other) { + return getDelegate().compareTo(unwrap(other)); + } +} diff --git a/aksw-commons-utils-parent/aksw-commons-utils/src/main/java/org/aksw/commons/util/lifecycle/ResourceMgr.java b/aksw-commons-utils-parent/aksw-commons-utils/src/main/java/org/aksw/commons/util/lifecycle/ResourceMgr.java index 9021b090..92395e64 100644 --- a/aksw-commons-utils-parent/aksw-commons-utils/src/main/java/org/aksw/commons/util/lifecycle/ResourceMgr.java +++ b/aksw-commons-utils-parent/aksw-commons-utils/src/main/java/org/aksw/commons/util/lifecycle/ResourceMgr.java @@ -77,7 +77,6 @@ public boolean isClosed() { /** Create a path and register the filesystem with the resource manager. */ public static Path toPath(ResourceMgr resourceMgr, Class clz, String classPath) throws IOException { - // GtfsMadridBench.class.getResource(name).toURI()); URL url = clz.getResource(classPath); return toPath(resourceMgr, url); }