diff --git a/pom.xml b/pom.xml index 20d0051d3..998eb2d68 100644 --- a/pom.xml +++ b/pom.xml @@ -792,6 +792,13 @@ + + + ch.jalu + injector + 0.2 + + net.ricecode diff --git a/src/main/java/fr/xephi/authme/AuthMe.java b/src/main/java/fr/xephi/authme/AuthMe.java index bb9d06a67..4ccc56274 100644 --- a/src/main/java/fr/xephi/authme/AuthMe.java +++ b/src/main/java/fr/xephi/authme/AuthMe.java @@ -1,5 +1,7 @@ package fr.xephi.authme; +import ch.jalu.injector.Injector; +import ch.jalu.injector.InjectorBuilder; import com.google.common.annotations.VisibleForTesting; import fr.xephi.authme.api.API; import fr.xephi.authme.api.NewAPI; @@ -16,7 +18,6 @@ import fr.xephi.authme.datasource.MySQL; import fr.xephi.authme.datasource.SQLite; import fr.xephi.authme.hooks.BungeeCordMessage; import fr.xephi.authme.hooks.PluginHooks; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.initialization.MetricsStarter; import fr.xephi.authme.listener.AuthMeBlockListener; @@ -110,7 +111,7 @@ public class AuthMe extends JavaPlugin { private PluginHooks pluginHooks; private SpawnLoader spawnLoader; private BukkitService bukkitService; - private AuthMeServiceInitializer initializer; + private Injector injector; private GeoLiteAPI geoLiteApi; /** @@ -224,20 +225,20 @@ public class AuthMe extends JavaPlugin { MigrationService.changePlainTextToSha256(newSettings, database, new SHA256()); // Injector initialization - initializer = new AuthMeServiceInitializer("fr.xephi.authme"); + injector = new InjectorBuilder().addDefaultHandlers("fr.xephi.authme").create(); // Register elements of the Bukkit / JavaPlugin environment - initializer.register(AuthMe.class, this); - initializer.register(Server.class, getServer()); - initializer.register(PluginManager.class, getServer().getPluginManager()); - initializer.register(BukkitScheduler.class, getServer().getScheduler()); - initializer.provide(DataFolder.class, getDataFolder()); + injector.register(AuthMe.class, this); + injector.register(Server.class, getServer()); + injector.register(PluginManager.class, getServer().getPluginManager()); + injector.register(BukkitScheduler.class, getServer().getScheduler()); + injector.provide(DataFolder.class, getDataFolder()); // Register elements we instantiate manually - initializer.register(NewSetting.class, newSettings); - initializer.register(DataSource.class, database); + injector.register(NewSetting.class, newSettings); + injector.register(DataSource.class, database); - instantiateServices(initializer); + instantiateServices(injector); // Set up Metrics MetricsStarter.setupMetrics(this, newSettings); @@ -256,7 +257,7 @@ public class AuthMe extends JavaPlugin { reloadSupportHook(); // Register event listeners - registerEventListeners(initializer); + registerEventListeners(injector); // Start Email recall task if needed scheduleRecallEmailTask(); @@ -276,25 +277,25 @@ public class AuthMe extends JavaPlugin { } // Purge on start if enabled - PurgeService purgeService = initializer.get(PurgeService.class); + PurgeService purgeService = injector.getSingleton(PurgeService.class); purgeService.runAutoPurge(); } - protected void instantiateServices(AuthMeServiceInitializer initializer) { + protected void instantiateServices(Injector injector) { // Some statically injected things - initializer.register(PlayerCache.class, PlayerCache.getInstance()); + injector.register(PlayerCache.class, PlayerCache.getInstance()); - messages = initializer.get(Messages.class); - permsMan = initializer.get(PermissionsManager.class); - bukkitService = initializer.get(BukkitService.class); - pluginHooks = initializer.get(PluginHooks.class); - passwordSecurity = initializer.get(PasswordSecurity.class); - spawnLoader = initializer.get(SpawnLoader.class); - commandHandler = initializer.get(CommandHandler.class); - management = initializer.get(Management.class); - geoLiteApi = initializer.get(GeoLiteAPI.class); - initializer.get(NewAPI.class); - initializer.get(API.class); + messages = injector.getSingleton(Messages.class); + permsMan = injector.getSingleton(PermissionsManager.class); + bukkitService = injector.getSingleton(BukkitService.class); + pluginHooks = injector.getSingleton(PluginHooks.class); + passwordSecurity = injector.getSingleton(PasswordSecurity.class); + spawnLoader = injector.getSingleton(SpawnLoader.class); + commandHandler = injector.getSingleton(CommandHandler.class); + management = injector.getSingleton(Management.class); + geoLiteApi = injector.getSingleton(GeoLiteAPI.class); + injector.getSingleton(NewAPI.class); + injector.getSingleton(API.class); } /** @@ -316,27 +317,27 @@ public class AuthMe extends JavaPlugin { /** * Register all event listeners. */ - protected void registerEventListeners(AuthMeServiceInitializer initializer) { + protected void registerEventListeners(Injector injector) { // Get the plugin manager instance PluginManager pluginManager = getServer().getPluginManager(); // Register event listeners - pluginManager.registerEvents(initializer.get(AuthMePlayerListener.class), this); - pluginManager.registerEvents(initializer.get(AuthMeBlockListener.class), this); - pluginManager.registerEvents(initializer.get(AuthMeEntityListener.class), this); - pluginManager.registerEvents(initializer.get(AuthMeServerListener.class), this); + pluginManager.registerEvents(injector.getSingleton(AuthMePlayerListener.class), this); + pluginManager.registerEvents(injector.getSingleton(AuthMeBlockListener.class), this); + pluginManager.registerEvents(injector.getSingleton(AuthMeEntityListener.class), this); + pluginManager.registerEvents(injector.getSingleton(AuthMeServerListener.class), this); // Try to register 1.6 player listeners try { Class.forName("org.bukkit.event.player.PlayerEditBookEvent"); - pluginManager.registerEvents(initializer.get(AuthMePlayerListener16.class), this); + pluginManager.registerEvents(injector.getSingleton(AuthMePlayerListener16.class), this); } catch (ClassNotFoundException ignore) { } // Try to register 1.8 player listeners try { Class.forName("org.bukkit.event.player.PlayerInteractAtEntityEvent"); - pluginManager.registerEvents(initializer.get(AuthMePlayerListener18.class), this); + pluginManager.registerEvents(injector.getSingleton(AuthMePlayerListener18.class), this); } catch (ClassNotFoundException ignore) { } } @@ -365,8 +366,8 @@ public class AuthMe extends JavaPlugin { private void setupBungeeCordHook() { if (newSettings.getProperty(HooksSettings.BUNGEECORD)) { Messenger messenger = Bukkit.getMessenger(); - messenger.registerOutgoingPluginChannel(plugin, "BungeeCord"); - messenger.registerIncomingPluginChannel(plugin, "BungeeCord", initializer.get(BungeeCordMessage.class)); + messenger.registerOutgoingPluginChannel(this, "BungeeCord"); + messenger.registerIncomingPluginChannel(this, "BungeeCord", injector.getSingleton(BungeeCordMessage.class)); } } @@ -420,9 +421,9 @@ public class AuthMe extends JavaPlugin { @Override public void onDisable() { // Save player data - BukkitService bukkitService = initializer.getIfAvailable(BukkitService.class); - LimboCache limboCache = initializer.getIfAvailable(LimboCache.class); - AuthGroupHandler authGroupHandler = initializer.getIfAvailable(AuthGroupHandler.class); + BukkitService bukkitService = injector.getIfAvailable(BukkitService.class); + LimboCache limboCache = injector.getIfAvailable(LimboCache.class); + AuthGroupHandler authGroupHandler = injector.getIfAvailable(AuthGroupHandler.class); if (bukkitService != null && limboCache != null) { Collection players = bukkitService.getOnlinePlayers(); @@ -579,7 +580,7 @@ public class AuthMe extends JavaPlugin { } if (newSettings.getProperty(RestrictionSettings.TELEPORT_UNAUTHED_TO_SPAWN) && !newSettings.getProperty(RestrictionSettings.NO_TELEPORT)) { - PlayerDataStorage playerDataStorage = initializer.getIfAvailable(PlayerDataStorage.class); + PlayerDataStorage playerDataStorage = injector.getIfAvailable(PlayerDataStorage.class); if (playerDataStorage != null && !playerDataStorage.hasData(player)) { playerDataStorage.saveData(player); } diff --git a/src/main/java/fr/xephi/authme/command/CommandHandler.java b/src/main/java/fr/xephi/authme/command/CommandHandler.java index da5299e22..743b01e82 100644 --- a/src/main/java/fr/xephi/authme/command/CommandHandler.java +++ b/src/main/java/fr/xephi/authme/command/CommandHandler.java @@ -1,8 +1,8 @@ package fr.xephi.authme.command; +import ch.jalu.injector.Injector; import fr.xephi.authme.AuthMe; import fr.xephi.authme.command.help.HelpProvider; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.util.StringUtils; import org.bukkit.ChatColor; @@ -37,12 +37,12 @@ public class CommandHandler { private Map, ExecutableCommand> commands = new HashMap<>(); @Inject - public CommandHandler(AuthMeServiceInitializer initializer, CommandMapper commandMapper, + public CommandHandler(Injector injector, CommandMapper commandMapper, PermissionsManager permissionsManager, HelpProvider helpProvider) { this.commandMapper = commandMapper; this.permissionsManager = permissionsManager; this.helpProvider = helpProvider; - initializeCommands(initializer, commandMapper.getCommandClasses()); + initializeCommands(injector, commandMapper.getCommandClasses()); } /** @@ -90,12 +90,13 @@ public class CommandHandler { /** * Initialize all required ExecutableCommand objects. * + * @param injector the injector * @param commandClasses the classes to instantiate */ - private void initializeCommands(AuthMeServiceInitializer initializer, + private void initializeCommands(Injector injector, Set> commandClasses) { for (Class clazz : commandClasses) { - commands.put(clazz, initializer.newInstance(clazz)); + commands.put(clazz, injector.newInstance(clazz)); } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java index fef7cfb38..a4a064869 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ConverterCommand.java @@ -1,5 +1,6 @@ package fr.xephi.authme.command.executable.authme; +import ch.jalu.injector.Injector; import com.google.common.annotations.VisibleForTesting; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.command.CommandService; @@ -11,7 +12,6 @@ import fr.xephi.authme.converter.RoyalAuthConverter; import fr.xephi.authme.converter.SqliteToSql; import fr.xephi.authme.converter.vAuthConverter; import fr.xephi.authme.converter.xAuthConverter; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.util.BukkitService; import org.bukkit.command.CommandSender; @@ -31,7 +31,7 @@ public class ConverterCommand implements ExecutableCommand { private BukkitService bukkitService; @Inject - private AuthMeServiceInitializer initializer; + private Injector injector; @Override public void executeCommand(final CommandSender sender, List arguments) { @@ -46,7 +46,7 @@ public class ConverterCommand implements ExecutableCommand { } // Get the proper converter instance - final Converter converter = initializer.newInstance(jobType.getConverterClass()); + final Converter converter = injector.newInstance(jobType.getConverterClass()); // Run the convert job bukkitService.runTaskAsynchronously(new Runnable() { diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java index 73534902d..1a7d1a691 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/ReloadCommand.java @@ -1,17 +1,20 @@ package fr.xephi.authme.command.executable.authme; +import ch.jalu.injector.Injector; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.command.CommandService; import fr.xephi.authme.command.ExecutableCommand; import fr.xephi.authme.datasource.DataSource; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; +import fr.xephi.authme.initialization.Reloadable; +import fr.xephi.authme.initialization.SettingsDependent; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.properties.DatabaseSettings; import org.bukkit.command.CommandSender; import javax.inject.Inject; +import java.util.Collection; import java.util.List; /** @@ -23,7 +26,7 @@ public class ReloadCommand implements ExecutableCommand { private AuthMe plugin; @Inject - private AuthMeServiceInitializer initializer; + private Injector injector; @Inject private NewSetting settings; @@ -44,7 +47,7 @@ public class ReloadCommand implements ExecutableCommand { ConsoleLogger.info("Note: cannot change database type during /authme reload"); sender.sendMessage("Note: cannot change database type during /authme reload"); } - initializer.performReloadOnServices(); + performReloadOnServices(); commandService.send(sender, MessageKey.CONFIG_RELOAD_SUCCESS); } catch (Exception e) { sender.sendMessage("Error occurred during reload of AuthMe: aborting"); @@ -52,4 +55,16 @@ public class ReloadCommand implements ExecutableCommand { plugin.stopOrUnload(); } } + + private void performReloadOnServices() { + Collection reloadables = injector.retrieveAllOfType(Reloadable.class); + for (Reloadable reloadable : reloadables) { + reloadable.reload(); + } + + Collection settingsDependents = injector.retrieveAllOfType(SettingsDependent.class); + for (SettingsDependent dependent : settingsDependents) { + dependent.reload(settings); + } + } } diff --git a/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java b/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java index a7e6575ef..86437dd77 100644 --- a/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java +++ b/src/main/java/fr/xephi/authme/command/executable/authme/VersionCommand.java @@ -31,11 +31,13 @@ public class VersionCommand implements ExecutableCommand { + " v" + AuthMe.getPluginVersion() + ChatColor.GRAY + " (build: " + AuthMe.getPluginBuildNumber() + ")"); sender.sendMessage(ChatColor.GOLD + "Developers:"); Collection onlinePlayers = bukkitService.getOnlinePlayers(); - printDeveloper(sender, "Xephi", "xephi59", "Lead Developer", onlinePlayers); + printDeveloper(sender, "Alexandre Vanhecke", "xephi59", "Original Author", onlinePlayers); + printDeveloper(sender, "Lucas J.", "ljacqu", "Main Developer", onlinePlayers); + printDeveloper(sender, "Gnat008", "gnat008", "Developer", onlinePlayers); printDeveloper(sender, "DNx5", "DNx5", "Developer", onlinePlayers); printDeveloper(sender, "games647", "games647", "Developer", onlinePlayers); printDeveloper(sender, "Tim Visee", "timvisee", "Developer", onlinePlayers); - printDeveloper(sender, "Sgdc3", "sgdc3", "Project manager, Contributor", onlinePlayers); + printDeveloper(sender, "Gabriele C.", "sgdc3", "Project manager, Contributor", onlinePlayers); sender.sendMessage(ChatColor.GOLD + "Website: " + ChatColor.WHITE + "http://dev.bukkit.org/bukkit-plugins/authme-reloaded/"); sender.sendMessage(ChatColor.GOLD + "License: " + ChatColor.WHITE + "GNU GPL v3.0" diff --git a/src/main/java/fr/xephi/authme/hooks/PluginHooks.java b/src/main/java/fr/xephi/authme/hooks/PluginHooks.java index 76f8e0347..f3a066e19 100644 --- a/src/main/java/fr/xephi/authme/hooks/PluginHooks.java +++ b/src/main/java/fr/xephi/authme/hooks/PluginHooks.java @@ -1,5 +1,6 @@ package fr.xephi.authme.hooks; +import ch.jalu.injector.annotations.NoFieldScan; import com.earth2me.essentials.Essentials; import com.onarandombox.MultiverseCore.MultiverseCore; import com.onarandombox.MultiverseCore.api.MVWorldManager; @@ -17,6 +18,7 @@ import java.io.File; /** * Hooks into third-party plugins and allows to perform actions on them. */ +@NoFieldScan public class PluginHooks { private final PluginManager pluginManager; diff --git a/src/main/java/fr/xephi/authme/initialization/AuthMeServiceInitializer.java b/src/main/java/fr/xephi/authme/initialization/AuthMeServiceInitializer.java deleted file mode 100644 index e10ce724b..000000000 --- a/src/main/java/fr/xephi/authme/initialization/AuthMeServiceInitializer.java +++ /dev/null @@ -1,288 +0,0 @@ -package fr.xephi.authme.initialization; - -import com.google.common.base.Preconditions; -import com.google.common.collect.ImmutableSet; -import fr.xephi.authme.settings.NewSetting; - -import javax.annotation.PostConstruct; -import java.lang.annotation.Annotation; -import java.lang.reflect.InvocationTargetException; -import java.lang.reflect.Method; -import java.lang.reflect.Modifier; -import java.util.HashMap; -import java.util.HashSet; -import java.util.Map; -import java.util.Set; - -/** - * Dependency injector of AuthMe: initializes and injects services and tasks. - *

- * Only constructor and field injection are supported, indicated with the JSR330 - * {@link javax.inject.Inject @Inject} annotation. - *

- * {@link PostConstruct @PostConstruct} methods are recognized and invoked upon - * instantiation. Note that the parent classes are not scanned for such methods. - */ -public class AuthMeServiceInitializer { - - private final Set ALLOWED_PACKAGES; - private final Map, Object> objects; - - /** - * Constructor. - * - * @param allowedPackages list of allowed packages. Only classes whose package - * starts with any of the given entries will be instantiated - */ - public AuthMeServiceInitializer(String... allowedPackages) { - ALLOWED_PACKAGES = ImmutableSet.copyOf(allowedPackages); - objects = new HashMap<>(); - objects.put(getClass(), this); - } - - /** - * Retrieves or instantiates an object of the given type. - * - * @param clazz the class to retrieve the value for - * @param the class' type - * @return object of the class' type - */ - public T get(Class clazz) { - return get(clazz, new HashSet>()); - } - - /** - * Register an object with a custom class (supertype). Use this for example to specify a - * concrete implementation of an interface or an abstract class. - * - * @param clazz the class to register the object for - * @param object the object - * @param the class' type - */ - public void register(Class clazz, T object) { - if (objects.containsKey(clazz)) { - throw new IllegalStateException("There is already an object present for " + clazz); - } - Preconditions.checkNotNull(object); - objects.put(clazz, object); - } - - /** - * Associate an annotation with a value. - * - * @param annotation the annotation - * @param value the value - */ - public void provide(Class annotation, Object value) { - if (objects.containsKey(annotation)) { - throw new IllegalStateException("Annotation @" + annotation.getClass().getSimpleName() - + " already registered"); - } - Preconditions.checkNotNull(value); - objects.put(annotation, value); - } - - /** - * Creates a new instance of the given class and does not keep track of it afterwards, - * unlike {@link #get(Class)} (singleton scope). - * - * @param clazz the class to instantiate - * @param the class' type - * @return new instance of class T - */ - public T newInstance(Class clazz) { - return instantiate(clazz, new HashSet>()); - } - - /** - * Returns an instance of the given class if available. This simply returns the instance if present and - * otherwise {@code null}. Calling this method will not instantiate anything. - * - * @param clazz the class to retrieve the instance for - * @param the class' type - * @return instance or null if none available - */ - public T getIfAvailable(Class clazz) { - if (Annotation.class.isAssignableFrom(clazz)) { - throw new UnsupportedOperationException("Annotations may not be retrieved in this way!"); - } - return clazz.cast(objects.get(clazz)); - } - - /** - * Returns an instance of the given class by retrieving it or by instantiating it if not yet present. - * - * @param clazz the class to retrieve a value for - * @param traversedClasses the list of traversed classes - * @param the class' type - * @return instance or associated value (for annotations) - */ - private T get(Class clazz, Set> traversedClasses) { - if (Annotation.class.isAssignableFrom(clazz)) { - throw new UnsupportedOperationException("Cannot retrieve annotated elements in this way!"); - } else if (objects.containsKey(clazz)) { - return clazz.cast(objects.get(clazz)); - } - - // First time we come across clazz, need to instantiate it. Validate that we can do so - validatePackage(clazz); - validateInstantiable(clazz); - - // Add the clazz to the list of traversed classes in a new Set, so each path we take has its own Set. - traversedClasses = new HashSet<>(traversedClasses); - traversedClasses.add(clazz); - T object = instantiate(clazz, traversedClasses); - storeObject(object); - return object; - } - - /** - * Performs a reload on all applicable instances which are registered. - * Requires that the {@link NewSetting settings} instance be registered. - *

- * Note that the order in which these classes are reloaded is not guaranteed. - */ - public void performReloadOnServices() { - NewSetting settings = (NewSetting) objects.get(NewSetting.class); - if (settings == null) { - throw new IllegalStateException("Settings instance is null"); - } - for (Object object : objects.values()) { - if (object instanceof SettingsDependent) { - ((SettingsDependent) object).reload(settings); - } - - if (object instanceof Reloadable) { - ((Reloadable) object).reload(); - } - } - } - - /** - * Instantiates the given class by locating its @Inject elements and retrieving - * or instantiating the required instances. - * - * @param clazz the class to instantiate - * @param traversedClasses collection of classes already traversed - * @param the class' type - * @return the instantiated object - */ - private T instantiate(Class clazz, Set> traversedClasses) { - Injection injection = InjectionHelper.getInjection(clazz); - if (injection == null) { - throw new IllegalStateException("Did not find injection method for " + clazz + ". Make sure you have " - + "a constructor with @Inject or fields with @Inject. Fields with @Inject require " - + "the default constructor"); - } - - validateInjectionHasNoCircularDependencies(injection.getDependencies(), traversedClasses); - Object[] dependencies = resolveDependencies(injection, traversedClasses); - T object = injection.instantiateWith(dependencies); - executePostConstructMethod(object); - return object; - } - - /** - * Resolves the dependencies for the given class instantiation, i.e. returns a collection that satisfy - * the class' dependencies by retrieving elements or instantiating them where necessary. - * - * @param injection the injection parameters - * @param traversedClasses collection of traversed classes - * @return array with the parameters to use in the constructor - */ - private Object[] resolveDependencies(Injection injection, Set> traversedClasses) { - Class[] dependencies = injection.getDependencies(); - Class[] annotations = injection.getDependencyAnnotations(); - Object[] values = new Object[dependencies.length]; - for (int i = 0; i < dependencies.length; ++i) { - if (annotations[i] == null) { - values[i] = get(dependencies[i], traversedClasses); - } else { - Object value = objects.get(annotations[i]); - if (value == null) { - throw new IllegalStateException("Value for field with @" + annotations[i].getSimpleName() - + " must be registered beforehand"); - } - values[i] = value; - } - } - return values; - } - - /** - * Stores the given object with its class as key. Throws an exception if the key already has - * a value associated to it. - * - * @param object the object to store - */ - private void storeObject(Object object) { - if (objects.containsKey(object.getClass())) { - throw new IllegalStateException("There is already an object present for " + object.getClass()); - } - Preconditions.checkNotNull(object); - objects.put(object.getClass(), object); - } - - /** - * Validates that none of the dependencies' types are present in the given collection - * of traversed classes. This prevents circular dependencies. - * - * @param dependencies the dependencies of the class - * @param traversedClasses the collection of traversed classes - */ - private static void validateInjectionHasNoCircularDependencies(Class[] dependencies, - Set> traversedClasses) { - for (Class clazz : dependencies) { - if (traversedClasses.contains(clazz)) { - throw new IllegalStateException("Found cyclic dependency - already traversed '" + clazz - + "' (full traversal list: " + traversedClasses + ")"); - } - } - } - - /** - * Validates the package of a parameter type to ensure that it is part of the allowed packages. - * This ensures that we don't try to instantiate things that are beyond our reach in case some - * external parameter type has not been registered. - * - * @param clazz the class to validate - */ - private void validatePackage(Class clazz) { - if (clazz.getPackage() == null) { - throw new IllegalStateException("Primitive types must be provided explicitly (or use an annotation)."); - } - String packageName = clazz.getPackage().getName(); - for (String allowedPackage : ALLOWED_PACKAGES) { - if (packageName.startsWith(allowedPackage)) { - return; - } - } - throw new IllegalStateException("Class " + clazz + " with package " + packageName + " is outside of the " - + "allowed packages. It must be provided explicitly or the package must be passed to the constructor."); - } - - /** - * Executes an object's method annotated with {@link PostConstruct} if present. - * Throws an exception if there are multiple such methods, or if the method is static. - * - * @param object the object to execute the post construct method for - */ - private static void executePostConstructMethod(Object object) { - Method postConstructMethod = InjectionHelper.getAndValidatePostConstructMethod(object.getClass()); - if (postConstructMethod != null) { - try { - postConstructMethod.setAccessible(true); - postConstructMethod.invoke(object); - } catch (IllegalAccessException | InvocationTargetException e) { - throw new UnsupportedOperationException("Error executing @PostConstruct method", e); - } - } - } - - private static void validateInstantiable(Class clazz) { - if (clazz.isEnum() || clazz.isInterface() || Modifier.isAbstract(clazz.getModifiers())) { - throw new IllegalStateException("Class " + clazz.getSimpleName() + " cannot be instantiated"); - } - } - -} diff --git a/src/main/java/fr/xephi/authme/listener/protocollib/ProtocolLibService.java b/src/main/java/fr/xephi/authme/listener/protocollib/ProtocolLibService.java index 3a817b78a..9298679b6 100644 --- a/src/main/java/fr/xephi/authme/listener/protocollib/ProtocolLibService.java +++ b/src/main/java/fr/xephi/authme/listener/protocollib/ProtocolLibService.java @@ -1,5 +1,6 @@ package fr.xephi.authme.listener.protocollib; +import ch.jalu.injector.annotations.NoFieldScan; import fr.xephi.authme.AuthMe; import fr.xephi.authme.ConsoleLogger; import fr.xephi.authme.cache.auth.PlayerCache; @@ -11,6 +12,7 @@ import org.bukkit.entity.Player; import javax.inject.Inject; +@NoFieldScan public class ProtocolLibService implements SettingsDependent { /* Packet Adapters */ diff --git a/src/main/java/fr/xephi/authme/security/PasswordSecurity.java b/src/main/java/fr/xephi/authme/security/PasswordSecurity.java index 6e6eac83c..819b15f2d 100644 --- a/src/main/java/fr/xephi/authme/security/PasswordSecurity.java +++ b/src/main/java/fr/xephi/authme/security/PasswordSecurity.java @@ -1,8 +1,8 @@ package fr.xephi.authme.security; +import ch.jalu.injector.Injector; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.events.PasswordEncryptionEvent; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; import fr.xephi.authme.initialization.Reloadable; import fr.xephi.authme.security.crypts.EncryptionMethod; import fr.xephi.authme.security.crypts.HashedPassword; @@ -28,7 +28,7 @@ public class PasswordSecurity implements Reloadable { private PluginManager pluginManager; @Inject - private AuthMeServiceInitializer initializer; + private Injector injector; private HashAlgorithm algorithm; private boolean supportOldAlgorithm; @@ -155,7 +155,7 @@ public class PasswordSecurity implements Reloadable { if (HashAlgorithm.CUSTOM.equals(algorithm) || HashAlgorithm.PLAINTEXT.equals(algorithm)) { return null; } - return initializer.newInstance(algorithm.getClazz()); + return injector.newInstance(algorithm.getClazz()); } private void hashPasswordForNewAlgorithm(String password, String playerName) { diff --git a/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java b/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java index c5c199db5..9ec1cbdee 100644 --- a/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java +++ b/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java @@ -1,10 +1,11 @@ package fr.xephi.authme; +import ch.jalu.injector.Injector; +import ch.jalu.injector.InjectorBuilder; import com.google.common.io.Files; import fr.xephi.authme.api.NewAPI; import fr.xephi.authme.command.CommandHandler; import fr.xephi.authme.datasource.DataSource; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.listener.AuthMeBlockListener; import fr.xephi.authme.permission.PermissionsManager; @@ -42,7 +43,7 @@ import static org.mockito.Mockito.mock; /** * Integration test verifying that all services can be initialized in {@link AuthMe} - * with the {@link AuthMeServiceInitializer}. + * with the {@link Injector}. */ @RunWith(MockitoJUnitRunner.class) public class AuthMeInitializationTest { @@ -97,29 +98,29 @@ public class AuthMeInitializationTest { // We only require it right now because of usages of AuthMe#getInstance() ReflectionTestUtils.setField(AuthMe.class, null, "plugin", authMe); - AuthMeServiceInitializer initializer = new AuthMeServiceInitializer("fr.xephi.authme"); - initializer.provide(DataFolder.class, dataFolder); - initializer.register(Server.class, server); - initializer.register(PluginManager.class, pluginManager); + Injector injector = new InjectorBuilder().addDefaultHandlers("fr.xephi.authme").create(); + injector.provide(DataFolder.class, dataFolder); + injector.register(Server.class, server); + injector.register(PluginManager.class, pluginManager); - initializer.register(AuthMe.class, authMe); - initializer.register(NewSetting.class, settings); - initializer.register(DataSource.class, mock(DataSource.class)); + injector.register(AuthMe.class, authMe); + injector.register(NewSetting.class, settings); + injector.register(DataSource.class, mock(DataSource.class)); // when - authMe.instantiateServices(initializer); - authMe.registerEventListeners(initializer); + authMe.instantiateServices(injector); + authMe.registerEventListeners(injector); // then // Take a few samples and ensure that they are not null - assertThat(initializer.getIfAvailable(AuthMeBlockListener.class), not(nullValue())); - assertThat(initializer.getIfAvailable(CommandHandler.class), not(nullValue())); - assertThat(initializer.getIfAvailable(Management.class), not(nullValue())); - assertThat(initializer.getIfAvailable(NewAPI.class), not(nullValue())); - assertThat(initializer.getIfAvailable(PasswordSecurity.class), not(nullValue())); - assertThat(initializer.getIfAvailable(PermissionsManager.class), not(nullValue())); - assertThat(initializer.getIfAvailable(ProcessSyncPlayerLogin.class), not(nullValue())); - assertThat(initializer.getIfAvailable(PurgeService.class), not(nullValue())); + assertThat(injector.getIfAvailable(AuthMeBlockListener.class), not(nullValue())); + assertThat(injector.getIfAvailable(CommandHandler.class), not(nullValue())); + assertThat(injector.getIfAvailable(Management.class), not(nullValue())); + assertThat(injector.getIfAvailable(NewAPI.class), not(nullValue())); + assertThat(injector.getIfAvailable(PasswordSecurity.class), not(nullValue())); + assertThat(injector.getIfAvailable(PermissionsManager.class), not(nullValue())); + assertThat(injector.getIfAvailable(ProcessSyncPlayerLogin.class), not(nullValue())); + assertThat(injector.getIfAvailable(PurgeService.class), not(nullValue())); } } diff --git a/src/test/java/fr/xephi/authme/cache/backup/PlayerDataStorageTest.java b/src/test/java/fr/xephi/authme/cache/backup/PlayerDataStorageTest.java index 236a4e281..3480b7d52 100644 --- a/src/test/java/fr/xephi/authme/cache/backup/PlayerDataStorageTest.java +++ b/src/test/java/fr/xephi/authme/cache/backup/PlayerDataStorageTest.java @@ -1,12 +1,12 @@ package fr.xephi.authme.cache.backup; +import ch.jalu.injector.testing.BeforeInjecting; +import ch.jalu.injector.testing.DelayedInjectionRunner; +import ch.jalu.injector.testing.InjectDelayed; import fr.xephi.authme.TestHelper; import fr.xephi.authme.cache.limbo.PlayerData; import fr.xephi.authme.initialization.DataFolder; import fr.xephi.authme.permission.PermissionsManager; -import fr.xephi.authme.runner.BeforeInjecting; -import fr.xephi.authme.runner.DelayedInjectionRunner; -import fr.xephi.authme.runner.InjectDelayed; import fr.xephi.authme.settings.SpawnLoader; import fr.xephi.authme.util.BukkitService; import fr.xephi.authme.util.StringUtils; diff --git a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java index 85ae92a76..cfcb00f55 100644 --- a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java @@ -1,21 +1,20 @@ package fr.xephi.authme.command; +import ch.jalu.injector.Injector; import com.google.common.collect.Sets; import fr.xephi.authme.command.TestCommandsUtil.TestLoginCommand; import fr.xephi.authme.command.TestCommandsUtil.TestRegisterCommand; import fr.xephi.authme.command.TestCommandsUtil.TestUnregisterCommand; import fr.xephi.authme.command.help.HelpProvider; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; import fr.xephi.authme.permission.PermissionsManager; -import fr.xephi.authme.runner.BeforeInjecting; -import fr.xephi.authme.runner.DelayedInjectionRunner; -import fr.xephi.authme.runner.InjectDelayed; import org.bukkit.command.CommandSender; +import org.junit.Before; import org.junit.Test; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; import org.mockito.Mock; import org.mockito.invocation.InvocationOnMock; +import org.mockito.runners.MockitoJUnitRunner; import org.mockito.stubbing.Answer; import java.util.Collections; @@ -49,14 +48,13 @@ import static org.mockito.Mockito.verify; // Justification: It's more readable to use asList() everywhere in the test when we often generated two lists where one // often consists of only one element, e.g. myMethod(asList("authme"), asList("my", "args"), ...) @SuppressWarnings("ArraysAsListWithZeroOrOneArgument") -@RunWith(DelayedInjectionRunner.class) +@RunWith(MockitoJUnitRunner.class) public class CommandHandlerTest { - @InjectDelayed private CommandHandler handler; @Mock - private AuthMeServiceInitializer initializer; + private Injector injector; @Mock private CommandMapper commandMapper; @Mock @@ -66,23 +64,25 @@ public class CommandHandlerTest { private Map, ExecutableCommand> mockedCommands = new HashMap<>(); - @BeforeInjecting + @Before @SuppressWarnings("unchecked") public void initializeCommandMapper() { given(commandMapper.getCommandClasses()).willReturn(Sets.newHashSet( ExecutableCommand.class, TestLoginCommand.class, TestRegisterCommand.class, TestUnregisterCommand.class)); setInjectorToMockExecutableCommandClasses(); + + handler = new CommandHandler(injector, commandMapper, permissionsManager, helpProvider); } /** - * Makes the initializer return a mock when {@link AuthMeServiceInitializer#newInstance(Class)} is invoked - * with (a child of) ExecutableCommand.class. The mocks the initializer creates are stored in {@link #mockedCommands}. + * Makes the injector return a mock when {@link Injector#newInstance(Class)} is invoked + * with (a child of) ExecutableCommand.class. The mocks the injector creates are stored in {@link #mockedCommands}. *

* The {@link CommandMapper} is mocked in {@link #initializeCommandMapper()} to return certain test classes. */ @SuppressWarnings("unchecked") private void setInjectorToMockExecutableCommandClasses() { - given(initializer.newInstance(any(Class.class))).willAnswer(new Answer() { + given(injector.newInstance(any(Class.class))).willAnswer(new Answer() { @Override public Object answer(InvocationOnMock invocation) throws Throwable { Class clazz = (Class) invocation.getArguments()[0]; diff --git a/src/test/java/fr/xephi/authme/command/CommandMapperTest.java b/src/test/java/fr/xephi/authme/command/CommandMapperTest.java index 472ffa472..3fd023a4e 100644 --- a/src/test/java/fr/xephi/authme/command/CommandMapperTest.java +++ b/src/test/java/fr/xephi/authme/command/CommandMapperTest.java @@ -1,14 +1,14 @@ package fr.xephi.authme.command; +import ch.jalu.injector.testing.BeforeInjecting; +import ch.jalu.injector.testing.DelayedInjectionRunner; +import ch.jalu.injector.testing.InjectDelayed; import fr.xephi.authme.command.TestCommandsUtil.TestLoginCommand; import fr.xephi.authme.command.TestCommandsUtil.TestRegisterCommand; import fr.xephi.authme.command.TestCommandsUtil.TestUnregisterCommand; import fr.xephi.authme.command.executable.HelpCommand; import fr.xephi.authme.permission.PermissionNode; import fr.xephi.authme.permission.PermissionsManager; -import fr.xephi.authme.runner.BeforeInjecting; -import fr.xephi.authme.runner.InjectDelayed; -import fr.xephi.authme.runner.DelayedInjectionRunner; import org.bukkit.command.CommandSender; import org.junit.BeforeClass; import org.junit.Test; diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/ConverterCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/ConverterCommandTest.java index 5f781752f..2f4eaa944 100644 --- a/src/test/java/fr/xephi/authme/command/executable/authme/ConverterCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/authme/ConverterCommandTest.java @@ -1,9 +1,9 @@ package fr.xephi.authme.command.executable.authme; +import ch.jalu.injector.Injector; import fr.xephi.authme.TestHelper; import fr.xephi.authme.command.CommandService; import fr.xephi.authme.converter.RakamakConverter; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.util.BukkitService; import org.bukkit.command.CommandSender; @@ -43,7 +43,7 @@ public class ConverterCommandTest { private BukkitService bukkitService; @Mock - private AuthMeServiceInitializer initializer; + private Injector injector; @Test public void shouldHandleUnknownConversionType() { @@ -56,7 +56,7 @@ public class ConverterCommandTest { // then verify(commandService).send(sender, MessageKey.ERROR); verifyNoMoreInteractions(commandService); - verifyZeroInteractions(initializer); + verifyZeroInteractions(injector); verifyZeroInteractions(bukkitService); } @@ -87,7 +87,7 @@ public class ConverterCommandTest { // given ConverterCommand.ConvertType type = ConverterCommand.ConvertType.RAKAMAK; RakamakConverter converter = mock(RakamakConverter.class); - given(initializer.newInstance(RakamakConverter.class)).willReturn(converter); + given(injector.newInstance(RakamakConverter.class)).willReturn(converter); CommandSender sender = mock(CommandSender.class); // when @@ -97,8 +97,8 @@ public class ConverterCommandTest { // then verify(converter).execute(sender); verifyNoMoreInteractions(converter); - verify(initializer).newInstance(type.getConverterClass()); - verifyNoMoreInteractions(initializer); + verify(injector).newInstance(type.getConverterClass()); + verifyNoMoreInteractions(injector); } } diff --git a/src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java b/src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java index 676c3b221..f21d34081 100644 --- a/src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java +++ b/src/test/java/fr/xephi/authme/command/executable/authme/ReloadCommandTest.java @@ -1,11 +1,13 @@ package fr.xephi.authme.command.executable.authme; +import ch.jalu.injector.Injector; import fr.xephi.authme.AuthMe; import fr.xephi.authme.TestHelper; import fr.xephi.authme.command.CommandService; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.datasource.DataSourceType; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; +import fr.xephi.authme.initialization.Reloadable; +import fr.xephi.authme.initialization.SettingsDependent; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.properties.DatabaseSettings; @@ -19,14 +21,18 @@ import org.mockito.InjectMocks; import org.mockito.Mock; import org.mockito.runners.MockitoJUnitRunner; +import java.util.ArrayList; +import java.util.Arrays; import java.util.Collections; +import java.util.List; import static org.hamcrest.Matchers.containsString; import static org.mockito.BDDMockito.given; +import static org.mockito.Matchers.any; import static org.mockito.Matchers.argThat; -import static org.mockito.Matchers.matches; import static org.mockito.Mockito.doThrow; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; import static org.mockito.Mockito.verify; /** @@ -42,7 +48,7 @@ public class ReloadCommandTest { private AuthMe authMe; @Mock - private AuthMeServiceInitializer initializer; + private Injector injector; @Mock private NewSetting settings; @@ -71,13 +77,19 @@ public class ReloadCommandTest { CommandSender sender = mock(CommandSender.class); given(settings.getProperty(DatabaseSettings.BACKEND)).willReturn(DataSourceType.MYSQL); given(dataSource.getType()).willReturn(DataSourceType.MYSQL); + List reloadables = Arrays.asList( + mock(Reloadable.class), mock(Reloadable.class), mock(Reloadable.class)); + List dependents = Arrays.asList( + mock(SettingsDependent.class), mock(SettingsDependent.class)); + given(injector.retrieveAllOfType(Reloadable.class)).willReturn(reloadables); + given(injector.retrieveAllOfType(SettingsDependent.class)).willReturn(dependents); // when command.executeCommand(sender, Collections.emptyList()); // then verify(settings).reload(); - verify(initializer).performReloadOnServices(); + verifyReloadingCalls(reloadables, dependents); verify(commandService).send(sender, MessageKey.CONFIG_RELOAD_SUCCESS); } @@ -85,7 +97,7 @@ public class ReloadCommandTest { public void shouldHandleReloadError() { // given CommandSender sender = mock(CommandSender.class); - doThrow(IllegalStateException.class).when(initializer).performReloadOnServices(); + doThrow(IllegalStateException.class).when(injector).retrieveAllOfType(Reloadable.class); given(settings.getProperty(DatabaseSettings.BACKEND)).willReturn(DataSourceType.MYSQL); given(dataSource.getType()).willReturn(DataSourceType.MYSQL); @@ -94,8 +106,8 @@ public class ReloadCommandTest { // then verify(settings).reload(); - verify(initializer).performReloadOnServices(); - verify(sender).sendMessage(matches("Error occurred.*")); + verify(injector).retrieveAllOfType(Reloadable.class); + verify(sender).sendMessage(argThat(containsString("Error occurred"))); verify(authMe).stopOrUnload(); } @@ -105,13 +117,24 @@ public class ReloadCommandTest { CommandSender sender = mock(CommandSender.class); given(settings.getProperty(DatabaseSettings.BACKEND)).willReturn(DataSourceType.MYSQL); given(dataSource.getType()).willReturn(DataSourceType.SQLITE); + given(injector.retrieveAllOfType(Reloadable.class)).willReturn(new ArrayList()); + given(injector.retrieveAllOfType(SettingsDependent.class)).willReturn(new ArrayList()); // when command.executeCommand(sender, Collections.emptyList()); // then verify(settings).reload(); - verify(initializer).performReloadOnServices(); + verify(injector, times(2)).retrieveAllOfType(any(Class.class)); verify(sender).sendMessage(argThat(containsString("cannot change database type"))); } + + private void verifyReloadingCalls(List reloadables, List dependents) { + for (Reloadable reloadable : reloadables) { + verify(reloadable).reload(); + } + for (SettingsDependent dependent : dependents) { + verify(dependent).reload(settings); + } + } } diff --git a/src/test/java/fr/xephi/authme/converter/CrazyLoginConverterTest.java b/src/test/java/fr/xephi/authme/converter/CrazyLoginConverterTest.java index 615ef915c..d3005cb26 100644 --- a/src/test/java/fr/xephi/authme/converter/CrazyLoginConverterTest.java +++ b/src/test/java/fr/xephi/authme/converter/CrazyLoginConverterTest.java @@ -1,11 +1,11 @@ package fr.xephi.authme.converter; +import ch.jalu.injector.testing.DelayedInjectionRunner; +import ch.jalu.injector.testing.InjectDelayed; import fr.xephi.authme.TestHelper; import fr.xephi.authme.cache.auth.PlayerAuth; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.initialization.DataFolder; -import fr.xephi.authme.runner.DelayedInjectionRunner; -import fr.xephi.authme.runner.InjectDelayed; import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.properties.ConverterSettings; import org.bukkit.command.CommandSender; diff --git a/src/test/java/fr/xephi/authme/initialization/AuthMeServiceInitializerTest.java b/src/test/java/fr/xephi/authme/initialization/AuthMeServiceInitializerTest.java deleted file mode 100644 index e03a14355..000000000 --- a/src/test/java/fr/xephi/authme/initialization/AuthMeServiceInitializerTest.java +++ /dev/null @@ -1,340 +0,0 @@ -package fr.xephi.authme.initialization; - -import fr.xephi.authme.initialization.samples.AlphaService; -import fr.xephi.authme.initialization.samples.BadFieldInjection; -import fr.xephi.authme.initialization.samples.BetaManager; -import fr.xephi.authme.initialization.samples.CircularClasses; -import fr.xephi.authme.initialization.samples.ClassWithAbstractDependency; -import fr.xephi.authme.initialization.samples.ClassWithAnnotations; -import fr.xephi.authme.initialization.samples.Duration; -import fr.xephi.authme.initialization.samples.FieldInjectionWithAnnotations; -import fr.xephi.authme.initialization.samples.GammaService; -import fr.xephi.authme.initialization.samples.InstantiationFallbackClasses; -import fr.xephi.authme.initialization.samples.InvalidClass; -import fr.xephi.authme.initialization.samples.InvalidPostConstruct; -import fr.xephi.authme.initialization.samples.InvalidStaticFieldInjection; -import fr.xephi.authme.initialization.samples.PostConstructTestClass; -import fr.xephi.authme.initialization.samples.ProvidedClass; -import fr.xephi.authme.initialization.samples.Size; -import fr.xephi.authme.settings.NewSetting; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; - -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.equalTo; -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.Mockito.mock; - -/** - * Test for {@link AuthMeServiceInitializer}. - */ -public class AuthMeServiceInitializerTest { - - private static final String ALLOWED_PACKAGE = "fr.xephi.authme.initialization"; - - private AuthMeServiceInitializer initializer; - - // As we test many cases that throw exceptions, we use JUnit's ExpectedException Rule - // to make sure that we receive the exception we expect - @Rule - public ExpectedException expectedException = ExpectedException.none(); - - @Before - public void setInitializer() { - initializer = new AuthMeServiceInitializer(ALLOWED_PACKAGE); - initializer.register(ProvidedClass.class, new ProvidedClass("")); - } - - @Test - public void shouldInitializeElements() { - // given / when - BetaManager betaManager = initializer.get(BetaManager.class); - - // then - assertThat(betaManager, not(nullValue())); - for (Object o : betaManager.getDependencies()) { - assertThat(o, not(nullValue())); - } - } - - @Test - public void shouldThrowForInvalidPackage() { - // given / when / then - expectRuntimeExceptionWith("outside of the allowed packages"); - initializer.get(InvalidClass.class); - } - - @Test - public void shouldThrowForUnregisteredPrimitiveType() { - // given / when / then - expectRuntimeExceptionWith("Primitive types must be provided"); - initializer.get(int.class); - } - - @Test - public void shouldPassValueByAnnotation() { - // given - int size = 12; - long duration = -15482L; - initializer.provide(Size.class, size); - initializer.provide(Duration.class, duration); - - // when - ClassWithAnnotations object = initializer.get(ClassWithAnnotations.class); - - // then - assertThat(object, not(nullValue())); - assertThat(object.getSize(), equalTo(size)); - assertThat(object.getDuration(), equalTo(duration)); - // some sample check to make sure we only have one instance of GammaService - assertThat(object.getGammaService(), equalTo(initializer.get(BetaManager.class).getDependencies()[1])); - } - - @Test - public void shouldRecognizeCircularReferences() { - // given / when / then - expectRuntimeExceptionWith("Found cyclic dependency"); - initializer.get(CircularClasses.Circular3.class); - } - - @Test - public void shouldThrowForUnregisteredAnnotation() { - // given - initializer.provide(Size.class, 4523); - - // when / then - expectRuntimeExceptionWith("must be registered beforehand"); - initializer.get(ClassWithAnnotations.class); - } - - @Test - public void shouldThrowForFieldInjectionWithoutNoArgsConstructor() { - // given / when / then - expectRuntimeExceptionWith("Did not find injection method"); - initializer.get(BadFieldInjection.class); - } - - @Test - public void shouldInjectFieldsWithAnnotationsProperly() { - // given - initializer.provide(Size.class, 2809375); - initializer.provide(Duration.class, 13095L); - - // when - FieldInjectionWithAnnotations result = initializer.get(FieldInjectionWithAnnotations.class); - - // then - assertThat(result.getSize(), equalTo(2809375)); - assertThat(result.getDuration(), equalTo(13095L)); - assertThat(result.getBetaManager(), not(nullValue())); - assertThat(result.getClassWithAnnotations(), not(nullValue())); - assertThat(result.getClassWithAnnotations().getGammaService(), - equalTo(result.getBetaManager().getDependencies()[1])); - } - - @Test - public void shouldThrowForAnnotationAsKey() { - // given / when / then - expectRuntimeExceptionWith("Cannot retrieve annotated elements in this way"); - initializer.get(Size.class); - } - - @Test - public void shouldThrowForSecondRegistration() { - // given / when / then - expectRuntimeExceptionWith("There is already an object present"); - initializer.register(ProvidedClass.class, new ProvidedClass("")); - } - - @Test - public void shouldThrowForSecondAnnotationRegistration() { - // given - initializer.provide(Size.class, 12); - - // when / then - expectRuntimeExceptionWith("already registered"); - initializer.provide(Size.class, -8); - } - - @Test - public void shouldThrowForNullValueAssociatedToAnnotation() { - // given / when / then - expectedException.expect(NullPointerException.class); - initializer.provide(Duration.class, null); - } - - @Test - public void shouldThrowForRegisterWithNull() { - // given / when / then - expectedException.expect(NullPointerException.class); - initializer.register(String.class, null); - } - - @Test - public void shouldExecutePostConstructMethod() { - // given - initializer.provide(Size.class, 15123); - - // when - PostConstructTestClass testClass = initializer.get(PostConstructTestClass.class); - - // then - assertThat(testClass.wasPostConstructCalled(), equalTo(true)); - assertThat(testClass.getBetaManager(), not(nullValue())); - } - - @Test - public void shouldThrowForInvalidPostConstructMethod() { - // given / when / then - expectRuntimeExceptionWith("@PostConstruct method may not be static or have any parameters"); - initializer.get(InvalidPostConstruct.WithParams.class); - } - - @Test - public void shouldThrowForStaticPostConstructMethod() { - // given / when / then - expectRuntimeExceptionWith("@PostConstruct method may not be static or have any parameters"); - initializer.get(InvalidPostConstruct.Static.class); - } - - @Test - public void shouldForwardExceptionFromPostConstruct() { - // given / when / then - expectRuntimeExceptionWith("Error executing @PostConstruct method"); - initializer.get(InvalidPostConstruct.ThrowsException.class); - } - - @Test - public void shouldThrowForMultiplePostConstructMethods() { - // given / when / then - expectRuntimeExceptionWith("Multiple methods with @PostConstruct"); - initializer.get(InvalidPostConstruct.MultiplePostConstructs.class); - } - - @Test - public void shouldThrowForPostConstructNotReturningVoid() { - // given / when / then - expectRuntimeExceptionWith("@PostConstruct method must have return type void"); - initializer.get(InvalidPostConstruct.NotVoidReturnType.class); - } - - @Test - public void shouldThrowForAbstractNonRegisteredDependency() { - // given / when / then - expectRuntimeExceptionWith("cannot be instantiated"); - initializer.get(ClassWithAbstractDependency.class); - } - - @Test - public void shouldInstantiateWithImplementationOfAbstractDependency() { - // given - ClassWithAbstractDependency.ConcreteDependency concrete = new ClassWithAbstractDependency.ConcreteDependency(); - initializer.register(ClassWithAbstractDependency.AbstractDependency.class, concrete); - - // when - ClassWithAbstractDependency cwad = initializer.get(ClassWithAbstractDependency.class); - - // then - assertThat(cwad.getAbstractDependency() == concrete, equalTo(true)); - assertThat(cwad.getAlphaService(), not(nullValue())); - } - - @Test - public void shouldThrowForAlreadyRegisteredClass() { - // given - initializer.register(BetaManager.class, new BetaManager()); - - // when / then - expectRuntimeExceptionWith("There is already an object present"); - initializer.register(BetaManager.class, new BetaManager()); - } - - @Test - public void shouldCreateNewUntrackedInstance() { - // given / when - AlphaService singletonScoped = initializer.get(AlphaService.class); - AlphaService requestScoped = initializer.newInstance(AlphaService.class); - - // then - assertThat(singletonScoped.getProvidedClass(), not(nullValue())); - assertThat(singletonScoped.getProvidedClass(), equalTo(requestScoped.getProvidedClass())); - assertThat(singletonScoped, not(sameInstance(requestScoped))); - } - - @Test - public void shouldThrowForStaticFieldInjection() { - // given / when / then - expectRuntimeExceptionWith("is static but annotated with @Inject"); - initializer.newInstance(InvalidStaticFieldInjection.class); - } - - @Test - public void shouldFallbackToSimpleInstantiationForPlainClass() { - // given / when - InstantiationFallbackClasses.HasFallbackDependency result = - initializer.get(InstantiationFallbackClasses.HasFallbackDependency.class); - - // then - assertThat(result, not(nullValue())); - assertThat(result.getGammaService(), not(nullValue())); - assertThat(result.getFallbackDependency(), not(nullValue())); - } - - @Test - public void shouldPerformReloadOnApplicableInstances() { - // given - initializer.provide(Size.class, 12); - initializer.provide(Duration.class, -113L); - initializer.register(NewSetting.class, mock(NewSetting.class)); - - GammaService gammaService = initializer.get(GammaService.class); - PostConstructTestClass postConstructTestClass = initializer.get(PostConstructTestClass.class); - ProvidedClass providedClass = initializer.get(ProvidedClass.class); - initializer.get(ClassWithAnnotations.class); - // Assert that no class was somehow reloaded at initialization - assertThat(gammaService.getWasReloaded() || postConstructTestClass.getWasReloaded() - || providedClass.getWasReloaded(), equalTo(false)); - - // when - initializer.performReloadOnServices(); - - // then - assertThat(gammaService.getWasReloaded(), equalTo(true)); - assertThat(postConstructTestClass.getWasReloaded(), equalTo(true)); - assertThat(providedClass.getWasReloaded(), equalTo(true)); - } - - @Test - public void shouldThrowForNullSetting() { - // given / when / then - expectRuntimeExceptionWith("Settings instance is null"); - initializer.performReloadOnServices(); - } - - @Test - public void shouldRetrieveExistingInstancesOnly() { - // given - initializer.get(GammaService.class); - - // when - AlphaService alphaService = initializer.getIfAvailable(AlphaService.class); - BetaManager betaManager = initializer.getIfAvailable(BetaManager.class); - - // then - // was initialized because is dependency of GammaService - assertThat(alphaService, not(nullValue())); - // nothing caused this to be initialized - assertThat(betaManager, nullValue()); - } - - private void expectRuntimeExceptionWith(String message) { - expectedException.expect(RuntimeException.class); - expectedException.expectMessage(containsString(message)); - } - -} diff --git a/src/test/java/fr/xephi/authme/initialization/ConstructorInjectionTest.java b/src/test/java/fr/xephi/authme/initialization/ConstructorInjectionTest.java deleted file mode 100644 index cc55b4c3e..000000000 --- a/src/test/java/fr/xephi/authme/initialization/ConstructorInjectionTest.java +++ /dev/null @@ -1,83 +0,0 @@ -package fr.xephi.authme.initialization; - -import fr.xephi.authme.initialization.samples.AlphaService; -import fr.xephi.authme.initialization.samples.BetaManager; -import fr.xephi.authme.initialization.samples.ClassWithAnnotations; -import fr.xephi.authme.initialization.samples.Duration; -import fr.xephi.authme.initialization.samples.GammaService; -import fr.xephi.authme.initialization.samples.InvalidClass; -import fr.xephi.authme.initialization.samples.ProvidedClass; -import fr.xephi.authme.initialization.samples.Size; -import org.junit.Test; - -import static org.hamcrest.Matchers.arrayContaining; -import static org.hamcrest.Matchers.equalTo; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - -/** - * Test for {@link ConstructorInjection}. - */ -public class ConstructorInjectionTest { - - @SuppressWarnings("unchecked") - @Test - public void shouldReturnDependencies() { - // given - Injection injection = ConstructorInjection.provide(ClassWithAnnotations.class).get(); - - // when - Class[] dependencies = injection.getDependencies(); - Class[] annotations = injection.getDependencyAnnotations(); - - // then - assertThat(dependencies, arrayContaining(int.class, GammaService.class, long.class)); - assertThat(annotations, arrayContaining((Class) Size.class, null, Duration.class)); - } - - @Test - public void shouldInstantiate() { - // given - GammaService gammaService = new GammaService( - AlphaService.newInstance(new ProvidedClass(""))); - Injection injection = ConstructorInjection.provide(ClassWithAnnotations.class).get(); - - // when - ClassWithAnnotations instance = injection.instantiateWith(-112, gammaService, 19L); - - // then - assertThat(instance, not(nullValue())); - assertThat(instance.getSize(), equalTo(-112)); - assertThat(instance.getGammaService(), equalTo(gammaService)); - assertThat(instance.getDuration(), equalTo(19L)); - } - - @Test(expected = NullPointerException.class) - public void shouldThrowForNullValue() { - // given - Injection injection = ConstructorInjection.provide(ClassWithAnnotations.class).get(); - - // when / then - injection.instantiateWith(-112, null, 12L); - } - - @Test(expected = RuntimeException.class) - public void shouldThrowUponInstantiationError() { - // given - AlphaService alphaService = AlphaService.newInstance(new ProvidedClass("")); - Injection injection = ConstructorInjection.provide(InvalidClass.class).get(); - - // when - injection.instantiateWith(alphaService, 5); - } - - @Test - public void shouldReturnNullForNoConstructorInjection() { - // given / when - Injection injection = ConstructorInjection.provide(BetaManager.class).get(); - - // then - assertThat(injection, nullValue()); - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/FieldInjectionTest.java b/src/test/java/fr/xephi/authme/initialization/FieldInjectionTest.java deleted file mode 100644 index 89e460e5c..000000000 --- a/src/test/java/fr/xephi/authme/initialization/FieldInjectionTest.java +++ /dev/null @@ -1,132 +0,0 @@ -package fr.xephi.authme.initialization; - -import fr.xephi.authme.initialization.samples.AlphaService; -import fr.xephi.authme.initialization.samples.BadFieldInjection; -import fr.xephi.authme.initialization.samples.BetaManager; -import fr.xephi.authme.initialization.samples.ClassWithAnnotations; -import fr.xephi.authme.initialization.samples.Duration; -import fr.xephi.authme.initialization.samples.FieldInjectionWithAnnotations; -import fr.xephi.authme.initialization.samples.GammaService; -import fr.xephi.authme.initialization.samples.InvalidStaticFieldInjection; -import fr.xephi.authme.initialization.samples.ProvidedClass; -import fr.xephi.authme.initialization.samples.Size; -import org.junit.Test; - -import javax.inject.Inject; - -import static org.hamcrest.Matchers.arrayContaining; -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - -/** - * Test for {@link FieldInjection}. - */ - -public class FieldInjectionTest { - - @SuppressWarnings("unchecked") - @Test - public void shouldReturnDependencies() { - // given - FieldInjection injection = - FieldInjection.provide(FieldInjectionWithAnnotations.class).get(); - - // when - Class[] dependencies = injection.getDependencies(); - Class[] annotations = injection.getDependencyAnnotations(); - - // then - assertThat(dependencies, arrayContaining(BetaManager.class, int.class, long.class, ClassWithAnnotations.class)); - assertThat(annotations, arrayContaining((Class) null, Size.class, Duration.class, null)); - } - - @Test - public void shouldInstantiateClass() { - // given - FieldInjection injection = FieldInjection.provide(BetaManager.class).get(); - ProvidedClass providedClass = new ProvidedClass(""); - AlphaService alphaService = AlphaService.newInstance(providedClass); - GammaService gammaService = new GammaService(alphaService); - - // when - BetaManager betaManager = injection.instantiateWith(providedClass, gammaService, alphaService); - - // then - assertThat(betaManager, not(nullValue())); - assertThat(betaManager.getDependencies(), arrayContaining(providedClass, gammaService, alphaService)); - } - - @Test - public void shouldProvideNullForImpossibleFieldInjection() { - // given / when - FieldInjection injection = FieldInjection.provide(BadFieldInjection.class).get(); - - // then - assertThat(injection, nullValue()); - } - - @Test(expected = RuntimeException.class) - public void shouldForwardExceptionDuringInstantiation() { - // given - FieldInjection injection = FieldInjection.provide(ThrowingConstructor.class).get(); - - // when / when - injection.instantiateWith(new ProvidedClass("")); - } - - @Test(expected = RuntimeException.class) - public void shouldThrowForInvalidFieldValue() { - // given - ProvidedClass providedClass = new ProvidedClass(""); - AlphaService alphaService = AlphaService.newInstance(providedClass); - GammaService gammaService = new GammaService(alphaService); - FieldInjection injection = FieldInjection.provide(BetaManager.class).get(); - - // when / then - // Correct order is provided, gamma, alpha - injection.instantiateWith(providedClass, alphaService, gammaService); - } - - @Test(expected = NullPointerException.class) - public void shouldThrowForNullValue() { - // given - ProvidedClass providedClass = new ProvidedClass(""); - AlphaService alphaService = AlphaService.newInstance(providedClass); - FieldInjection injection = FieldInjection.provide(BetaManager.class).get(); - - // when / then - // Correct order is provided, gamma, alpha - injection.instantiateWith(providedClass, null, alphaService); - } - - @Test(expected = RuntimeException.class) - public void shouldThrowForStaticFieldInjection() { - // given / when / then - FieldInjection.provide(InvalidStaticFieldInjection.class).get(); - } - - @Test - public void shouldNotReturnFieldInjectionForZeroInjectFields() { - // given / when - Injection injection = FieldInjection.provide(NoInjectionClass.class).get(); - - // then - assertThat(injection, nullValue()); - } - - - @SuppressWarnings("unused") - private static class ThrowingConstructor { - @Inject - private ProvidedClass providedClass; - - public ThrowingConstructor() { - throw new UnsupportedOperationException("Exception in constructor"); - } - } - - private static class NoInjectionClass { - - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/InstantiationFallbackTest.java b/src/test/java/fr/xephi/authme/initialization/InstantiationFallbackTest.java deleted file mode 100644 index 2676c404b..000000000 --- a/src/test/java/fr/xephi/authme/initialization/InstantiationFallbackTest.java +++ /dev/null @@ -1,78 +0,0 @@ -package fr.xephi.authme.initialization; - -import fr.xephi.authme.initialization.samples.GammaService; -import fr.xephi.authme.initialization.samples.InstantiationFallbackClasses; -import org.junit.Test; - -import static org.hamcrest.Matchers.not; -import static org.hamcrest.Matchers.nullValue; -import static org.junit.Assert.assertThat; - -/** - * Test for {@link InstantiationFallback}. - */ -public class InstantiationFallbackTest { - - @Test - public void shouldInstantiateClass() { - // given - Injection instantiation = - InstantiationFallback.provide(InstantiationFallbackClasses.FallbackClass.class).get(); - - // when - InstantiationFallbackClasses.FallbackClass result = instantiation.instantiateWith(); - - // then - assertThat(result, not(nullValue())); - } - - @Test(expected = RuntimeException.class) - public void shouldThrowIfArgumentsAreSupplied() { - // given - Injection instantiation = - InstantiationFallback.provide(InstantiationFallbackClasses.FallbackClass.class).get(); - - // when / then - instantiation.instantiateWith("some argument"); - } - - @Test - public void shouldReturnNullForClassWithInjectMethod() { - // given / when - Injection instantiation = - InstantiationFallback.provide(InstantiationFallbackClasses.InvalidInjectOnMethodClass.class).get(); - - // then - assertThat(instantiation, nullValue()); - } - - @Test - public void shouldReturnNullForMissingNoArgsConstructor() { - // given / when - Injection instantiation = - InstantiationFallback.provide(InstantiationFallbackClasses.InvalidFallbackClass.class).get(); - - // then - assertThat(instantiation, nullValue()); - } - - @Test - public void shouldReturnNullForDifferentInjectionType() { - // given / when - Injection instantiation = InstantiationFallback.provide(GammaService.class).get(); - - // then - assertThat(instantiation, nullValue()); - } - - @Test - public void shouldReturnNullForClassWithPostConstruct() { - // given / when - Injection instantiation = - InstantiationFallback.provide(InstantiationFallbackClasses.ClassWithPostConstruct.class).get(); - - // then - assertThat(instantiation, nullValue()); - } - -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/AlphaService.java b/src/test/java/fr/xephi/authme/initialization/samples/AlphaService.java deleted file mode 100644 index 21dd3b32e..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/AlphaService.java +++ /dev/null @@ -1,30 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import javax.inject.Inject; - -/** - * Sample - class with dependency to ProvidedClass. - */ -public class AlphaService { - - private ProvidedClass providedClass; - - @Inject - AlphaService(ProvidedClass providedClass) { - this.providedClass = providedClass; - } - - public ProvidedClass getProvidedClass() { - return providedClass; - } - - /** - * Creates a new instance (for instantiations in tests). - * - * @param providedClass . - * @return created instance - */ - public static AlphaService newInstance(ProvidedClass providedClass) { - return new AlphaService(providedClass); - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/BadFieldInjection.java b/src/test/java/fr/xephi/authme/initialization/samples/BadFieldInjection.java deleted file mode 100644 index 7e218c4c7..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/BadFieldInjection.java +++ /dev/null @@ -1,17 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import javax.inject.Inject; - -/** - * Sample class with invalid field injection (requires default constructor). - */ -public class BadFieldInjection { - - @SuppressWarnings("unused") - @Inject - private AlphaService alphaService; - - public BadFieldInjection(BetaManager betaManager) { - throw new IllegalStateException("Should never be called"); - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/BetaManager.java b/src/test/java/fr/xephi/authme/initialization/samples/BetaManager.java deleted file mode 100644 index 8c2fe923f..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/BetaManager.java +++ /dev/null @@ -1,20 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import javax.inject.Inject; - -/** - * Sample - depends on Provided, alpha and gamma. - */ -public class BetaManager { - - @Inject - private ProvidedClass providedClass; - @Inject - private GammaService gammaService; - @Inject - private AlphaService alphaService; - - public Object[] getDependencies() { - return new Object[]{providedClass, gammaService, alphaService}; - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/CircularClasses.java b/src/test/java/fr/xephi/authme/initialization/samples/CircularClasses.java deleted file mode 100644 index dc2313e35..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/CircularClasses.java +++ /dev/null @@ -1,30 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import javax.inject.Inject; - -/** - * Classes with circular dependencies. - */ -public abstract class CircularClasses { - - public static final class Circular1 { - @Inject - public Circular1(AlphaService alphaService, Circular3 circular3) { - // -- - } - } - - public static final class Circular2 { - @Inject - public Circular2(Circular1 circular1) { - // -- - } - } - - public static final class Circular3 { - @Inject - public Circular3(Circular2 circular2, BetaManager betaManager) { - // -- - } - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/ClassWithAbstractDependency.java b/src/test/java/fr/xephi/authme/initialization/samples/ClassWithAbstractDependency.java deleted file mode 100644 index 25b651b32..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/ClassWithAbstractDependency.java +++ /dev/null @@ -1,32 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import javax.inject.Inject; - -/** - * Test with an abstract class declared as dependency. - */ -public class ClassWithAbstractDependency { - - private final AlphaService alphaService; - private final AbstractDependency abstractDependency; - - @Inject - public ClassWithAbstractDependency(AlphaService as, AbstractDependency ad) { - this.alphaService = as; - this.abstractDependency = ad; - } - - public AlphaService getAlphaService() { - return alphaService; - } - - public AbstractDependency getAbstractDependency() { - return abstractDependency; - } - - public static abstract class AbstractDependency { - } - - public static final class ConcreteDependency extends AbstractDependency { - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/ClassWithAnnotations.java b/src/test/java/fr/xephi/authme/initialization/samples/ClassWithAnnotations.java deleted file mode 100644 index 61dca71b8..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/ClassWithAnnotations.java +++ /dev/null @@ -1,29 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import javax.inject.Inject; - -public class ClassWithAnnotations { - - private int size; - private GammaService gammaService; - private long duration; - - @Inject - ClassWithAnnotations(@Size int size, GammaService gammaService, @Duration long duration) { - this.size = size; - this.gammaService = gammaService; - this.duration = duration; - } - - public int getSize() { - return size; - } - - public GammaService getGammaService() { - return gammaService; - } - - public long getDuration() { - return duration; - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/Duration.java b/src/test/java/fr/xephi/authme/initialization/samples/Duration.java deleted file mode 100644 index e61c6d28b..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/Duration.java +++ /dev/null @@ -1,14 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Sample annotation. - */ -@Target({ElementType.PARAMETER, ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface Duration { -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/FieldInjectionWithAnnotations.java b/src/test/java/fr/xephi/authme/initialization/samples/FieldInjectionWithAnnotations.java deleted file mode 100644 index 65bdf537d..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/FieldInjectionWithAnnotations.java +++ /dev/null @@ -1,40 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import javax.inject.Inject; - -/** - * Sample - field injection, including custom annotations. - */ -public class FieldInjectionWithAnnotations { - - @Inject - private BetaManager betaManager; - @Inject - @Size - private int size; - @Duration - @Inject - private long duration; - @Inject - protected ClassWithAnnotations classWithAnnotations; - - FieldInjectionWithAnnotations() { - } - - public BetaManager getBetaManager() { - return betaManager; - } - - public int getSize() { - return size; - } - - public long getDuration() { - return duration; - } - - public ClassWithAnnotations getClassWithAnnotations() { - return classWithAnnotations; - } - -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/GammaService.java b/src/test/java/fr/xephi/authme/initialization/samples/GammaService.java deleted file mode 100644 index 158187ea3..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/GammaService.java +++ /dev/null @@ -1,32 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import fr.xephi.authme.initialization.Reloadable; - -import javax.inject.Inject; - -/** - * Sample - class dependent on alpha service. - */ -public class GammaService implements Reloadable { - - private AlphaService alphaService; - private boolean wasReloaded; - - @Inject - public GammaService(AlphaService alphaService) { - this.alphaService = alphaService; - } - - public AlphaService getAlphaService() { - return alphaService; - } - - @Override - public void reload() { - wasReloaded = true; - } - - public boolean getWasReloaded() { - return wasReloaded; - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/InstantiationFallbackClasses.java b/src/test/java/fr/xephi/authme/initialization/samples/InstantiationFallbackClasses.java deleted file mode 100644 index c7fbd7e26..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/InstantiationFallbackClasses.java +++ /dev/null @@ -1,54 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import javax.annotation.PostConstruct; -import javax.inject.Inject; - -/** - * Sample class - tests various situations for the instantiation fallback. - */ -public abstract class InstantiationFallbackClasses { - - public static final class FallbackClass { - // No @Inject annotations, public no-args constructor - } - - public static final class HasFallbackDependency { - @Inject - private FallbackClass fallbackClass; - - @Inject - private GammaService gammaService; - - public GammaService getGammaService() { - return gammaService; - } - - public FallbackClass getFallbackDependency() { - return fallbackClass; - } - } - - public static final class InvalidFallbackClass { - private InvalidFallbackClass() { - // no-args constructor must be public for fallback instantiation - } - } - - public static final class InvalidInjectOnMethodClass { - // We don't support method injection but this should still be detected and an exception returned - // Only use instantiation fallback if we're sure there isn't some sort of misconfiguration - @Inject - public void setGammaService(GammaService gammaService) { - // -- - } - } - - // Class with @PostConstruct method should never be instantiated by instantiation fallback - public static final class ClassWithPostConstruct { - @PostConstruct - public void postConstructMethod() { - // -- - } - } - -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/InvalidClass.java b/src/test/java/fr/xephi/authme/initialization/samples/InvalidClass.java deleted file mode 100644 index b896af9d6..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/InvalidClass.java +++ /dev/null @@ -1,14 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import javax.inject.Inject; - -/** - * Sample - invalid class, since Integer parameter type is outside of the allowed package and not annotated. - */ -public class InvalidClass { - - @Inject - public InvalidClass(AlphaService alphaService, Integer i) { - throw new IllegalStateException("Should never be called"); - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/InvalidPostConstruct.java b/src/test/java/fr/xephi/authme/initialization/samples/InvalidPostConstruct.java deleted file mode 100644 index 1e8325495..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/InvalidPostConstruct.java +++ /dev/null @@ -1,71 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import javax.annotation.PostConstruct; -import javax.inject.Inject; - -/** - * Class with invalid @PostConstruct method. - */ - -@SuppressWarnings("unused") -public abstract class InvalidPostConstruct { - - public static final class WithParams { - @Inject - private AlphaService alphaService; - @Inject - private ProvidedClass providedClass; - - WithParams() { } - - @PostConstruct - public void invalidPostConstr(BetaManager betaManager) { - } - } - - public static final class Static { - @Inject - Static(BetaManager betaManager) { - // -- - } - - @PostConstruct - public static void invalidMethod() { - // -- - } - } - - public static final class ThrowsException { - @Inject - private ProvidedClass providedClass; - - @PostConstruct - public void throwingPostConstruct() { - throw new IllegalStateException("Exception in post construct"); - } - } - - public static final class NotVoidReturnType { - @Inject - private ProvidedClass providedClass; - - @PostConstruct - public int returnsInt() { - return 42; - } - } - - public static final class MultiplePostConstructs { - @Inject - private ProvidedClass providedClass; - - @PostConstruct - public void postConstruct1() { - // -- - } - @PostConstruct - public void postConstruct2() { - // -- - } - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/InvalidStaticFieldInjection.java b/src/test/java/fr/xephi/authme/initialization/samples/InvalidStaticFieldInjection.java deleted file mode 100644 index 83d88b0c2..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/InvalidStaticFieldInjection.java +++ /dev/null @@ -1,18 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import javax.inject.Inject; - -/** - * Sample class - attempted field injection on a static member. - */ -public class InvalidStaticFieldInjection { - - @SuppressWarnings("unused") - @Inject - private ProvidedClass providedClass; - @Inject - protected static AlphaService alphaService; - - InvalidStaticFieldInjection() { } - -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/PostConstructTestClass.java b/src/test/java/fr/xephi/authme/initialization/samples/PostConstructTestClass.java deleted file mode 100644 index b033fcc48..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/PostConstructTestClass.java +++ /dev/null @@ -1,45 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import fr.xephi.authme.initialization.SettingsDependent; -import fr.xephi.authme.settings.NewSetting; - -import javax.annotation.PostConstruct; -import javax.inject.Inject; - -/** - * Sample class for testing the execution of @PostConstruct methods. - */ -public class PostConstructTestClass implements SettingsDependent { - - @Inject - @Size - private int size; - @Inject - private BetaManager betaManager; - private boolean wasPostConstructCalled = false; - private boolean wasReloaded = false; - - @PostConstruct - public void postConstructMethod() { - wasPostConstructCalled = true; - } - - public boolean wasPostConstructCalled() { - return wasPostConstructCalled; - } - - public BetaManager getBetaManager() { - return betaManager; - } - - @Override - public void reload(NewSetting settings) { - if (settings != null) { - wasReloaded = true; - } - } - - public boolean getWasReloaded() { - return wasReloaded; - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/ProvidedClass.java b/src/test/java/fr/xephi/authme/initialization/samples/ProvidedClass.java deleted file mode 100644 index d3405abe0..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/ProvidedClass.java +++ /dev/null @@ -1,30 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import fr.xephi.authme.initialization.Reloadable; - -import javax.inject.Inject; - -/** - * Sample - class that is always provided to the initializer beforehand. - */ -public class ProvidedClass implements Reloadable { - - private boolean wasReloaded = false; - - @Inject - public ProvidedClass() { - throw new IllegalStateException("Should never be called (tests always provide this class)"); - } - - public ProvidedClass(String manualConstructor) { - } - - @Override - public void reload() { - wasReloaded = true; - } - - public boolean getWasReloaded() { - return wasReloaded; - } -} diff --git a/src/test/java/fr/xephi/authme/initialization/samples/Size.java b/src/test/java/fr/xephi/authme/initialization/samples/Size.java deleted file mode 100644 index 320a7b7c5..000000000 --- a/src/test/java/fr/xephi/authme/initialization/samples/Size.java +++ /dev/null @@ -1,14 +0,0 @@ -package fr.xephi.authme.initialization.samples; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Sample annotation. - */ -@Target({ElementType.PARAMETER, ElementType.FIELD}) -@Retention(RetentionPolicy.RUNTIME) -public @interface Size { -} diff --git a/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java b/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java index ac6171a42..b2afbe23c 100644 --- a/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java +++ b/src/test/java/fr/xephi/authme/listener/ListenerServiceTest.java @@ -1,11 +1,11 @@ package fr.xephi.authme.listener; +import ch.jalu.injector.testing.BeforeInjecting; +import ch.jalu.injector.testing.DelayedInjectionRunner; +import ch.jalu.injector.testing.InjectDelayed; import fr.xephi.authme.cache.auth.PlayerCache; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.hooks.PluginHooks; -import fr.xephi.authme.runner.BeforeInjecting; -import fr.xephi.authme.runner.InjectDelayed; -import fr.xephi.authme.runner.DelayedInjectionRunner; import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.properties.RegistrationSettings; import fr.xephi.authme.settings.properties.RestrictionSettings; diff --git a/src/test/java/fr/xephi/authme/runner/BeforeInjecting.java b/src/test/java/fr/xephi/authme/runner/BeforeInjecting.java deleted file mode 100644 index 349964af0..000000000 --- a/src/test/java/fr/xephi/authme/runner/BeforeInjecting.java +++ /dev/null @@ -1,14 +0,0 @@ -package fr.xephi.authme.runner; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Marks methods to run before {@link InjectDelayed} fields are instantiated. - */ -@Target(ElementType.METHOD) -@Retention(RetentionPolicy.RUNTIME) -public @interface BeforeInjecting { -} diff --git a/src/test/java/fr/xephi/authme/runner/DelayedInjectionRunner.java b/src/test/java/fr/xephi/authme/runner/DelayedInjectionRunner.java deleted file mode 100644 index 6d072e5f6..000000000 --- a/src/test/java/fr/xephi/authme/runner/DelayedInjectionRunner.java +++ /dev/null @@ -1,104 +0,0 @@ -package fr.xephi.authme.runner; - -import fr.xephi.authme.initialization.Injection; -import fr.xephi.authme.initialization.InjectionHelper; -import org.junit.runner.notification.RunNotifier; -import org.junit.runners.BlockJUnit4ClassRunner; -import org.junit.runners.model.FrameworkField; -import org.junit.runners.model.FrameworkMethod; -import org.junit.runners.model.InitializationError; -import org.junit.runners.model.Statement; -import org.mockito.Mock; -import org.mockito.MockitoAnnotations; - -import java.util.ArrayList; -import java.util.List; - -/** - * Custom JUnit runner which adds support for {@link InjectDelayed} and {@link BeforeInjecting}. - * This runner also initializes fields with Mockito's {@link Mock}, {@link org.mockito.Spy} and - * {@link org.mockito.InjectMocks}. - *

- * Mockito's {@link Mock} and {@link org.mockito.InjectMocks} are initialized before - * {@link org.junit.Before} methods are run. This leaves no possibility to initialize some mock - * behavior before {@link org.mockito.InjectMocks} fields get instantiated. - *

- * The runner fills this gap by introducing {@link BeforeInjecting}. At the time these methods - * are run Mockito's annotation will have taken effect but not {@link InjectDelayed}. Fields with - * this annotation are initialized after {@link BeforeInjecting} methods have been run. - *

- * Additionally, after a field annotated with {@link InjectDelayed} has been initialized, its - * {@link javax.annotation.PostConstruct} method will be invoked, if available. - *

- * Important: It is required to declare all dependencies of classes annotated with - * {@link InjectDelayed} as {@link Mock} fields. If a dependency is missing, an exception - * will be thrown. - */ -public class DelayedInjectionRunner extends BlockJUnit4ClassRunner { - - public DelayedInjectionRunner(Class clazz) throws InitializationError { - super(clazz); - } - - @Override - public Statement withBefores(FrameworkMethod method, Object target, Statement statement) { - // Initialize all Mockito annotations - MockitoAnnotations.initMocks(target); - - // Call chain normally: let parent handle @Before methods. - // Note that the chain of statements will be run from the end to the start, - // so @Before will be run AFTER our custom statements below - statement = super.withBefores(method, target, statement); - - // Add support for @BeforeInjecting and @InjectDelayed (again, reverse order) - statement = withDelayedInjects(target, statement); - return withBeforeInjectings(target, statement); - } - - @Override - public void run(final RunNotifier notifier) { - // add listener that validates framework usage at the end of each test - notifier.addListener(new DelayedInjectionRunnerValidator(notifier, getTestClass())); - super.run(notifier); - } - - /* Adds a Statement to the chain if @BeforeInjecting methods are present. */ - private Statement withBeforeInjectings(Object target, Statement statement) { - List beforeInjectings = getTestClass().getAnnotatedMethods(BeforeInjecting.class); - return beforeInjectings.isEmpty() - ? statement - : new RunBeforeInjectings(statement, beforeInjectings, target); - } - - /* - * Adds a Statement to the chain if @InjectDelayed methods are present. - * If fields have been found, the injection for the type is resolved and stored with the necessary dependencies. - */ - private Statement withDelayedInjects(Object target, Statement statement) { - List delayedFields = getTestClass().getAnnotatedFields(InjectDelayed.class); - if (delayedFields.isEmpty()) { - return statement; - } - - List pendingInjections = new ArrayList<>(delayedFields.size()); - for (FrameworkField field : delayedFields) { - pendingInjections.add(new PendingInjection(field.getField(), getInjection(field))); - } - InjectionResolver injectionResolver = new InjectionResolver(getTestClass(), target); - return new RunDelayedInjects(statement, pendingInjections, target, injectionResolver); - } - - /** - * Gets the injection method for the given field's type and ensures an injection method has been found. - * - * @param field the field to get the injection for - * @return the injection - */ - private static Injection getInjection(FrameworkField field) { - final Injection injection = InjectionHelper.getInjection(field.getType()); - if (injection == null) { - throw new IllegalStateException("No injection method available for field '" + field.getName() + "'"); - } - return injection; - } -} diff --git a/src/test/java/fr/xephi/authme/runner/DelayedInjectionRunnerValidator.java b/src/test/java/fr/xephi/authme/runner/DelayedInjectionRunnerValidator.java deleted file mode 100644 index 654dc90f9..000000000 --- a/src/test/java/fr/xephi/authme/runner/DelayedInjectionRunnerValidator.java +++ /dev/null @@ -1,36 +0,0 @@ -package fr.xephi.authme.runner; - -import org.junit.runner.Description; -import org.junit.runner.notification.Failure; -import org.junit.runner.notification.RunListener; -import org.junit.runner.notification.RunNotifier; -import org.junit.runners.model.TestClass; -import org.mockito.InjectMocks; -import org.mockito.Mockito; - -/** - * Validates that {@link DelayedInjectionRunner} is used as intended. - */ -class DelayedInjectionRunnerValidator extends RunListener { - - private final RunNotifier notifier; - private final TestClass testClass; - - public DelayedInjectionRunnerValidator(RunNotifier notifier, TestClass testClass) { - this.notifier = notifier; - this.testClass = testClass; - } - - @Override - public void testFinished(Description description) throws Exception { - try { - Mockito.validateMockitoUsage(); - if (!testClass.getAnnotatedFields(InjectMocks.class).isEmpty()) { - throw new IllegalStateException("Do not use @InjectMocks with the DelayedInjectionRunner:" + - " use @InjectDelayed or change runner"); - } - } catch (Throwable t) { - notifier.fireTestFailure(new Failure(description, t)); - } - } -} diff --git a/src/test/java/fr/xephi/authme/runner/InjectDelayed.java b/src/test/java/fr/xephi/authme/runner/InjectDelayed.java deleted file mode 100644 index b40bddb3a..000000000 --- a/src/test/java/fr/xephi/authme/runner/InjectDelayed.java +++ /dev/null @@ -1,16 +0,0 @@ -package fr.xephi.authme.runner; - -import java.lang.annotation.ElementType; -import java.lang.annotation.Retention; -import java.lang.annotation.RetentionPolicy; -import java.lang.annotation.Target; - -/** - * Marks fields to instantiate with mocks after {@link BeforeInjecting} methods. - * - * @see DelayedInjectionRunner - */ -@Target(ElementType.FIELD) -@Retention(RetentionPolicy.RUNTIME) -public @interface InjectDelayed { -} diff --git a/src/test/java/fr/xephi/authme/runner/InjectionResolver.java b/src/test/java/fr/xephi/authme/runner/InjectionResolver.java deleted file mode 100644 index 37477ee09..000000000 --- a/src/test/java/fr/xephi/authme/runner/InjectionResolver.java +++ /dev/null @@ -1,104 +0,0 @@ -package fr.xephi.authme.runner; - -import fr.xephi.authme.ReflectionTestUtils; -import fr.xephi.authme.initialization.Injection; -import fr.xephi.authme.initialization.InjectionHelper; -import org.junit.runners.model.FrameworkField; -import org.junit.runners.model.TestClass; -import org.mockito.Mock; - -import java.lang.annotation.Annotation; -import java.lang.reflect.Field; -import java.lang.reflect.Method; -import java.util.HashMap; -import java.util.List; -import java.util.Map; - -/** - * Resolves the dependencies of an injection based on the provided {@link TestClass} and {@link #target target}. - */ -class InjectionResolver { - - private final TestClass testClass; - private final Object target; - private final Map, Object> mocksByType; - - public InjectionResolver(TestClass testClass, Object target) { - this.testClass = testClass; - this.target = target; - this.mocksByType = gatherAvailableMocks(); - } - - public Object instantiate(Injection injection) { - Object[] dependencies = resolveDependencies(injection); - Object object = injection.instantiateWith(dependencies); - executePostConstructMethod(object); - return object; - } - - /** - * Returns a list of all objects for the given list of dependencies, retrieved from the given - * target's {@link Mock} fields. - * - * @param injection the injection whose dependencies to gather - * @return the resolved dependencies - */ - private Object[] resolveDependencies(Injection injection) { - final Class[] dependencies = injection.getDependencies(); - final Class[] annotations = injection.getDependencyAnnotations(); - Object[] resolvedValues = new Object[dependencies.length]; - for (int i = 0; i < dependencies.length; ++i) { - Object dependency = (annotations[i] == null) - ? resolveDependency(dependencies[i]) - : resolveAnnotation(annotations[i]); - resolvedValues[i] = dependency; - } - return resolvedValues; - } - - private Object resolveDependency(Class clazz) { - Object o = mocksByType.get(clazz); - if (o == null) { - throw new IllegalStateException("No mock found for '" + clazz + "'. " - + "All dependencies of @InjectDelayed must be provided as @Mock fields"); - } - return o; - } - - private Object resolveAnnotation(Class clazz) { - Class annotation = (Class) clazz; - List matches = testClass.getAnnotatedFields(annotation); - if (matches.isEmpty()) { - throw new IllegalStateException("No field found with @" + annotation.getSimpleName() + " in test class," - + "but a dependency in an @InjectDelayed field is using it"); - } else if (matches.size() > 1) { - throw new IllegalStateException("You cannot have multiple fields with @" + annotation.getSimpleName()); - } - return ReflectionTestUtils.getFieldValue(matches.get(0).getField(), target); - } - - /** - * Executes the class' PostConstruct method if available. Validates that all rules for - * {@link javax.annotation.PostConstruct} are met. - * - * @param object the object whose PostConstruct method should be run, if available - * @see InjectionHelper#getAndValidatePostConstructMethod - */ - private static void executePostConstructMethod(Object object) { - Method postConstructMethod = InjectionHelper.getAndValidatePostConstructMethod(object.getClass()); - if (postConstructMethod != null) { - ReflectionTestUtils.invokeMethod(postConstructMethod, object); - } - } - - private Map, Object> gatherAvailableMocks() { - List availableMocks = testClass.getAnnotatedFields(Mock.class); - Map, Object> mocksByType = new HashMap<>(); - for (FrameworkField frameworkField : availableMocks) { - Field field = frameworkField.getField(); - Object fieldValue = ReflectionTestUtils.getFieldValue(field, target); - mocksByType.put(field.getType(), fieldValue); - } - return mocksByType; - } -} diff --git a/src/test/java/fr/xephi/authme/runner/PendingInjection.java b/src/test/java/fr/xephi/authme/runner/PendingInjection.java deleted file mode 100644 index 25d33f473..000000000 --- a/src/test/java/fr/xephi/authme/runner/PendingInjection.java +++ /dev/null @@ -1,38 +0,0 @@ -package fr.xephi.authme.runner; - -import fr.xephi.authme.initialization.Injection; - -import java.lang.reflect.Field; - -/** - * Contains an injection and the field it's for. - */ -class PendingInjection { - - private final Field field; - private final Injection injection; - - public PendingInjection(Field field, Injection injection) { - this.field = field; - this.injection = injection; - } - - /** - * Returns the injection to perform. - * - * @return the injection - */ - public Injection getInjection() { - return injection; - } - - /** - * Returns the field the constructed object should be assigned to. - * - * @return the field in the test class - */ - public Field getField() { - return field; - } - -} diff --git a/src/test/java/fr/xephi/authme/runner/RunBeforeInjectings.java b/src/test/java/fr/xephi/authme/runner/RunBeforeInjectings.java deleted file mode 100644 index 7a6ba70b8..000000000 --- a/src/test/java/fr/xephi/authme/runner/RunBeforeInjectings.java +++ /dev/null @@ -1,33 +0,0 @@ -package fr.xephi.authme.runner; - -import fr.xephi.authme.ReflectionTestUtils; -import org.junit.runners.model.FrameworkMethod; -import org.junit.runners.model.Statement; - -import java.util.List; - -/** - * Statement for running {@link BeforeInjecting} methods. Such methods are run - * after Mockito's @Mock, @Spy and @InjectMocks have taken effect, - * but before {@link InjectDelayed} fields are handled. - */ -class RunBeforeInjectings extends Statement { - - private final Statement next; - private final List beforeInjectings; - private final Object target; - - public RunBeforeInjectings(Statement next, List beforeInjectings, Object target) { - this.next = next; - this.beforeInjectings = beforeInjectings; - this.target = target; - } - - @Override - public void evaluate() throws Throwable { - for (FrameworkMethod method : beforeInjectings) { - ReflectionTestUtils.invokeMethod(method.getMethod(), target); - } - next.evaluate(); - } -} diff --git a/src/test/java/fr/xephi/authme/runner/RunDelayedInjects.java b/src/test/java/fr/xephi/authme/runner/RunDelayedInjects.java deleted file mode 100644 index b59d71588..000000000 --- a/src/test/java/fr/xephi/authme/runner/RunDelayedInjects.java +++ /dev/null @@ -1,40 +0,0 @@ -package fr.xephi.authme.runner; - -import fr.xephi.authme.ReflectionTestUtils; -import org.junit.runners.model.Statement; - -import java.util.List; - -/** - * Statement for initializing {@link InjectDelayed} fields. These fields are - * constructed after {@link BeforeInjecting} and before JUnit's @Before. - */ -class RunDelayedInjects extends Statement { - - private final Statement next; - private final Object target; - private List pendingInjections; - private InjectionResolver injectionResolver; - - public RunDelayedInjects(Statement next, List pendingInjections, Object target, - InjectionResolver injectionResolver) { - this.next = next; - this.pendingInjections = pendingInjections; - this.target = target; - this.injectionResolver = injectionResolver; - } - - @Override - public void evaluate() throws Throwable { - for (PendingInjection pendingInjection : pendingInjections) { - if (ReflectionTestUtils.getFieldValue(pendingInjection.getField(), target) != null) { - throw new IllegalStateException("Field with @InjectDelayed must be null on startup"); - } - Object object = injectionResolver.instantiate(pendingInjection.getInjection()); - ReflectionTestUtils.setField(pendingInjection.getField(), target, object); - } - this.pendingInjections = null; - this.injectionResolver = null; - next.evaluate(); - } -} diff --git a/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java b/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java index 9f875a001..ea4cecc1a 100644 --- a/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java +++ b/src/test/java/fr/xephi/authme/security/HashAlgorithmIntegrationTest.java @@ -1,6 +1,7 @@ package fr.xephi.authme.security; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; +import ch.jalu.injector.Injector; +import ch.jalu.injector.InjectorBuilder; import fr.xephi.authme.security.crypts.EncryptionMethod; import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.settings.NewSetting; @@ -24,15 +25,15 @@ import static org.mockito.Mockito.mock; */ public class HashAlgorithmIntegrationTest { - private static AuthMeServiceInitializer initializer; + private static Injector injector; @BeforeClass public static void setUpConfigAndInjector() { NewSetting settings = mock(NewSetting.class); given(settings.getProperty(HooksSettings.BCRYPT_LOG2_ROUND)).willReturn(8); given(settings.getProperty(SecuritySettings.DOUBLE_MD5_SALT_LENGTH)).willReturn(16); - initializer = new AuthMeServiceInitializer(); - initializer.register(NewSetting.class, settings); + injector = new InjectorBuilder().addDefaultHandlers("fr.xephi.authme").create(); + injector.register(NewSetting.class, settings); } @Test @@ -55,7 +56,7 @@ public class HashAlgorithmIntegrationTest { // given / when / then for (HashAlgorithm algorithm : HashAlgorithm.values()) { if (!HashAlgorithm.CUSTOM.equals(algorithm) && !HashAlgorithm.PLAINTEXT.equals(algorithm)) { - EncryptionMethod method = initializer.newInstance(algorithm.getClazz()); + EncryptionMethod method = injector.newInstance(algorithm.getClazz()); HashedPassword hashedPassword = method.computeHash("pwd", "name"); assertThat("Salt should not be null if method.hasSeparateSalt(), and vice versa. Method: '" + method + "'", StringUtils.isEmpty(hashedPassword.getSalt()), equalTo(!method.hasSeparateSalt())); diff --git a/src/test/java/fr/xephi/authme/security/PasswordSecurityTest.java b/src/test/java/fr/xephi/authme/security/PasswordSecurityTest.java index e98f23771..28e6c946e 100644 --- a/src/test/java/fr/xephi/authme/security/PasswordSecurityTest.java +++ b/src/test/java/fr/xephi/authme/security/PasswordSecurityTest.java @@ -1,10 +1,11 @@ package fr.xephi.authme.security; +import ch.jalu.injector.Injector; +import ch.jalu.injector.InjectorBuilder; import fr.xephi.authme.ReflectionTestUtils; import fr.xephi.authme.TestHelper; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.events.PasswordEncryptionEvent; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; import fr.xephi.authme.security.crypts.EncryptionMethod; import fr.xephi.authme.security.crypts.HashedPassword; import fr.xephi.authme.security.crypts.JOOMLA; @@ -41,7 +42,7 @@ import static org.mockito.Mockito.verify; @RunWith(MockitoJUnitRunner.class) public class PasswordSecurityTest { - private AuthMeServiceInitializer initializer; + private Injector injector; @Mock private NewSetting settings; @@ -79,10 +80,10 @@ public class PasswordSecurityTest { return null; } }).when(pluginManager).callEvent(any(Event.class)); - initializer = new AuthMeServiceInitializer(); - initializer.register(NewSetting.class, settings); - initializer.register(DataSource.class, dataSource); - initializer.register(PluginManager.class, pluginManager); + injector = new InjectorBuilder().addDefaultHandlers("!! impossible package !!").create(); + injector.register(NewSetting.class, settings); + injector.register(DataSource.class, dataSource); + injector.register(PluginManager.class, pluginManager); } @Test @@ -97,7 +98,7 @@ public class PasswordSecurityTest { given(dataSource.getPassword(playerName)).willReturn(password); given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(true); initSettings(HashAlgorithm.BCRYPT, false); - PasswordSecurity security = initializer.newInstance(PasswordSecurity.class); + PasswordSecurity security = injector.newInstance(PasswordSecurity.class); // when boolean result = security.comparePassword(clearTextPass, playerName); @@ -120,7 +121,7 @@ public class PasswordSecurityTest { given(dataSource.getPassword(playerName)).willReturn(password); given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(false); initSettings(HashAlgorithm.CUSTOM, false); - PasswordSecurity security = initializer.newInstance(PasswordSecurity.class); + PasswordSecurity security = injector.newInstance(PasswordSecurity.class); // when boolean result = security.comparePassword(clearTextPass, playerName); @@ -140,7 +141,7 @@ public class PasswordSecurityTest { given(dataSource.getPassword(playerName)).willReturn(null); initSettings(HashAlgorithm.MD5, false); - PasswordSecurity security = initializer.newInstance(PasswordSecurity.class); + PasswordSecurity security = injector.newInstance(PasswordSecurity.class); // when boolean result = security.comparePassword(clearTextPass, playerName); @@ -168,7 +169,7 @@ public class PasswordSecurityTest { given(method.comparePassword(clearTextPass, password, playerLowerCase)).willReturn(false); given(method.computeHash(clearTextPass, playerLowerCase)).willReturn(newPassword); initSettings(HashAlgorithm.MD5, true); - PasswordSecurity security = initializer.newInstance(PasswordSecurity.class); + PasswordSecurity security = injector.newInstance(PasswordSecurity.class); // when boolean result = security.comparePassword(clearTextPass, playerName); @@ -193,7 +194,7 @@ public class PasswordSecurityTest { given(dataSource.getPassword(playerName)).willReturn(password); given(method.comparePassword(clearTextPass, password, playerName)).willReturn(false); initSettings(HashAlgorithm.MD5, true); - PasswordSecurity security = initializer.newInstance(PasswordSecurity.class); + PasswordSecurity security = injector.newInstance(PasswordSecurity.class); // when boolean result = security.comparePassword(clearTextPass, playerName); @@ -212,7 +213,7 @@ public class PasswordSecurityTest { HashedPassword hashedPassword = new HashedPassword("$T$est#Hash", "__someSalt__"); given(method.computeHash(password, usernameLowerCase)).willReturn(hashedPassword); initSettings(HashAlgorithm.JOOMLA, true); - PasswordSecurity security = initializer.newInstance(PasswordSecurity.class); + PasswordSecurity security = injector.newInstance(PasswordSecurity.class); // when HashedPassword result = security.computeHash(password, username); @@ -235,7 +236,7 @@ public class PasswordSecurityTest { given(method.computeHash(password, username)).willReturn(hashedPassword); given(method.hasSeparateSalt()).willReturn(true); initSettings(HashAlgorithm.XAUTH, false); - PasswordSecurity security = initializer.newInstance(PasswordSecurity.class); + PasswordSecurity security = injector.newInstance(PasswordSecurity.class); // when boolean result = security.comparePassword(password, hashedPassword, username); @@ -251,7 +252,7 @@ public class PasswordSecurityTest { public void shouldReloadSettings() { // given initSettings(HashAlgorithm.BCRYPT, false); - PasswordSecurity passwordSecurity = initializer.newInstance(PasswordSecurity.class); + PasswordSecurity passwordSecurity = injector.newInstance(PasswordSecurity.class); given(settings.getProperty(SecuritySettings.PASSWORD_HASH)).willReturn(HashAlgorithm.MD5); given(settings.getProperty(SecuritySettings.SUPPORT_OLD_PASSWORD_HASH)).willReturn(true); diff --git a/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java b/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java index 941c30f18..86e75c546 100644 --- a/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java +++ b/src/test/java/fr/xephi/authme/settings/SpawnLoaderTest.java @@ -1,13 +1,13 @@ package fr.xephi.authme.settings; +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.datasource.DataSource; import fr.xephi.authme.hooks.PluginHooks; import fr.xephi.authme.initialization.DataFolder; -import fr.xephi.authme.runner.BeforeInjecting; -import fr.xephi.authme.runner.DelayedInjectionRunner; -import fr.xephi.authme.runner.InjectDelayed; import fr.xephi.authme.settings.properties.RestrictionSettings; import org.bukkit.Location; import org.bukkit.World; diff --git a/src/test/java/fr/xephi/authme/util/ValidationServiceTest.java b/src/test/java/fr/xephi/authme/util/ValidationServiceTest.java index ddfc9c161..9b7d34f0d 100644 --- a/src/test/java/fr/xephi/authme/util/ValidationServiceTest.java +++ b/src/test/java/fr/xephi/authme/util/ValidationServiceTest.java @@ -1,13 +1,13 @@ package fr.xephi.authme.util; +import ch.jalu.injector.testing.BeforeInjecting; +import ch.jalu.injector.testing.DelayedInjectionRunner; +import ch.jalu.injector.testing.InjectDelayed; import com.google.common.base.Strings; import fr.xephi.authme.datasource.DataSource; import fr.xephi.authme.output.MessageKey; import fr.xephi.authme.permission.PermissionsManager; import fr.xephi.authme.permission.PlayerStatePermission; -import fr.xephi.authme.runner.BeforeInjecting; -import fr.xephi.authme.runner.DelayedInjectionRunner; -import fr.xephi.authme.runner.InjectDelayed; import fr.xephi.authme.settings.NewSetting; import fr.xephi.authme.settings.properties.EmailSettings; import fr.xephi.authme.settings.properties.RestrictionSettings; diff --git a/src/test/java/tools/checktestmocks/CheckTestMocks.java b/src/test/java/tools/checktestmocks/CheckTestMocks.java index dd6affc92..e27fe7df9 100644 --- a/src/test/java/tools/checktestmocks/CheckTestMocks.java +++ b/src/test/java/tools/checktestmocks/CheckTestMocks.java @@ -141,7 +141,7 @@ public class CheckTestMocks implements AutoToolTask { Injection injection = InjectionHelper.getInjection(realClass); return injection == null ? Collections.>emptySet() - : Sets.newHashSet(injection.getDependencies()); + : Sets.>newHashSet(injection.getDependencies()); } private static boolean isTestClassWithMocks(Class clazz) { diff --git a/src/test/java/tools/hashmethods/EncryptionMethodInfoGatherer.java b/src/test/java/tools/hashmethods/EncryptionMethodInfoGatherer.java index 26af6f829..51d7c38d8 100644 --- a/src/test/java/tools/hashmethods/EncryptionMethodInfoGatherer.java +++ b/src/test/java/tools/hashmethods/EncryptionMethodInfoGatherer.java @@ -1,6 +1,7 @@ package tools.hashmethods; -import fr.xephi.authme.initialization.AuthMeServiceInitializer; +import ch.jalu.injector.Injector; +import ch.jalu.injector.InjectorBuilder; import fr.xephi.authme.security.HashAlgorithm; import fr.xephi.authme.security.crypts.EncryptionMethod; import fr.xephi.authme.security.crypts.HexSaltedMethod; @@ -33,7 +34,7 @@ public class EncryptionMethodInfoGatherer { private final static Set> RELEVANT_ANNOTATIONS = newHashSet(HasSalt.class, Recommendation.class, AsciiRestricted.class); - private static AuthMeServiceInitializer initializer = createInitializer(); + private static Injector injector = createInitializer(); private Map descriptions; @@ -57,7 +58,7 @@ public class EncryptionMethodInfoGatherer { private static MethodDescription createDescription(HashAlgorithm algorithm) { Class clazz = algorithm.getClazz(); - EncryptionMethod method = initializer.newInstance(clazz); + EncryptionMethod method = injector.newInstance(clazz); if (method == null) { throw new NullPointerException("Method for '" + algorithm + "' is null"); } @@ -138,7 +139,7 @@ public class EncryptionMethodInfoGatherer { } @SuppressWarnings("unchecked") - private static AuthMeServiceInitializer createInitializer() { + private static Injector createInitializer() { NewSetting settings = mock(NewSetting.class); // Return the default value for any property when(settings.getProperty(any(Property.class))).thenAnswer(new Answer() { @@ -149,11 +150,11 @@ public class EncryptionMethodInfoGatherer { } }); - // By not passing any "allowed package" to the constructor, the initializer will throw if it needs to + // By passing some bogus "package" to the constructor, the injector will throw if it needs to // instantiate any dependency other than what we provide. - AuthMeServiceInitializer initializer = new AuthMeServiceInitializer(); - initializer.register(NewSetting.class, settings); - return initializer; + Injector injector = new InjectorBuilder().addDefaultHandlers("!!No package!!").create(); + injector.register(NewSetting.class, settings); + return injector; } } diff --git a/team.txt b/team.txt index 0d0f7f9bc..799d98023 100644 --- a/team.txt +++ b/team.txt @@ -1,14 +1,16 @@ AuthMe-Team: Active staff: -Xephi (Xephi59) - Leader, Main developer +ljacqu - Main Developer DNx5 - Developer -ljacqu - Developer TimVisee - Developer games647 - Developer Gnat008 - Developer Gabriele C. (sgdc3) - Project Manager, Contributor +Inactive staff: +Xephi (Xephi59) - Original developer + Retired staff: Maxetto - Ticket Manager, IT translator darkwarriors (d4rkwarriors) - Original AuthMeReloaded Author (Inactive)