diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/MessagesCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/MessagesCommand.java index 873281e1..6e55c4cb 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/MessagesCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/MessagesCommand.java @@ -3,16 +3,10 @@ package fr.xephi.authme.command.executable.authme; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.command.help.HelpMessagesService; -import fr.xephi.authme.initialization.DataFolder; -import fr.xephi.authme.message.Messages; import fr.xephi.authme.service.HelpTranslationGenerator; -import fr.xephi.authme.service.MessageUpdater; -import fr.xephi.authme.settings.Settings; -import fr.xephi.authme.settings.properties.PluginSettings; import org.bukkit.command.CommandSender; import javax.inject.Inject; -import java.io.File; import java.io.IOException; import java.util.List; @@ -22,15 +16,6 @@ import java.util.List; */ public class MessagesCommand implements ExecutableCommand { - private static final String DEFAULT_LANGUAGE = "en"; - - @Inject - private Settings settings; - @Inject - @DataFolder - private File dataFolder; - @Inject - private Messages messages; @Inject private HelpTranslationGenerator helpTranslationGenerator; @Inject @@ -40,8 +25,6 @@ public class MessagesCommand implements ExecutableCommand { public void executeCommand(CommandSender sender, List arguments) { if (!arguments.isEmpty() && "help".equalsIgnoreCase(arguments.get(0))) { updateHelpFile(sender); - } else { - updateMessagesFile(sender); } } @@ -55,25 +38,4 @@ public class MessagesCommand implements ExecutableCommand { ConsoleLogger.logException("Could not update help file:", e); } } - - private void updateMessagesFile(CommandSender sender) { - final String language = settings.getProperty(PluginSettings.MESSAGES_LANGUAGE); - try { - boolean isFileUpdated = new MessageUpdater( - new File(dataFolder, getMessagePath(language)), - getMessagePath(language), - getMessagePath(DEFAULT_LANGUAGE)) - .executeCopy(sender); - if (isFileUpdated) { - messages.reloadMessagesFile(); - } - } catch (Exception e) { - sender.sendMessage("Could not update messages: " + e.getMessage()); - ConsoleLogger.logException("Could not update messages:", e); - } - } - - private static String getMessagePath(String code) { - return "messages/messages_" + code + ".yml"; - } } diff --git a/src/main/java/fr/xephi/authme/message/AbstractMessageFileHandler.java b/src/main/java/fr/xephi/authme/message/AbstractMessageFileHandler.java index c5ff01b4..f88c6f3f 100644 --- a/src/main/java/fr/xephi/authme/message/AbstractMessageFileHandler.java +++ b/src/main/java/fr/xephi/authme/message/AbstractMessageFileHandler.java @@ -21,7 +21,7 @@ import java.io.InputStreamReader; */ public abstract class AbstractMessageFileHandler implements Reloadable { - private static final String DEFAULT_LANGUAGE = "en"; + protected static final String DEFAULT_LANGUAGE = "en"; @DataFolder @Inject @@ -34,20 +34,33 @@ public abstract class AbstractMessageFileHandler implements Reloadable { private FileConfiguration configuration; private final String defaultFile; private FileConfiguration defaultConfiguration; + private final String updateCommandAddition; protected AbstractMessageFileHandler() { this.defaultFile = createFilePath(DEFAULT_LANGUAGE); + String updateCommand = getUpdateCommand(); + this.updateCommandAddition = updateCommand == null + ? "" + : " or run " + updateCommand; } @Override @PostConstruct public void reload() { - String language = settings.getProperty(PluginSettings.MESSAGES_LANGUAGE); + String language = getLanguage(); filename = createFilePath(language); File messagesFile = initializeFile(filename); configuration = YamlConfiguration.loadConfiguration(messagesFile); } + protected String getLanguage() { + return settings.getProperty(PluginSettings.MESSAGES_LANGUAGE); + } + + protected File getUserLanguageFile() { + return new File(dataFolder, filename); + } + /** * Returns whether the message file configuration has an entry at the given path. * @@ -69,7 +82,7 @@ public abstract class AbstractMessageFileHandler implements Reloadable { if (message == null) { ConsoleLogger.warning("Error getting message with key '" + key + "'. " - + "Please update your config file '" + filename + "' or run " + getUpdateCommand()); + + "Please update your config file '" + filename + "'" + updateCommandAddition); return getDefault(key); } return message; diff --git a/src/main/java/fr/xephi/authme/message/MessagesFileHandler.java b/src/main/java/fr/xephi/authme/message/MessagesFileHandler.java index febe26c5..716bf33e 100644 --- a/src/main/java/fr/xephi/authme/message/MessagesFileHandler.java +++ b/src/main/java/fr/xephi/authme/message/MessagesFileHandler.java @@ -1,5 +1,8 @@ package fr.xephi.authme.message; +import fr.xephi.authme.ConsoleLogger; +import fr.xephi.authme.message.updater.MessageUpdater; + import javax.inject.Inject; /** @@ -7,10 +10,35 @@ import javax.inject.Inject; */ public class MessagesFileHandler extends AbstractMessageFileHandler { - @Inject // Trigger injection in the superclass + // TODO #1467: With the migration the messages handler has become so different that it would be worth + // to remove the extension and extract common features into a helper class instead + + @Inject + private MessageUpdater messageUpdater; + MessagesFileHandler() { } + @Override + public void reload() { + reloadInternal(false); + } + + private void reloadInternal(boolean isFromReload) { + super.reload(); + + String language = getLanguage(); + boolean hasChange = messageUpdater.migrateAndSave( + getUserLanguageFile(), createFilePath(language), createFilePath(DEFAULT_LANGUAGE)); + if (hasChange) { + if (isFromReload) { + ConsoleLogger.warning("Migration after reload attempt"); + } else { + reloadInternal(true); + } + } + } + @Override protected String createFilePath(String language) { return "messages/messages_" + language + ".yml"; diff --git a/src/main/java/fr/xephi/authme/message/updater/JarMessageSource.java b/src/main/java/fr/xephi/authme/message/updater/JarMessageSource.java new file mode 100644 index 00000000..13858bfc --- /dev/null +++ b/src/main/java/fr/xephi/authme/message/updater/JarMessageSource.java @@ -0,0 +1,57 @@ +package fr.xephi.authme.message.updater; + +import ch.jalu.configme.properties.Property; +import fr.xephi.authme.ConsoleLogger; +import fr.xephi.authme.util.FileUtils; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import java.io.IOException; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * Returns messages from the JAR's message files. Favors a local JAR (e.g. messages_nl.yml) + * before falling back to the default language (messages_en.yml). + */ +public class JarMessageSource { + + private final FileConfiguration localJarConfiguration; + private final FileConfiguration defaultJarConfiguration; + + /** + * Constructor. + * + * @param localJarPath path to the messages file of the language the plugin is configured to use (may not exist) + * @param defaultJarPath path to the default messages file in the JAR (must exist) + */ + public JarMessageSource(String localJarPath, String defaultJarPath) { + localJarConfiguration = localJarPath.equals(defaultJarPath) ? null : loadJarFile(localJarPath); + defaultJarConfiguration = loadJarFile(defaultJarPath); + + if (defaultJarConfiguration == null) { + throw new IllegalStateException("Default JAR file '" + defaultJarPath + "' could not be loaded"); + } + } + + public String getMessageFromJar(Property property) { + String key = property.getPath(); + String message = localJarConfiguration == null ? null : localJarConfiguration.getString(key); + return message == null ? defaultJarConfiguration.getString(key) : message; + } + + private static YamlConfiguration loadJarFile(String jarPath) { + try (InputStream stream = FileUtils.getResourceFromJar(jarPath)) { + if (stream == null) { + ConsoleLogger.debug("Could not load '" + jarPath + "' from JAR"); + return null; + } + try (InputStreamReader isr = new InputStreamReader(stream)) { + return YamlConfiguration.loadConfiguration(isr); + } + } catch (IOException e) { + ConsoleLogger.logException("Exception while handling JAR path '" + jarPath + "'", e); + } + return null; + } +} diff --git a/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java b/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java new file mode 100644 index 00000000..2fc6fb0f --- /dev/null +++ b/src/main/java/fr/xephi/authme/message/updater/MessageUpdater.java @@ -0,0 +1,90 @@ +package fr.xephi.authme.message.updater; + +import ch.jalu.configme.SettingsManager; +import ch.jalu.configme.properties.Property; +import ch.jalu.configme.properties.StringProperty; +import ch.jalu.configme.resource.YamlFileResource; +import com.google.common.collect.ImmutableList; +import fr.xephi.authme.ConsoleLogger; +import fr.xephi.authme.message.MessageKey; + +import java.io.File; +import java.util.List; + +/** + * Migrates the used messages file to a complete, up-to-date version when necessary. + */ +public class MessageUpdater { + + private static final List> TEXT_PROPERTIES = buildPropertyEntriesForMessageKeys(); + + /** + * Applies any necessary migrations to the user's messages file and saves it if it has been modified. + * + * @param userFile the user's messages file (yml file in the plugin's folder) + * @param localJarPath path to the messages file in the JAR for the same language (may not exist) + * @param defaultJarPath path to the messages file in the JAR for the default language + * @return true if the file has been migrated and saved, false if it is up-to-date + */ + public boolean migrateAndSave(File userFile, String localJarPath, String defaultJarPath) { + JarMessageSource jarMessageSource = new JarMessageSource(localJarPath, defaultJarPath); + return migrateAndSave(userFile, jarMessageSource); + } + + /** + * Performs the migration. + * + * @param userFile the file to verify and migrate + * @param jarMessageSource jar message source to get texts from if missing + * @return true if the file has been migrated and saved, false if it is up-to-date + */ + boolean migrateAndSave(File userFile, JarMessageSource jarMessageSource) { + // YamlConfiguration escapes all special characters when saving, making the file hard to use, so use ConfigMe + YamlFileResource userResource = new YamlFileResource(userFile); + SettingsManager settingsManager = SettingsManager.createWithProperties(userResource, null, TEXT_PROPERTIES); + + // Step 1: Migrate any old keys in the file to the new paths + boolean movedOldKeys = migrateOldKeys(userResource); + // Step 2: Take any missing messages from the message files shipped in the AuthMe JAR + boolean addedMissingKeys = addMissingKeys(jarMessageSource, userResource, settingsManager); + + if (movedOldKeys || addedMissingKeys) { + settingsManager.save(); + ConsoleLogger.debug("Successfully saved {0}", userFile); + return true; + } + return false; + } + + private boolean migrateOldKeys(YamlFileResource userResource) { + boolean hasChange = OldMessageKeysMigrater.migrateOldPaths(userResource); + if (hasChange) { + ConsoleLogger.info("Old keys have been moved to the new ones in your messages_xx.yml file"); + } + return hasChange; + } + + private boolean addMissingKeys(JarMessageSource jarMessageSource, YamlFileResource userResource, + SettingsManager settingsManager) { + int addedKeys = 0; + for (Property property : TEXT_PROPERTIES) { + if (!property.isPresent(userResource)) { + settingsManager.setProperty(property, jarMessageSource.getMessageFromJar(property)); + ++addedKeys; + } + } + if (addedKeys > 0) { + ConsoleLogger.info("Added " + addedKeys + " missing keys to your messages_xx.yml file"); + return true; + } + return false; + } + + private static List> buildPropertyEntriesForMessageKeys() { + ImmutableList.Builder> listBuilder = ImmutableList.builder(); + for (MessageKey messageKey : MessageKey.values()) { + listBuilder.add(new StringProperty(messageKey.getKey(), "")); + } + return listBuilder.build(); + } +} diff --git a/src/main/java/fr/xephi/authme/message/updater/OldMessageKeysMigrater.java b/src/main/java/fr/xephi/authme/message/updater/OldMessageKeysMigrater.java new file mode 100644 index 00000000..002b299d --- /dev/null +++ b/src/main/java/fr/xephi/authme/message/updater/OldMessageKeysMigrater.java @@ -0,0 +1,140 @@ +package fr.xephi.authme.message.updater; + +import ch.jalu.configme.resource.PropertyResource; +import com.google.common.collect.ImmutableMap; +import fr.xephi.authme.message.MessageKey; + +import java.util.Map; + +/** + * Migrates message files from the old keys (before 5.5) to the new ones. + * + * @see Issue #1467 + */ +final class OldMessageKeysMigrater { + + private static final Map KEYS_TO_OLD_PATH = ImmutableMap.builder() + .put(MessageKey.DENIED_COMMAND, "denied_command") + .put(MessageKey.SAME_IP_ONLINE, "same_ip_online") + .put(MessageKey.DENIED_CHAT, "denied_chat") + .put(MessageKey.KICK_ANTIBOT, "kick_antibot") + .put(MessageKey.UNKNOWN_USER, "unknown_user") + .put(MessageKey.NOT_LOGGED_IN, "not_logged_in") + .put(MessageKey.USAGE_LOGIN, "usage_log") + .put(MessageKey.WRONG_PASSWORD, "wrong_pwd") + .put(MessageKey.UNREGISTERED_SUCCESS, "unregistered") + .put(MessageKey.REGISTRATION_DISABLED, "reg_disabled") + .put(MessageKey.SESSION_RECONNECTION, "valid_session") + .put(MessageKey.LOGIN_SUCCESS, "login") + .put(MessageKey.ACCOUNT_NOT_ACTIVATED, "vb_nonActiv") + .put(MessageKey.NAME_ALREADY_REGISTERED, "user_regged") + .put(MessageKey.NO_PERMISSION, "no_perm") + .put(MessageKey.ERROR, "error") + .put(MessageKey.LOGIN_MESSAGE, "login_msg") + .put(MessageKey.REGISTER_MESSAGE, "reg_msg") + .put(MessageKey.MAX_REGISTER_EXCEEDED, "max_reg") + .put(MessageKey.USAGE_REGISTER, "usage_reg") + .put(MessageKey.USAGE_UNREGISTER, "usage_unreg") + .put(MessageKey.PASSWORD_CHANGED_SUCCESS, "pwd_changed") + .put(MessageKey.PASSWORD_MATCH_ERROR, "password_error") + .put(MessageKey.PASSWORD_IS_USERNAME_ERROR, "password_error_nick") + .put(MessageKey.PASSWORD_UNSAFE_ERROR, "password_error_unsafe") + .put(MessageKey.PASSWORD_CHARACTERS_ERROR, "password_error_chars") + .put(MessageKey.SESSION_EXPIRED, "invalid_session") + .put(MessageKey.MUST_REGISTER_MESSAGE, "reg_only") + .put(MessageKey.ALREADY_LOGGED_IN_ERROR, "logged_in") + .put(MessageKey.LOGOUT_SUCCESS, "logout") + .put(MessageKey.USERNAME_ALREADY_ONLINE_ERROR, "same_nick") + .put(MessageKey.REGISTER_SUCCESS, "registered") + .put(MessageKey.INVALID_PASSWORD_LENGTH, "pass_len") + .put(MessageKey.CONFIG_RELOAD_SUCCESS, "reload") + .put(MessageKey.LOGIN_TIMEOUT_ERROR, "timeout") + .put(MessageKey.USAGE_CHANGE_PASSWORD, "usage_changepassword") + .put(MessageKey.INVALID_NAME_LENGTH, "name_len") + .put(MessageKey.INVALID_NAME_CHARACTERS, "regex") + .put(MessageKey.ADD_EMAIL_MESSAGE, "add_email") + .put(MessageKey.FORGOT_PASSWORD_MESSAGE, "recovery_email") + .put(MessageKey.USAGE_CAPTCHA, "usage_captcha") + .put(MessageKey.CAPTCHA_WRONG_ERROR, "wrong_captcha") + .put(MessageKey.CAPTCHA_SUCCESS, "valid_captcha") + .put(MessageKey.CAPTCHA_FOR_REGISTRATION_REQUIRED, "captcha_for_registration") + .put(MessageKey.REGISTER_CAPTCHA_SUCCESS, "register_captcha_valid") + .put(MessageKey.KICK_FOR_VIP, "kick_forvip") + .put(MessageKey.KICK_FULL_SERVER, "kick_fullserver") + .put(MessageKey.USAGE_ADD_EMAIL, "usage_email_add") + .put(MessageKey.USAGE_CHANGE_EMAIL, "usage_email_change") + .put(MessageKey.USAGE_RECOVER_EMAIL, "usage_email_recovery") + .put(MessageKey.INVALID_NEW_EMAIL, "new_email_invalid") + .put(MessageKey.INVALID_OLD_EMAIL, "old_email_invalid") + .put(MessageKey.INVALID_EMAIL, "email_invalid") + .put(MessageKey.EMAIL_ADDED_SUCCESS, "email_added") + .put(MessageKey.CONFIRM_EMAIL_MESSAGE, "email_confirm") + .put(MessageKey.EMAIL_CHANGED_SUCCESS, "email_changed") + .put(MessageKey.EMAIL_SHOW, "email_show") + .put(MessageKey.SHOW_NO_EMAIL, "show_no_email") + .put(MessageKey.RECOVERY_EMAIL_SENT_MESSAGE, "email_send") + .put(MessageKey.COUNTRY_BANNED_ERROR, "country_banned") + .put(MessageKey.ANTIBOT_AUTO_ENABLED_MESSAGE, "antibot_auto_enabled") + .put(MessageKey.ANTIBOT_AUTO_DISABLED_MESSAGE, "antibot_auto_disabled") + .put(MessageKey.EMAIL_ALREADY_USED_ERROR, "email_already_used") + .put(MessageKey.TWO_FACTOR_CREATE, "two_factor_create") + .put(MessageKey.NOT_OWNER_ERROR, "not_owner_error") + .put(MessageKey.INVALID_NAME_CASE, "invalid_name_case") + .put(MessageKey.TEMPBAN_MAX_LOGINS, "tempban_max_logins") + .put(MessageKey.ACCOUNTS_OWNED_SELF, "accounts_owned_self") + .put(MessageKey.ACCOUNTS_OWNED_OTHER, "accounts_owned_other") + .put(MessageKey.KICK_FOR_ADMIN_REGISTER, "kicked_admin_registered") + .put(MessageKey.INCOMPLETE_EMAIL_SETTINGS, "incomplete_email_settings") + .put(MessageKey.EMAIL_SEND_FAILURE, "email_send_failure") + .put(MessageKey.RECOVERY_CODE_SENT, "recovery_code_sent") + .put(MessageKey.INCORRECT_RECOVERY_CODE, "recovery_code_incorrect") + .put(MessageKey.RECOVERY_TRIES_EXCEEDED, "recovery_tries_exceeded") + .put(MessageKey.RECOVERY_CODE_CORRECT, "recovery_code_correct") + .put(MessageKey.RECOVERY_CHANGE_PASSWORD, "recovery_change_password") + .put(MessageKey.CHANGE_PASSWORD_EXPIRED, "change_password_expired") + .put(MessageKey.EMAIL_COOLDOWN_ERROR, "email_cooldown_error") + .put(MessageKey.VERIFICATION_CODE_REQUIRED, "verification_code_required") + .put(MessageKey.USAGE_VERIFICATION_CODE, "usage_verification_code") + .put(MessageKey.INCORRECT_VERIFICATION_CODE, "incorrect_verification_code") + .put(MessageKey.VERIFICATION_CODE_VERIFIED, "verification_code_verified") + .put(MessageKey.VERIFICATION_CODE_ALREADY_VERIFIED, "verification_code_already_verified") + .put(MessageKey.VERIFICATION_CODE_EXPIRED, "verification_code_expired") + .put(MessageKey.VERIFICATION_CODE_EMAIL_NEEDED, "verification_code_email_needed") + .put(MessageKey.SECOND, "second") + .put(MessageKey.SECONDS, "seconds") + .put(MessageKey.MINUTE, "minute") + .put(MessageKey.MINUTES, "minutes") + .put(MessageKey.HOUR, "hour") + .put(MessageKey.HOURS, "hours") + .put(MessageKey.DAY, "day") + .put(MessageKey.DAYS, "days") + .build(); + + private OldMessageKeysMigrater() { + } + + /** + * Migrates any existing old key paths to their new paths if no text has been defined for the new key. + * + * @param resource the resource to modify and read from + * @return true if at least one message could be migrated, false otherwise + */ + static boolean migrateOldPaths(PropertyResource resource) { + boolean wasPropertyMoved = false; + for (Map.Entry migrationEntry : KEYS_TO_OLD_PATH.entrySet()) { + wasPropertyMoved |= moveIfApplicable(resource, migrationEntry.getKey().getKey(), migrationEntry.getValue()); + } + return wasPropertyMoved; + } + + private static boolean moveIfApplicable(PropertyResource resource, String newPath, String oldPath) { + if (resource.getString(newPath) == null) { + String textAtOldPath = resource.getString(oldPath); + if (textAtOldPath != null) { + resource.setValue(newPath, textAtOldPath); + return true; + } + } + return false; + } +} diff --git a/src/main/java/fr/xephi/authme/service/MessageUpdater.java b/src/main/java/fr/xephi/authme/service/MessageUpdater.java deleted file mode 100644 index 67cfe617..00000000 --- a/src/main/java/fr/xephi/authme/service/MessageUpdater.java +++ /dev/null @@ -1,138 +0,0 @@ -package fr.xephi.authme.service; - -import ch.jalu.configme.SettingsManager; -import ch.jalu.configme.configurationdata.ConfigurationData; -import ch.jalu.configme.properties.Property; -import ch.jalu.configme.properties.StringProperty; -import ch.jalu.configme.resource.YamlFileResource; -import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.message.MessageKey; -import fr.xephi.authme.util.FileUtils; -import fr.xephi.authme.util.StringUtils; -import org.bukkit.command.CommandSender; -import org.bukkit.configuration.file.FileConfiguration; -import org.bukkit.configuration.file.YamlConfiguration; - -import java.io.Closeable; -import java.io.File; -import java.io.IOException; -import java.io.InputStream; -import java.io.InputStreamReader; -import java.util.Arrays; -import java.util.List; -import java.util.stream.Collectors; - -/** - * Updates a user's messages file with messages from the JAR files. - */ -public class MessageUpdater { - - private final FileConfiguration userConfiguration; - private final FileConfiguration localJarConfiguration; - private final FileConfiguration defaultJarConfiguration; - - private final List> properties; - private final SettingsManager settingsManager; - private boolean hasMissingMessages = false; - - /** - * Constructor. - * - * @param userFile messages file in the data folder - * @param localJarFile path to messages file in JAR in local language - * @param defaultJarFile path to messages file in JAR for default language - * @throws Exception if userFile does not exist or no JAR messages file can be loaded - */ - public MessageUpdater(File userFile, String localJarFile, String defaultJarFile) throws Exception { - if (!userFile.exists()) { - throw new Exception("Local messages file does not exist"); - } - - userConfiguration = YamlConfiguration.loadConfiguration(userFile); - localJarConfiguration = loadJarFileOrSendError(localJarFile); - defaultJarConfiguration = localJarFile.equals(defaultJarFile) ? null : loadJarFileOrSendError(defaultJarFile); - if (localJarConfiguration == null && defaultJarConfiguration == null) { - throw new Exception("Could not load any JAR messages file to copy from"); - } - - properties = buildPropertyEntriesForMessageKeys(); - settingsManager = new SettingsManager( - new YamlFileResource(userFile), null, new ConfigurationData(properties)); - } - - /** - * Copies missing messages to the messages file. - * - * @param sender sender starting the copy process - * @return true if the messages file was updated, false otherwise - * @throws Exception if an error occurs during saving - */ - public boolean executeCopy(CommandSender sender) throws Exception { - copyMissingMessages(); - - if (!hasMissingMessages) { - sender.sendMessage("No new messages to add"); - return false; - } - - // Save user configuration file - try { - settingsManager.save(); - sender.sendMessage("Message file updated with new messages"); - return true; - } catch (Exception e) { - throw new Exception("Could not save to messages file: " + StringUtils.formatException(e)); - } - } - - private void copyMissingMessages() { - for (Property property : properties) { - String message = userConfiguration.getString(property.getPath()); - if (message == null) { - hasMissingMessages = true; - message = getMessageFromJar(property.getPath()); - } - settingsManager.setProperty(property, message); - } - } - - private String getMessageFromJar(String key) { - String message = (localJarConfiguration == null ? null : localJarConfiguration.getString(key)); - if (message != null) { - return message; - } - return (defaultJarConfiguration == null) ? null : defaultJarConfiguration.getString(key); - } - - private static FileConfiguration loadJarFileOrSendError(String jarPath) { - try (InputStream stream = FileUtils.getResourceFromJar(jarPath)) { - if (stream == null) { - ConsoleLogger.info("Could not load '" + jarPath + "' from JAR"); - return null; - } - InputStreamReader isr = new InputStreamReader(stream); - FileConfiguration configuration = YamlConfiguration.loadConfiguration(isr); - close(isr); - return configuration; - } catch (IOException e) { - ConsoleLogger.logException("Exception while handling JAR path '" + jarPath + "'", e); - } - return null; - } - - private static List> buildPropertyEntriesForMessageKeys() { - return Arrays.stream(MessageKey.values()) - .map(key -> new StringProperty(key.getKey(), "")) - .collect(Collectors.toList()); - } - - private static void close(Closeable closeable) { - if (closeable != null) { - try { - closeable.close(); - } catch (IOException e) { - ConsoleLogger.info("Cannot close '" + closeable + "': " + StringUtils.formatException(e)); - } - } - } -} diff --git a/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java b/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java index 5f9c80ca..1c67f4d0 100644 --- a/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java @@ -5,6 +5,7 @@ import com.google.common.io.Files; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.ReflectionTestUtils; import fr.xephi.authme.TestHelper; +import fr.xephi.authme.message.updater.MessageUpdater; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.PluginSettings; import fr.xephi.authme.util.FileUtils; @@ -275,6 +276,7 @@ public class MessagesIntegrationTest { MessagesFileHandler messagesFileHandler = new MessagesFileHandler(); ReflectionTestUtils.setField(AbstractMessageFileHandler.class, messagesFileHandler, "settings", settings); ReflectionTestUtils.setField(AbstractMessageFileHandler.class, messagesFileHandler, "dataFolder", dataFolder); + ReflectionTestUtils.setField(MessagesFileHandler.class, messagesFileHandler, "messageUpdater", mock(MessageUpdater.class)); ReflectionTestUtils.invokePostConstructMethods(messagesFileHandler); return messagesFileHandler; } diff --git a/src/test/java/fr/xephi/authme/message/updater/MessageUpdaterTest.java b/src/test/java/fr/xephi/authme/message/updater/MessageUpdaterTest.java new file mode 100644 index 00000000..a43a5f29 --- /dev/null +++ b/src/test/java/fr/xephi/authme/message/updater/MessageUpdaterTest.java @@ -0,0 +1,71 @@ +package fr.xephi.authme.message.updater; + +import com.google.common.io.Files; +import fr.xephi.authme.TestHelper; +import fr.xephi.authme.message.MessageKey; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.junit.BeforeClass; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; + +import java.io.File; +import java.io.IOException; + +import static org.hamcrest.Matchers.equalTo; +import static org.junit.Assert.assertThat; + +/** + * Test for {@link MessageUpdater}. + */ +public class MessageUpdaterTest { + + private MessageUpdater messageUpdater = new MessageUpdater(); + + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + + @BeforeClass + public static void setUpLogger() { + TestHelper.setupLogger(); + } + + @Test + public void shouldNotUpdateDefaultFile() throws IOException { + // given + String messagesFilePath = "messages/messages_en.yml"; + File messagesFile = temporaryFolder.newFile(); + Files.copy(TestHelper.getJarFile("/" + messagesFilePath), messagesFile); + long modifiedDate = messagesFile.lastModified(); + + // when + boolean wasChanged = messageUpdater.migrateAndSave(messagesFile, messagesFilePath, messagesFilePath); + + // then + assertThat(wasChanged, equalTo(false)); + assertThat(messagesFile.lastModified(), equalTo(modifiedDate)); + } + + @Test + public void shouldAddMissingKeys() throws IOException { + // given + File messagesFile = temporaryFolder.newFile(); + Files.copy(TestHelper.getJarFile(TestHelper.PROJECT_ROOT + "message/messages_test.yml"), messagesFile); + + // when + boolean wasChanged = messageUpdater.migrateAndSave(messagesFile, "does-not-exist", "messages/messages_en.yml"); + + // then + assertThat(wasChanged, equalTo(true)); + FileConfiguration configuration = YamlConfiguration.loadConfiguration(messagesFile); + // Existing keys should not be overridden + assertThat(configuration.getString(MessageKey.LOGIN_SUCCESS.getKey()), equalTo("&cHere we have&bdefined some colors &dand some other <hings")); + assertThat(configuration.getString(MessageKey.EMAIL_ALREADY_USED_ERROR.getKey()), equalTo("")); + // Check that new keys were added + assertThat(configuration.getString(MessageKey.SECOND.getKey()), equalTo("second")); + assertThat(configuration.getString(MessageKey.ERROR.getKey()), equalTo("&4An unexpected error occurred, please contact an administrator!")); + } + + // TODO #1467: Check migration of old keys +}