mirror of
https://github.com/BlueMap-Minecraft/BlueMap.git
synced 2025-01-26 02:01:32 +01:00
Remove all usages of java.io.File and bad usages of Path.of()
This commit is contained in:
parent
ce25eb52e3
commit
d7dd8931a5
@ -200,7 +200,7 @@ private synchronized void loadMap(String id, MapConfig mapConfig) throws Configu
|
|||||||
dimension = DataPack.DIMENSION_THE_END;
|
dimension = DataPack.DIMENSION_THE_END;
|
||||||
} else if (
|
} else if (
|
||||||
worldFolder.getNameCount() > 3 &&
|
worldFolder.getNameCount() > 3 &&
|
||||||
worldFolder.getName(worldFolder.getNameCount() - 3).equals(Path.of("dimensions"))
|
worldFolder.getName(worldFolder.getNameCount() - 3).toString().equals("dimensions")
|
||||||
) {
|
) {
|
||||||
String namespace = worldFolder.getName(worldFolder.getNameCount() - 2).toString();
|
String namespace = worldFolder.getName(worldFolder.getNameCount() - 2).toString();
|
||||||
String value = worldFolder.getName(worldFolder.getNameCount() - 1).toString();
|
String value = worldFolder.getName(worldFolder.getNameCount() - 1).toString();
|
||||||
|
@ -32,21 +32,15 @@
|
|||||||
import de.bluecolored.bluemap.core.logger.Logger;
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import de.bluecolored.bluemap.core.resources.adapter.ResourcesGson;
|
import de.bluecolored.bluemap.core.resources.adapter.ResourcesGson;
|
||||||
import de.bluecolored.bluemap.core.util.FileHelper;
|
import de.bluecolored.bluemap.core.util.FileHelper;
|
||||||
import org.apache.commons.io.FileUtils;
|
|
||||||
|
|
||||||
import java.io.BufferedReader;
|
import java.io.*;
|
||||||
import java.io.BufferedWriter;
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
|
||||||
import java.net.URL;
|
import java.net.URL;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
|
import java.nio.file.StandardCopyOption;
|
||||||
import java.nio.file.StandardOpenOption;
|
import java.nio.file.StandardOpenOption;
|
||||||
import java.util.Enumeration;
|
|
||||||
import java.util.HashSet;
|
import java.util.HashSet;
|
||||||
import java.util.Set;
|
import java.util.Set;
|
||||||
import java.util.zip.ZipEntry;
|
|
||||||
import java.util.zip.ZipFile;
|
|
||||||
|
|
||||||
public class WebFilesManager {
|
public class WebFilesManager {
|
||||||
|
|
||||||
@ -114,39 +108,17 @@ public boolean filesNeedUpdate() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
public void updateFiles() throws IOException {
|
public void updateFiles() throws IOException {
|
||||||
URL fileResource = getClass().getResource("/de/bluecolored/bluemap/webapp.zip");
|
URL zippedWebapp = getClass().getResource("/de/bluecolored/bluemap/webapp.zip");
|
||||||
File tempFile = File.createTempFile("bluemap_webroot_extraction", null);
|
if (zippedWebapp == null) throw new IOException("Failed to open bundled webapp.");
|
||||||
|
|
||||||
if (fileResource == null) throw new IOException("Failed to open bundled webapp.");
|
// extract zip to webroot
|
||||||
|
FileHelper.extractZipFile(zippedWebapp, webRoot, StandardCopyOption.REPLACE_EXISTING);
|
||||||
|
|
||||||
try {
|
// set version in index.html
|
||||||
FileUtils.copyURLToFile(fileResource, tempFile, 10000, 10000);
|
Path indexFile = webRoot.resolve("index.html");
|
||||||
try (ZipFile zipFile = new ZipFile(tempFile)){
|
String indexContent = Files.readString(indexFile);
|
||||||
Enumeration<? extends ZipEntry> entries = zipFile.entries();
|
indexContent = indexContent.replace("%version%", BlueMap.VERSION);
|
||||||
while(entries.hasMoreElements()) {
|
Files.writeString(indexFile, indexContent);
|
||||||
ZipEntry zipEntry = entries.nextElement();
|
|
||||||
if (zipEntry.isDirectory()) {
|
|
||||||
File dir = webRoot.resolve(zipEntry.getName()).toFile();
|
|
||||||
FileUtils.forceMkdir(dir);
|
|
||||||
} else {
|
|
||||||
File target = webRoot.resolve(zipEntry.getName()).toFile();
|
|
||||||
FileUtils.forceMkdirParent(target);
|
|
||||||
FileUtils.copyInputStreamToFile(zipFile.getInputStream(zipEntry), target);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
// set version in index.html
|
|
||||||
Path indexFile = webRoot.resolve("index.html");
|
|
||||||
String indexContent = Files.readString(indexFile);
|
|
||||||
indexContent = indexContent.replace("%version%", BlueMap.VERSION);
|
|
||||||
Files.writeString(indexFile, indexContent);
|
|
||||||
|
|
||||||
} finally {
|
|
||||||
if (!tempFile.delete()) {
|
|
||||||
Logger.global.logWarning("Failed to delete file: " + tempFile);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal", "unused", "MismatchedQueryAndUpdateOfCollection"})
|
@SuppressWarnings({"FieldMayBeFinal", "FieldCanBeLocal", "unused", "MismatchedQueryAndUpdateOfCollection"})
|
||||||
|
@ -40,7 +40,6 @@
|
|||||||
import java.util.stream.Stream;
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
public class WebAppImpl implements WebApp {
|
public class WebAppImpl implements WebApp {
|
||||||
private static final Path IMAGE_ROOT_PATH = Path.of("data", "images");
|
|
||||||
|
|
||||||
private final Plugin plugin;
|
private final Plugin plugin;
|
||||||
|
|
||||||
@ -88,8 +87,8 @@ public String createImage(BufferedImage image, String path) throws IOException {
|
|||||||
Path webRoot = getWebRoot().toAbsolutePath();
|
Path webRoot = getWebRoot().toAbsolutePath();
|
||||||
String separator = webRoot.getFileSystem().getSeparator();
|
String separator = webRoot.getFileSystem().getSeparator();
|
||||||
|
|
||||||
Path imageRootFolder = webRoot.resolve(IMAGE_ROOT_PATH);
|
Path imageRootFolder = webRoot.resolve("data").resolve("images");
|
||||||
Path imagePath = imageRootFolder.resolve(Path.of(path.replace("/", separator) + ".png")).toAbsolutePath();
|
Path imagePath = imageRootFolder.resolve(path.replace("/", separator) + ".png").toAbsolutePath();
|
||||||
|
|
||||||
FileHelper.createDirectories(imagePath.getParent());
|
FileHelper.createDirectories(imagePath.getParent());
|
||||||
Files.deleteIfExists(imagePath);
|
Files.deleteIfExists(imagePath);
|
||||||
@ -108,7 +107,7 @@ public Map<String, String> availableImages() throws IOException {
|
|||||||
Path webRoot = getWebRoot().toAbsolutePath();
|
Path webRoot = getWebRoot().toAbsolutePath();
|
||||||
String separator = webRoot.getFileSystem().getSeparator();
|
String separator = webRoot.getFileSystem().getSeparator();
|
||||||
|
|
||||||
Path imageRootPath = webRoot.resolve("data").resolve(IMAGE_ROOT_PATH).toAbsolutePath();
|
Path imageRootPath = webRoot.resolve("data").resolve("images").toAbsolutePath();
|
||||||
|
|
||||||
Map<String, String> availableImagesMap = new HashMap<>();
|
Map<String, String> availableImagesMap = new HashMap<>();
|
||||||
|
|
||||||
|
@ -46,6 +46,13 @@
|
|||||||
@Getter
|
@Getter
|
||||||
public class BlueMapConfigManager implements BlueMapConfiguration {
|
public class BlueMapConfigManager implements BlueMapConfiguration {
|
||||||
|
|
||||||
|
public static final String CORE_CONFIG_NAME = "core";
|
||||||
|
public static final String WEBSERVER_CONFIG_NAME = "webserver";
|
||||||
|
public static final String WEBAPP_CONFIG_NAME = "webapp";
|
||||||
|
public static final String PLUGIN_CONFIG_NAME = "plugin";
|
||||||
|
public static final String MAPS_CONFIG_FOLDER_NAME = "maps";
|
||||||
|
public static final String STORAGES_CONFIG_FOLDER_NAME = "storages";
|
||||||
|
|
||||||
private final ConfigManager configManager;
|
private final ConfigManager configManager;
|
||||||
|
|
||||||
private final CoreConfig coreConfig;
|
private final CoreConfig coreConfig;
|
||||||
@ -92,16 +99,15 @@ private BlueMapConfigManager(
|
|||||||
}
|
}
|
||||||
|
|
||||||
private CoreConfig loadCoreConfig(Path defaultDataFolder, boolean useMetricsConfig) throws ConfigurationException {
|
private CoreConfig loadCoreConfig(Path defaultDataFolder, boolean useMetricsConfig) throws ConfigurationException {
|
||||||
Path configFileRaw = Path.of("core");
|
Path configFile = configManager.resolveConfigFile(CORE_CONFIG_NAME);
|
||||||
Path configFile = configManager.findConfigPath(configFileRaw);
|
|
||||||
Path configFolder = configFile.getParent();
|
Path configFolder = configFile.getParent();
|
||||||
|
|
||||||
if (!Files.exists(configFile)) {
|
if (!Files.exists(configFile)) {
|
||||||
try {
|
try {
|
||||||
FileHelper.createDirectories(configFolder);
|
FileHelper.createDirectories(configFolder);
|
||||||
Files.writeString(
|
Files.writeString(
|
||||||
configFolder.resolve("core.conf"),
|
configFile,
|
||||||
configManager.loadConfigTemplate("/de/bluecolored/bluemap/config/core.conf")
|
configManager.loadConfigTemplate(CORE_CONFIG_NAME)
|
||||||
.setConditional("metrics", useMetricsConfig)
|
.setConditional("metrics", useMetricsConfig)
|
||||||
.setVariable("timestamp", LocalDateTime.now().withNano(0).toString())
|
.setVariable("timestamp", LocalDateTime.now().withNano(0).toString())
|
||||||
.setVariable("version", BlueMap.VERSION)
|
.setVariable("version", BlueMap.VERSION)
|
||||||
@ -118,7 +124,7 @@ private CoreConfig loadCoreConfig(Path defaultDataFolder, boolean useMetricsConf
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return configManager.loadConfig(configFileRaw, CoreConfig.class);
|
return configManager.loadConfig(CORE_CONFIG_NAME, CoreConfig.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
@ -137,16 +143,15 @@ private int suggestRenderThreadCount() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
private WebserverConfig loadWebserverConfig(Path defaultWebroot, Path dataRoot) throws ConfigurationException {
|
private WebserverConfig loadWebserverConfig(Path defaultWebroot, Path dataRoot) throws ConfigurationException {
|
||||||
Path configFileRaw = Path.of("webserver");
|
Path configFile = configManager.resolveConfigFile(WEBSERVER_CONFIG_NAME);
|
||||||
Path configFile = configManager.findConfigPath(configFileRaw);
|
|
||||||
Path configFolder = configFile.getParent();
|
Path configFolder = configFile.getParent();
|
||||||
|
|
||||||
if (!Files.exists(configFile)) {
|
if (!Files.exists(configFile)) {
|
||||||
try {
|
try {
|
||||||
FileHelper.createDirectories(configFolder);
|
FileHelper.createDirectories(configFolder);
|
||||||
Files.writeString(
|
Files.writeString(
|
||||||
configFolder.resolve("webserver.conf"),
|
configFile,
|
||||||
configManager.loadConfigTemplate("/de/bluecolored/bluemap/config/webserver.conf")
|
configManager.loadConfigTemplate(WEBSERVER_CONFIG_NAME)
|
||||||
.setVariable("webroot", formatPath(defaultWebroot))
|
.setVariable("webroot", formatPath(defaultWebroot))
|
||||||
.setVariable("logfile", formatPath(dataRoot.resolve("logs").resolve("webserver.log")))
|
.setVariable("logfile", formatPath(dataRoot.resolve("logs").resolve("webserver.log")))
|
||||||
.setVariable("logfile-with-time", formatPath(dataRoot.resolve("logs").resolve("webserver_%1$tF_%1$tT.log")))
|
.setVariable("logfile-with-time", formatPath(dataRoot.resolve("logs").resolve("webserver_%1$tF_%1$tT.log")))
|
||||||
@ -158,20 +163,19 @@ private WebserverConfig loadWebserverConfig(Path defaultWebroot, Path dataRoot)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return configManager.loadConfig(configFileRaw, WebserverConfig.class);
|
return configManager.loadConfig(WEBSERVER_CONFIG_NAME, WebserverConfig.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private WebappConfig loadWebappConfig(Path defaultWebroot) throws ConfigurationException {
|
private WebappConfig loadWebappConfig(Path defaultWebroot) throws ConfigurationException {
|
||||||
Path configFileRaw = Path.of("webapp");
|
Path configFile = configManager.resolveConfigFile(WEBAPP_CONFIG_NAME);
|
||||||
Path configFile = configManager.findConfigPath(configFileRaw);
|
|
||||||
Path configFolder = configFile.getParent();
|
Path configFolder = configFile.getParent();
|
||||||
|
|
||||||
if (!Files.exists(configFile)) {
|
if (!Files.exists(configFile)) {
|
||||||
try {
|
try {
|
||||||
FileHelper.createDirectories(configFolder);
|
FileHelper.createDirectories(configFolder);
|
||||||
Files.writeString(
|
Files.writeString(
|
||||||
configFolder.resolve("webapp.conf"),
|
configFile,
|
||||||
configManager.loadConfigTemplate("/de/bluecolored/bluemap/config/webapp.conf")
|
configManager.loadConfigTemplate(WEBAPP_CONFIG_NAME)
|
||||||
.setVariable("webroot", formatPath(defaultWebroot))
|
.setVariable("webroot", formatPath(defaultWebroot))
|
||||||
.build(),
|
.build(),
|
||||||
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING
|
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING
|
||||||
@ -181,20 +185,19 @@ private WebappConfig loadWebappConfig(Path defaultWebroot) throws ConfigurationE
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return configManager.loadConfig(configFileRaw, WebappConfig.class);
|
return configManager.loadConfig(WEBAPP_CONFIG_NAME, WebappConfig.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private PluginConfig loadPluginConfig() throws ConfigurationException {
|
private PluginConfig loadPluginConfig() throws ConfigurationException {
|
||||||
Path configFileRaw = Path.of("plugin");
|
Path configFile = configManager.resolveConfigFile(PLUGIN_CONFIG_NAME);
|
||||||
Path configFile = configManager.findConfigPath(configFileRaw);
|
|
||||||
Path configFolder = configFile.getParent();
|
Path configFolder = configFile.getParent();
|
||||||
|
|
||||||
if (!Files.exists(configFile)) {
|
if (!Files.exists(configFile)) {
|
||||||
try {
|
try {
|
||||||
FileHelper.createDirectories(configFolder);
|
FileHelper.createDirectories(configFolder);
|
||||||
Files.writeString(
|
Files.writeString(
|
||||||
configFolder.resolve("plugin.conf"),
|
configFile,
|
||||||
configManager.loadConfigTemplate("/de/bluecolored/bluemap/config/plugin.conf")
|
configManager.loadConfigTemplate(PLUGIN_CONFIG_NAME)
|
||||||
.build(),
|
.build(),
|
||||||
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING
|
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING
|
||||||
);
|
);
|
||||||
@ -203,14 +206,13 @@ private PluginConfig loadPluginConfig() throws ConfigurationException {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
return configManager.loadConfig(configFileRaw, PluginConfig.class);
|
return configManager.loadConfig(PLUGIN_CONFIG_NAME, PluginConfig.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
private Map<String, MapConfig> loadMapConfigs(Collection<ServerWorld> autoConfigWorlds) throws ConfigurationException {
|
private Map<String, MapConfig> loadMapConfigs(Collection<ServerWorld> autoConfigWorlds) throws ConfigurationException {
|
||||||
Map<String, MapConfig> mapConfigs = new HashMap<>();
|
Map<String, MapConfig> mapConfigs = new HashMap<>();
|
||||||
|
|
||||||
Path mapFolder = Paths.get("maps");
|
Path mapConfigFolder = configManager.getConfigRoot().resolve(MAPS_CONFIG_FOLDER_NAME);
|
||||||
Path mapConfigFolder = configManager.getConfigRoot().resolve(mapFolder);
|
|
||||||
|
|
||||||
if (!Files.exists(mapConfigFolder)){
|
if (!Files.exists(mapConfigFolder)){
|
||||||
try {
|
try {
|
||||||
@ -290,8 +292,7 @@ private Map<String, MapConfig> loadMapConfigs(Collection<ServerWorld> autoConfig
|
|||||||
try (Stream<Path> configFiles = Files.list(mapConfigFolder)) {
|
try (Stream<Path> configFiles = Files.list(mapConfigFolder)) {
|
||||||
for (var configFile : configFiles.toArray(Path[]::new)) {
|
for (var configFile : configFiles.toArray(Path[]::new)) {
|
||||||
if (!configManager.isConfigFile(configFile)) continue;
|
if (!configManager.isConfigFile(configFile)) continue;
|
||||||
Path rawConfig = configManager.getRaw(configFile);
|
String id = sanitiseMapId(configManager.getConfigName(configFile));
|
||||||
String id = sanitiseMapId(rawConfig.getFileName().toString());
|
|
||||||
|
|
||||||
if (mapConfigs.containsKey(id)) {
|
if (mapConfigs.containsKey(id)) {
|
||||||
throw new ConfigurationException("At least two of your map-config file-names result in ambiguous map-id's!\n" +
|
throw new ConfigurationException("At least two of your map-config file-names result in ambiguous map-id's!\n" +
|
||||||
@ -299,7 +300,7 @@ private Map<String, MapConfig> loadMapConfigs(Collection<ServerWorld> autoConfig
|
|||||||
"To resolve this issue, rename this file to something else.");
|
"To resolve this issue, rename this file to something else.");
|
||||||
}
|
}
|
||||||
|
|
||||||
MapConfig mapConfig = configManager.loadConfig(rawConfig, MapConfig.class);
|
MapConfig mapConfig = configManager.loadConfig(configFile, MapConfig.class);
|
||||||
mapConfigs.put(id, mapConfig);
|
mapConfigs.put(id, mapConfig);
|
||||||
}
|
}
|
||||||
} catch (IOException ex) {
|
} catch (IOException ex) {
|
||||||
@ -315,8 +316,7 @@ private Map<String, MapConfig> loadMapConfigs(Collection<ServerWorld> autoConfig
|
|||||||
private Map<String, StorageConfig> loadStorageConfigs(Path defaultWebroot) throws ConfigurationException {
|
private Map<String, StorageConfig> loadStorageConfigs(Path defaultWebroot) throws ConfigurationException {
|
||||||
Map<String, StorageConfig> storageConfigs = new HashMap<>();
|
Map<String, StorageConfig> storageConfigs = new HashMap<>();
|
||||||
|
|
||||||
Path storageFolder = Paths.get("storages");
|
Path storageConfigFolder = configManager.getConfigRoot().resolve(STORAGES_CONFIG_FOLDER_NAME);
|
||||||
Path storageConfigFolder = configManager.getConfigRoot().resolve(storageFolder);
|
|
||||||
|
|
||||||
if (!Files.exists(storageConfigFolder)){
|
if (!Files.exists(storageConfigFolder)){
|
||||||
try {
|
try {
|
||||||
@ -345,11 +345,10 @@ private Map<String, StorageConfig> loadStorageConfigs(Path defaultWebroot) throw
|
|||||||
try (Stream<Path> configFiles = Files.list(storageConfigFolder)) {
|
try (Stream<Path> configFiles = Files.list(storageConfigFolder)) {
|
||||||
for (var configFile : configFiles.toArray(Path[]::new)) {
|
for (var configFile : configFiles.toArray(Path[]::new)) {
|
||||||
if (!configManager.isConfigFile(configFile)) continue;
|
if (!configManager.isConfigFile(configFile)) continue;
|
||||||
Path rawConfig = configManager.getRaw(configFile);
|
String id = configManager.getConfigName(configFile);
|
||||||
String id = rawConfig.getFileName().toString();
|
|
||||||
|
|
||||||
StorageConfig storageConfig = configManager.loadConfig(rawConfig, StorageConfig.Base.class); // load superclass
|
StorageConfig storageConfig = configManager.loadConfig(configFile, StorageConfig.Base.class); // load superclass
|
||||||
storageConfig = configManager.loadConfig(rawConfig, storageConfig.getStorageType().getConfigType()); // load actual config type
|
storageConfig = configManager.loadConfig(configFile, storageConfig.getStorageType().getConfigType()); // load actual config type
|
||||||
|
|
||||||
storageConfigs.put(id, storageConfig);
|
storageConfigs.put(id, storageConfig);
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,45 @@
|
|||||||
|
package de.bluecolored.bluemap.common.config;
|
||||||
|
|
||||||
|
import de.bluecolored.bluemap.core.util.Key;
|
||||||
|
import de.bluecolored.bluemap.core.util.Keyed;
|
||||||
|
import de.bluecolored.bluemap.core.util.Registry;
|
||||||
|
import lombok.Getter;
|
||||||
|
import lombok.RequiredArgsConstructor;
|
||||||
|
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
||||||
|
import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
|
||||||
|
import org.spongepowered.configurate.loader.AbstractConfigurationLoader;
|
||||||
|
|
||||||
|
import java.util.function.Supplier;
|
||||||
|
|
||||||
|
public interface ConfigLoader extends Keyed {
|
||||||
|
|
||||||
|
ConfigLoader HOCON = new Impl(Key.bluemap("hocon"), ".conf", HoconConfigurationLoader::builder);
|
||||||
|
ConfigLoader JSON = new Impl(Key.bluemap("json"), ".json", GsonConfigurationLoader::builder);
|
||||||
|
|
||||||
|
ConfigLoader DEFAULT = HOCON;
|
||||||
|
|
||||||
|
Registry<ConfigLoader> REGISTRY = new Registry<>(
|
||||||
|
HOCON,
|
||||||
|
JSON
|
||||||
|
);
|
||||||
|
|
||||||
|
String getFileSuffix();
|
||||||
|
|
||||||
|
AbstractConfigurationLoader.Builder<?, ?> createLoaderBuilder();
|
||||||
|
|
||||||
|
@RequiredArgsConstructor
|
||||||
|
@Getter
|
||||||
|
class Impl implements ConfigLoader {
|
||||||
|
|
||||||
|
private final Key key;
|
||||||
|
private final String fileSuffix;
|
||||||
|
private final Supplier<AbstractConfigurationLoader.Builder<?, ?>> builderSupplier;
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public AbstractConfigurationLoader.Builder<?, ?> createLoaderBuilder() {
|
||||||
|
return builderSupplier.get();
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -32,8 +32,6 @@
|
|||||||
import org.apache.commons.io.IOUtils;
|
import org.apache.commons.io.IOUtils;
|
||||||
import org.spongepowered.configurate.ConfigurateException;
|
import org.spongepowered.configurate.ConfigurateException;
|
||||||
import org.spongepowered.configurate.ConfigurationNode;
|
import org.spongepowered.configurate.ConfigurationNode;
|
||||||
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
|
||||||
import org.spongepowered.configurate.hocon.HoconConfigurationLoader;
|
|
||||||
import org.spongepowered.configurate.loader.AbstractConfigurationLoader;
|
import org.spongepowered.configurate.loader.AbstractConfigurationLoader;
|
||||||
import org.spongepowered.configurate.loader.ConfigurationLoader;
|
import org.spongepowered.configurate.loader.ConfigurationLoader;
|
||||||
import org.spongepowered.configurate.serialize.SerializationException;
|
import org.spongepowered.configurate.serialize.SerializationException;
|
||||||
@ -43,14 +41,11 @@
|
|||||||
import java.nio.charset.StandardCharsets;
|
import java.nio.charset.StandardCharsets;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.*;
|
import java.util.Objects;
|
||||||
|
|
||||||
public class ConfigManager {
|
public class ConfigManager {
|
||||||
|
|
||||||
private static final String[] CONFIG_FILE_ENDINGS = new String[] {
|
private static final String CONFIG_TEMPLATE_RESOURCE_PATH = "/de/bluecolored/bluemap/config/";
|
||||||
".conf",
|
|
||||||
".json"
|
|
||||||
};
|
|
||||||
|
|
||||||
private final Path configRoot;
|
private final Path configRoot;
|
||||||
|
|
||||||
@ -58,32 +53,63 @@ public ConfigManager(Path configRoot) {
|
|||||||
this.configRoot = configRoot;
|
this.configRoot = configRoot;
|
||||||
}
|
}
|
||||||
|
|
||||||
public <T> T loadConfig(Path rawPath, Class<T> type) throws ConfigurationException {
|
public <T> T loadConfig(String name, Class<T> type) throws ConfigurationException {
|
||||||
Path path = findConfigPath(rawPath);
|
Path file = resolveConfigFile(name);
|
||||||
ConfigurationNode configNode = loadConfigFile(path);
|
return loadConfig(file, type);
|
||||||
|
}
|
||||||
|
|
||||||
|
public <T> T loadConfig(Path file, Class<T> type) throws ConfigurationException {
|
||||||
|
ConfigurationNode configNode = loadConfigFile(file);
|
||||||
try {
|
try {
|
||||||
return Objects.requireNonNull(configNode.get(type));
|
return Objects.requireNonNull(configNode.get(type));
|
||||||
} catch (SerializationException | NullPointerException ex) {
|
} catch (SerializationException | NullPointerException ex) {
|
||||||
throw new ConfigurationException(
|
throw new ConfigurationException(
|
||||||
"BlueMap failed to parse this file:\n" +
|
"BlueMap failed to parse this file:\n" +
|
||||||
path + "\n" +
|
file + "\n" +
|
||||||
"Check if the file is correctly formatted and all values are correct!",
|
"Check if the file is correctly formatted and all values are correct!",
|
||||||
ex);
|
ex);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public ConfigurationNode loadConfig(Path rawPath) throws ConfigurationException {
|
public ConfigTemplate loadConfigTemplate(String name) throws IOException {
|
||||||
Path path = findConfigPath(rawPath);
|
String resource = CONFIG_TEMPLATE_RESOURCE_PATH + name + ConfigLoader.DEFAULT.getFileSuffix();
|
||||||
return loadConfigFile(path);
|
|
||||||
}
|
|
||||||
|
|
||||||
public ConfigTemplate loadConfigTemplate(String resource) throws IOException {
|
|
||||||
InputStream in = BlueMap.class.getResourceAsStream(resource);
|
InputStream in = BlueMap.class.getResourceAsStream(resource);
|
||||||
if (in == null) throw new IOException("Resource not found: " + resource);
|
if (in == null) throw new IOException("Resource not found: " + resource);
|
||||||
String configTemplate = IOUtils.toString(in, StandardCharsets.UTF_8);
|
String configTemplate = IOUtils.toString(in, StandardCharsets.UTF_8);
|
||||||
return new ConfigTemplate(configTemplate);
|
return new ConfigTemplate(configTemplate);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
public Path resolveConfigFile(String name) {
|
||||||
|
for (ConfigLoader configLoader : ConfigLoader.REGISTRY.values()) {
|
||||||
|
Path path = configRoot.resolve(name + configLoader.getFileSuffix());
|
||||||
|
if (Files.isRegularFile(path)) return path;
|
||||||
|
}
|
||||||
|
|
||||||
|
return configRoot.resolve(name + ConfigLoader.DEFAULT.getFileSuffix());
|
||||||
|
}
|
||||||
|
|
||||||
|
@SuppressWarnings("BooleanMethodIsAlwaysInverted")
|
||||||
|
public boolean isConfigFile(Path file) {
|
||||||
|
String fileName = file.getFileName().toString();
|
||||||
|
for (ConfigLoader configLoader : ConfigLoader.REGISTRY.values())
|
||||||
|
if (fileName.endsWith(configLoader.getFileSuffix())) return true;
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
|
||||||
|
public String getConfigName(Path file) {
|
||||||
|
String fileName = file.getFileName().toString();
|
||||||
|
for (ConfigLoader configLoader : ConfigLoader.REGISTRY.values()) {
|
||||||
|
String suffix = configLoader.getFileSuffix();
|
||||||
|
if (fileName.endsWith(suffix))
|
||||||
|
return fileName.substring(0, fileName.length() - suffix.length());
|
||||||
|
}
|
||||||
|
return fileName;
|
||||||
|
}
|
||||||
|
|
||||||
|
public Path getConfigRoot() {
|
||||||
|
return configRoot;
|
||||||
|
}
|
||||||
|
|
||||||
private ConfigurationNode loadConfigFile(Path path) throws ConfigurationException {
|
private ConfigurationNode loadConfigFile(Path path) throws ConfigurationException {
|
||||||
if (!Files.exists(path)) {
|
if (!Files.exists(path)) {
|
||||||
throw new ConfigurationException(
|
throw new ConfigurationException(
|
||||||
@ -110,58 +136,17 @@ private ConfigurationNode loadConfigFile(Path path) throws ConfigurationExceptio
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
public Path getConfigRoot() {
|
private ConfigurationLoader<? extends ConfigurationNode> getLoader(Path path){
|
||||||
return configRoot;
|
AbstractConfigurationLoader.Builder<?, ?> builder = null;
|
||||||
}
|
for (ConfigLoader loader : ConfigLoader.REGISTRY.values()) {
|
||||||
|
if (path.getFileName().endsWith(loader.getFileSuffix())) {
|
||||||
public Path findConfigPath(Path rawPath) {
|
builder = loader.createLoaderBuilder();
|
||||||
if (!rawPath.startsWith(configRoot))
|
|
||||||
rawPath = configRoot.resolve(rawPath);
|
|
||||||
|
|
||||||
for (String fileEnding : CONFIG_FILE_ENDINGS) {
|
|
||||||
if (rawPath.getFileName().endsWith(fileEnding)) return rawPath;
|
|
||||||
}
|
|
||||||
|
|
||||||
for (String fileEnding : CONFIG_FILE_ENDINGS) {
|
|
||||||
Path path = rawPath.getParent().resolve(rawPath.getFileName() + fileEnding);
|
|
||||||
if (Files.exists(path)) return path;
|
|
||||||
}
|
|
||||||
|
|
||||||
return rawPath.getParent().resolve(rawPath.getFileName() + CONFIG_FILE_ENDINGS[0]);
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean isConfigFile(Path path) {
|
|
||||||
if (!Files.isRegularFile(path)) return false;
|
|
||||||
|
|
||||||
String fileName = path.getFileName().toString();
|
|
||||||
for (String fileEnding : CONFIG_FILE_ENDINGS) {
|
|
||||||
if (fileName.endsWith(fileEnding)) return true;
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
|
||||||
|
|
||||||
public Path getRaw(Path path) {
|
|
||||||
String fileName = path.getFileName().toString();
|
|
||||||
String rawName = null;
|
|
||||||
|
|
||||||
for (String fileEnding : CONFIG_FILE_ENDINGS) {
|
|
||||||
if (fileName.endsWith(fileEnding)) {
|
|
||||||
rawName = fileName.substring(0, fileName.length() - fileEnding.length());
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if (rawName == null) return path;
|
if (builder == null)
|
||||||
return path.getParent().resolve(rawName);
|
builder = ConfigLoader.DEFAULT.createLoaderBuilder();
|
||||||
}
|
|
||||||
|
|
||||||
private ConfigurationLoader<? extends ConfigurationNode> getLoader(Path path){
|
|
||||||
AbstractConfigurationLoader.Builder<?, ?> builder;
|
|
||||||
if (path.getFileName().endsWith(".json"))
|
|
||||||
builder = GsonConfigurationLoader.builder();
|
|
||||||
else
|
|
||||||
builder = HoconConfigurationLoader.builder();
|
|
||||||
|
|
||||||
return builder
|
return builder
|
||||||
.path(path)
|
.path(path)
|
||||||
|
@ -167,7 +167,7 @@ private void load(@Nullable ResourcePack preloadedResourcePack) throws IOExcepti
|
|||||||
|
|
||||||
BlueMapConfiguration configProvider = blueMap.getConfig();
|
BlueMapConfiguration configProvider = blueMap.getConfig();
|
||||||
if (configProvider instanceof BlueMapConfigManager) {
|
if (configProvider instanceof BlueMapConfigManager) {
|
||||||
Logger.global.logWarning("Please check: " + ((BlueMapConfigManager) configProvider).getConfigManager().findConfigPath(Path.of("core")).toAbsolutePath().normalize());
|
Logger.global.logWarning("Please check: " + ((BlueMapConfigManager) configProvider).getConfigManager().resolveConfigFile(BlueMapConfigManager.CORE_CONFIG_NAME).toAbsolutePath().normalize());
|
||||||
}
|
}
|
||||||
|
|
||||||
Logger.global.logInfo("If you have changed the config you can simply reload the plugin using: /bluemap reload");
|
Logger.global.logInfo("If you have changed the config you can simply reload the plugin using: /bluemap reload");
|
||||||
|
@ -25,14 +25,15 @@
|
|||||||
package de.bluecolored.bluemap.common.web;
|
package de.bluecolored.bluemap.common.web;
|
||||||
|
|
||||||
import de.bluecolored.bluemap.common.web.http.*;
|
import de.bluecolored.bluemap.common.web.http.*;
|
||||||
|
import de.bluecolored.bluemap.core.logger.Logger;
|
||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.NonNull;
|
import lombok.NonNull;
|
||||||
import lombok.Setter;
|
import lombok.Setter;
|
||||||
import org.apache.commons.lang3.time.DateFormatUtils;
|
import org.apache.commons.lang3.time.DateFormatUtils;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.FileInputStream;
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.InvalidPathException;
|
import java.nio.file.InvalidPathException;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.Calendar;
|
import java.util.Calendar;
|
||||||
@ -54,10 +55,16 @@ public FileRequestHandler(Path webRoot) {
|
|||||||
public HttpResponse handle(HttpRequest request) {
|
public HttpResponse handle(HttpRequest request) {
|
||||||
if (!request.getMethod().equalsIgnoreCase("GET"))
|
if (!request.getMethod().equalsIgnoreCase("GET"))
|
||||||
return new HttpResponse(HttpStatusCode.BAD_REQUEST);
|
return new HttpResponse(HttpStatusCode.BAD_REQUEST);
|
||||||
return generateResponse(request);
|
|
||||||
|
try {
|
||||||
|
return generateResponse(request);
|
||||||
|
} catch (IOException e) {
|
||||||
|
Logger.global.logError("Failed to serve file", e);
|
||||||
|
return new HttpResponse(HttpStatusCode.INTERNAL_SERVER_ERROR);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
private HttpResponse generateResponse(HttpRequest request) {
|
private HttpResponse generateResponse(HttpRequest request) throws IOException {
|
||||||
String path = request.getPath();
|
String path = request.getPath();
|
||||||
|
|
||||||
// normalize path
|
// normalize path
|
||||||
@ -76,36 +83,34 @@ private HttpResponse generateResponse(HttpRequest request) {
|
|||||||
return new HttpResponse(HttpStatusCode.FORBIDDEN);
|
return new HttpResponse(HttpStatusCode.FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
File file = filePath.toFile();
|
|
||||||
|
|
||||||
// redirect to have correct relative paths
|
// redirect to have correct relative paths
|
||||||
if (file.isDirectory() && !request.getPath().endsWith("/")) {
|
if (Files.isDirectory(filePath) && !request.getPath().endsWith("/")) {
|
||||||
HttpResponse response = new HttpResponse(HttpStatusCode.SEE_OTHER);
|
HttpResponse response = new HttpResponse(HttpStatusCode.SEE_OTHER);
|
||||||
response.addHeader("Location", "/" + path + "/" + (request.getGETParamString().isEmpty() ? "" : "?" + request.getGETParamString()));
|
response.addHeader("Location", "/" + path + "/" + (request.getGETParamString().isEmpty() ? "" : "?" + request.getGETParamString()));
|
||||||
return response;
|
return response;
|
||||||
}
|
}
|
||||||
|
|
||||||
// default to index.html
|
// default to index.html
|
||||||
if (!file.exists() || file.isDirectory()){
|
if (!Files.exists(filePath) || Files.isDirectory(filePath)){
|
||||||
file = new File(filePath + "/index.html");
|
filePath = filePath.resolve("/index.html");
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!file.exists() || file.isDirectory()) {
|
if (!Files.exists(filePath) || Files.isDirectory(filePath)){
|
||||||
return new HttpResponse(HttpStatusCode.NOT_FOUND);
|
return new HttpResponse(HttpStatusCode.NOT_FOUND);
|
||||||
}
|
}
|
||||||
|
|
||||||
// don't send php files
|
// don't send php files
|
||||||
if (file.getName().endsWith(".php")) {
|
if (filePath.getFileName().toString().endsWith(".php")) {
|
||||||
return new HttpResponse(HttpStatusCode.FORBIDDEN);
|
return new HttpResponse(HttpStatusCode.FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check if file is still in web-root and is not a directory
|
// check if file is still in web-root and is not a directory
|
||||||
if (!file.toPath().normalize().startsWith(webRoot) || file.isDirectory()){
|
if (!filePath.normalize().startsWith(webRoot) || Files.isDirectory(filePath)){
|
||||||
return new HttpResponse(HttpStatusCode.FORBIDDEN);
|
return new HttpResponse(HttpStatusCode.FORBIDDEN);
|
||||||
}
|
}
|
||||||
|
|
||||||
// check modified
|
// check modified
|
||||||
long lastModified = file.lastModified();
|
long lastModified = Files.getLastModifiedTime(filePath).to(TimeUnit.MILLISECONDS);
|
||||||
HttpHeader modHeader = request.getHeader("If-Modified-Since");
|
HttpHeader modHeader = request.getHeader("If-Modified-Since");
|
||||||
if (modHeader != null){
|
if (modHeader != null){
|
||||||
try {
|
try {
|
||||||
@ -117,7 +122,10 @@ private HttpResponse generateResponse(HttpRequest request) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
//check ETag
|
//check ETag
|
||||||
String eTag = Long.toHexString(file.length()) + Integer.toHexString(file.hashCode()) + Long.toHexString(lastModified);
|
String eTag =
|
||||||
|
Long.toHexString(Files.size(filePath)) +
|
||||||
|
Integer.toHexString(filePath.hashCode()) +
|
||||||
|
Long.toHexString(lastModified);
|
||||||
HttpHeader etagHeader = request.getHeader("If-None-Match");
|
HttpHeader etagHeader = request.getHeader("If-None-Match");
|
||||||
if (etagHeader != null){
|
if (etagHeader != null){
|
||||||
if(etagHeader.getValue().equals(eTag)) {
|
if(etagHeader.getValue().equals(eTag)) {
|
||||||
@ -133,7 +141,7 @@ private HttpResponse generateResponse(HttpRequest request) {
|
|||||||
response.addHeader("Cache-Control", "max-age=" + TimeUnit.DAYS.toSeconds(1));
|
response.addHeader("Cache-Control", "max-age=" + TimeUnit.DAYS.toSeconds(1));
|
||||||
|
|
||||||
//add content type header
|
//add content type header
|
||||||
String filetype = file.getName();
|
String filetype = filePath.getFileName().toString();
|
||||||
int pointIndex = filetype.lastIndexOf('.');
|
int pointIndex = filetype.lastIndexOf('.');
|
||||||
if (pointIndex >= 0) filetype = filetype.substring(pointIndex + 1);
|
if (pointIndex >= 0) filetype = filetype.substring(pointIndex + 1);
|
||||||
String contentType = toContentType(filetype);
|
String contentType = toContentType(filetype);
|
||||||
@ -141,7 +149,7 @@ private HttpResponse generateResponse(HttpRequest request) {
|
|||||||
|
|
||||||
//send response
|
//send response
|
||||||
try {
|
try {
|
||||||
response.setData(new FileInputStream(file));
|
response.setData(Files.newInputStream(filePath));
|
||||||
return response;
|
return response;
|
||||||
} catch (FileNotFoundException e) {
|
} catch (FileNotFoundException e) {
|
||||||
return new HttpResponse(HttpStatusCode.NOT_FOUND);
|
return new HttpResponse(HttpStatusCode.NOT_FOUND);
|
||||||
@ -155,21 +163,21 @@ private static String timestampToString(long time){
|
|||||||
private static long stringToTimestamp(String timeString) throws IllegalArgumentException {
|
private static long stringToTimestamp(String timeString) throws IllegalArgumentException {
|
||||||
try {
|
try {
|
||||||
int day = Integer.parseInt(timeString.substring(5, 7));
|
int day = Integer.parseInt(timeString.substring(5, 7));
|
||||||
|
int month = switch (timeString.substring(8, 11)) {
|
||||||
int month = Calendar.JANUARY;
|
case "Jan" -> Calendar.JANUARY;
|
||||||
switch (timeString.substring(8, 11)){
|
case "Feb" -> Calendar.FEBRUARY;
|
||||||
case "Feb" : month = Calendar.FEBRUARY; break;
|
case "Mar" -> Calendar.MARCH;
|
||||||
case "Mar" : month = Calendar.MARCH; break;
|
case "Apr" -> Calendar.APRIL;
|
||||||
case "Apr" : month = Calendar.APRIL; break;
|
case "May" -> Calendar.MAY;
|
||||||
case "May" : month = Calendar.MAY; break;
|
case "Jun" -> Calendar.JUNE;
|
||||||
case "Jun" : month = Calendar.JUNE; break;
|
case "Jul" -> Calendar.JULY;
|
||||||
case "Jul" : month = Calendar.JULY; break;
|
case "Aug" -> Calendar.AUGUST;
|
||||||
case "Aug" : month = Calendar.AUGUST; break;
|
case "Sep" -> Calendar.SEPTEMBER;
|
||||||
case "Sep" : month = Calendar.SEPTEMBER; break;
|
case "Oct" -> Calendar.OCTOBER;
|
||||||
case "Oct" : month = Calendar.OCTOBER; break;
|
case "Nov" -> Calendar.NOVEMBER;
|
||||||
case "Nov" : month = Calendar.NOVEMBER; break;
|
case "Dec" -> Calendar.DECEMBER;
|
||||||
case "Dec" : month = Calendar.DECEMBER; break;
|
default -> throw new IllegalArgumentException("Invalid timestamp format");
|
||||||
}
|
};
|
||||||
int year = Integer.parseInt(timeString.substring(12, 16));
|
int year = Integer.parseInt(timeString.substring(12, 16));
|
||||||
int hour = Integer.parseInt(timeString.substring(17, 19));
|
int hour = Integer.parseInt(timeString.substring(17, 19));
|
||||||
int min = Integer.parseInt(timeString.substring(20, 22));
|
int min = Integer.parseInt(timeString.substring(20, 22));
|
||||||
@ -183,38 +191,21 @@ private static long stringToTimestamp(String timeString) throws IllegalArgumentE
|
|||||||
}
|
}
|
||||||
|
|
||||||
private static String toContentType(String fileEnding) {
|
private static String toContentType(String fileEnding) {
|
||||||
String contentType = "text/plain";
|
return switch (fileEnding) {
|
||||||
switch (fileEnding) {
|
case "json" -> "application/json";
|
||||||
case "json" :
|
case "png" -> "image/png";
|
||||||
contentType = "application/json";
|
case "jpg",
|
||||||
break;
|
"jpeg",
|
||||||
case "png" :
|
"jpe" -> "image/jpeg";
|
||||||
contentType = "image/png";
|
case "svg" -> "image/svg+xml";
|
||||||
break;
|
case "css" -> "text/css";
|
||||||
case "jpg" :
|
case "js" -> "text/javascript";
|
||||||
case "jpeg" :
|
case "html",
|
||||||
case "jpe" :
|
"htm",
|
||||||
contentType = "image/jpeg";
|
"shtml" -> "text/html";
|
||||||
break;
|
case "xml" -> "text/xml";
|
||||||
case "svg" :
|
default -> "text/plain";
|
||||||
contentType = "image/svg+xml";
|
};
|
||||||
break;
|
|
||||||
case "css" :
|
|
||||||
contentType = "text/css";
|
|
||||||
break;
|
|
||||||
case "js" :
|
|
||||||
contentType = "text/javascript";
|
|
||||||
break;
|
|
||||||
case "html" :
|
|
||||||
case "htm" :
|
|
||||||
case "shtml" :
|
|
||||||
contentType = "text/html";
|
|
||||||
break;
|
|
||||||
case "xml" :
|
|
||||||
contentType = "text/xml";
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
return contentType;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -0,0 +1,78 @@
|
|||||||
|
/*
|
||||||
|
* This file is part of BlueMap, licensed under the MIT License (MIT).
|
||||||
|
*
|
||||||
|
* Copyright (c) Blue (Lukas Rieger) <https://bluecolored.de>
|
||||||
|
* Copyright (c) contributors
|
||||||
|
*
|
||||||
|
* Permission is hereby granted, free of charge, to any person obtaining a copy
|
||||||
|
* of this software and associated documentation files (the "Software"), to deal
|
||||||
|
* in the Software without restriction, including without limitation the rights
|
||||||
|
* to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
||||||
|
* copies of the Software, and to permit persons to whom the Software is
|
||||||
|
* furnished to do so, subject to the following conditions:
|
||||||
|
*
|
||||||
|
* The above copyright notice and this permission notice shall be included in
|
||||||
|
* all copies or substantial portions of the Software.
|
||||||
|
*
|
||||||
|
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
||||||
|
* IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||||
|
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
||||||
|
* AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
||||||
|
* LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||||
|
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
|
||||||
|
* THE SOFTWARE.
|
||||||
|
*/
|
||||||
|
package de.bluecolored.bluemap.core.util;
|
||||||
|
|
||||||
|
import org.jetbrains.annotations.Nullable;
|
||||||
|
|
||||||
|
import java.io.IOException;
|
||||||
|
import java.nio.file.*;
|
||||||
|
import java.nio.file.attribute.BasicFileAttributes;
|
||||||
|
|
||||||
|
public class CopyingPathVisitor extends SimpleFileVisitor<Path> {
|
||||||
|
|
||||||
|
private final Path targetPath;
|
||||||
|
private final CopyOption[] options;
|
||||||
|
|
||||||
|
@Nullable private Path sourcePath;
|
||||||
|
|
||||||
|
public CopyingPathVisitor(Path target, CopyOption... options) {
|
||||||
|
this.targetPath = target;
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
public CopyingPathVisitor(@Nullable Path source, Path target, CopyOption... options) {
|
||||||
|
this.sourcePath = source;
|
||||||
|
this.targetPath = target;
|
||||||
|
this.options = options;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult preVisitDirectory(Path source, BasicFileAttributes attributes) throws IOException {
|
||||||
|
// the first directory we visit will be the sourcePath
|
||||||
|
if (sourcePath == null) sourcePath = source;
|
||||||
|
|
||||||
|
Path target = resolveTarget(source);
|
||||||
|
if (Files.notExists(target)) Files.createDirectory(target);
|
||||||
|
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
@Override
|
||||||
|
public FileVisitResult visitFile(Path source, BasicFileAttributes attributes) throws IOException {
|
||||||
|
Path target = resolveTarget(source);
|
||||||
|
Files.copy(source, target, options);
|
||||||
|
|
||||||
|
return FileVisitResult.CONTINUE;
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Resolves the target file or directory using Path#toString() to make it compatible across different file-systems
|
||||||
|
*/
|
||||||
|
private Path resolveTarget(Path source) {
|
||||||
|
if (sourcePath == null) return targetPath;
|
||||||
|
return targetPath.resolve(sourcePath.relativize(source).toString());
|
||||||
|
}
|
||||||
|
|
||||||
|
}
|
@ -28,7 +28,9 @@
|
|||||||
|
|
||||||
import java.io.FileNotFoundException;
|
import java.io.FileNotFoundException;
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
|
import java.io.InputStream;
|
||||||
import java.io.OutputStream;
|
import java.io.OutputStream;
|
||||||
|
import java.net.URL;
|
||||||
import java.nio.file.*;
|
import java.nio.file.*;
|
||||||
import java.nio.file.attribute.FileAttribute;
|
import java.nio.file.attribute.FileAttribute;
|
||||||
|
|
||||||
@ -46,14 +48,14 @@ public static OutputStream createFilepartOutputStream(final Path file) throws IO
|
|||||||
return new OnCloseOutputStream(os, () -> {
|
return new OnCloseOutputStream(os, () -> {
|
||||||
if (!Files.exists(partFile)) return;
|
if (!Files.exists(partFile)) return;
|
||||||
FileHelper.createDirectories(folder);
|
FileHelper.createDirectories(folder);
|
||||||
FileHelper.move(partFile, file);
|
FileHelper.atomicMove(partFile, file);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Tries to move the file atomically, but fallbacks to a normal move operation if moving atomically fails
|
* Tries to move the file atomically, but fallbacks to a normal move operation if moving atomically fails
|
||||||
*/
|
*/
|
||||||
public static void move(Path from, Path to) throws IOException {
|
public static void atomicMove(Path from, Path to) throws IOException {
|
||||||
try {
|
try {
|
||||||
Files.move(from, to, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
|
Files.move(from, to, StandardCopyOption.ATOMIC_MOVE, StandardCopyOption.REPLACE_EXISTING);
|
||||||
} catch (FileNotFoundException | NoSuchFileException ignore) {
|
} catch (FileNotFoundException | NoSuchFileException ignore) {
|
||||||
@ -77,4 +79,39 @@ public static Path createDirectories(Path dir, FileAttribute<?>... attrs) throws
|
|||||||
return Files.createDirectories(dir, attrs);
|
return Files.createDirectories(dir, attrs);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entire zip-file into the given target directory
|
||||||
|
*/
|
||||||
|
public static void extractZipFile(URL zipFile, Path targetDirectory, CopyOption... options) throws IOException {
|
||||||
|
Path temp = Files.createTempFile(null, ".zip");
|
||||||
|
FileHelper.copy(zipFile, temp);
|
||||||
|
FileHelper.extractZipFile(temp, targetDirectory, options);
|
||||||
|
Files.deleteIfExists(temp);
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Extracts the entire zip-file into the given target directory
|
||||||
|
*/
|
||||||
|
public static void extractZipFile(Path zipFile, Path targetDirectory, CopyOption... options) throws IOException {
|
||||||
|
try (FileSystem webappZipFs = FileSystems.newFileSystem(zipFile, (ClassLoader) null)) {
|
||||||
|
CopyingPathVisitor copyAction = new CopyingPathVisitor(targetDirectory, options);
|
||||||
|
for (Path root : webappZipFs.getRootDirectories()) {
|
||||||
|
Files.walkFileTree(root, copyAction);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Copies from a URL to a target-path
|
||||||
|
*/
|
||||||
|
public static void copy(URL source, Path target) throws IOException {
|
||||||
|
try (
|
||||||
|
InputStream in = source.openStream();
|
||||||
|
OutputStream out = Files.newOutputStream(target)
|
||||||
|
) {
|
||||||
|
in.transferTo(out);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
@ -45,17 +45,16 @@
|
|||||||
import lombok.Getter;
|
import lombok.Getter;
|
||||||
import lombok.ToString;
|
import lombok.ToString;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.io.InputStream;
|
import java.io.InputStream;
|
||||||
import java.nio.file.Files;
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.util.ArrayList;
|
|
||||||
import java.util.Collection;
|
import java.util.Collection;
|
||||||
import java.util.Collections;
|
|
||||||
import java.util.List;
|
import java.util.List;
|
||||||
|
import java.util.Objects;
|
||||||
import java.util.concurrent.TimeUnit;
|
import java.util.concurrent.TimeUnit;
|
||||||
import java.util.function.Predicate;
|
import java.util.function.Predicate;
|
||||||
|
import java.util.stream.Stream;
|
||||||
|
|
||||||
@Getter
|
@Getter
|
||||||
@ToString
|
@ToString
|
||||||
@ -162,25 +161,33 @@ private Region getRegion(Vector2i pos) {
|
|||||||
|
|
||||||
@Override
|
@Override
|
||||||
public Collection<Vector2i> listRegions() {
|
public Collection<Vector2i> listRegions() {
|
||||||
File[] regionFiles = getRegionFolder().toFile().listFiles();
|
try (Stream<Path> stream = Files.list(regionFolder)) {
|
||||||
if (regionFiles == null) return Collections.emptyList();
|
return stream
|
||||||
|
.map(file -> {
|
||||||
|
try {
|
||||||
|
String fileName = file.getFileName().toString();
|
||||||
|
|
||||||
List<Vector2i> regions = new ArrayList<>(regionFiles.length);
|
if (RegionType.forFileName(fileName) == null) return null;
|
||||||
|
if (Files.size(file) <= 0) return null;
|
||||||
|
|
||||||
for (File file : regionFiles) {
|
String[] filenameParts = fileName.split("\\.");
|
||||||
if (RegionType.forFileName(file.getName()) == null) continue;
|
int rX = Integer.parseInt(filenameParts[1]);
|
||||||
if (file.length() <= 0) continue;
|
int rZ = Integer.parseInt(filenameParts[2]);
|
||||||
|
|
||||||
try {
|
return new Vector2i(rX, rZ);
|
||||||
String[] filenameParts = file.getName().split("\\.");
|
} catch (IOException ex) {
|
||||||
int rX = Integer.parseInt(filenameParts[1]);
|
Logger.global.logError("Failed to read region-file: " + file, ex);
|
||||||
int rZ = Integer.parseInt(filenameParts[2]);
|
return null;
|
||||||
|
} catch (NumberFormatException ignore) {
|
||||||
regions.add(new Vector2i(rX, rZ));
|
return null;
|
||||||
} catch (NumberFormatException ignore) {}
|
}
|
||||||
|
})
|
||||||
|
.filter(Objects::nonNull)
|
||||||
|
.toList();
|
||||||
|
} catch (IOException ex) {
|
||||||
|
Logger.global.logError("Failed to list regions for world: '" + getId() + "'", ex);
|
||||||
|
return List.of();
|
||||||
}
|
}
|
||||||
|
|
||||||
return regions;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
@Override
|
@Override
|
||||||
|
@ -48,11 +48,11 @@
|
|||||||
import org.apache.commons.lang3.time.DurationFormatUtils;
|
import org.apache.commons.lang3.time.DurationFormatUtils;
|
||||||
import org.checkerframework.checker.nullness.qual.Nullable;
|
import org.checkerframework.checker.nullness.qual.Nullable;
|
||||||
|
|
||||||
import java.io.File;
|
|
||||||
import java.io.IOException;
|
import java.io.IOException;
|
||||||
import java.net.BindException;
|
import java.net.BindException;
|
||||||
import java.net.InetSocketAddress;
|
import java.net.InetSocketAddress;
|
||||||
import java.net.UnknownHostException;
|
import java.net.UnknownHostException;
|
||||||
|
import java.nio.file.Files;
|
||||||
import java.nio.file.Path;
|
import java.nio.file.Path;
|
||||||
import java.time.Instant;
|
import java.time.Instant;
|
||||||
import java.time.ZoneId;
|
import java.time.ZoneId;
|
||||||
@ -363,7 +363,7 @@ public static void main(String[] args) {
|
|||||||
if (blueMap != null) {
|
if (blueMap != null) {
|
||||||
BlueMapConfiguration configProvider = blueMap.getConfig();
|
BlueMapConfiguration configProvider = blueMap.getConfig();
|
||||||
if (configProvider instanceof BlueMapConfigManager) {
|
if (configProvider instanceof BlueMapConfigManager) {
|
||||||
Logger.global.logWarning("Please check: " + ((BlueMapConfigManager) configProvider).getConfigManager().findConfigPath(Path.of("core")).toAbsolutePath().normalize());
|
Logger.global.logWarning("Please check: " + ((BlueMapConfigManager) configProvider).getConfigManager().resolveConfigFile(BlueMapConfigManager.CORE_CONFIG_NAME).toAbsolutePath().normalize());
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
System.exit(2);
|
System.exit(2);
|
||||||
@ -461,19 +461,20 @@ private static void printHelp() {
|
|||||||
private static String getCliCommand() {
|
private static String getCliCommand() {
|
||||||
String filename = "bluemap-cli.jar";
|
String filename = "bluemap-cli.jar";
|
||||||
try {
|
try {
|
||||||
File file = new File(BlueMapCLI.class.getProtectionDomain()
|
Path file = Path.of(BlueMapCLI.class.getProtectionDomain()
|
||||||
.getCodeSource()
|
.getCodeSource()
|
||||||
.getLocation()
|
.getLocation()
|
||||||
.getPath());
|
.toURI());
|
||||||
|
|
||||||
if (file.isFile()) {
|
if (Files.isRegularFile(file)) {
|
||||||
try {
|
try {
|
||||||
filename = "." + File.separator + new File("").getCanonicalFile().toPath().relativize(file.toPath());
|
filename = "." + file.getFileSystem().getSeparator() +
|
||||||
|
Path.of("").toRealPath().relativize(file.toRealPath());
|
||||||
} catch (IllegalArgumentException ex) {
|
} catch (IllegalArgumentException ex) {
|
||||||
filename = file.getAbsolutePath();
|
filename = file.toAbsolutePath().toString();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} catch (IOException ignore) {}
|
} catch (Exception ignore) {}
|
||||||
return "java -jar " + filename;
|
return "java -jar " + filename;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user