package net.knarcraft.knarlib.util; import net.knarcraft.knarlib.config.StargateYamlConfiguration; import net.knarcraft.knarlib.plugin.ConfigCommentPlugin; import net.knarcraft.knarlib.property.ColorConversion; import org.bukkit.configuration.ConfigurationSection; import org.bukkit.configuration.MemorySection; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; import org.bukkit.plugin.Plugin; import org.jetbrains.annotations.NotNull; import org.jetbrains.annotations.Nullable; import java.io.File; import java.io.IOException; import java.io.InputStream; import java.util.Map; import java.util.logging.Level; /** * A helper class for dealing with a plugin's configuration file */ @SuppressWarnings("unused") public final class ConfigHelper { private static final String CONFIG_FILE = "config.yml"; private static final String BACKUP_CONFIG_FILE = "config.yml.old"; private static final String MIGRATION_FILE = "config-migrations.txt"; private ConfigHelper() { } /** * Gets the relative string path of the configuration file * * @return

The configuration file path

*/ public static String getConfigFile() { return CONFIG_FILE; } /** * Saves any missing configuration values to the given plugin's configuration * * @param plugin

The plugin to add missing default values to

*/ public static void saveDefaults(@NotNull Plugin plugin) { plugin.saveDefaultConfig(); plugin.getConfig().options().copyDefaults(true); plugin.reloadConfig(); plugin.saveConfig(); } /** * Changes all configuration values from the old name to the new name * *

Note: This method expects a file "config-migrations.txt" in the resources directory that contains mappings: * oldKey=replacementKey in order to migrate from old to new configuration values. * The old configuration file will be saved to config.yml.old

* * @param plugin

The plugin to migrate the configuration for

* @return

True if the migration succeeded without any issues

*/ public static boolean migrateConfig(@NotNull ConfigCommentPlugin plugin) { File dataFolder = plugin.getDataFolder(); File config = new File(dataFolder, CONFIG_FILE); //Save the old config just in case something goes wrong FileConfiguration oldConfiguration = plugin.getConfig(); try { oldConfiguration.save(new File(dataFolder, BACKUP_CONFIG_FILE)); } catch (IOException exception) { plugin.getLogger().log(Level.WARNING, "Unable to save old backup and do migration"); return false; } // Read the default configuration InputStream configStream = loadInternalFile(plugin, CONFIG_FILE, "internal configuration"); if (configStream == null) { return false; } YamlConfiguration newConfiguration = StargateYamlConfiguration.loadConfiguration( FileHelper.getBufferedReaderFromInputStream(configStream)); //Read all available config migrations Map migrationFields; try { InputStream migrationStream = loadInternalFile(plugin, MIGRATION_FILE, "internal migration paths"); if (migrationStream == null) { return false; } migrationFields = FileHelper.readKeyValuePairs(FileHelper.getBufferedReaderFromInputStream(migrationStream), "=", ColorConversion.NONE); } catch (IOException exception) { plugin.getLogger().log(Level.WARNING, "Unable to load config migration file"); return false; } // Replace old config names with the new ones for (String key : migrationFields.keySet()) { if (oldConfiguration.contains(key)) { migrateProperty(migrationFields, key, oldConfiguration); } } // Copy all keys to the new config for (String key : StargateYamlConfiguration.getKeysWithoutComments(oldConfiguration, true)) { if (oldConfiguration.get(key) instanceof MemorySection) { continue; } newConfiguration.set(key, oldConfiguration.get(key)); } // Save merged configuration if (!StargateYamlConfiguration.saveConfiguration(plugin, newConfiguration)) { return false; } plugin.reloadConfig(); return true; } /** * Migrates one configuration property * * @param migrationFields

The configuration fields to be migrated

* @param key

The key/path of the property to migrate

* @param oldConfiguration

The original pre-migration configuration

*/ private static void migrateProperty(@NotNull Map migrationFields, @NotNull String key, @NotNull FileConfiguration oldConfiguration) { String newPath = migrationFields.get(key); Object oldValue = oldConfiguration.get(key); if (!newPath.trim().isEmpty()) { if (oldConfiguration.isConfigurationSection(key)) { // Copy each value of a configuration section ConfigurationSection sourceSection = oldConfiguration.getConfigurationSection(key); ConfigurationSection destinationSection = oldConfiguration.createSection(newPath); if (sourceSection == null) { return; } for (String path : StargateYamlConfiguration.getKeysWithoutComments(sourceSection, true)) { destinationSection.set(path, sourceSection.get(path)); } } else { // Copy the value to the new path oldConfiguration.set(newPath, oldValue); } } // Remove the old path's value oldConfiguration.set(key, null); } /** * Loads a file from the internal plugin .jar * * @param plugin

The plugin to load the file from

* @param fileName

The file to load

* @param fileDescription

The file description to use in error messages

* @return

An input stream for the file, or null if the file could not be read

*/ @Nullable private static InputStream loadInternalFile(@NotNull Plugin plugin, @NotNull String fileName, @NotNull String fileDescription) { InputStream configStream = FileHelper.getInputStreamForInternalFile("/" + fileName); if (configStream == null) { plugin.getLogger().log(Level.SEVERE, "Could not migrate the configuration, as the " + fileDescription + " could not be read!"); return null; } else { return configStream; } } }