mirror of
https://github.com/AuthMe/AuthMeReloaded.git
synced 2024-11-23 02:35:11 +01:00
Service injector - implement stricter requirements for PostConstruct methods
- Implement similar restrictions as prescribed by the PostConstruct documentation: - Class may have at most one method annotated with PostConstruct - PostConstruct method must return void - Javadoc: replace mentions of injector construction where any injection method was meant
This commit is contained in:
parent
383820cd22
commit
f014485789
@ -144,8 +144,8 @@ public class AuthMeServiceInitializer {
|
|||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Instantiates the given class by locating an @Inject constructor and retrieving
|
* Instantiates the given class by locating its @Inject elements and retrieving
|
||||||
* or instantiating its parameters.
|
* or instantiating the required instances.
|
||||||
*
|
*
|
||||||
* @param clazz the class to instantiate
|
* @param clazz the class to instantiate
|
||||||
* @param traversedClasses collection of classes already traversed
|
* @param traversedClasses collection of classes already traversed
|
||||||
@ -164,13 +164,13 @@ public class AuthMeServiceInitializer {
|
|||||||
validateInjectionHasNoCircularDependencies(injection.getDependencies(), traversedClasses);
|
validateInjectionHasNoCircularDependencies(injection.getDependencies(), traversedClasses);
|
||||||
Object[] dependencies = resolveDependencies(injection, traversedClasses);
|
Object[] dependencies = resolveDependencies(injection, traversedClasses);
|
||||||
T object = injection.instantiateWith(dependencies);
|
T object = injection.instantiateWith(dependencies);
|
||||||
executePostConstructMethods(object);
|
executePostConstructMethod(object);
|
||||||
return object;
|
return object;
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Resolves the dependencies for the given constructor, i.e. returns a collection that satisfy
|
* Resolves the dependencies for the given class instantiation, i.e. returns a collection that satisfy
|
||||||
* the constructor's parameter types by retrieving elements or instantiating them where necessary.
|
* the class' dependencies by retrieving elements or instantiating them where necessary.
|
||||||
*
|
*
|
||||||
* @param injection the injection parameters
|
* @param injection the injection parameters
|
||||||
* @param traversedClasses collection of traversed classes
|
* @param traversedClasses collection of traversed classes
|
||||||
@ -247,22 +247,21 @@ public class AuthMeServiceInitializer {
|
|||||||
+ "allowed packages. It must be provided explicitly or the package must be passed to the constructor.");
|
+ "allowed packages. It must be provided explicitly or the package must be passed to the constructor.");
|
||||||
}
|
}
|
||||||
|
|
||||||
private static void executePostConstructMethods(Object object) {
|
/**
|
||||||
for (Method method : object.getClass().getDeclaredMethods()) {
|
* Executes an object's method annotated with {@link PostConstruct} if present.
|
||||||
if (method.isAnnotationPresent(PostConstruct.class)) {
|
* Throws an exception if there are multiple such methods, or if the method is static.
|
||||||
if (method.getParameterTypes().length == 0 && !Modifier.isStatic(method.getModifiers())) {
|
*
|
||||||
|
* @param object the object to execute the post construct method for
|
||||||
|
*/
|
||||||
|
private static void executePostConstructMethod(Object object) {
|
||||||
|
Method postConstructMethod = getAndValidatePostConstructMethod(object.getClass());
|
||||||
|
if (postConstructMethod != null) {
|
||||||
try {
|
try {
|
||||||
method.setAccessible(true);
|
postConstructMethod.setAccessible(true);
|
||||||
method.invoke(object);
|
postConstructMethod.invoke(object);
|
||||||
} catch (IllegalAccessException | InvocationTargetException e) {
|
} catch (IllegalAccessException | InvocationTargetException e) {
|
||||||
throw new UnsupportedOperationException(e);
|
throw new UnsupportedOperationException(e);
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
throw new IllegalStateException(String.format("@PostConstruct methods may not be static or have "
|
|
||||||
+ " any parameters. Method '%s' of class '%s' is either static or has parameters",
|
|
||||||
method.getName(), object.getClass().getSimpleName()));
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -272,6 +271,31 @@ public class AuthMeServiceInitializer {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Validate and locate the given class' post construct method. Returns {@code null} if none present.
|
||||||
|
*
|
||||||
|
* @param clazz the class to search
|
||||||
|
* @return post construct method, or null
|
||||||
|
*/
|
||||||
|
private static Method getAndValidatePostConstructMethod(Class<?> clazz) {
|
||||||
|
Method postConstructMethod = null;
|
||||||
|
for (Method method : clazz.getDeclaredMethods()) {
|
||||||
|
if (method.isAnnotationPresent(PostConstruct.class)) {
|
||||||
|
if (postConstructMethod != null) {
|
||||||
|
throw new IllegalStateException("Multiple methods with @PostConstruct on " + clazz);
|
||||||
|
} else if (method.getParameterTypes().length > 0 || Modifier.isStatic(method.getModifiers())) {
|
||||||
|
throw new IllegalStateException("@PostConstruct method may not be static or have any parameters. "
|
||||||
|
+ "Invalid method in " + clazz);
|
||||||
|
} else if (method.getReturnType() != void.class) {
|
||||||
|
throw new IllegalStateException("@PostConstruct method must be void. Offending class: " + clazz);
|
||||||
|
} else {
|
||||||
|
postConstructMethod = method;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return postConstructMethod;
|
||||||
|
}
|
||||||
|
|
||||||
@SafeVarargs
|
@SafeVarargs
|
||||||
private static <T> Injection<T> firstNotNull(Provider<? extends Injection<T>>... providers) {
|
private static <T> Injection<T> firstNotNull(Provider<? extends Injection<T>>... providers) {
|
||||||
for (Provider<? extends Injection<T>> provider : providers) {
|
for (Provider<? extends Injection<T>> provider : providers) {
|
||||||
|
@ -96,11 +96,9 @@ public class PermissionsManager implements PermissionsService {
|
|||||||
|
|
||||||
/**
|
/**
|
||||||
* Setup and hook into the permissions systems.
|
* Setup and hook into the permissions systems.
|
||||||
*
|
|
||||||
* @return The detected permissions system.
|
|
||||||
*/
|
*/
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
public PermissionsSystemType setup() {
|
public void setup() {
|
||||||
// Force-unhook from current hooked permissions systems
|
// Force-unhook from current hooked permissions systems
|
||||||
unhook();
|
unhook();
|
||||||
|
|
||||||
@ -177,7 +175,7 @@ public class PermissionsManager implements PermissionsService {
|
|||||||
ConsoleLogger.info("Hooked into " + type.getName() + "!");
|
ConsoleLogger.info("Hooked into " + type.getName() + "!");
|
||||||
|
|
||||||
// Return the used permissions system type
|
// Return the used permissions system type
|
||||||
return type;
|
return;
|
||||||
|
|
||||||
} catch (Exception ex) {
|
} catch (Exception ex) {
|
||||||
// An error occurred, show a warning message
|
// An error occurred, show a warning message
|
||||||
@ -187,7 +185,6 @@ public class PermissionsManager implements PermissionsService {
|
|||||||
|
|
||||||
// No recognized permissions system found, show a message and return
|
// No recognized permissions system found, show a message and return
|
||||||
ConsoleLogger.info("No supported permissions system found! Permissions are disabled!");
|
ConsoleLogger.info("No supported permissions system found! Permissions are disabled!");
|
||||||
return null;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -166,7 +166,7 @@ public class AuthMeServiceInitializerTest {
|
|||||||
PostConstructTestClass testClass = initializer.get(PostConstructTestClass.class);
|
PostConstructTestClass testClass = initializer.get(PostConstructTestClass.class);
|
||||||
|
|
||||||
// then
|
// then
|
||||||
assertThat(testClass.werePostConstructsCalled(), equalTo(true));
|
assertThat(testClass.wasPostConstructCalled(), equalTo(true));
|
||||||
assertThat(testClass.getBetaManager(), not(nullValue()));
|
assertThat(testClass.getBetaManager(), not(nullValue()));
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -188,6 +188,18 @@ public class AuthMeServiceInitializerTest {
|
|||||||
initializer.get(InvalidPostConstruct.ThrowsException.class);
|
initializer.get(InvalidPostConstruct.ThrowsException.class);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@Test(expected = RuntimeException.class)
|
||||||
|
public void shouldThrowForMultiplePostConstructMethods() {
|
||||||
|
// given / when / then
|
||||||
|
initializer.get(InvalidPostConstruct.MultiplePostConstructs.class);
|
||||||
|
}
|
||||||
|
|
||||||
|
@Test(expected = RuntimeException.class)
|
||||||
|
public void shouldThrowForPostConstructNotReturningVoid() {
|
||||||
|
// given / when / then
|
||||||
|
initializer.get(InvalidPostConstruct.NotVoidReturnType.class);
|
||||||
|
}
|
||||||
|
|
||||||
@Test(expected = RuntimeException.class)
|
@Test(expected = RuntimeException.class)
|
||||||
public void shouldThrowForAbstractNonRegisteredDependency() {
|
public void shouldThrowForAbstractNonRegisteredDependency() {
|
||||||
// given / when / then
|
// given / when / then
|
||||||
|
@ -9,10 +9,8 @@ import javax.inject.Inject;
|
|||||||
public abstract class InvalidPostConstruct {
|
public abstract class InvalidPostConstruct {
|
||||||
|
|
||||||
public static final class WithParams {
|
public static final class WithParams {
|
||||||
@SuppressWarnings("unused")
|
|
||||||
@Inject
|
@Inject
|
||||||
private AlphaService alphaService;
|
private AlphaService alphaService;
|
||||||
@SuppressWarnings("unused")
|
|
||||||
@Inject
|
@Inject
|
||||||
private ProvidedClass providedClass;
|
private ProvidedClass providedClass;
|
||||||
|
|
||||||
@ -41,4 +39,28 @@ public abstract class InvalidPostConstruct {
|
|||||||
throw new IllegalStateException("Exception in post construct");
|
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() {
|
||||||
|
// --
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
@ -17,22 +17,15 @@ public class PostConstructTestClass implements SettingsDependent {
|
|||||||
@Inject
|
@Inject
|
||||||
private BetaManager betaManager;
|
private BetaManager betaManager;
|
||||||
private boolean wasPostConstructCalled = false;
|
private boolean wasPostConstructCalled = false;
|
||||||
private boolean wasSecondPostConstructCalled = false;
|
|
||||||
private boolean wasReloaded = false;
|
private boolean wasReloaded = false;
|
||||||
|
|
||||||
@PostConstruct
|
@PostConstruct
|
||||||
protected void setFieldToTrue() {
|
public void postConstructMethod() {
|
||||||
wasPostConstructCalled = true;
|
wasPostConstructCalled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
@PostConstruct
|
public boolean wasPostConstructCalled() {
|
||||||
public int otherPostConstructMethod() {
|
return wasPostConstructCalled;
|
||||||
wasSecondPostConstructCalled = true;
|
|
||||||
return 42;
|
|
||||||
}
|
|
||||||
|
|
||||||
public boolean werePostConstructsCalled() {
|
|
||||||
return wasPostConstructCalled && wasSecondPostConstructCalled;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
public BetaManager getBetaManager() {
|
public BetaManager getBetaManager() {
|
||||||
|
Loading…
Reference in New Issue
Block a user