arguments) {
@@ -52,7 +52,7 @@ public class ConverterCommand implements ExecutableCommand {
}
// Get the proper converter instance
- final Converter converter = injector.newInstance(converterClass);
+ final Converter converter = converterFactory.newInstance(converterClass);
// Run the convert job
bukkitService.runTaskAsynchronously(new Runnable() {
diff --git a/src/main/java/fr/xephi/authme/initialization/factory/Factory.java b/src/main/java/fr/xephi/authme/initialization/factory/Factory.java
new file mode 100644
index 00000000..0f4ae62a
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/initialization/factory/Factory.java
@@ -0,0 +1,19 @@
+package fr.xephi.authme.initialization.factory;
+
+/**
+ * Injectable factory that creates new instances of a certain type.
+ *
+ * @param the parent type to which the factory is limited to
+ */
+public interface Factory
{
+
+ /**
+ * Creates an instance of the given class.
+ *
+ * @param clazz the class to instantiate
+ * @param the class type
+ * @return new instance of the class
+ */
+ C newInstance(Class clazz);
+
+}
diff --git a/src/main/java/fr/xephi/authme/initialization/factory/FactoryDependencyHandler.java b/src/main/java/fr/xephi/authme/initialization/factory/FactoryDependencyHandler.java
new file mode 100644
index 00000000..04c11c68
--- /dev/null
+++ b/src/main/java/fr/xephi/authme/initialization/factory/FactoryDependencyHandler.java
@@ -0,0 +1,46 @@
+package fr.xephi.authme.initialization.factory;
+
+import ch.jalu.injector.Injector;
+import ch.jalu.injector.context.ResolvedInstantiationContext;
+import ch.jalu.injector.handlers.dependency.DependencyHandler;
+import ch.jalu.injector.handlers.instantiation.DependencyDescription;
+import ch.jalu.injector.utils.ReflectionUtils;
+
+/**
+ * Dependency handler that builds {@link Factory} objects.
+ */
+public class FactoryDependencyHandler implements DependencyHandler {
+
+ @Override
+ public Object resolveValue(ResolvedInstantiationContext> context, DependencyDescription dependencyDescription) {
+ if (dependencyDescription.getType() == Factory.class) {
+ Class> genericType = ReflectionUtils.getGenericType(dependencyDescription.getGenericType());
+ if (genericType == null) {
+ throw new IllegalStateException("Factory fields must have concrete generic type. " +
+ "Cannot get generic type for field in '" + context.getMappedClass() + "'");
+ }
+
+ return new FactoryImpl<>(genericType, context.getInjector());
+ }
+ return null;
+ }
+
+ private static final class FactoryImpl implements Factory
{
+
+ private final Injector injector;
+ private final Class
parentClass;
+
+ FactoryImpl(Class
parentClass, Injector injector) {
+ this.parentClass = parentClass;
+ this.injector = injector;
+ }
+
+ @Override
+ public C newInstance(Class clazz) {
+ if (parentClass.isAssignableFrom(clazz)) {
+ return injector.newInstance(clazz);
+ }
+ throw new IllegalArgumentException(clazz + " not child of " + parentClass);
+ }
+ }
+}
diff --git a/src/main/java/fr/xephi/authme/security/PasswordSecurity.java b/src/main/java/fr/xephi/authme/security/PasswordSecurity.java
index 8549b388..d2947108 100644
--- a/src/main/java/fr/xephi/authme/security/PasswordSecurity.java
+++ b/src/main/java/fr/xephi/authme/security/PasswordSecurity.java
@@ -1,9 +1,9 @@
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.Reloadable;
+import fr.xephi.authme.initialization.factory.Factory;
import fr.xephi.authme.security.crypts.EncryptionMethod;
import fr.xephi.authme.security.crypts.HashedPassword;
import fr.xephi.authme.settings.Settings;
@@ -29,7 +29,7 @@ public class PasswordSecurity implements Reloadable {
private PluginManager pluginManager;
@Inject
- private Injector injector;
+ private Factory hashAlgorithmFactory;
private HashAlgorithm algorithm;
private Collection legacyAlgorithms;
@@ -154,7 +154,7 @@ public class PasswordSecurity implements Reloadable {
if (HashAlgorithm.CUSTOM.equals(algorithm) || HashAlgorithm.PLAINTEXT.equals(algorithm)) {
return null;
}
- return injector.newInstance(algorithm.getClazz());
+ return hashAlgorithmFactory.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 aae925b5..89132fcf 100644
--- a/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java
+++ b/src/test/java/fr/xephi/authme/AuthMeInitializationTest.java
@@ -8,6 +8,7 @@ import fr.xephi.authme.api.NewAPI;
import fr.xephi.authme.command.CommandHandler;
import fr.xephi.authme.datasource.DataSource;
import fr.xephi.authme.initialization.DataFolder;
+import fr.xephi.authme.initialization.factory.FactoryDependencyHandler;
import fr.xephi.authme.listener.BlockListener;
import fr.xephi.authme.permission.PermissionsManager;
import fr.xephi.authme.process.Management;
@@ -91,7 +92,10 @@ public class AuthMeInitializationTest {
Settings settings =
new Settings(dataFolder, mock(PropertyResource.class), null, buildConfigurationData());
- Injector injector = new InjectorBuilder().addDefaultHandlers("fr.xephi.authme").create();
+ Injector injector = new InjectorBuilder()
+ .addHandlers(new FactoryDependencyHandler())
+ .addDefaultHandlers("fr.xephi.authme")
+ .create();
injector.provide(DataFolder.class, dataFolder);
injector.register(Server.class, server);
injector.register(PluginManager.class, pluginManager);
diff --git a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java
index 1166cef2..e343199f 100644
--- a/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java
+++ b/src/test/java/fr/xephi/authme/command/CommandHandlerTest.java
@@ -6,6 +6,7 @@ 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.factory.Factory;
import fr.xephi.authme.message.MessageKey;
import fr.xephi.authme.message.Messages;
import fr.xephi.authme.permission.PermissionsManager;
@@ -56,7 +57,7 @@ public class CommandHandlerTest {
private CommandHandler handler;
@Mock
- private Injector injector;
+ private Factory commandFactory;
@Mock
private CommandMapper commandMapper;
@Mock
@@ -75,7 +76,7 @@ public class CommandHandlerTest {
ExecutableCommand.class, TestLoginCommand.class, TestRegisterCommand.class, TestUnregisterCommand.class));
setInjectorToMockExecutableCommandClasses();
- handler = new CommandHandler(injector, commandMapper, permissionsManager, messages, helpProvider);
+ handler = new CommandHandler(commandFactory, commandMapper, permissionsManager, messages, helpProvider);
}
/**
@@ -86,7 +87,7 @@ public class CommandHandlerTest {
*/
@SuppressWarnings("unchecked")
private void setInjectorToMockExecutableCommandClasses() {
- given(injector.newInstance(any(Class.class))).willAnswer(new Answer