172 lines
5 KiB
Java
172 lines
5 KiB
Java
package net.minecraft.server.packs.linkfs;
|
|
|
|
import com.google.common.base.Splitter;
|
|
import it.unimi.dsi.fastutil.objects.Object2ObjectOpenHashMap;
|
|
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.HashMap;
|
|
import java.util.List;
|
|
import java.util.Map;
|
|
import java.util.Set;
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Stream;
|
|
import org.jetbrains.annotations.Nullable;
|
|
|
|
public class LinkFileSystem extends FileSystem {
|
|
private static final Set<String> VIEWS = Set.of("basic");
|
|
public static final String PATH_SEPARATOR = "/";
|
|
private static final Splitter PATH_SPLITTER = Splitter.on('/');
|
|
private final FileStore store;
|
|
private final FileSystemProvider provider = new LinkFSProvider();
|
|
private final LinkFSPath root;
|
|
|
|
LinkFileSystem(String name, LinkFileSystem.DirectoryEntry root) {
|
|
this.store = new LinkFSFileStore(name);
|
|
this.root = buildPath(root, this, "", null);
|
|
}
|
|
|
|
private static LinkFSPath buildPath(LinkFileSystem.DirectoryEntry directory, LinkFileSystem fileSystem, String name, @Nullable LinkFSPath parent) {
|
|
Object2ObjectOpenHashMap<String, LinkFSPath> object2ObjectOpenHashMap = new Object2ObjectOpenHashMap<>();
|
|
LinkFSPath linkFSPath = new LinkFSPath(fileSystem, name, parent, new PathContents.DirectoryContents(object2ObjectOpenHashMap));
|
|
directory.files
|
|
.forEach((string, path) -> object2ObjectOpenHashMap.put(string, new LinkFSPath(fileSystem, string, linkFSPath, new PathContents.FileContents(path))));
|
|
directory.children.forEach((string, directoryEntry) -> object2ObjectOpenHashMap.put(string, buildPath(directoryEntry, fileSystem, string, linkFSPath)));
|
|
object2ObjectOpenHashMap.trim();
|
|
return linkFSPath;
|
|
}
|
|
|
|
public FileSystemProvider provider() {
|
|
return this.provider;
|
|
}
|
|
|
|
public void close() {
|
|
}
|
|
|
|
public boolean isOpen() {
|
|
return true;
|
|
}
|
|
|
|
public boolean isReadOnly() {
|
|
return true;
|
|
}
|
|
|
|
public String getSeparator() {
|
|
return "/";
|
|
}
|
|
|
|
public Iterable<Path> getRootDirectories() {
|
|
return List.of(this.root);
|
|
}
|
|
|
|
public Iterable<FileStore> getFileStores() {
|
|
return List.of(this.store);
|
|
}
|
|
|
|
public Set<String> supportedFileAttributeViews() {
|
|
return VIEWS;
|
|
}
|
|
|
|
public Path getPath(String string, String... strings) {
|
|
Stream<String> stream = Stream.of(string);
|
|
if (strings.length > 0) {
|
|
stream = Stream.concat(stream, Stream.of(strings));
|
|
}
|
|
|
|
String string2 = (String)stream.collect(Collectors.joining("/"));
|
|
if (string2.equals("/")) {
|
|
return this.root;
|
|
} else if (string2.startsWith("/")) {
|
|
LinkFSPath linkFSPath = this.root;
|
|
|
|
for (String string3 : PATH_SPLITTER.split(string2.substring(1))) {
|
|
if (string3.isEmpty()) {
|
|
throw new IllegalArgumentException("Empty paths not allowed");
|
|
}
|
|
|
|
linkFSPath = linkFSPath.resolveName(string3);
|
|
}
|
|
|
|
return linkFSPath;
|
|
} else {
|
|
LinkFSPath linkFSPath = null;
|
|
|
|
for (String string3 : PATH_SPLITTER.split(string2)) {
|
|
if (string3.isEmpty()) {
|
|
throw new IllegalArgumentException("Empty paths not allowed");
|
|
}
|
|
|
|
linkFSPath = new LinkFSPath(this, string3, linkFSPath, PathContents.RELATIVE);
|
|
}
|
|
|
|
if (linkFSPath == null) {
|
|
throw new IllegalArgumentException("Empty paths not allowed");
|
|
} else {
|
|
return linkFSPath;
|
|
}
|
|
}
|
|
}
|
|
|
|
public PathMatcher getPathMatcher(String string) {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
public UserPrincipalLookupService getUserPrincipalLookupService() {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
public WatchService newWatchService() {
|
|
throw new UnsupportedOperationException();
|
|
}
|
|
|
|
public FileStore store() {
|
|
return this.store;
|
|
}
|
|
|
|
public LinkFSPath rootPath() {
|
|
return this.root;
|
|
}
|
|
|
|
public static LinkFileSystem.Builder builder() {
|
|
return new LinkFileSystem.Builder();
|
|
}
|
|
|
|
public static class Builder {
|
|
private final LinkFileSystem.DirectoryEntry root = new LinkFileSystem.DirectoryEntry();
|
|
|
|
public LinkFileSystem.Builder put(List<String> pathString, String fileName, Path filePath) {
|
|
LinkFileSystem.DirectoryEntry directoryEntry = this.root;
|
|
|
|
for (String string : pathString) {
|
|
directoryEntry = (LinkFileSystem.DirectoryEntry)directoryEntry.children.computeIfAbsent(string, stringx -> new LinkFileSystem.DirectoryEntry());
|
|
}
|
|
|
|
directoryEntry.files.put(fileName, filePath);
|
|
return this;
|
|
}
|
|
|
|
public LinkFileSystem.Builder put(List<String> pathString, Path filePath) {
|
|
if (pathString.isEmpty()) {
|
|
throw new IllegalArgumentException("Path can't be empty");
|
|
} else {
|
|
int i = pathString.size() - 1;
|
|
return this.put(pathString.subList(0, i), (String)pathString.get(i), filePath);
|
|
}
|
|
}
|
|
|
|
public FileSystem build(String name) {
|
|
return new LinkFileSystem(name, this.root);
|
|
}
|
|
}
|
|
|
|
record DirectoryEntry(Map<String, LinkFileSystem.DirectoryEntry> children, Map<String, Path> files) {
|
|
|
|
public DirectoryEntry() {
|
|
this(new HashMap(), new HashMap());
|
|
}
|
|
}
|
|
}
|