mirror of
https://github.com/PolyhedralDev/Terra.git
synced 2026-10-18 22:44:42 +00:00
Merge pull request #560 from everbuild-org/feat/extend-search-path
feat: add extensible registry interface and integrate into config and meta-config registries
This commit is contained in:
+93
@@ -0,0 +1,93 @@
|
||||
package com.dfsek.terra.registry;
|
||||
|
||||
import com.google.errorprone.annotations.MustBeClosed;
|
||||
import org.intellij.lang.annotations.Pattern;
|
||||
import org.jspecify.annotations.Nullable;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.Arrays;
|
||||
import java.util.Objects;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
|
||||
/**
|
||||
* A file-discoverable registry that can be extended by system properties
|
||||
* <br>
|
||||
* The main use-case for this is to allow for customized locations of file-system-based key entries,
|
||||
* such as putting config packs into custom locations.
|
||||
* <br>
|
||||
* Two system properties are used to define the search path:
|
||||
* <br>
|
||||
* <code>terra.registry.{searchPathName}.searchPath</code> is a list of "parent folder" paths (like the pack directory) that
|
||||
* will be searched for contained files.
|
||||
* <br>
|
||||
* <code>terra.registry.{searchPathName}.extraPath</code> is a list of files that will be directly evaluated for membership and
|
||||
* as such will be directly treated as members of the registry.
|
||||
* <br>
|
||||
* These system properties are formatted like UNIX-style paths, with each path separated by a colon (':') character.
|
||||
*/
|
||||
public interface ExtensibleRegistry {
|
||||
/**
|
||||
* Get a lowercase search path name for this registry that will get plugged into
|
||||
* <br>
|
||||
* <code>terra.registry.{searchPathName}.searchPath</code>
|
||||
* <br>
|
||||
* and
|
||||
* <br>
|
||||
* <code>terra.registry.{searchPathName}.extraPath</code>
|
||||
*/
|
||||
@Pattern("^[a-z._]+$")
|
||||
String getRegistryName();
|
||||
|
||||
/**
|
||||
* Check if a path may be a member of this registry heuristically.
|
||||
*
|
||||
* @param path Path to check
|
||||
*
|
||||
* @return True if the path is a member of this registry.
|
||||
*/
|
||||
boolean validatePathIsMember(Path path);
|
||||
|
||||
default @MustBeClosed Stream<Path> getMemberPaths(Path baseSearchPath) {
|
||||
String basePropertyName = "terra.registry." + getRegistryName();
|
||||
|
||||
Stream<Path> searchPath = Stream.concat(
|
||||
parseValidPaths(System.getProperty(basePropertyName + ".search-path")),
|
||||
Stream.of(baseSearchPath)
|
||||
);
|
||||
|
||||
Stream<Path> extraPath = parseValidPaths(System.getProperty(basePropertyName + ".extra-path"));
|
||||
|
||||
return Stream.concat(
|
||||
searchPath
|
||||
.filter(Files::isDirectory)
|
||||
.flatMap(ExtensibleRegistry::listDirectory),
|
||||
extraPath
|
||||
)
|
||||
.filter(this::validatePathIsMember);
|
||||
}
|
||||
|
||||
private static Stream<Path> parseValidPaths(@Nullable String paths) {
|
||||
return Stream.ofNullable(paths)
|
||||
.flatMap(p -> Arrays.stream(p.split(":")))
|
||||
.filter(v -> !v.isBlank())
|
||||
.map(v -> {
|
||||
try {
|
||||
return Path.of(v).toAbsolutePath().normalize();
|
||||
} catch (Exception e) {
|
||||
return null;
|
||||
}
|
||||
})
|
||||
.filter(Objects::nonNull);
|
||||
}
|
||||
|
||||
private static Stream<Path> listDirectory(Path dir) {
|
||||
try {
|
||||
return Files.list(dir);
|
||||
} catch(IOException e) {
|
||||
return Stream.empty();
|
||||
}
|
||||
}
|
||||
}
|
||||
+13
-2
@@ -29,13 +29,14 @@ import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.config.ConfigPack;
|
||||
import com.dfsek.terra.api.util.reflection.TypeKey;
|
||||
import com.dfsek.terra.config.pack.ConfigPackImpl;
|
||||
import com.dfsek.terra.registry.ExtensibleRegistry;
|
||||
import com.dfsek.terra.registry.OpenRegistryImpl;
|
||||
|
||||
|
||||
/**
|
||||
* Class to hold config packs
|
||||
*/
|
||||
public class ConfigRegistry extends OpenRegistryImpl<ConfigPack> {
|
||||
public class ConfigRegistry extends OpenRegistryImpl<ConfigPack> implements ExtensibleRegistry {
|
||||
|
||||
public ConfigRegistry() {
|
||||
super(TypeKey.of(ConfigPack.class));
|
||||
@@ -45,7 +46,7 @@ public class ConfigRegistry extends OpenRegistryImpl<ConfigPack> {
|
||||
Path packsDirectory = platform.getDataFolder().toPath().resolve("packs");
|
||||
Files.createDirectories(packsDirectory);
|
||||
List<Exception> failedLoads = new CopyOnWriteArrayList<>();
|
||||
try(Stream<Path> packs = Files.list(packsDirectory)) {
|
||||
try(Stream<Path> packs = getMemberPaths(packsDirectory)) {
|
||||
packs.parallel().forEach(path -> {
|
||||
try {
|
||||
ConfigPack pack = new ConfigPackImpl(path, platform);
|
||||
@@ -60,6 +61,16 @@ public class ConfigRegistry extends OpenRegistryImpl<ConfigPack> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRegistryName() {
|
||||
return "config";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validatePathIsMember(Path path) {
|
||||
return Files.isDirectory(path)|| path.getFileName().endsWith(".zip");
|
||||
}
|
||||
|
||||
public static class PackLoadFailuresException extends Exception {
|
||||
@Serial
|
||||
private static final long serialVersionUID = 538998844645186306L;
|
||||
|
||||
+14
-3
@@ -28,6 +28,7 @@ import com.dfsek.terra.api.Platform;
|
||||
import com.dfsek.terra.api.config.MetaPack;
|
||||
import com.dfsek.terra.api.util.reflection.TypeKey;
|
||||
import com.dfsek.terra.config.pack.MetaPackImpl;
|
||||
import com.dfsek.terra.registry.ExtensibleRegistry;
|
||||
import com.dfsek.terra.registry.OpenRegistryImpl;
|
||||
import com.dfsek.terra.registry.master.ConfigRegistry.PackLoadFailuresException;
|
||||
|
||||
@@ -35,7 +36,7 @@ import com.dfsek.terra.registry.master.ConfigRegistry.PackLoadFailuresException;
|
||||
/**
|
||||
* Class to hold config packs
|
||||
*/
|
||||
public class MetaConfigRegistry extends OpenRegistryImpl<MetaPack> {
|
||||
public class MetaConfigRegistry extends OpenRegistryImpl<MetaPack> implements ExtensibleRegistry {
|
||||
|
||||
public MetaConfigRegistry() {
|
||||
super(TypeKey.of(MetaPack.class));
|
||||
@@ -45,8 +46,8 @@ public class MetaConfigRegistry extends OpenRegistryImpl<MetaPack> {
|
||||
Path packsDirectory = platform.getDataFolder().toPath().resolve("metapacks");
|
||||
Files.createDirectories(packsDirectory);
|
||||
List<IOException> failedLoads = new ArrayList<>();
|
||||
try(Stream<Path> packs = Files.list(packsDirectory)) {
|
||||
packs.forEach(path -> {
|
||||
try(Stream<Path> paths = getMemberPaths(packsDirectory)) {
|
||||
paths.forEach(path -> {
|
||||
try {
|
||||
MetaPack pack = new MetaPackImpl(path, platform, configRegistry);
|
||||
registerChecked(pack.getRegistryKey(), pack);
|
||||
@@ -59,4 +60,14 @@ public class MetaConfigRegistry extends OpenRegistryImpl<MetaPack> {
|
||||
throw new PackLoadFailuresException(failedLoads);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getRegistryName() {
|
||||
return "metaconfig";
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean validatePathIsMember(Path path) {
|
||||
return Files.isDirectory(path) || path.getFileName().endsWith(".zip");
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user