CopyOnWriteFSProvider.java

net.minecraft.util.filefix.virtualfilesystem.CopyOnWriteFSProvider

信息

  • 全限定名:net.minecraft.util.filefix.virtualfilesystem.CopyOnWriteFSProvider
  • 类型:public class
  • 包:net.minecraft.util.filefix.virtualfilesystem
  • 源码路径:src/main/java/net/minecraft/util/filefix/virtualfilesystem/CopyOnWriteFSProvider.java
  • 起始行号:L39
  • 继承:FileSystemProvider
  • 职责:

    TODO

字段/常量

  • SCHEME

    • 类型: String
    • 修饰符: public static final
    • 源码定位: L40
    • 说明:

      TODO

  • DUMMY_DIRECTORY_VIEW

    • 类型: BasicFileAttributeView
    • 修饰符: private static final public public public
    • 源码定位: L41
    • 说明:

      TODO

  • fs

    • 类型: CopyOnWriteFileSystem
    • 修饰符: private final
    • 源码定位: L56
    • 说明:

      TODO

内部类/嵌套类型

  • net.minecraft.util.filefix.virtualfilesystem.CopyOnWriteFSProvider.ChannelFactory
    • 类型: interface
    • 修饰符: private
    • 源码定位: L337
    • 说明:

      TODO

构造器

public CopyOnWriteFSProvider(CopyOnWriteFileSystem fileSystem) @ L58

  • 构造器名:CopyOnWriteFSProvider
  • 源码定位:L58
  • 修饰符:public

参数:

  • fileSystem: CopyOnWriteFileSystem

说明:

TODO

方法

下面的方法块按源码顺序生成。

public String getScheme() @ L62

  • 方法名:getScheme
  • 源码定位:L62
  • 返回类型:String
  • 修饰符:public

参数:

说明:

TODO

public FileSystem newFileSystem(URI uri, Map<String,?> env) @ L67

  • 方法名:newFileSystem
  • 源码定位:L67
  • 返回类型:FileSystem
  • 修饰符:public

参数:

  • uri: URI
  • env: Map<String,?>

说明:

TODO

public FileSystem getFileSystem(URI uri) @ L72

  • 方法名:getFileSystem
  • 源码定位:L72
  • 返回类型:FileSystem
  • 修饰符:public

参数:

  • uri: URI

说明:

TODO

public Path getPath(URI uri) @ L77

  • 方法名:getPath
  • 源码定位:L77
  • 返回类型:Path
  • 修饰符:public

参数:

  • uri: URI

说明:

TODO

public SeekableByteChannel newByteChannel(Path path, Set<?extends OpenOption> options, FileAttribute<?>... attrs) @ L82

  • 方法名:newByteChannel
  • 源码定位:L82
  • 返回类型:SeekableByteChannel
  • 修饰符:public

参数:

  • path: Path
  • options: Set<?extends OpenOption>
  • attrs: FileAttribute<?>…

说明:

TODO

public FileChannel newFileChannel(Path path, Set<?extends OpenOption> options, FileAttribute<?>... attrs) @ L87

  • 方法名:newFileChannel
  • 源码定位:L87
  • 返回类型:FileChannel
  • 修饰符:public

参数:

  • path: Path
  • options: Set<?extends OpenOption>
  • attrs: FileAttribute<?>…

说明:

TODO

private synchronized <C> C newChannel(Path path, Set<?extends OpenOption> options, FileAttribute<?>[] attrs, CopyOnWriteFSProvider.ChannelFactory<C> channelFactory) @ L92

  • 方法名:newChannel
  • 源码定位:L92
  • 返回类型: C
  • 修饰符:private synchronized

参数:

  • path: Path
  • options: Set<?extends OpenOption>
  • attrs: FileAttribute<?>[]
  • channelFactory: CopyOnWriteFSProvider.ChannelFactory

说明:

TODO

private static boolean wantsWrite(Set<?extends OpenOption> options) @ L125

  • 方法名:wantsWrite
  • 源码定位:L125
  • 返回类型:boolean
  • 修饰符:private static

参数:

  • options: Set<?extends OpenOption>

说明:

TODO

public synchronized DirectoryStream<Path> newDirectoryStream(Path dir, Filter<?super Path> filter) @ L129

  • 方法名:newDirectoryStream
  • 源码定位:L129
  • 返回类型:DirectoryStream
  • 修饰符:public synchronized

参数:

  • dir: Path
  • filter: Filter<?super Path>

说明:

TODO

public synchronized void createDirectory(Path dir, FileAttribute<?>... attrs) @ L158

  • 方法名:createDirectory
  • 源码定位:L158
  • 返回类型:void
  • 修饰符:public synchronized

参数:

  • dir: Path
  • attrs: FileAttribute<?>…

说明:

TODO

public synchronized void delete(Path path) @ L175

  • 方法名:delete
  • 源码定位:L175
  • 返回类型:void
  • 修饰符:public synchronized

参数:

  • path: Path

说明:

TODO

public void copy(Path source, Path target, CopyOption... options) @ L195

  • 方法名:copy
  • 源码定位:L195
  • 返回类型:void
  • 修饰符:public

参数:

  • source: Path
  • target: Path
  • options: CopyOption…

说明:

TODO

public synchronized void move(Path source, Path target, CopyOption... options) @ L200

  • 方法名:move
  • 源码定位:L200
  • 返回类型:void
  • 修饰符:public synchronized

参数:

  • source: Path
  • target: Path
  • options: CopyOption…

说明:

TODO

public boolean isSameFile(Path path, Path path2) @ L251

  • 方法名:isSameFile
  • 源码定位:L251
  • 返回类型:boolean
  • 修饰符:public

参数:

  • path: Path
  • path2: Path

说明:

TODO

public boolean isHidden(Path path) @ L256

  • 方法名:isHidden
  • 源码定位:L256
  • 返回类型:boolean
  • 修饰符:public

参数:

  • path: Path

说明:

TODO

public FileStore getFileStore(Path path) @ L261

  • 方法名:getFileStore
  • 源码定位:L261
  • 返回类型:FileStore
  • 修饰符:public

参数:

  • path: Path

说明:

TODO

public synchronized void checkAccess(Path path, AccessMode... modes) @ L266

  • 方法名:checkAccess
  • 源码定位:L266
  • 返回类型:void
  • 修饰符:public synchronized

参数:

  • path: Path
  • modes: AccessMode…

说明:

TODO

public synchronized <V extends FileAttributeView> V getFileAttributeView(Path path, Class<V> type, LinkOption... options) @ L279

  • 方法名:getFileAttributeView
  • 源码定位:L279
  • 返回类型: V
  • 修饰符:public synchronized

参数:

  • path: Path
  • type: Class
  • options: LinkOption…

说明:

TODO

public synchronized <A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption... options) @ L310

参数:

说明:

TODO

public Map<String,Object> readAttributes(Path path, String attributes, LinkOption... options) @ L322

  • 方法名:readAttributes
  • 源码定位:L322
  • 返回类型:Map<String,Object>
  • 修饰符:public

参数:

  • path: Path
  • attributes: String
  • options: LinkOption…

说明:

TODO

public void setAttribute(Path path, String attribute, Object value, LinkOption... options) @ L327

  • 方法名:setAttribute
  • 源码定位:L327
  • 返回类型:void
  • 修饰符:public

参数:

  • path: Path
  • attribute: String
  • value: Object
  • options: LinkOption…

说明:

TODO

public synchronized CopyOnWriteFSPath getRealPath(CopyOnWriteFSPath path) @ L332

  • 方法名:getRealPath
  • 源码定位:L332
  • 返回类型:CopyOnWriteFSPath
  • 修饰符:public synchronized

参数:

  • path: CopyOnWriteFSPath

说明:

TODO

代码

public class CopyOnWriteFSProvider extends FileSystemProvider {
    public static final String SCHEME = "x-mc-copy-on-write";
    private static final BasicFileAttributeView DUMMY_DIRECTORY_VIEW = new BasicFileAttributeView() {
        @Override
        public String name() {
            return "basic";
        }
 
        @Override
        public BasicFileAttributes readAttributes() {
            return DummyFileAttributes.DIRECTORY;
        }
 
        @Override
        public void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime) throws IOException {
        }
    };
    private final CopyOnWriteFileSystem fs;
 
    public CopyOnWriteFSProvider(CopyOnWriteFileSystem fileSystem) {
        this.fs = fileSystem;
    }
 
    @Override
    public String getScheme() {
        return "x-mc-copy-on-write";
    }
 
    @Override
    public FileSystem newFileSystem(URI uri, Map<String, ?> env) throws IOException {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public FileSystem getFileSystem(URI uri) {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public Path getPath(URI uri) {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public SeekableByteChannel newByteChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
        return this.newChannel(path, options, attrs, Files::newByteChannel);
    }
 
    @Override
    public FileChannel newFileChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException {
        return this.newChannel(path, options, attrs, FileChannel::open);
    }
 
    private synchronized <C> C newChannel(
        Path path, Set<? extends OpenOption> options, FileAttribute<?>[] attrs, CopyOnWriteFSProvider.ChannelFactory<C> channelFactory
    ) throws IOException {
        CopyOnWriteFSPath cowPath = CopyOnWriteFSPath.asCow(path);
        if (options.contains(StandardOpenOption.DELETE_ON_CLOSE)) {
            throw new UnsupportedOperationException("DELETE_ON_CLOSE is not supported by CowFS");
        } else {
            return (C)(switch (this.fs.fileTree().byPathOrNull(cowPath)) {
                case null -> {
                    if (!options.contains(StandardOpenOption.CREATE) && !options.contains(StandardOpenOption.CREATE_NEW)) {
                        throw new CowFSNoSuchFileException(cowPath.toString());
                    }
 
                    DirectoryNode directoryNode = this.fs.fileTree().directoryByPath(Objects.requireNonNull(cowPath.getParent()));
                    Path tempFile = this.fs.createTemporaryFilePath();
                    C result = channelFactory.newChannel(tempFile, options, attrs);
                    FileNode child = new FileNode(cowPath, tempFile, true);
                    directoryNode.addChild(child);
                    yield result;
                }
                case FileNode fileNode -> {
                    if (wantsWrite(options)) {
                        fileNode.ensureCopy();
                    }
 
                    yield channelFactory.newChannel(fileNode.storagePath(), options, attrs);
                }
                case DirectoryNode var14 -> throw new CowFSFileSystemException(cowPath + ": not a regular file");
                default -> throw new MatchException(null, null);
            });
        }
    }
 
    private static boolean wantsWrite(Set<? extends OpenOption> options) {
        return options.contains(StandardOpenOption.WRITE) || !options.contains(StandardOpenOption.READ) && options.contains(StandardOpenOption.APPEND);
    }
 
    @Override
    public synchronized DirectoryStream<Path> newDirectoryStream(Path dir, Filter<? super Path> filter) throws IOException {
        CopyOnWriteFSPath cowPath = CopyOnWriteFSPath.asCow(dir);
        DirectoryNode directoryNode = this.fs.fileTree().directoryByPath(cowPath);
        final List<Path> result = new ArrayList<>();
 
        for (Node childNode : directoryNode.children()) {
            Path path = childNode.path();
            if (filter.accept(path)) {
                result.add(path);
            }
        }
 
        return new DirectoryStream<Path>() {
            {
                Objects.requireNonNull(CopyOnWriteFSProvider.this);
            }
 
            @Override
            public void close() {
            }
 
            @Override
            public Iterator<Path> iterator() {
                return result.iterator();
            }
        };
    }
 
    @Override
    public synchronized void createDirectory(Path dir, FileAttribute<?>... attrs) throws IOException {
        CopyOnWriteFSPath cowPath = CopyOnWriteFSPath.asCow(dir);
        CopyOnWriteFSPath parent = cowPath.getParent();
        if (parent == null) {
            throw new CowFSFileAlreadyExistsException(cowPath.toString());
        } else {
            DirectoryNode parentFolder = this.fs.fileTree().directoryByPath(parent);
            String folderName = Objects.requireNonNull(cowPath.getFileName()).toString();
            if (parentFolder.getChild(folderName) != null) {
                throw new CowFSFileAlreadyExistsException(cowPath.toString());
            } else {
                parentFolder.addChild(new DirectoryNode(cowPath));
            }
        }
    }
 
    @Override
    public synchronized void delete(Path path) throws IOException {
        CopyOnWriteFSPath cowPath = CopyOnWriteFSPath.asCow(path);
        Node node = this.fs.fileTree().byPath(cowPath);
        if (node.parent == null) {
            throw new CowFSFileSystemException("Can't remove root");
        } else {
            String name = Objects.requireNonNull(node.name());
            if (node instanceof DirectoryNode directoryNode) {
                if (!directoryNode.children().isEmpty()) {
                    throw new CowFSDirectoryNotEmptyException(cowPath.toString());
                }
            } else if (node instanceof FileNode fileNode) {
                fileNode.deleteCopy();
            }
 
            node.parent.removeChild(name);
        }
    }
 
    @Override
    public void copy(Path source, Path target, CopyOption... options) throws IOException {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public synchronized void move(Path source, Path target, CopyOption... options) throws IOException {
        CopyOnWriteFSPath sourceCow = CopyOnWriteFSPath.asCow(source);
        CopyOnWriteFSPath targetCow = CopyOnWriteFSPath.asCow(target);
        if (sourceCow.isRoot()) {
            throw new CowFSFileSystemException(sourceCow + ": can't move root directory");
        } else {
            boolean replaceExisting = false;
 
            for (CopyOption option : options) {
                if (option.equals(StandardCopyOption.ATOMIC_MOVE)) {
                    throw new AtomicMoveNotSupportedException(sourceCow.toString(), targetCow.toString(), "CowFs does not support atomic move");
                }
 
                if (option.equals(StandardCopyOption.REPLACE_EXISTING)) {
                    replaceExisting = true;
                }
            }
 
            Node sourceNode = this.fs.fileTree().byPathOrNull(sourceCow);
            if (sourceNode == null) {
                throw new CowFSNoSuchFileException(sourceCow.toString());
            } else {
                CopyOnWriteFSPath parent = targetCow.toAbsolutePath().getParent();
                if (parent == null) {
                    throw new CowFSFileAlreadyExistsException(targetCow.toString());
                } else if (this.fs.fileTree().byPathOrNull(parent) instanceof DirectoryNode folderTarget) {
                    String newName = Objects.requireNonNull(targetCow.getFileName()).toString();
                    Node oldChild = folderTarget.getChild(newName);
                    if (oldChild != null) {
                        if (oldChild.equals(sourceNode)) {
                            return;
                        }
 
                        if (!replaceExisting) {
                            throw new CowFSFileAlreadyExistsException(targetCow.toString());
                        }
 
                        folderTarget.removeChild(newName);
                    }
 
                    Objects.requireNonNull(sourceNode.parent).removeChild(Objects.requireNonNull(sourceNode.name()));
                    sourceNode.setPath(targetCow);
                    folderTarget.addChild(sourceNode);
                } else {
                    throw new CowFSNoSuchFileException(targetCow.toString());
                }
            }
        }
    }
 
    @Override
    public boolean isSameFile(Path path, Path path2) {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public boolean isHidden(Path path) {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public FileStore getFileStore(Path path) {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public synchronized void checkAccess(Path path, AccessMode... modes) throws IOException {
        CopyOnWriteFSPath cowPath = CopyOnWriteFSPath.asCow(path);
        Node node = this.fs.fileTree().byPath(cowPath);
 
        Path checkPath = switch (node) {
            case DirectoryNode var9 -> this.fs.tmpDirectory();
            case FileNode file -> file.storagePath();
            default -> throw new MatchException(null, null);
        };
        checkPath.getFileSystem().provider().checkAccess(checkPath, modes);
    }
 
    @Override
    public synchronized <V extends FileAttributeView> @Nullable V getFileAttributeView(Path path, Class<V> type, LinkOption... options) {
        final CopyOnWriteFSPath cowPath = CopyOnWriteFSPath.asCow(path);
 
        return (V)(switch (this.fs.fileTree().byPathOrNull(cowPath)) {
            case null -> type == BasicFileAttributeView.class ? new BasicFileAttributeView() {
                {
                    Objects.requireNonNull(CopyOnWriteFSProvider.this);
                }
 
                @Override
                public String name() {
                    return "basic";
                }
 
                @Override
                public BasicFileAttributes readAttributes() throws IOException {
                    throw new CowFSNoSuchFileException(cowPath.toString());
                }
 
                @Override
                public void setTimes(FileTime lastModifiedTime, FileTime lastAccessTime, FileTime createTime) throws IOException {
                    throw new CowFSNoSuchFileException(cowPath.toString());
                }
            } : null;
            case DirectoryNode var9 -> type == BasicFileAttributeView.class ? DUMMY_DIRECTORY_VIEW : null;
            case FileNode file -> Files.getFileAttributeView(file.storagePath(), type, options);
            default -> throw new MatchException(null, null);
        });
    }
 
    @Override
    public synchronized <A extends BasicFileAttributes> A readAttributes(Path path, Class<A> type, LinkOption... options) throws IOException {
        CopyOnWriteFSPath cowPath = CopyOnWriteFSPath.asCow(path);
        Node node = this.fs.fileTree().byPath(cowPath);
 
        return (A)(switch (node) {
            case DirectoryNode var9 -> DummyFileAttributes.DIRECTORY;
            case FileNode file -> Files.readAttributes(file.storagePath(), type, options);
            default -> throw new MatchException(null, null);
        });
    }
 
    @Override
    public Map<String, Object> readAttributes(Path path, String attributes, LinkOption... options) {
        throw new UnsupportedOperationException();
    }
 
    @Override
    public void setAttribute(Path path, String attribute, Object value, LinkOption... options) {
        throw new UnsupportedOperationException();
    }
 
    public synchronized CopyOnWriteFSPath getRealPath(CopyOnWriteFSPath path) throws CowFSNoSuchFileException {
        return this.fs.fileTree().byPath(path.toAbsolutePath()).path;
    }
 
    @FunctionalInterface
    private interface ChannelFactory<C> {
        C newChannel(Path path, Set<? extends OpenOption> options, FileAttribute<?>... attrs) throws IOException;
    }
}

引用的其他类