diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java index d359a6aa..e4b69b16 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/HolographicDisplays.java @@ -8,7 +8,6 @@ package me.filoghost.holographicdisplays.plugin; import com.gmail.filoghost.holographicdisplays.api.internal.HologramsAPIProvider; import me.filoghost.fcommons.FCommonsPlugin; import me.filoghost.fcommons.FeatureSupport; -import me.filoghost.fcommons.config.exception.ConfigException; import me.filoghost.fcommons.logging.ErrorCollector; import me.filoghost.holographicdisplays.api.internal.HolographicDisplaysAPIProvider; import me.filoghost.holographicdisplays.common.nms.NMSManager; @@ -20,9 +19,9 @@ import me.filoghost.holographicdisplays.plugin.commands.HologramCommandManager; import me.filoghost.holographicdisplays.plugin.config.ConfigManager; import me.filoghost.holographicdisplays.plugin.config.HologramDatabase; import me.filoghost.holographicdisplays.plugin.config.Settings; -import me.filoghost.holographicdisplays.plugin.config.upgrade.LegacyAnimationsUpgrade; -import me.filoghost.holographicdisplays.plugin.config.upgrade.LegacyDatabaseUpgrade; -import me.filoghost.holographicdisplays.plugin.config.upgrade.LegacySymbolsUpgrade; +import me.filoghost.holographicdisplays.plugin.config.upgrade.AnimationsLegacyUpgrade; +import me.filoghost.holographicdisplays.plugin.config.upgrade.DatabaseLegacyUpgrade; +import me.filoghost.holographicdisplays.plugin.config.upgrade.SymbolsLegacyUpgrade; import me.filoghost.holographicdisplays.plugin.hologram.api.APIHologramManager; import me.filoghost.holographicdisplays.plugin.hologram.internal.InternalHologramManager; import me.filoghost.holographicdisplays.plugin.hologram.tracking.LineTrackerManager; @@ -44,7 +43,6 @@ import org.bukkit.Bukkit; import org.bukkit.ChatColor; import org.bukkit.entity.Player; -import java.io.IOException; import java.util.concurrent.TimeUnit; public class HolographicDisplays extends FCommonsPlugin { @@ -107,21 +105,9 @@ public class HolographicDisplays extends FCommonsPlugin { APIHologramManager apiHologramManager = new APIHologramManager(lineTrackerManager); // Run only once at startup, before loading the configuration - try { - LegacySymbolsUpgrade.run(configManager, errorCollector); - } catch (ConfigException e) { - errorCollector.add(e, "couldn't automatically convert symbols file to the new format"); - } - try { - LegacyAnimationsUpgrade.run(configManager, errorCollector); - } catch (IOException e) { - errorCollector.add(e, "couldn't automatically convert animation files to the new format"); - } - try { - LegacyDatabaseUpgrade.run(configManager); - } catch (ConfigException | IOException e) { - errorCollector.add(e, "couldn't automatically convert database file to the new format"); - } + new SymbolsLegacyUpgrade(configManager, errorCollector).tryRun(); + new AnimationsLegacyUpgrade(configManager, errorCollector).tryRun(); + new DatabaseLegacyUpgrade(configManager, errorCollector).tryRun(); // Load the configuration load(true, errorCollector); diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/ConfigManager.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/ConfigManager.java index 20b9c6b9..ab500700 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/ConfigManager.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/ConfigManager.java @@ -145,7 +145,7 @@ public class ConfigManager extends BaseConfigManager { errorCollector.add(e, "error while loading config file \"" + formatPath(file) + "\""); } - private String formatPath(Path path) { + public String formatPath(Path path) { return ConfigErrors.formatPath(getRootDataFolder(), path); } diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/AnimationsLegacyUpgrade.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/AnimationsLegacyUpgrade.java new file mode 100644 index 00000000..ff9872bb --- /dev/null +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/AnimationsLegacyUpgrade.java @@ -0,0 +1,95 @@ +/* + * Copyright (C) filoghost and contributors + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ +package me.filoghost.holographicdisplays.plugin.config.upgrade; + +import me.filoghost.fcommons.config.Config; +import me.filoghost.fcommons.config.exception.ConfigSaveException; +import me.filoghost.fcommons.logging.ErrorCollector; +import me.filoghost.holographicdisplays.plugin.config.ConfigManager; +import me.filoghost.holographicdisplays.plugin.util.FileUtils; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; +import java.util.List; +import java.util.stream.Stream; + +public class AnimationsLegacyUpgrade extends LegacyUpgrade { + + private static final String SPEED_PREFIX = "speed:"; + + private final Path animationFolder; + + public AnimationsLegacyUpgrade(ConfigManager configManager, ErrorCollector errorCollector) { + super(configManager, errorCollector); + this.animationFolder = configManager.getAnimationsFolder(); + } + + @Override + public Path getFile() { + return animationFolder; + } + + @Override + public void run() throws IOException { + if (!Files.isDirectory(animationFolder)) { + return; + } + + try (Stream animationFiles = Files.list(animationFolder)) { + animationFiles.filter(Files::isRegularFile).forEach(file -> { + tryRun(file, () -> upgradeAnimationFile(file)); + }); + } + } + + + private void upgradeAnimationFile(Path oldFile) throws IOException, ConfigSaveException { + String oldFileName = oldFile.getFileName().toString(); + if (FileUtils.hasFileExtension(oldFileName, "yml")) { + return; // Probably a file already with the new format + } + + List lines = Files.readAllLines(oldFile); + if (lines.size() == 0) { + return; + } + + // Remove the first line that only contains the speed + String firstLine = lines.remove(0).trim(); + if (!firstLine.toLowerCase().startsWith(SPEED_PREFIX)) { + return; // Not a valid animation + } + + String newFileName; + if (FileUtils.hasFileExtension(oldFileName, "txt")) { + newFileName = FileUtils.removeFileExtension(oldFileName) + ".yml"; + } else { + newFileName = oldFileName + ".yml"; + } + Path newFile = oldFile.resolveSibling(newFileName); + + if (Files.isRegularFile(newFile)) { + return; // Already existing, do not override + } + + double speed; + try { + speed = Double.parseDouble(firstLine.substring(SPEED_PREFIX.length()).trim()); + } catch (NumberFormatException e) { + speed = 0.5; + } + + Config config = new Config(); + config.setDouble("interval-seconds", speed); + config.setStringList("animation-frames", lines); + + createBackupFile(oldFile); + configManager.getConfigLoader(newFile).save(config); + Files.delete(oldFile); + } + +} diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyDatabaseUpgrade.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/DatabaseLegacyUpgrade.java similarity index 72% rename from plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyDatabaseUpgrade.java rename to plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/DatabaseLegacyUpgrade.java index a5d514f2..2f5e8e86 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyDatabaseUpgrade.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/DatabaseLegacyUpgrade.java @@ -11,20 +11,30 @@ import me.filoghost.fcommons.config.ConfigSection; import me.filoghost.fcommons.config.ConfigType; import me.filoghost.fcommons.config.ConfigValue; import me.filoghost.fcommons.config.FileConfig; -import me.filoghost.fcommons.config.exception.ConfigLoadException; -import me.filoghost.fcommons.config.exception.ConfigSaveException; +import me.filoghost.fcommons.config.exception.ConfigException; +import me.filoghost.fcommons.logging.ErrorCollector; import me.filoghost.holographicdisplays.plugin.config.ConfigManager; -import java.io.IOException; -import java.nio.file.Files; +import java.nio.file.Path; -public class LegacyDatabaseUpgrade { +public class DatabaseLegacyUpgrade extends LegacyUpgrade implements LegacyUpgradeTask { - public static void run(ConfigManager configManager) throws ConfigLoadException, ConfigSaveException, IOException { - ConfigLoader databaseConfigLoader = configManager.getConfigLoader("database.yml"); + private final ConfigLoader databaseConfigLoader; + public DatabaseLegacyUpgrade(ConfigManager configManager, ErrorCollector errorCollector) { + super(configManager, errorCollector); + this.databaseConfigLoader = configManager.getConfigLoader("database.yml"); + } + + @Override + public Path getFile() { + return databaseConfigLoader.getFile(); + } + + @Override + public void run() throws ConfigException { if (!databaseConfigLoader.fileExists()) { - return; // Database doesn't exist yet, nothing to convert + return; // Database file doesn't exist, nothing to upgrade } FileConfig databaseConfig = databaseConfigLoader.load(); @@ -42,12 +52,12 @@ public class LegacyDatabaseUpgrade { } if (changed) { - Files.copy(databaseConfigLoader.getFile(), LegacyUpgradeUtils.getBackupFile(databaseConfigLoader.getFile())); + createBackupFile(databaseConfigLoader.getFile()); databaseConfigLoader.save(databaseConfig); } } - private static ConfigSection convertLegacySerializedLocation(String legacySerializedLocation) { + private ConfigSection convertLegacySerializedLocation(String legacySerializedLocation) { String[] legacyLocationParts = Strings.splitAndTrim(legacySerializedLocation, ","); ConfigSection positionSection = new ConfigSection(); diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyAnimationsUpgrade.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyAnimationsUpgrade.java deleted file mode 100644 index b0c46e19..00000000 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyAnimationsUpgrade.java +++ /dev/null @@ -1,81 +0,0 @@ -/* - * Copyright (C) filoghost and contributors - * - * SPDX-License-Identifier: GPL-3.0-or-later - */ -package me.filoghost.holographicdisplays.plugin.config.upgrade; - -import me.filoghost.fcommons.config.Config; -import me.filoghost.fcommons.logging.ErrorCollector; -import me.filoghost.holographicdisplays.plugin.config.ConfigManager; -import me.filoghost.holographicdisplays.plugin.util.FileUtils; - -import java.io.IOException; -import java.nio.file.Files; -import java.nio.file.Path; -import java.util.List; -import java.util.stream.Stream; - -public class LegacyAnimationsUpgrade { - - private static final String SPEED_PREFIX = "speed:"; - - public static void run(ConfigManager configManager, ErrorCollector errorCollector) throws IOException { - Path animationFolder = configManager.getAnimationsFolder(); - - if (!Files.isDirectory(animationFolder)) { - return; - } - - try (Stream animationFiles = Files.list(animationFolder)) { - animationFiles.filter(Files::isRegularFile).forEach(file -> convertFile(file, configManager, errorCollector)); - } - } - - private static void convertFile(Path oldFile, ConfigManager configManager, ErrorCollector errorCollector) { - if (LegacyUpgradeUtils.isBackupFile(oldFile)) { - return; // Ignore backup files - } - - try { - List lines = Files.readAllLines(oldFile); - if (lines.size() == 0) { - return; - } - - // Remove the first line that only contains the speed - String firstLine = lines.remove(0).trim(); - if (!firstLine.toLowerCase().startsWith(SPEED_PREFIX)) { - return; // Not a valid animation - } - - String newFileName = oldFile.getFileName().toString(); - if (FileUtils.hasFileExtension(newFileName, "txt")) { - newFileName = FileUtils.removeFileExtension(newFileName); - } - newFileName += ".yml"; - Path newFile = oldFile.resolveSibling(newFileName); - - if (Files.isRegularFile(newFile)) { - return; // Already created, do not override - } - - double speed; - try { - speed = Double.parseDouble(firstLine.substring(SPEED_PREFIX.length()).trim()); - } catch (NumberFormatException e) { - speed = 0.5; - } - - Config config = new Config(); - config.setDouble("interval-seconds", speed); - config.setStringList("animation-frames", lines); - configManager.getConfigLoader(newFile).save(config); - - Files.move(oldFile, LegacyUpgradeUtils.getBackupFile(oldFile)); - } catch (Exception e) { - errorCollector.add(e, "couldn't automatically convert animation file \"" + oldFile.getFileName() + "\" to the new format"); - } - } - -} diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyUpgrade.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyUpgrade.java new file mode 100644 index 00000000..2aa1cfcf --- /dev/null +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyUpgrade.java @@ -0,0 +1,86 @@ +/* + * Copyright (C) filoghost and contributors + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ +package me.filoghost.holographicdisplays.plugin.config.upgrade; + +import me.filoghost.fcommons.Preconditions; +import me.filoghost.fcommons.config.exception.ConfigException; +import me.filoghost.fcommons.logging.ErrorCollector; +import me.filoghost.holographicdisplays.plugin.config.ConfigManager; + +import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; + +public abstract class LegacyUpgrade implements LegacyUpgradeTask { + + protected final ConfigManager configManager; + private final ErrorCollector errorCollector; + private final Path rootDataFolder; + private final Path backupsFolder; + + public LegacyUpgrade(ConfigManager configManager, ErrorCollector errorCollector) { + this.configManager = configManager; + this.errorCollector = errorCollector; + this.rootDataFolder = configManager.getRootDataFolder(); + this.backupsFolder = rootDataFolder.resolve("old-files"); + } + + protected abstract Path getFile(); + + public final void tryRun() { + tryRun(getFile(), this); + } + + protected final void tryRun(Path file, LegacyUpgradeTask task) { + try { + task.run(); + } catch (IOException | ConfigException e) { + errorCollector.add(e, "error while upgrading \"" + configManager.formatPath(file) + "\" to the new format"); + } + } + + protected final void createBackupFile(Path file) { + Preconditions.checkArgument(file.startsWith(rootDataFolder), "file is outside data folder"); + Preconditions.checkArgument(!file.startsWith(backupsFolder), "file is inside backups folder"); + + Path pathFromRootDataFolderToFile = file.subpath(rootDataFolder.getNameCount(), file.getNameCount()); + Path backupFile = backupsFolder.resolve(pathFromRootDataFolderToFile); + + // Find the first available destination file if already existing + int copyIndex = 1; + while (Files.isRegularFile(backupFile)) { + backupFile = getAlternativeCopyFile(backupFile, copyIndex); + copyIndex++; + } + + try { + Files.createDirectories(backupFile.getParent()); + Files.copy(file, backupFile); + } catch (IOException e) { + errorCollector.add(e, "error while copying file \"" + configManager.formatPath(file) + "\"" + + " to \"" + configManager.formatPath(backupsFolder) + "\""); + } + } + + private Path getAlternativeCopyFile(Path file, int copyIndex) { + String fileName = file.getFileName().toString(); + int extensionBeginIndex = fileName.lastIndexOf('.'); + String fileNameWithoutExtension; + String extensionWithSeparator; + + if (extensionBeginIndex >= 0) { + fileNameWithoutExtension = fileName.substring(0, extensionBeginIndex); + extensionWithSeparator = fileName.substring(extensionBeginIndex); + } else { + fileNameWithoutExtension = fileName; + extensionWithSeparator = ""; + } + + // Insert the copy index before the extension + return file.resolveSibling(fileNameWithoutExtension + " (" + copyIndex + ")" + extensionWithSeparator); + } + +} diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyUpgradeTask.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyUpgradeTask.java new file mode 100644 index 00000000..3c65a793 --- /dev/null +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyUpgradeTask.java @@ -0,0 +1,16 @@ +/* + * Copyright (C) filoghost and contributors + * + * SPDX-License-Identifier: GPL-3.0-or-later + */ +package me.filoghost.holographicdisplays.plugin.config.upgrade; + +import me.filoghost.fcommons.config.exception.ConfigException; + +import java.io.IOException; + +public interface LegacyUpgradeTask { + + void run() throws IOException, ConfigException; + +} diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyUpgradeUtils.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyUpgradeUtils.java deleted file mode 100644 index 4414393a..00000000 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacyUpgradeUtils.java +++ /dev/null @@ -1,22 +0,0 @@ -/* - * Copyright (C) filoghost and contributors - * - * SPDX-License-Identifier: GPL-3.0-or-later - */ -package me.filoghost.holographicdisplays.plugin.config.upgrade; - -import me.filoghost.holographicdisplays.plugin.util.FileUtils; - -import java.nio.file.Path; - -class LegacyUpgradeUtils { - - static Path getBackupFile(Path file) { - return file.resolveSibling(file.getFileName() + ".backup"); - } - - static boolean isBackupFile(Path file) { - return FileUtils.hasFileExtension(file, "backup"); - } - -} diff --git a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacySymbolsUpgrade.java b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/SymbolsLegacyUpgrade.java similarity index 64% rename from plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacySymbolsUpgrade.java rename to plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/SymbolsLegacyUpgrade.java index ef4d1b23..c5bb4a76 100644 --- a/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/LegacySymbolsUpgrade.java +++ b/plugin/src/main/java/me/filoghost/holographicdisplays/plugin/config/upgrade/SymbolsLegacyUpgrade.java @@ -11,8 +11,8 @@ import me.filoghost.fcommons.config.ConfigErrors; import me.filoghost.fcommons.config.ConfigLoader; import me.filoghost.fcommons.config.ConfigPath; import me.filoghost.fcommons.config.ConfigSection; +import me.filoghost.fcommons.config.exception.ConfigException; import me.filoghost.fcommons.config.exception.ConfigLoadException; -import me.filoghost.fcommons.config.exception.ConfigSaveException; import me.filoghost.fcommons.logging.ErrorCollector; import me.filoghost.holographicdisplays.plugin.config.ConfigManager; import org.apache.commons.lang.StringEscapeUtils; @@ -22,19 +22,31 @@ import java.nio.file.Files; import java.nio.file.Path; import java.util.List; -public class LegacySymbolsUpgrade { +public class SymbolsLegacyUpgrade extends LegacyUpgrade { - public static void run(ConfigManager configManager, ErrorCollector errorCollector) throws ConfigLoadException, ConfigSaveException { - Path oldFile = configManager.getRootDataFolder().resolve("symbols.yml"); + private final Path oldFile; + + public SymbolsLegacyUpgrade(ConfigManager configManager, ErrorCollector errorCollector) { + super(configManager, errorCollector); + this.oldFile = configManager.getRootDataFolder().resolve("symbols.yml"); + } + + @Override + protected Path getFile() { + return oldFile; + } + + @Override + public void run() throws IOException, ConfigException { ConfigLoader newConfigLoader = configManager.getConfigLoader("custom-placeholders.yml"); Path newFile = newConfigLoader.getFile(); if (!Files.isRegularFile(oldFile)) { - return; // Old file doesn't exist, ignore upgrade + return; // Old file doesn't exist, nothing to upgrade } if (Files.isRegularFile(newFile)) { - return; // Already created, do not override + return; // Already existing, do not override } Config newConfig = new Config(); @@ -55,37 +67,32 @@ public class LegacySymbolsUpgrade { // Ignore bad line if (!line.contains(":")) { - errorCollector.add("couldn't convert invalid line in " + oldFile.getFileName() + ": " + line); continue; } - String[] parts = Strings.splitAndTrim(line, ":", 2); - String placeholder = unquote(parts[0]); - String replacement = StringEscapeUtils.unescapeJava(unquote(parts[1])); + String[] placeholderAndReplacement = Strings.splitAndTrim(line, ":", 2); + String placeholder = unquote(placeholderAndReplacement[0]); + String replacement = StringEscapeUtils.unescapeJava(unquote(placeholderAndReplacement[1])); placeholdersSection.setString(ConfigPath.literal(placeholder), replacement); } - try { - Files.move(oldFile, LegacyUpgradeUtils.getBackupFile(oldFile)); - } catch (IOException e) { - errorCollector.add(e, "couldn't rename " + oldFile.getFileName()); - } + createBackupFile(oldFile); newConfigLoader.save(newConfig); + Files.delete(oldFile); } private static String unquote(String input) { if (input.length() < 2) { - // Too short, cannot be a quoted string + // Too short to be a quoted string return input; } - if (input.startsWith("'") && input.endsWith("'")) { - return input.substring(1, input.length() - 1); - } else if (input.startsWith("\"") && input.endsWith("\"")) { - return input.substring(1, input.length() - 1); - } - return input; + if ((input.startsWith("'") && input.endsWith("'")) || (input.startsWith("\"") && input.endsWith("\""))) { + return input.substring(1, input.length() - 1); + } else { + return input; + } } }