diff --git a/src/main/java/fr/xephi/authme/message/MessageFileHandler.java b/src/main/java/fr/xephi/authme/message/MessageFileHandler.java index a0d4e947..5d19e8f4 100644 --- a/src/main/java/fr/xephi/authme/message/MessageFileHandler.java +++ b/src/main/java/fr/xephi/authme/message/MessageFileHandler.java @@ -1,6 +1,7 @@ package fr.xephi.authme.message; import fr.xephi.authme.ConsoleLogger; +import fr.xephi.authme.util.FileUtils; import org.bukkit.configuration.file.FileConfiguration; import org.bukkit.configuration.file.YamlConfiguration; @@ -16,6 +17,7 @@ public class MessageFileHandler { // regular file private final String filename; private final FileConfiguration configuration; + private final String updateAddition; // default file private final String defaultFile; private FileConfiguration defaultConfiguration; @@ -25,11 +27,15 @@ public class MessageFileHandler { * * @param file the file to use for messages * @param defaultFile the default file from the JAR to use if no message is found + * @param updateCommand command to update the messages file (nullable) to show in error messages */ - public MessageFileHandler(File file, String defaultFile) { + public MessageFileHandler(File file, String defaultFile, String updateCommand) { this.filename = file.getName(); this.configuration = YamlConfiguration.loadConfiguration(file); this.defaultFile = defaultFile; + this.updateAddition = updateCommand == null + ? "" + : " (or run " + updateCommand + ")"; } /** @@ -53,7 +59,7 @@ public class MessageFileHandler { if (message == null) { ConsoleLogger.warning("Error getting message with key '" + key + "'. " - + "Please update your config file '" + filename + "' (or run /authme messages)"); + + "Please update your config file '" + filename + "'" + updateAddition); return getDefault(key); } return message; @@ -78,7 +84,7 @@ public class MessageFileHandler { */ private String getDefault(String key) { if (defaultConfiguration == null) { - InputStream stream = MessageFileHandler.class.getClassLoader().getResourceAsStream(defaultFile); + InputStream stream = FileUtils.getResourceFromJar(defaultFile); defaultConfiguration = YamlConfiguration.loadConfiguration(new InputStreamReader(stream)); } String message = defaultConfiguration.getString(key); diff --git a/src/main/java/fr/xephi/authme/message/MessageFileHandlerProvider.java b/src/main/java/fr/xephi/authme/message/MessageFileHandlerProvider.java index 987caecc..5b809b2c 100644 --- a/src/main/java/fr/xephi/authme/message/MessageFileHandlerProvider.java +++ b/src/main/java/fr/xephi/authme/message/MessageFileHandlerProvider.java @@ -36,10 +36,23 @@ public class MessageFileHandlerProvider { * @return the message file handler */ public MessageFileHandler initializeHandler(Function pathBuilder) { + return initializeHandler(pathBuilder, null); + } + + /** + * Initializes a message file handler with the messages file of the configured language. + * Ensures beforehand that the messages file exists or creates it otherwise. + * + * @param pathBuilder function taking the configured language code as argument and returning the messages file + * @param updateCommand command to run to update the languages file (nullable) + * @return the message file handler + */ + public MessageFileHandler initializeHandler(Function pathBuilder, String updateCommand) { String language = settings.getProperty(PluginSettings.MESSAGES_LANGUAGE); return new MessageFileHandler( initializeFile(language, pathBuilder), - pathBuilder.apply(DEFAULT_LANGUAGE)); + pathBuilder.apply(DEFAULT_LANGUAGE), + updateCommand); } /** @@ -53,7 +66,8 @@ public class MessageFileHandlerProvider { File initializeFile(String language, Function pathBuilder) { String filePath = pathBuilder.apply(language); File file = new File(dataFolder, filePath); - if (FileUtils.copyFileFromResource(file, filePath)) { + // Check that JAR file exists to avoid logging an error + if (FileUtils.getResourceFromJar(filePath) != null && FileUtils.copyFileFromResource(file, filePath)) { return file; } diff --git a/src/main/java/fr/xephi/authme/message/Messages.java b/src/main/java/fr/xephi/authme/message/Messages.java index 86fa2db6..5d777ab8 100644 --- a/src/main/java/fr/xephi/authme/message/Messages.java +++ b/src/main/java/fr/xephi/authme/message/Messages.java @@ -107,7 +107,7 @@ public class Messages implements Reloadable { @Override public void reload() { this.messageFileHandler = messageFileHandlerProvider - .initializeHandler(lang -> "messages/messages_" + lang + ".yml"); + .initializeHandler(lang -> "messages/messages_" + lang + ".yml", "/authme messages"); } private static String formatMessage(String message) { diff --git a/src/main/resources/messages/help_br.yml b/src/main/resources/messages/help_br.yml index 1a143c8e..be4983ab 100644 --- a/src/main/resources/messages/help_br.yml +++ b/src/main/resources/messages/help_br.yml @@ -4,6 +4,7 @@ # ------------------------------------------------------- # Lista de textos usados na seção de ajuda: common: + header: '==========[ Ajuda AuthMeReloaded ]==========' optional: 'Opcional' hasPermission: 'Você tem permissão' noPermission: 'Sem Permissão' diff --git a/src/test/java/fr/xephi/authme/command/help/HelpMessagesServiceTest.java b/src/test/java/fr/xephi/authme/command/help/HelpMessagesServiceTest.java index 292b0ec9..ea0f372a 100644 --- a/src/test/java/fr/xephi/authme/command/help/HelpMessagesServiceTest.java +++ b/src/test/java/fr/xephi/authme/command/help/HelpMessagesServiceTest.java @@ -39,10 +39,10 @@ public class HelpMessagesServiceTest { @Mock private MessageFileHandlerProvider messageFileHandlerProvider; - @SuppressWarnings("unchecked") @BeforeInjecting + @SuppressWarnings("unchecked") public void initializeHandler() { - MessageFileHandler handler = new MessageFileHandler(getJarFile(TEST_FILE), "messages/messages_en.yml"); + MessageFileHandler handler = new MessageFileHandler(getJarFile(TEST_FILE), "messages/messages_en.yml", null); given(messageFileHandlerProvider.initializeHandler(any(Function.class))).willReturn(handler); } diff --git a/src/test/java/fr/xephi/authme/message/HelpMessageConsistencyTest.java b/src/test/java/fr/xephi/authme/message/HelpMessageConsistencyTest.java new file mode 100644 index 00000000..399fd93a --- /dev/null +++ b/src/test/java/fr/xephi/authme/message/HelpMessageConsistencyTest.java @@ -0,0 +1,93 @@ +package fr.xephi.authme.message; + +import fr.xephi.authme.TestHelper; +import fr.xephi.authme.command.help.HelpMessage; +import fr.xephi.authme.command.help.HelpSection; +import fr.xephi.authme.permission.DefaultPermission; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; +import org.hamcrest.Matcher; +import org.junit.Before; +import org.junit.Test; + +import java.io.File; +import java.util.Arrays; +import java.util.List; +import java.util.regex.Pattern; +import java.util.stream.Collectors; + +import static org.hamcrest.Matchers.both; +import static org.hamcrest.Matchers.emptyString; +import static org.hamcrest.Matchers.not; +import static org.hamcrest.Matchers.nullValue; +import static org.junit.Assert.assertThat; + +/** + * Tests that all help_xx.yml files contain all entries for + * {@link HelpSection}, {@link HelpMessage} and {@link DefaultPermission}. + */ +public class HelpMessageConsistencyTest { + + private static final String MESSAGES_FOLDER = "/messages"; + private static final Pattern HELP_MESSAGES_FILE = Pattern.compile("help_[a-z]+\\.yml"); + + private List helpFiles; + + @Before + public void findHelpMessagesFiles() { + File folder = TestHelper.getJarFile(MESSAGES_FOLDER); + File[] files = folder.listFiles(); + if (files == null || files.length == 0) { + throw new IllegalStateException("Could not get files from '" + MESSAGES_FOLDER + "'"); + } + helpFiles = Arrays.stream(files) + .filter(file -> HELP_MESSAGES_FILE.matcher(file.getName()).matches()) + .collect(Collectors.toList()); + } + + @Test + public void shouldHaveRequiredEntries() { + for (File file : helpFiles) { + // given + FileConfiguration configuration = YamlConfiguration.loadConfiguration(file); + + // when / then + assertHasAllHelpSectionEntries(file.getName(), configuration); + } + } + + private void assertHasAllHelpSectionEntries(String filename, FileConfiguration configuration) { + for (HelpSection section : HelpSection.values()) { + assertThat(filename + " should have entry for HelpSection '" + section + "'", + configuration.getString(section.getKey()), notEmptyString()); + } + + for (HelpMessage message : HelpMessage.values()) { + assertThat(filename + " should have entry for HelpMessage '" + message + "'", + configuration.getString(message.getKey()), notEmptyString()); + } + + for (DefaultPermission defaultPermission : DefaultPermission.values()) { + assertThat(filename + " should have entry for DefaultPermission '" + defaultPermission + "'", + configuration.getString(getPathForDefaultPermission(defaultPermission)), notEmptyString()); + } + } + + private static String getPathForDefaultPermission(DefaultPermission defaultPermission) { + String path = "common.defaultPermissions."; + switch (defaultPermission) { + case ALLOWED: + return path + "allowed"; + case NOT_ALLOWED: + return path + "notAllowed"; + case OP_ONLY: + return path + "opOnly"; + default: + throw new IllegalStateException("Unknown default permission '" + defaultPermission + "'"); + } + } + + private static Matcher notEmptyString() { + return both(not(emptyString())).and(not(nullValue())); + } +} diff --git a/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java b/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java index 12949c5a..94fe9a0d 100644 --- a/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java @@ -233,8 +233,8 @@ public class MessagesIntegrationTest { @SuppressWarnings("unchecked") private static MessageFileHandlerProvider providerReturning(File file, String defaultFile) { MessageFileHandlerProvider handler = mock(MessageFileHandlerProvider.class); - given(handler.initializeHandler(any(Function.class))) - .willReturn(new MessageFileHandler(file, defaultFile)); + given(handler.initializeHandler(any(Function.class), anyString())) + .willReturn(new MessageFileHandler(file, defaultFile, "/authme messages")); return handler; } }