Create directories with symlinks in mind, fixes #349
This commit is contained in:
parent
4534202c75
commit
81f309b0be
|
@ -45,7 +45,7 @@ import de.bluecolored.bluemap.core.map.BmMap;
|
|||
import de.bluecolored.bluemap.core.mca.MCAWorld;
|
||||
import de.bluecolored.bluemap.core.resources.resourcepack.ResourcePack;
|
||||
import de.bluecolored.bluemap.core.storage.Storage;
|
||||
import de.bluecolored.bluemap.core.util.AtomicFileHelper;
|
||||
import de.bluecolored.bluemap.core.util.FileHelper;
|
||||
import de.bluecolored.bluemap.core.world.World;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
import org.spongepowered.configurate.ConfigurateException;
|
||||
|
@ -315,7 +315,7 @@ public class BlueMapService implements Closeable {
|
|||
Path resourcePackFolder = serverInterface.getConfigFolder().resolve("resourcepacks");
|
||||
|
||||
try {
|
||||
Files.createDirectories(resourcePackFolder);
|
||||
FileHelper.createDirectories(resourcePackFolder);
|
||||
} catch (IOException ex) {
|
||||
throw new ConfigurationException(
|
||||
"BlueMap failed to create this folder:\n" +
|
||||
|
@ -330,11 +330,11 @@ public class BlueMapService implements Closeable {
|
|||
try {
|
||||
Logger.global.logInfo("Downloading " + minecraftVersion.getResource().getClientUrl() + " to " + defaultResourceFile + " ...");
|
||||
|
||||
Files.createDirectories(defaultResourceFile.getParent());
|
||||
FileHelper.createDirectories(defaultResourceFile.getParent());
|
||||
Path tempResourceFile = defaultResourceFile.getParent().resolve(defaultResourceFile.getFileName() + ".filepart");
|
||||
Files.deleteIfExists(tempResourceFile);
|
||||
FileUtils.copyURLToFile(new URL(minecraftVersion.getResource().getClientUrl()), tempResourceFile.toFile(), 10000, 10000);
|
||||
AtomicFileHelper.move(tempResourceFile, defaultResourceFile);
|
||||
FileHelper.move(tempResourceFile, defaultResourceFile);
|
||||
} catch (IOException ex) {
|
||||
throw new ConfigurationException("Failed to download resources!", ex);
|
||||
}
|
||||
|
@ -346,7 +346,7 @@ public class BlueMapService implements Closeable {
|
|||
|
||||
try {
|
||||
Files.deleteIfExists(resourceExtensionsFile);
|
||||
Files.createDirectories(resourceExtensionsFile.getParent());
|
||||
FileHelper.createDirectories(resourceExtensionsFile.getParent());
|
||||
URL resourceExtensionsUrl = Objects.requireNonNull(
|
||||
Plugin.class.getResource(
|
||||
"/de/bluecolored/bluemap/" + minecraftVersion.getResource().getResourcePrefix() +
|
||||
|
|
|
@ -29,6 +29,7 @@ import de.bluecolored.bluemap.common.config.WebappConfig;
|
|||
import de.bluecolored.bluemap.core.BlueMap;
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
import de.bluecolored.bluemap.core.resources.adapter.ResourcesGson;
|
||||
import de.bluecolored.bluemap.core.util.FileHelper;
|
||||
import org.apache.commons.io.FileUtils;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
|
@ -64,7 +65,7 @@ public class WebFilesManager {
|
|||
}
|
||||
|
||||
public void saveSettings() throws IOException {
|
||||
Files.createDirectories(getSettingsFile().getParent());
|
||||
FileHelper.createDirectories(getSettingsFile().getParent());
|
||||
try (BufferedWriter writer = Files.newBufferedWriter(getSettingsFile(),
|
||||
StandardOpenOption.CREATE, StandardOpenOption.TRUNCATE_EXISTING)) {
|
||||
ResourcesGson.addAdapter(new GsonBuilder())
|
||||
|
|
|
@ -2,6 +2,7 @@ package de.bluecolored.bluemap.common.api;
|
|||
|
||||
import de.bluecolored.bluemap.api.WebApp;
|
||||
import de.bluecolored.bluemap.common.plugin.Plugin;
|
||||
import de.bluecolored.bluemap.core.util.FileHelper;
|
||||
|
||||
import javax.imageio.ImageIO;
|
||||
import java.awt.image.BufferedImage;
|
||||
|
@ -51,7 +52,7 @@ public class WebAppImpl implements WebApp {
|
|||
Path imageRootFolder = webRoot.resolve(IMAGE_ROOT_PATH);
|
||||
Path imagePath = imageRootFolder.resolve(Path.of(path.replace("/", separator) + ".png")).toAbsolutePath();
|
||||
|
||||
Files.createDirectories(imagePath.getParent());
|
||||
FileHelper.createDirectories(imagePath.getParent());
|
||||
Files.deleteIfExists(imagePath);
|
||||
Files.createFile(imagePath);
|
||||
|
||||
|
|
|
@ -6,6 +6,7 @@ import de.bluecolored.bluemap.common.config.storage.StorageConfig;
|
|||
import de.bluecolored.bluemap.common.serverinterface.ServerInterface;
|
||||
import de.bluecolored.bluemap.core.BlueMap;
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
import de.bluecolored.bluemap.core.util.FileHelper;
|
||||
import de.bluecolored.bluemap.core.util.Tristate;
|
||||
|
||||
import java.io.IOException;
|
||||
|
@ -101,7 +102,7 @@ public class BlueMapConfigs implements BlueMapConfigProvider {
|
|||
presetRenderThreadCount = 3;
|
||||
|
||||
try {
|
||||
Files.createDirectories(configFolder);
|
||||
FileHelper.createDirectories(configFolder);
|
||||
Files.writeString(
|
||||
configFolder.resolve("core.conf"),
|
||||
configManager.loadConfigTemplate("/de/bluecolored/bluemap/config/core.conf")
|
||||
|
@ -129,7 +130,7 @@ public class BlueMapConfigs implements BlueMapConfigProvider {
|
|||
|
||||
if (!Files.exists(configFile)) {
|
||||
try {
|
||||
Files.createDirectories(configFolder);
|
||||
FileHelper.createDirectories(configFolder);
|
||||
Files.writeString(
|
||||
configFolder.resolve("webserver.conf"),
|
||||
configManager.loadConfigTemplate("/de/bluecolored/bluemap/config/webserver.conf")
|
||||
|
@ -152,7 +153,7 @@ public class BlueMapConfigs implements BlueMapConfigProvider {
|
|||
|
||||
if (!Files.exists(configFile)) {
|
||||
try {
|
||||
Files.createDirectories(configFolder);
|
||||
FileHelper.createDirectories(configFolder);
|
||||
Files.writeString(
|
||||
configFolder.resolve("webapp.conf"),
|
||||
configManager.loadConfigTemplate("/de/bluecolored/bluemap/config/webapp.conf")
|
||||
|
@ -175,7 +176,7 @@ public class BlueMapConfigs implements BlueMapConfigProvider {
|
|||
|
||||
if (!Files.exists(configFile)) {
|
||||
try {
|
||||
Files.createDirectories(configFolder);
|
||||
FileHelper.createDirectories(configFolder);
|
||||
Files.writeString(
|
||||
configFolder.resolve("plugin.conf"),
|
||||
configManager.loadConfigTemplate("/de/bluecolored/bluemap/config/plugin.conf")
|
||||
|
@ -198,7 +199,7 @@ public class BlueMapConfigs implements BlueMapConfigProvider {
|
|||
|
||||
if (!Files.exists(mapConfigFolder)){
|
||||
try {
|
||||
Files.createDirectories(mapConfigFolder);
|
||||
FileHelper.createDirectories(mapConfigFolder);
|
||||
var worlds = serverInterface.getLoadedWorlds();
|
||||
if (worlds.isEmpty()) {
|
||||
Files.writeString(
|
||||
|
@ -281,7 +282,7 @@ public class BlueMapConfigs implements BlueMapConfigProvider {
|
|||
|
||||
if (!Files.exists(storageConfigFolder)){
|
||||
try {
|
||||
Files.createDirectories(storageConfigFolder);
|
||||
FileHelper.createDirectories(storageConfigFolder);
|
||||
Files.writeString(
|
||||
storageConfigFolder.resolve("file.conf"),
|
||||
configManager.loadConfigTemplate("/de/bluecolored/bluemap/config/storages/file.conf")
|
||||
|
|
|
@ -47,6 +47,7 @@ import de.bluecolored.bluemap.core.map.BmMap;
|
|||
import de.bluecolored.bluemap.core.metrics.Metrics;
|
||||
import de.bluecolored.bluemap.core.storage.MetaType;
|
||||
import de.bluecolored.bluemap.core.storage.Storage;
|
||||
import de.bluecolored.bluemap.core.util.FileHelper;
|
||||
import de.bluecolored.bluemap.core.world.World;
|
||||
import org.spongepowered.configurate.gson.GsonConfigurationLoader;
|
||||
import org.spongepowered.configurate.serialize.SerializationException;
|
||||
|
@ -56,7 +57,6 @@ import java.io.OutputStream;
|
|||
import java.io.OutputStreamWriter;
|
||||
import java.io.Writer;
|
||||
import java.net.UnknownHostException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -160,7 +160,7 @@ public class Plugin implements ServerEventListener {
|
|||
//create and start webserver
|
||||
if (webserverConfig.isEnabled()) {
|
||||
Path webroot = webserverConfig.getWebroot();
|
||||
Files.createDirectories(webroot);
|
||||
FileHelper.createDirectories(webroot);
|
||||
|
||||
RoutingRequestHandler routingRequestHandler = new RoutingRequestHandler();
|
||||
|
||||
|
|
|
@ -30,6 +30,7 @@ import de.bluecolored.bluemap.common.rendermanager.WorldRegionRenderTask;
|
|||
import de.bluecolored.bluemap.api.debug.DebugDump;
|
||||
import de.bluecolored.bluemap.core.logger.Logger;
|
||||
import de.bluecolored.bluemap.core.map.BmMap;
|
||||
import de.bluecolored.bluemap.core.util.FileHelper;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
|
@ -60,7 +61,7 @@ public class RegionFileWatchService extends Thread {
|
|||
this.scheduledUpdates = new HashMap<>();
|
||||
|
||||
Path folder = map.getWorld().getSaveFolder().resolve("region");
|
||||
Files.createDirectories(folder);
|
||||
FileHelper.createDirectories(folder);
|
||||
|
||||
this.watchService = folder.getFileSystem().newWatchService();
|
||||
|
||||
|
|
|
@ -27,7 +27,7 @@ package de.bluecolored.bluemap.core.storage.file;
|
|||
import com.flowpowered.math.vector.Vector2i;
|
||||
import de.bluecolored.bluemap.api.debug.DebugDump;
|
||||
import de.bluecolored.bluemap.core.storage.*;
|
||||
import de.bluecolored.bluemap.core.util.AtomicFileHelper;
|
||||
import de.bluecolored.bluemap.core.util.FileHelper;
|
||||
import de.bluecolored.bluemap.core.util.DeletingPathVisitor;
|
||||
|
||||
import java.io.*;
|
||||
|
@ -70,7 +70,7 @@ public class FileStorage extends Storage {
|
|||
Compression compression = lod == 0 ? this.hiresCompression : Compression.NONE;
|
||||
Path file = getFilePath(mapId, lod, tile);
|
||||
|
||||
OutputStream os = AtomicFileHelper.createFilepartOutputStream(file);
|
||||
OutputStream os = FileHelper.createFilepartOutputStream(file);
|
||||
os = new BufferedOutputStream(os);
|
||||
|
||||
try {
|
||||
|
@ -140,7 +140,7 @@ public class FileStorage extends Storage {
|
|||
public OutputStream writeMeta(String mapId, MetaType metaType) throws IOException {
|
||||
Path file = getFilePath(mapId).resolve(metaType.getFilePath());
|
||||
|
||||
OutputStream os = AtomicFileHelper.createFilepartOutputStream(file);
|
||||
OutputStream os = FileHelper.createFilepartOutputStream(file);
|
||||
os = new BufferedOutputStream(os);
|
||||
|
||||
return os;
|
||||
|
|
|
@ -28,24 +28,32 @@ import java.io.FileNotFoundException;
|
|||
import java.io.IOException;
|
||||
import java.io.OutputStream;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
|
||||
public class AtomicFileHelper {
|
||||
public class FileHelper {
|
||||
|
||||
/**
|
||||
* Creates an OutputStream that writes to a ".filepart"-file first and then atomically moves (overwrites) to the final target atomically
|
||||
* once the stream gets closed.
|
||||
*/
|
||||
public static OutputStream createFilepartOutputStream(final Path file) throws IOException {
|
||||
final Path partFile = getPartFile(file);
|
||||
Files.createDirectories(partFile.getParent());
|
||||
FileHelper.createDirectories(partFile.getParent());
|
||||
|
||||
OutputStream os = Files.newOutputStream(partFile, StandardOpenOption.WRITE, StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE);
|
||||
return new WrappedOutputStream(os, () -> {
|
||||
if (!Files.exists(partFile)) return;
|
||||
|
||||
Files.deleteIfExists(file);
|
||||
Files.createDirectories(file.getParent());
|
||||
FileHelper.createDirectories(file.getParent());
|
||||
|
||||
AtomicFileHelper.move(partFile, file);
|
||||
FileHelper.move(partFile, file);
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* 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 {
|
||||
try {
|
||||
Files.move(from, to, StandardCopyOption.ATOMIC_MOVE);
|
||||
|
@ -57,6 +65,15 @@ public class AtomicFileHelper {
|
|||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Same as {@link Files#createDirectories(Path, FileAttribute[])} but accepts symlinked folders.
|
||||
* @see Files#createDirectories(Path, FileAttribute[])
|
||||
*/
|
||||
public static Path createDirectories(Path dir, FileAttribute<?>... attrs) throws IOException {
|
||||
if (Files.isDirectory(dir)) return dir;
|
||||
return Files.createDirectories(dir, attrs);
|
||||
}
|
||||
|
||||
private static Path getPartFile(Path file) {
|
||||
return file.normalize().getParent().resolve(file.getFileName() + ".filepart");
|
||||
}
|
|
@ -48,12 +48,12 @@ import de.bluecolored.bluemap.core.logger.LoggerLogger;
|
|||
import de.bluecolored.bluemap.core.map.BmMap;
|
||||
import de.bluecolored.bluemap.core.metrics.Metrics;
|
||||
import de.bluecolored.bluemap.core.storage.Storage;
|
||||
import de.bluecolored.bluemap.core.util.FileHelper;
|
||||
import org.apache.commons.cli.*;
|
||||
import org.apache.commons.lang3.time.DurationFormatUtils;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Path;
|
||||
import java.util.*;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
@ -181,7 +181,7 @@ public class BlueMapCLI implements ServerInterface {
|
|||
Logger.global.logInfo("Starting webserver ...");
|
||||
|
||||
WebserverConfig config = blueMap.getConfigs().getWebserverConfig();
|
||||
Files.createDirectories(config.getWebroot());
|
||||
FileHelper.createDirectories(config.getWebroot());
|
||||
|
||||
RoutingRequestHandler routingRequestHandler = new RoutingRequestHandler();
|
||||
|
||||
|
@ -274,7 +274,7 @@ public class BlueMapCLI implements ServerInterface {
|
|||
cli.configFolder = Path.of("config");
|
||||
if (cmd.hasOption("c")) {
|
||||
cli.configFolder = Path.of(cmd.getOptionValue("c"));
|
||||
Files.createDirectories(cli.configFolder);
|
||||
FileHelper.createDirectories(cli.configFolder);
|
||||
}
|
||||
|
||||
//minecraft version
|
||||
|
@ -323,7 +323,7 @@ public class BlueMapCLI implements ServerInterface {
|
|||
Logger.global.logInfo("Generated default config files for you, here: " + cli.configFolder.toAbsolutePath().normalize() + "\n");
|
||||
|
||||
//create resourcepacks folder
|
||||
Files.createDirectories(cli.configFolder.resolve( "resourcepacks"));
|
||||
FileHelper.createDirectories(cli.configFolder.resolve( "resourcepacks"));
|
||||
|
||||
//print help
|
||||
BlueMapCLI.printHelp();
|
||||
|
|
Loading…
Reference in New Issue