All Downloads are FREE. Search and download functionalities are using the official Maven repository.

io.virtdata.docsys.metafs.fs.layerfs.LayerFSProvider Maven / Gradle / Ivy

package io.virtdata.docsys.metafs.fs.layerfs;

import io.virtdata.docsys.metafs.core.MetaFSProvider;
import io.virtdata.docsys.metafs.core.MetaPath;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;

import java.io.IOException;
import java.net.URI;
import java.nio.channels.SeekableByteChannel;
import java.nio.file.*;
import java.nio.file.attribute.BasicFileAttributes;
import java.nio.file.attribute.FileAttribute;
import java.nio.file.attribute.FileAttributeView;
import java.nio.file.spi.FileSystemProvider;
import java.security.InvalidParameterException;
import java.util.*;
import java.util.function.Function;
import java.util.stream.Collectors;

@SuppressWarnings("ALL")
public class LayerFSProvider extends MetaFSProvider {

    private static LayerFSProvider instance;
    private final Logger logger = LoggerFactory.getLogger(LayerFSProvider.class);

    private LayerFSProvider() {
    }

    public synchronized static LayerFSProvider get() {
        if (instance == null) {
            instance = new LayerFSProvider();
        }
        return instance;
    }

    @Override
    public synchronized FileSystem newFileSystem(URI uri, Map env) throws IOException {
        boolean readonly = true;
        LayerFS fs = new LayerFS(uri.toString());
        fs.setWritable(env != null && env.get("writable").toString().equals("true"));
        return fs;
    }

    @Override
    public SeekableByteChannel newByteChannel(Path path, Set options, FileAttribute... attrs) throws IOException {
        MetaPath metapath = assertMetaPath(path);
        LayerFS layerFS = assertLayerFS(metapath);
        return layerFS.newByteChannel(path, options, attrs);
    }

//    @Override
//    public FileChannel newFileChannel(Path path, Set options, FileAttribute... attrs) throws IOException {
//        MetaPath metapath = assertMetaPath(path);
//        LayerFS layerFS = assertLayerFS(metapath);
//        return layerFS.newFileChannel(path, options, attrs);
//    }


    @Override
    public DirectoryStream newDirectoryStream(Path dir, DirectoryStream.Filter filter) throws IOException {
        MetaPath metapath = assertMetaPath(dir);
        LayerFS layerFS = assertLayerFS(metapath);

        Set names = new HashSet<>();
        Set paths = new HashSet<>();
        IOException possibleException = null;
        int foundDirectoryCount = 0;
        for (FileSystem fs : layerFS.getWrappedFilesystems()) {
            Path fsSpecificPath = fs.getPath(metapath.toString());
            try {
                DirectoryStream dsp = fs.provider().newDirectoryStream(fsSpecificPath, filter);
                foundDirectoryCount++;
                for (Path path : dsp) {
                    if (!names.contains(path.toString())) {
                        names.add(path.toString());
                        paths.add(path);
                    }
                }
            } catch (IOException ioe) {
                possibleException = ioe;
            }
        }
        if (foundDirectoryCount == 0) {
            throw new IOException("Unable to find even one directory entry in addLayers for path " + dir);
        }

        return new DirectoryStream() {
            @Override
            public Iterator iterator() {
                return paths.iterator();
            }

            @Override
            public void close() throws IOException {
            }
        };
    }

    @Override
    public  V getFileAttributeView(Path path, Class type, LinkOption... options) {
        return acceptFirstSuccess(path, p -> {
            try {
                p.getFileSystem().provider().readAttributes(p,BasicFileAttributes.class);
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
            return p.getFileSystem().provider().getFileAttributeView(p, type, options);
        });
    }


    @Override
    public  A readAttributes(Path path, Class type, LinkOption... options) throws IOException {
        return acceptFirstSuccess(path, p -> {
            try {
                FileSystem fs = p.getFileSystem();
                FileSystemProvider provider = fs.provider();
                A a = provider.readAttributes(p, type, options);
                return a;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    @Override
    public Map readAttributes(Path path, String attributes, LinkOption... options) throws IOException {
        return acceptFirstSuccess(path, p -> {
            try {
                FileSystem fileSystem = p.getFileSystem();
                FileSystemProvider provider = fileSystem.provider();
                Map map = provider.readAttributes(p, attributes, options);
                return map;
            } catch (IOException e) {
                throw new RuntimeException(e);
            }
        });
    }

    private  T acceptFirstSuccess(Path path, Function process) {
        MetaPath metapath = assertMetaPath(path);
        LayerFS layerFS = assertLayerFS(metapath);
        List exceptions = new ArrayList<>();
        for (FileSystem wrappedFilesystem : layerFS.getWrappedFilesystems()) {
            try {
                Path localizedpath = wrappedFilesystem.getPath(metapath.toString());
                return process.apply(localizedpath);
            } catch (Exception e) {
                exceptions.add(e);
            }
        }
        throw new RuntimeException(
                exceptions.size() + " exceptions occurred:"
                        + exceptions.stream()
                        .map(Exception::getMessage)
                        .collect(Collectors.joining(",\n","\n","")));
    }

    @Override
    public void checkAccess(Path path, AccessMode... modes) throws IOException {
        MetaPath metapath = assertMetaPath(path);
        LayerFS layerFS = assertLayerFS(metapath);
        layerFS.checkAccess(path, modes);
    }


    private Path findFirstWritablePath(Path toWrite, List fileSystems) {
        for (FileSystem fs : fileSystems) {
            if (!fs.isReadOnly()) {
                return fs.getPath(toWrite.toString());
            }
        }
        throw new RuntimeException("Unable to find a writable filesystem in addLayers.");

    }

    private Path findFirstReadablePath(Path toRead, List fileSystems) {
        for (FileSystem fileSystem : fileSystems) {
            try {
                Path fsSpecificPath = fileSystem.getPath(toRead.toString());
                fsSpecificPath.getFileSystem().provider().checkAccess(fsSpecificPath, AccessMode.READ);
                return fsSpecificPath;
            } catch (IOException e) {
                logger.trace("Did not find readable file " + toRead + " in fs " + fileSystem);
            }
        }
        throw new RuntimeException("Unable to find a readable " + toRead + " in any addLayer");
    }

    private LayerFS assertLayerFS(MetaPath path) {
        if (!(path.getFileSystem() instanceof LayerFS)) {

            throw new RuntimeException("Unable to do LayerFS operations on Path from filesystem of type " + path.getFileSystem().getClass().getCanonicalName());
        }
        return (LayerFS) path.getFileSystem();
    }

    private MetaPath assertMetaPath(Path path) {
        if (!(path instanceof MetaPath)) {
            throw new InvalidParameterException("Unable to do MetaPath operations on Path of type " + path.getClass().getCanonicalName());
        }
        return (MetaPath) path;
    }
}




© 2015 - 2025 Weber Informatics LLC | Privacy Policy