mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-10-02 16:38:24 +02:00
#1467 Implement messages file migration
- Create messages updater called when a messages YML file is loaded - Work in progress - Does not yet include changes to any message keys
This commit is contained in:
parent
b3a191d7e2
commit
820e443b81
@ -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<String> 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";
|
||||
}
|
||||
}
|
||||
|
@ -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;
|
||||
|
@ -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";
|
||||
|
@ -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<String> 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;
|
||||
}
|
||||
}
|
@ -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<Property<String>> 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<String> 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<Property<String>> buildPropertyEntriesForMessageKeys() {
|
||||
ImmutableList.Builder<Property<String>> listBuilder = ImmutableList.builder();
|
||||
for (MessageKey messageKey : MessageKey.values()) {
|
||||
listBuilder.add(new StringProperty(messageKey.getKey(), ""));
|
||||
}
|
||||
return listBuilder.build();
|
||||
}
|
||||
}
|
@ -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 <a href="https://github.com/AuthMe/AuthMeReloaded/issues/1467">Issue #1467</a>
|
||||
*/
|
||||
final class OldMessageKeysMigrater {
|
||||
|
||||
private static final Map<MessageKey, String> KEYS_TO_OLD_PATH = ImmutableMap.<MessageKey, String>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<MessageKey, String> 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;
|
||||
}
|
||||
}
|
@ -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<Property<String>> 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<String> 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<Property<String>> 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));
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
@ -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;
|
||||
}
|
||||
|
@ -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
|
||||
}
|
Loading…
Reference in New Issue
Block a user