Skip to content

Commit

Permalink
Create directories with symlinks in mind, fixes #349
Browse files Browse the repository at this point in the history
  • Loading branch information
TBlueF committed Oct 14, 2022
1 parent 4534202 commit 81f309b
Show file tree
Hide file tree
Showing 9 changed files with 48 additions and 27 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,7 @@
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;
Expand Down Expand Up @@ -315,7 +315,7 @@ public synchronized ResourcePack getResourcePack() throws ConfigurationException
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" +
Expand All @@ -330,11 +330,11 @@ public synchronized ResourcePack getResourcePack() throws ConfigurationException
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);
}
Expand All @@ -346,7 +346,7 @@ public synchronized ResourcePack getResourcePack() throws ConfigurationException

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() +
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -29,6 +29,7 @@
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;
Expand Down Expand Up @@ -64,7 +65,7 @@ public void loadSettings() throws IOException {
}

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())
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@

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;
Expand Down Expand Up @@ -51,7 +52,7 @@ public String createImage(BufferedImage image, String path) throws IOException {
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);

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
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;
Expand Down Expand Up @@ -101,7 +102,7 @@ private synchronized CoreConfig loadCoreConfig(Path defaultDataFolder) throws Co
presetRenderThreadCount = 3;

try {
Files.createDirectories(configFolder);
FileHelper.createDirectories(configFolder);
Files.writeString(
configFolder.resolve("core.conf"),
configManager.loadConfigTemplate("/de/bluecolored/bluemap/config/core.conf")
Expand Down Expand Up @@ -129,7 +130,7 @@ private synchronized WebserverConfig loadWebserverConfig(Path defaultWebroot) th

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")
Expand All @@ -152,7 +153,7 @@ private synchronized WebappConfig loadWebappConfig(Path defaultWebroot) throws C

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")
Expand All @@ -175,7 +176,7 @@ private synchronized PluginConfig loadPluginConfig() throws ConfigurationExcepti

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")
Expand All @@ -198,7 +199,7 @@ private synchronized Map<String, MapConfig> loadMapConfigs() throws Configuratio

if (!Files.exists(mapConfigFolder)){
try {
Files.createDirectories(mapConfigFolder);
FileHelper.createDirectories(mapConfigFolder);
var worlds = serverInterface.getLoadedWorlds();
if (worlds.isEmpty()) {
Files.writeString(
Expand Down Expand Up @@ -281,7 +282,7 @@ private synchronized Map<String, StorageConfig> loadStorageConfigs(Path defaultW

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")
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -47,6 +47,7 @@
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;
Expand All @@ -56,7 +57,6 @@
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;
Expand Down Expand Up @@ -160,7 +160,7 @@ public void load() throws IOException {
//create and start webserver
if (webserverConfig.isEnabled()) {
Path webroot = webserverConfig.getWebroot();
Files.createDirectories(webroot);
FileHelper.createDirectories(webroot);

RoutingRequestHandler routingRequestHandler = new RoutingRequestHandler();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
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.*;
Expand Down Expand Up @@ -60,7 +61,7 @@ public RegionFileWatchService(RenderManager renderManager, BmMap map, boolean ve
this.scheduledUpdates = new HashMap<>();

Path folder = map.getWorld().getSaveFolder().resolve("region");
Files.createDirectories(folder);
FileHelper.createDirectories(folder);

this.watchService = folder.getFileSystem().newWatchService();

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@
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.*;
Expand Down Expand Up @@ -70,7 +70,7 @@ public OutputStream writeMapTile(String mapId, int lod, Vector2i tile) throws IO
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 {
Expand Down Expand Up @@ -140,7 +140,7 @@ public void deleteMapTile(String mapId, int lod, Vector2i tile) throws IOExcepti
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;
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -28,24 +28,32 @@
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);
Expand All @@ -57,6 +65,15 @@ public static void move(Path from, Path to) throws IOException {
}
}

/**
* 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");
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -48,12 +48,12 @@
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;
Expand Down Expand Up @@ -181,7 +181,7 @@ public void startWebserver(BlueMapService blueMap, boolean verbose) throws IOExc
Logger.global.logInfo("Starting webserver ...");

WebserverConfig config = blueMap.getConfigs().getWebserverConfig();
Files.createDirectories(config.getWebroot());
FileHelper.createDirectories(config.getWebroot());

RoutingRequestHandler routingRequestHandler = new RoutingRequestHandler();

Expand Down Expand Up @@ -274,7 +274,7 @@ public static void main(String[] args) {
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
Expand Down Expand Up @@ -323,7 +323,7 @@ public static void main(String[] args) {
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();
Expand Down

0 comments on commit 81f309b

Please sign in to comment.