From 7b349d4bc3bd7139cbac04de68ce1937c7e483af Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tom=C3=A1s=20F?= Date: Thu, 2 Jul 2020 18:55:08 +0100 Subject: [PATCH] Implement configuration files migration --- .../java/com/tomff/beesplus/BeesPlus.java | 20 ++- .../beesplus/core/migrations/AddField.java | 35 +++++ .../beesplus/core/migrations/Migration.java | 21 +++ .../core/migrations/MigrationsExecutor.java | 121 ++++++++++++++++++ .../beesplus/core/migrations/Operation.java | 13 ++ 5 files changed, 207 insertions(+), 3 deletions(-) create mode 100644 src/main/java/com/tomff/beesplus/core/migrations/AddField.java create mode 100644 src/main/java/com/tomff/beesplus/core/migrations/Migration.java create mode 100644 src/main/java/com/tomff/beesplus/core/migrations/MigrationsExecutor.java create mode 100644 src/main/java/com/tomff/beesplus/core/migrations/Operation.java diff --git a/src/main/java/com/tomff/beesplus/BeesPlus.java b/src/main/java/com/tomff/beesplus/BeesPlus.java index 785003e..d78f1e4 100644 --- a/src/main/java/com/tomff/beesplus/BeesPlus.java +++ b/src/main/java/com/tomff/beesplus/BeesPlus.java @@ -1,12 +1,15 @@ package com.tomff.beesplus; -import com.tomff.beesplus.handlers.DamageHandler; -import com.tomff.beesplus.handlers.RightClickHandler; -import com.tomff.beesplus.items.*; import com.tomff.beesplus.core.UpdateChecker; import com.tomff.beesplus.core.gui.GuiHandler; import com.tomff.beesplus.core.gui.GuiViewTracker; import com.tomff.beesplus.core.items.CustomItemManager; +import com.tomff.beesplus.core.migrations.AddField; +import com.tomff.beesplus.core.migrations.Migration; +import com.tomff.beesplus.core.migrations.MigrationsExecutor; +import com.tomff.beesplus.handlers.DamageHandler; +import com.tomff.beesplus.handlers.RightClickHandler; +import com.tomff.beesplus.items.*; import com.tomff.beesplus.localization.Localization; import com.tomff.beesplus.localization.LocalizationWrapper; import org.bstats.bukkit.Metrics; @@ -26,6 +29,7 @@ public class BeesPlus extends JavaPlugin { @Override public void onEnable() { + performMigrations(); saveDefaultConfig(); guiViewTracker = new GuiViewTracker(); @@ -76,6 +80,16 @@ public class BeesPlus extends JavaPlugin { return true; } + private void performMigrations() { + MigrationsExecutor migrationsExecutor = new MigrationsExecutor(this); + + migrationsExecutor.addMigration(1, new Migration() + .add(new AddField("config.yml", "beehiveupgrade.maximumpopulation", 9)) + ); + + migrationsExecutor.migrate(); + } + private void registerItems() { BeeHiveUpgrade beeHiveUpgrade = new BeeHiveUpgrade(this); diff --git a/src/main/java/com/tomff/beesplus/core/migrations/AddField.java b/src/main/java/com/tomff/beesplus/core/migrations/AddField.java new file mode 100644 index 0000000..6d9820e --- /dev/null +++ b/src/main/java/com/tomff/beesplus/core/migrations/AddField.java @@ -0,0 +1,35 @@ +package com.tomff.beesplus.core.migrations; + +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; + +public class AddField implements Operation { + private File file; + + private String fieldPath; + private Object fieldValue; + + public AddField(String filePath, String fieldPath, Object fieldValue) { + file = new File(BASE_PATH, filePath); + + this.fieldPath = fieldPath; + this.fieldValue = fieldValue; + } + + @Override + public void execute() throws IOException { + YamlConfiguration config = new YamlConfiguration(); + + try { + config.load(file); + } catch (IOException | InvalidConfigurationException e) { + e.printStackTrace(); + } + + config.set(fieldPath, fieldValue); + config.save(file); + } +} diff --git a/src/main/java/com/tomff/beesplus/core/migrations/Migration.java b/src/main/java/com/tomff/beesplus/core/migrations/Migration.java new file mode 100644 index 0000000..9da2996 --- /dev/null +++ b/src/main/java/com/tomff/beesplus/core/migrations/Migration.java @@ -0,0 +1,21 @@ +package com.tomff.beesplus.core.migrations; + +import java.util.ArrayList; +import java.util.List; + +public class Migration { + private List operations; + + public Migration() { + this.operations = new ArrayList<>(); + } + + public Migration add(Operation operation) { + operations.add(operation); + return this; + } + + public List getOperations() { + return operations; + } +} diff --git a/src/main/java/com/tomff/beesplus/core/migrations/MigrationsExecutor.java b/src/main/java/com/tomff/beesplus/core/migrations/MigrationsExecutor.java new file mode 100644 index 0000000..3b3e4e9 --- /dev/null +++ b/src/main/java/com/tomff/beesplus/core/migrations/MigrationsExecutor.java @@ -0,0 +1,121 @@ +package com.tomff.beesplus.core.migrations; + +import com.tomff.beesplus.BeesPlus; +import org.bukkit.configuration.InvalidConfigurationException; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.File; +import java.io.IOException; +import java.util.HashMap; +import java.util.Map; + +public class MigrationsExecutor { + private int latestVersion; + + private Map migrations; + private File migrationFileRegistry; + private YamlConfiguration yaml; + + private BeesPlus beesPlus; + + public MigrationsExecutor(BeesPlus beesPlus) { + this.beesPlus = beesPlus; + this.migrations = new HashMap<>(); + this.yaml = new YamlConfiguration(); + this.migrationFileRegistry = new File(beesPlus.getDataFolder(), "migration.yml"); + this.latestVersion = 0; + } + + public void addMigration(int version, Migration migration) { + migrations.put(version, migration); + + if (version > latestVersion) { + this.latestVersion = version; + } + } + + public void migrate() { + if (hasConfig() && !hasMigrationRegistry()) { + loadRegistry(); + + migrateFrom(0); + return; + } + + if (!loadRegistry()) return; + + int version = yaml.getInt("migration", 0); + if (version == latestVersion) return; + + migrateFrom(version); + } + + private void migrateFrom(int version) { + beesPlus.getLogger().info("Old files detected. Migrating files to migration v" + latestVersion); + + for (int nextVersion = version + 1; nextVersion <= latestVersion; nextVersion++) { + performMigration(migrations.get(nextVersion)); + } + + setCurrentMigration(latestVersion); + } + + public void setCurrentMigration(int version) { + yaml.set("migration", version); + try { + yaml.save(migrationFileRegistry); + } catch (IOException e) { + beesPlus.getLogger().severe("An error occurred while trying to update the migration version"); + e.printStackTrace(); + } + } + + private void createIfNotExist() { + if (!hasMigrationRegistry()) { + yaml.set("migration", latestVersion); + + try { + yaml.save(migrationFileRegistry); + } catch (IOException e) { + e.printStackTrace(); + beesPlus.getLogger().severe("An error occurred while trying to create the migration registry file!"); + } + } + } + + private boolean loadRegistry() { + createIfNotExist(); + + try { + yaml.load(migrationFileRegistry); + } catch (IOException | InvalidConfigurationException e) { + beesPlus.getLogger().severe("An error occurred while opening the migration registry file."); + beesPlus.getLogger().severe("Suggested action: please delete the BeesPlus plugin folder and restart."); + e.printStackTrace(); + + return false; + } + + return true; + } + + private void performMigration(Migration migration) { + for(Operation operation : migration.getOperations()) { + try { + operation.execute(); + } catch (IOException e) { + e.printStackTrace(); + beesPlus.getLogger().severe("An error occurred while migrating a file"); + } + } + } + + private boolean hasMigrationRegistry() { + return migrationFileRegistry.exists(); + } + + private boolean hasConfig() { + return new File(beesPlus.getDataFolder(), "config.yml").exists(); + } + +} diff --git a/src/main/java/com/tomff/beesplus/core/migrations/Operation.java b/src/main/java/com/tomff/beesplus/core/migrations/Operation.java new file mode 100644 index 0000000..3976688 --- /dev/null +++ b/src/main/java/com/tomff/beesplus/core/migrations/Operation.java @@ -0,0 +1,13 @@ +package com.tomff.beesplus.core.migrations; + +import com.tomff.beesplus.BeesPlus; +import org.bukkit.plugin.java.JavaPlugin; + +import java.io.File; +import java.io.IOException; + +public interface Operation { + File BASE_PATH = JavaPlugin.getPlugin(BeesPlus.class).getDataFolder(); + + void execute() throws IOException; +}