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 bf778d9e..873281e1 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 @@ -49,7 +49,7 @@ public class MessagesCommand implements ExecutableCommand { try { helpTranslationGenerator.updateHelpFile(); sender.sendMessage("Successfully updated the help file"); - helpMessagesService.reload(); + helpMessagesService.reloadMessagesFile(); } catch (IOException e) { sender.sendMessage("Could not update help file: " + e.getMessage()); ConsoleLogger.logException("Could not update help file:", e); @@ -65,7 +65,7 @@ public class MessagesCommand implements ExecutableCommand { getMessagePath(DEFAULT_LANGUAGE)) .executeCopy(sender); if (isFileUpdated) { - messages.reload(); + messages.reloadMessagesFile(); } } catch (Exception e) { sender.sendMessage("Could not update messages: " + e.getMessage()); diff --git a/src/main/java/fr/xephi/authme/command/help/HelpMessagesService.java b/src/main/java/fr/xephi/authme/command/help/HelpMessagesService.java index 2a94b675..994d967b 100644 --- a/src/main/java/fr/xephi/authme/command/help/HelpMessagesService.java +++ b/src/main/java/fr/xephi/authme/command/help/HelpMessagesService.java @@ -4,9 +4,7 @@ import com.google.common.base.CaseFormat; import fr.xephi.authme.command.CommandArgumentDescription; import fr.xephi.authme.command.CommandDescription; import fr.xephi.authme.command.CommandUtils; -import fr.xephi.authme.initialization.Reloadable; -import fr.xephi.authme.message.MessageFileHandlerProvider; -import fr.xephi.authme.message.MessageFileHandler; +import fr.xephi.authme.message.HelpMessagesFileHandler; import fr.xephi.authme.permission.DefaultPermission; import javax.inject.Inject; @@ -16,20 +14,18 @@ import java.util.stream.Collectors; /** * Manages translatable help messages. */ -public class HelpMessagesService implements Reloadable { +public class HelpMessagesService { private static final String COMMAND_PREFIX = "commands."; private static final String DESCRIPTION_SUFFIX = ".description"; private static final String DETAILED_DESCRIPTION_SUFFIX = ".detailedDescription"; private static final String DEFAULT_PERMISSIONS_PATH = "common.defaultPermissions."; - private final MessageFileHandlerProvider messageFileHandlerProvider; - private MessageFileHandler messageFileHandler; + private final HelpMessagesFileHandler helpMessagesFileHandler; @Inject - HelpMessagesService(MessageFileHandlerProvider messageFileHandlerProvider) { - this.messageFileHandlerProvider = messageFileHandlerProvider; - reload(); + HelpMessagesService(HelpMessagesFileHandler helpMessagesFileHandler) { + this.helpMessagesFileHandler = helpMessagesFileHandler; } /** @@ -40,7 +36,7 @@ public class HelpMessagesService implements Reloadable { */ public CommandDescription buildLocalizedDescription(CommandDescription command) { final String path = COMMAND_PREFIX + getCommandSubPath(command); - if (!messageFileHandler.hasSection(path)) { + if (!helpMessagesFileHandler.hasSection(path)) { // Messages file does not have a section for this command - return the provided command return command; } @@ -72,36 +68,39 @@ public class HelpMessagesService implements Reloadable { } public String getMessage(HelpMessage message) { - return messageFileHandler.getMessage(message.getKey()); + return helpMessagesFileHandler.getMessage(message.getKey()); } public String getMessage(HelpSection section) { - return messageFileHandler.getMessage(section.getKey()); + return helpMessagesFileHandler.getMessage(section.getKey()); } public String getMessage(DefaultPermission defaultPermission) { // e.g. {default_permissions_path}.opOnly for DefaultPermission.OP_ONLY String path = DEFAULT_PERMISSIONS_PATH + getDefaultPermissionsSubPath(defaultPermission); - return messageFileHandler.getMessage(path); + return helpMessagesFileHandler.getMessage(path); } public static String getDefaultPermissionsSubPath(DefaultPermission defaultPermission) { return CaseFormat.UPPER_UNDERSCORE.to(CaseFormat.LOWER_CAMEL, defaultPermission.name()); } - @Override - public void reload() { - messageFileHandler = messageFileHandlerProvider.initializeHandler( - lang -> "messages/help_" + lang + ".yml"); - } - private String getText(String path, Supplier defaultTextGetter) { - String message = messageFileHandler.getMessageIfExists(path); + String message = helpMessagesFileHandler.getMessageIfExists(path); return message == null ? defaultTextGetter.get() : message; } + + /** + * Triggers a reload of the help messages file. Note that this method is not needed + * to be called for /authme reload. + */ + public void reloadMessagesFile() { + helpMessagesFileHandler.reload(); + } + /** * Returns the command subpath for the given command (i.e. the path to the translations for the given * command under "commands"). diff --git a/src/main/java/fr/xephi/authme/message/AbstractMessageFileHandler.java b/src/main/java/fr/xephi/authme/message/AbstractMessageFileHandler.java new file mode 100644 index 00000000..c5ff01b4 --- /dev/null +++ b/src/main/java/fr/xephi/authme/message/AbstractMessageFileHandler.java @@ -0,0 +1,141 @@ +package fr.xephi.authme.message; + +import com.google.common.annotations.VisibleForTesting; +import fr.xephi.authme.ConsoleLogger; +import fr.xephi.authme.initialization.DataFolder; +import fr.xephi.authme.initialization.Reloadable; +import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.properties.PluginSettings; +import fr.xephi.authme.util.FileUtils; +import org.bukkit.configuration.file.FileConfiguration; +import org.bukkit.configuration.file.YamlConfiguration; + +import javax.annotation.PostConstruct; +import javax.inject.Inject; +import java.io.File; +import java.io.InputStream; +import java.io.InputStreamReader; + +/** + * Handles a YAML message file with a default file fallback. + */ +public abstract class AbstractMessageFileHandler implements Reloadable { + + private static final String DEFAULT_LANGUAGE = "en"; + + @DataFolder + @Inject + private File dataFolder; + + @Inject + private Settings settings; + + private String filename; + private FileConfiguration configuration; + private final String defaultFile; + private FileConfiguration defaultConfiguration; + + protected AbstractMessageFileHandler() { + this.defaultFile = createFilePath(DEFAULT_LANGUAGE); + } + + @Override + @PostConstruct + public void reload() { + String language = settings.getProperty(PluginSettings.MESSAGES_LANGUAGE); + filename = createFilePath(language); + File messagesFile = initializeFile(filename); + configuration = YamlConfiguration.loadConfiguration(messagesFile); + } + + /** + * Returns whether the message file configuration has an entry at the given path. + * + * @param path the path to verify + * @return true if an entry exists for the path in the messages file, false otherwise + */ + public boolean hasSection(String path) { + return configuration.get(path) != null; + } + + /** + * Returns the message for the given key. + * + * @param key the key to retrieve the message for + * @return the message + */ + public String getMessage(String key) { + String message = configuration.getString(key); + + if (message == null) { + ConsoleLogger.warning("Error getting message with key '" + key + "'. " + + "Please update your config file '" + filename + "' or run " + getUpdateCommand()); + return getDefault(key); + } + return message; + } + + /** + * Returns the message for the given key only if it exists, + * i.e. without falling back to the default file. + * + * @param key the key to retrieve the message for + * @return the message, or {@code null} if not available + */ + public String getMessageIfExists(String key) { + return configuration.getString(key); + } + + /** + * Gets the message from the default file. + * + * @param key the key to retrieve the message for + * @return the message from the default file + */ + private String getDefault(String key) { + if (defaultConfiguration == null) { + InputStream stream = FileUtils.getResourceFromJar(defaultFile); + defaultConfiguration = YamlConfiguration.loadConfiguration(new InputStreamReader(stream)); + } + String message = defaultConfiguration.getString(key); + return message == null + ? "Error retrieving message '" + key + "'" + : message; + } + + /** + * Creates the path to the messages file for the given language code. + * + * @param language the language code + * @return path to the message file for the given language + */ + protected abstract String createFilePath(String language); + + /** + * @return command with which the messages file can be updated; output when a message is missing from the file + */ + protected abstract String getUpdateCommand(); + + /** + * Copies the messages file from the JAR to the local messages/ folder if it doesn't exist. + * + * @param filePath path to the messages file to use + * @return the messages file to use + */ + @VisibleForTesting + File initializeFile(String filePath) { + File file = new File(dataFolder, filePath); + // Check that JAR file exists to avoid logging an error + if (FileUtils.getResourceFromJar(filePath) != null && FileUtils.copyFileFromResource(file, filePath)) { + return file; + } + + if (FileUtils.copyFileFromResource(file, defaultFile)) { + return file; + } else { + ConsoleLogger.warning("Wanted to copy default messages file '" + defaultFile + + "' from JAR but it didn't exist"); + return null; + } + } +} diff --git a/src/main/java/fr/xephi/authme/message/HelpMessagesFileHandler.java b/src/main/java/fr/xephi/authme/message/HelpMessagesFileHandler.java new file mode 100644 index 00000000..18eed4ae --- /dev/null +++ b/src/main/java/fr/xephi/authme/message/HelpMessagesFileHandler.java @@ -0,0 +1,23 @@ +package fr.xephi.authme.message; + +import javax.inject.Inject; + +/** + * File handler for the help_xx.yml resource. + */ +public class HelpMessagesFileHandler extends AbstractMessageFileHandler { + + @Inject // Trigger injection in the superclass + HelpMessagesFileHandler() { + } + + @Override + protected String createFilePath(String language) { + return "messages/help_" + language + ".yml"; + } + + @Override + protected String getUpdateCommand() { + return "/authme messages help"; + } +} diff --git a/src/main/java/fr/xephi/authme/message/MessageFileHandler.java b/src/main/java/fr/xephi/authme/message/MessageFileHandler.java deleted file mode 100644 index 5d19e8f4..00000000 --- a/src/main/java/fr/xephi/authme/message/MessageFileHandler.java +++ /dev/null @@ -1,95 +0,0 @@ -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; - -import java.io.File; -import java.io.InputStream; -import java.io.InputStreamReader; - -/** - * Handles a YAML message file with a default file fallback. - */ -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; - - /** - * Constructor. - * - * @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, String updateCommand) { - this.filename = file.getName(); - this.configuration = YamlConfiguration.loadConfiguration(file); - this.defaultFile = defaultFile; - this.updateAddition = updateCommand == null - ? "" - : " (or run " + updateCommand + ")"; - } - - /** - * Returns whether the message file configuration has an entry at the given path. - * - * @param path the path to verify - * @return true if an entry exists for the path in the messages file, false otherwise - */ - public boolean hasSection(String path) { - return configuration.get(path) != null; - } - - /** - * Returns the message for the given key. - * - * @param key the key to retrieve the message for - * @return the message - */ - public String getMessage(String key) { - String message = configuration.getString(key); - - if (message == null) { - ConsoleLogger.warning("Error getting message with key '" + key + "'. " - + "Please update your config file '" + filename + "'" + updateAddition); - return getDefault(key); - } - return message; - } - - /** - * Returns the message for the given key only if it exists, - * i.e. without falling back to the default file. - * - * @param key the key to retrieve the message for - * @return the message, or {@code null} if not available - */ - public String getMessageIfExists(String key) { - return configuration.getString(key); - } - - /** - * Gets the message from the default file. - * - * @param key the key to retrieve the message for - * @return the message from the default file - */ - private String getDefault(String key) { - if (defaultConfiguration == null) { - InputStream stream = FileUtils.getResourceFromJar(defaultFile); - defaultConfiguration = YamlConfiguration.loadConfiguration(new InputStreamReader(stream)); - } - String message = defaultConfiguration.getString(key); - return message == null - ? "Error retrieving message '" + key + "'" - : message; - } -} diff --git a/src/main/java/fr/xephi/authme/message/MessageFileHandlerProvider.java b/src/main/java/fr/xephi/authme/message/MessageFileHandlerProvider.java deleted file mode 100644 index 5b809b2c..00000000 --- a/src/main/java/fr/xephi/authme/message/MessageFileHandlerProvider.java +++ /dev/null @@ -1,81 +0,0 @@ -package fr.xephi.authme.message; - -import com.google.common.annotations.VisibleForTesting; -import fr.xephi.authme.initialization.DataFolder; -import fr.xephi.authme.settings.Settings; -import fr.xephi.authme.settings.properties.PluginSettings; -import fr.xephi.authme.util.FileUtils; - -import javax.inject.Inject; -import java.io.File; -import java.util.function.Function; - -/** - * Injectable creator of {@link MessageFileHandler} instances. - * - * @see MessageFileHandler - */ -public class MessageFileHandlerProvider { - - private static final String DEFAULT_LANGUAGE = "en"; - - @Inject - @DataFolder - private File dataFolder; - @Inject - private Settings settings; - - MessageFileHandlerProvider() { - } - - /** - * 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 - * @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), - updateCommand); - } - - /** - * Copies the messages file from the JAR if it doesn't exist. - * - * @param language the configured language code - * @param pathBuilder function returning message file name with language as argument - * @return the messages file to use - */ - @VisibleForTesting - File initializeFile(String language, Function pathBuilder) { - String filePath = pathBuilder.apply(language); - File file = new File(dataFolder, filePath); - // Check that JAR file exists to avoid logging an error - if (FileUtils.getResourceFromJar(filePath) != null && FileUtils.copyFileFromResource(file, filePath)) { - return file; - } - - String defaultFilePath = pathBuilder.apply(DEFAULT_LANGUAGE); - if (FileUtils.copyFileFromResource(file, defaultFilePath)) { - return file; - } - return null; - } - -} diff --git a/src/main/java/fr/xephi/authme/message/Messages.java b/src/main/java/fr/xephi/authme/message/Messages.java index d7fdcec8..8c9f2f42 100644 --- a/src/main/java/fr/xephi/authme/message/Messages.java +++ b/src/main/java/fr/xephi/authme/message/Messages.java @@ -2,7 +2,6 @@ package fr.xephi.authme.message; import com.google.common.collect.ImmutableMap; import fr.xephi.authme.ConsoleLogger; -import fr.xephi.authme.initialization.Reloadable; import fr.xephi.authme.util.expiring.Duration; import org.bukkit.ChatColor; import org.bukkit.command.CommandSender; @@ -14,7 +13,7 @@ import java.util.concurrent.TimeUnit; /** * Class for retrieving and sending translatable messages to players. */ -public class Messages implements Reloadable { +public class Messages { // Custom Authme tag replaced to new line private static final String NEWLINE_TAG = "%nl%"; @@ -33,16 +32,14 @@ public class Messages implements Reloadable { .put(TimeUnit.HOURS, MessageKey.HOURS) .put(TimeUnit.DAYS, MessageKey.DAYS).build(); - private final MessageFileHandlerProvider messageFileHandlerProvider; - private MessageFileHandler messageFileHandler; + private MessagesFileHandler messagesFileHandler; /* * Constructor. */ @Inject - Messages(MessageFileHandlerProvider messageFileHandlerProvider) { - this.messageFileHandlerProvider = messageFileHandlerProvider; - reload(); + Messages(MessagesFileHandler messagesFileHandler) { + this.messagesFileHandler = messagesFileHandler; } /** @@ -113,7 +110,7 @@ public class Messages implements Reloadable { */ private String retrieveMessage(MessageKey key) { return formatMessage( - messageFileHandler.getMessage(key.getKey())); + messagesFileHandler.getMessage(key.getKey())); } /** @@ -138,10 +135,12 @@ public class Messages implements Reloadable { return message; } - @Override - public void reload() { - this.messageFileHandler = messageFileHandlerProvider - .initializeHandler(lang -> "messages/messages_" + lang + ".yml", "/authme messages"); + /** + * Triggers a reload of the messages file. Note that this method is not necessary + * to be called for /authme reload. + */ + public void reloadMessagesFile() { + messagesFileHandler.reload(); } private static String formatMessage(String message) { diff --git a/src/main/java/fr/xephi/authme/message/MessagesFileHandler.java b/src/main/java/fr/xephi/authme/message/MessagesFileHandler.java new file mode 100644 index 00000000..febe26c5 --- /dev/null +++ b/src/main/java/fr/xephi/authme/message/MessagesFileHandler.java @@ -0,0 +1,23 @@ +package fr.xephi.authme.message; + +import javax.inject.Inject; + +/** + * File handler for the messages_xx.yml resource. + */ +public class MessagesFileHandler extends AbstractMessageFileHandler { + + @Inject // Trigger injection in the superclass + MessagesFileHandler() { + } + + @Override + protected String createFilePath(String language) { + return "messages/messages_" + language + ".yml"; + } + + @Override + protected String getUpdateCommand() { + return "/authme messages"; + } +} diff --git a/src/test/java/fr/xephi/authme/ReflectionTestUtils.java b/src/test/java/fr/xephi/authme/ReflectionTestUtils.java index b48f5efc..033bed27 100644 --- a/src/test/java/fr/xephi/authme/ReflectionTestUtils.java +++ b/src/test/java/fr/xephi/authme/ReflectionTestUtils.java @@ -1,5 +1,8 @@ package fr.xephi.authme; +import ch.jalu.injector.handlers.postconstruct.PostConstructMethodInvoker; + +import java.lang.reflect.Constructor; import java.lang.reflect.Field; import java.lang.reflect.InvocationTargetException; import java.lang.reflect.Method; @@ -102,4 +105,32 @@ public final class ReflectionTestUtils { throw new UnsupportedOperationException("Could not invoke method '" + method + "'", e); } } + + /** + * Runs all methods annotated with {@link javax.annotation.PostConstruct} on the given instance + * (including such methods on superclasses). + * + * @param instance the instance to process + */ + public static void invokePostConstructMethods(Object instance) { + // Use the implementation of the injector to invoke all @PostConstruct methods the same way + new PostConstructMethodInvoker().postProcess(instance, null, null); + } + + /** + * Creates a new instance of the given class, using a no-args constructor (which may be hidden). + * + * @param clazz the class to instantiate + * @param the class' type + * @return the created instance + */ + public static T newInstance(Class clazz) { + try { + Constructor constructor = clazz.getDeclaredConstructor(); + constructor.setAccessible(true); + return constructor.newInstance(); + } catch (ReflectiveOperationException e) { + throw new UnsupportedOperationException("Could not invoke no-args constructor of class " + clazz, e); + } + } } 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 bef86fca..c7202a92 100644 --- a/src/test/java/fr/xephi/authme/command/help/HelpMessagesServiceTest.java +++ b/src/test/java/fr/xephi/authme/command/help/HelpMessagesServiceTest.java @@ -1,64 +1,55 @@ package fr.xephi.authme.command.help; -import ch.jalu.injector.testing.BeforeInjecting; -import ch.jalu.injector.testing.DelayedInjectionRunner; -import ch.jalu.injector.testing.InjectDelayed; +import com.google.common.io.Files; +import fr.xephi.authme.ReflectionTestUtils; +import fr.xephi.authme.TestHelper; import fr.xephi.authme.command.CommandDescription; import fr.xephi.authme.command.TestCommandsUtil; -import fr.xephi.authme.message.MessageFileHandler; -import fr.xephi.authme.message.MessageFileHandlerProvider; +import fr.xephi.authme.message.AbstractMessageFileHandler; +import fr.xephi.authme.message.HelpMessagesFileHandler; import fr.xephi.authme.permission.DefaultPermission; +import fr.xephi.authme.settings.Settings; +import fr.xephi.authme.settings.properties.PluginSettings; +import org.junit.Before; +import org.junit.Rule; import org.junit.Test; -import org.junit.runner.RunWith; -import org.mockito.ArgumentCaptor; -import org.mockito.Mock; +import org.junit.rules.TemporaryFolder; +import java.io.File; +import java.io.IOException; import java.util.Collection; -import java.util.function.Function; -import static fr.xephi.authme.TestHelper.getJarFile; import static fr.xephi.authme.command.TestCommandsUtil.getCommandWithLabel; import static org.hamcrest.Matchers.equalTo; import static org.hamcrest.Matchers.hasSize; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; import static org.hamcrest.Matchers.sameInstance; import static org.junit.Assert.assertThat; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.mock; /** * Test for {@link HelpMessagesService}. */ -@RunWith(DelayedInjectionRunner.class) public class HelpMessagesServiceTest { private static final String TEST_FILE = "/fr/xephi/authme/command/help/help_test.yml"; private static final Collection COMMANDS = TestCommandsUtil.generateCommands(); - @InjectDelayed private HelpMessagesService helpMessagesService; - @Mock - private MessageFileHandlerProvider messageFileHandlerProvider; + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + private File dataFolder; - @BeforeInjecting - @SuppressWarnings("unchecked") - public void initializeHandler() { - MessageFileHandler handler = new MessageFileHandler(getJarFile(TEST_FILE), "messages/messages_en.yml", null); - given(messageFileHandlerProvider.initializeHandler(any(Function.class))).willReturn(handler); - } + @Before + public void initializeHandler() throws IOException, InstantiationException, IllegalAccessException { + dataFolder = temporaryFolder.newFolder(); + new File(dataFolder, "messages").mkdirs(); + File messagesFile = new File(dataFolder, "messages/help_test.yml"); + Files.copy(TestHelper.getJarFile(TEST_FILE), messagesFile); - @Test - @SuppressWarnings("unchecked") - public void shouldUseExistingFileAsTextFile() { - // given / when / then - ArgumentCaptor> functionCaptor = ArgumentCaptor.forClass(Function.class); - verify(messageFileHandlerProvider).initializeHandler(functionCaptor.capture()); - Function helpFilePathBuilder = functionCaptor.getValue(); - String defaultFilePath = helpFilePathBuilder.apply("en"); - assertThat(getClass().getClassLoader().getResource(defaultFilePath), not(nullValue())); + HelpMessagesFileHandler helpMessagesFileHandler = createMessagesFileHandler(); + helpMessagesService = new HelpMessagesService(helpMessagesFileHandler); } @Test @@ -154,4 +145,15 @@ public class HelpMessagesServiceTest { // then assertThat(description, equalTo(command.getDescription())); } + + private HelpMessagesFileHandler createMessagesFileHandler() throws IllegalAccessException, InstantiationException { + Settings settings = mock(Settings.class); + given(settings.getProperty(PluginSettings.MESSAGES_LANGUAGE)).willReturn("test"); + + HelpMessagesFileHandler messagesFileHandler = ReflectionTestUtils.newInstance(HelpMessagesFileHandler.class); + ReflectionTestUtils.setField(AbstractMessageFileHandler.class, messagesFileHandler, "settings", settings); + ReflectionTestUtils.setField(AbstractMessageFileHandler.class, messagesFileHandler, "dataFolder", dataFolder); + ReflectionTestUtils.invokePostConstructMethods(messagesFileHandler); + return messagesFileHandler; + } } diff --git a/src/test/java/fr/xephi/authme/message/MessageFileHandlerProviderTest.java b/src/test/java/fr/xephi/authme/message/MessageFileHandlerProviderTest.java deleted file mode 100644 index 044b3411..00000000 --- a/src/test/java/fr/xephi/authme/message/MessageFileHandlerProviderTest.java +++ /dev/null @@ -1,175 +0,0 @@ -package fr.xephi.authme.message; - -import ch.jalu.injector.testing.BeforeInjecting; -import ch.jalu.injector.testing.DelayedInjectionRunner; -import ch.jalu.injector.testing.InjectDelayed; -import com.google.common.io.Files; -import fr.xephi.authme.TestHelper; -import fr.xephi.authme.initialization.DataFolder; -import fr.xephi.authme.settings.Settings; -import fr.xephi.authme.settings.properties.PluginSettings; -import org.hamcrest.Description; -import org.hamcrest.Matcher; -import org.hamcrest.TypeSafeMatcher; -import org.junit.BeforeClass; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.junit.runner.RunWith; -import org.mockito.Mock; -import org.mockito.Mockito; - -import java.io.File; -import java.io.IOException; -import java.util.function.Function; - -import static fr.xephi.authme.TestHelper.getJarFile; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; -import static org.mockito.BDDMockito.given; -import static org.mockito.Mockito.doReturn; -import static org.mockito.Mockito.verify; - -/** - * Test for {@link MessageFileHandlerProvider}. - */ -@RunWith(DelayedInjectionRunner.class) -public class MessageFileHandlerProviderTest { - - private static final Function MESSAGES_BUILDER = lang -> "messages/messages_" + lang + ".yml"; - - @InjectDelayed - private MessageFileHandlerProvider handlerProvider; - - @DataFolder - private File dataFolder; - @Mock - private Settings settings; - - @Rule - public TemporaryFolder temporaryFolder = new TemporaryFolder(); - - @BeforeClass - public static void initLogger() { - TestHelper.setupLogger(); - } - - @BeforeInjecting - public void initDataFolder() throws IOException { - this.dataFolder = temporaryFolder.newFolder(); - } - - @Test - public void shouldReturnExistingMessagesFile() { - // given - String language = "fr"; - // use another language file to make sure we won't copy over it - String jarFile = "/messages/messages_it.yml"; - File existingFile = copyFromJar(MESSAGES_BUILDER.apply(language), jarFile); - - // when - File result = handlerProvider.initializeFile(language, MESSAGES_BUILDER); - - // then - assertThat(result, equalTo(existingFile)); - assertThat(result.exists(), equalTo(true)); - assertThat(result, equalToFile(getJarFile(jarFile))); - } - - @Test - public void shouldCopyFromJarFile() { - // given - String language = "nl"; - - // when - File result = handlerProvider.initializeFile(language, MESSAGES_BUILDER); - - // then - File expectedFile = new File(dataFolder, MESSAGES_BUILDER.apply(language)); - assertThat(result, equalTo(expectedFile)); - assertThat(result.exists(), equalTo(true)); - assertThat(result, equalToFile(getJarFile("/messages/messages_nl.yml"))); - } - - @Test - public void shouldCopyDefaultFileForUnknownLanguage() { - // given - String language = "zxx"; - - // when - File result = handlerProvider.initializeFile(language, MESSAGES_BUILDER); - - // then - File expectedFile = new File(dataFolder, MESSAGES_BUILDER.apply(language)); - assertThat(result, equalTo(expectedFile)); - assertThat(result.exists(), equalTo(true)); - assertThat(result, equalToFile(getJarFile("/messages/messages_en.yml"))); - } - - @Test - public void shouldReturnNullForNonExistentDefault() { - // given - Function fileFunction = s -> "bogus"; - - // when - File result = handlerProvider.initializeFile("gsw", fileFunction); - - // then - assertThat(result, nullValue()); - } - - @Test - public void shouldCreateHandler() { - // given - String language = "fr"; - given(settings.getProperty(PluginSettings.MESSAGES_LANGUAGE)).willReturn(language); - - MessageFileHandlerProvider provider = Mockito.spy(handlerProvider); - Function fileFunction = lang -> "file_" + lang + ".txt"; - File file = new File(dataFolder, "some_file.txt"); - doReturn(file).when(provider).initializeFile(language, fileFunction); - - // when - MessageFileHandler handler = provider.initializeHandler(fileFunction); - - // then - assertThat(handler, not(nullValue())); - verify(settings).getProperty(PluginSettings.MESSAGES_LANGUAGE); - verify(provider).initializeFile(language, fileFunction); - } - - private File copyFromJar(String path, String jarPath) { - File file = new File(dataFolder, path); - if (!file.getParentFile().mkdirs()) { - throw new IllegalStateException("Could not create folders for '" + file + "'"); - } - try { - Files.copy(getJarFile(jarPath), file); - return file; - } catch (IOException e) { - throw new IllegalStateException(e); - } - } - - private static Matcher equalToFile(File file) { - return new TypeSafeMatcher() { - @Override - protected boolean matchesSafely(File item) { - try { - return Files.equal(item, file); - } catch (IOException e) { - throw new IllegalStateException("IOException during matcher evaluation", e); - } - } - - @Override - public void describeTo(Description description) { - description.appendText("Equal to file '" + file + "'"); - } - }; - } - - -} diff --git a/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java b/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java index 79e87317..5f9c80ca 100644 --- a/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/message/MessagesIntegrationTest.java @@ -1,21 +1,28 @@ package fr.xephi.authme.message; import com.google.common.collect.ImmutableMap; +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.settings.Settings; +import fr.xephi.authme.settings.properties.PluginSettings; +import fr.xephi.authme.util.FileUtils; import fr.xephi.authme.util.expiring.Duration; import org.bukkit.command.CommandSender; import org.bukkit.entity.Player; import org.junit.Before; import org.junit.BeforeClass; +import org.junit.Rule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.mockito.ArgumentCaptor; import org.mockito.Mockito; import java.io.File; +import java.io.IOException; import java.util.Map; import java.util.concurrent.TimeUnit; -import java.util.function.Function; import java.util.logging.Logger; import static org.hamcrest.Matchers.arrayWithSize; @@ -23,7 +30,6 @@ import static org.hamcrest.Matchers.contains; import static org.hamcrest.Matchers.containsString; import static org.hamcrest.Matchers.equalTo; import static org.junit.Assert.assertThat; -import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.BDDMockito.given; import static org.mockito.Mockito.mock; @@ -38,9 +44,12 @@ import static org.mockito.hamcrest.MockitoHamcrest.argThat; public class MessagesIntegrationTest { private static final String YML_TEST_FILE = TestHelper.PROJECT_ROOT + "message/messages_test.yml"; - private static final String YML_DEFAULT_TEST_FILE = "messages/messages_en.yml"; private Messages messages; + @Rule + public TemporaryFolder temporaryFolder = new TemporaryFolder(); + private File dataFolder; + @BeforeClass public static void setup() { TestHelper.setupLogger(); @@ -55,10 +64,15 @@ public class MessagesIntegrationTest { * file that should contain all messages, but again, for testing, it just contains a few. */ @Before - public void setUpMessages() { - File testFile = TestHelper.getJarFile(YML_TEST_FILE); - MessageFileHandlerProvider provider = providerReturning(testFile, YML_DEFAULT_TEST_FILE); - messages = new Messages(provider); + public void setUpMessages() throws IOException { + dataFolder = temporaryFolder.newFolder(); + File testFile = new File(dataFolder, "messages/messages_test.yml"); + new File(dataFolder, "messages").mkdirs(); + FileUtils.create(testFile); + Files.copy(TestHelper.getJarFile(YML_TEST_FILE), testFile); + + MessagesFileHandler fileHandler = createMessagesFileHandler(); + messages = new Messages(fileHandler); } @Test @@ -254,11 +268,14 @@ public class MessagesIntegrationTest { } } - @SuppressWarnings("unchecked") - private static MessageFileHandlerProvider providerReturning(File file, String defaultFile) { - MessageFileHandlerProvider handler = mock(MessageFileHandlerProvider.class); - given(handler.initializeHandler(any(Function.class), anyString())) - .willReturn(new MessageFileHandler(file, defaultFile, "/authme messages")); - return handler; + private MessagesFileHandler createMessagesFileHandler() { + Settings settings = mock(Settings.class); + given(settings.getProperty(PluginSettings.MESSAGES_LANGUAGE)).willReturn("test"); + + MessagesFileHandler messagesFileHandler = new MessagesFileHandler(); + ReflectionTestUtils.setField(AbstractMessageFileHandler.class, messagesFileHandler, "settings", settings); + ReflectionTestUtils.setField(AbstractMessageFileHandler.class, messagesFileHandler, "dataFolder", dataFolder); + ReflectionTestUtils.invokePostConstructMethods(messagesFileHandler); + return messagesFileHandler; } } diff --git a/src/test/java/fr/xephi/authme/service/HelpTranslationGeneratorIntegrationTest.java b/src/test/java/fr/xephi/authme/service/HelpTranslationGeneratorIntegrationTest.java index 1ebd108f..3e094cc2 100644 --- a/src/test/java/fr/xephi/authme/service/HelpTranslationGeneratorIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/service/HelpTranslationGeneratorIntegrationTest.java @@ -10,7 +10,7 @@ import fr.xephi.authme.command.help.HelpMessage; import fr.xephi.authme.command.help.HelpMessagesService; import fr.xephi.authme.command.help.HelpSection; import fr.xephi.authme.initialization.DataFolder; -import fr.xephi.authme.message.MessageFileHandlerProvider; +import fr.xephi.authme.message.HelpMessagesFileHandler; import fr.xephi.authme.settings.Settings; import fr.xephi.authme.settings.properties.PluginSettings; import org.bukkit.configuration.MemorySection; @@ -44,7 +44,7 @@ public class HelpTranslationGeneratorIntegrationTest { @InjectDelayed private HelpMessagesService helpMessagesService; @InjectDelayed - private MessageFileHandlerProvider messageFileHandlerProvider; + private HelpMessagesFileHandler helpMessagesFileHandler; @InjectDelayed private CommandInitializer commandInitializer;