Skip to content

Commit c1acab7

Browse files
committed
Added @Inject and @component
1 parent 02492ce commit c1acab7

File tree

13 files changed

+205
-13
lines changed

13 files changed

+205
-13
lines changed
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.javadiscord.jdi.core.annotations;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Retention(RetentionPolicy.RUNTIME)
9+
@Target({ElementType.METHOD})
10+
public @interface Component {}
Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,10 @@
1+
package com.javadiscord.jdi.core.annotations;
2+
3+
import java.lang.annotation.ElementType;
4+
import java.lang.annotation.Retention;
5+
import java.lang.annotation.RetentionPolicy;
6+
import java.lang.annotation.Target;
7+
8+
@Retention(RetentionPolicy.RUNTIME)
9+
@Target({ElementType.FIELD})
10+
public @interface Inject {}
Lines changed: 92 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,92 @@
1+
package com.javadiscord.jdi.core.processor.loader;
2+
3+
import java.io.File;
4+
import java.lang.reflect.Field;
5+
import java.lang.reflect.Method;
6+
import java.util.HashMap;
7+
import java.util.List;
8+
import java.util.Map;
9+
10+
import com.javadiscord.jdi.core.annotations.Component;
11+
import com.javadiscord.jdi.core.annotations.Inject;
12+
import com.javadiscord.jdi.core.processor.ClassFileUtil;
13+
import com.javadiscord.jdi.core.processor.validator.ComponentValidator;
14+
15+
import org.apache.logging.log4j.LogManager;
16+
import org.apache.logging.log4j.Logger;
17+
18+
public class ComponentLoader {
19+
private static final Logger LOGGER = LogManager.getLogger(ComponentLoader.class);
20+
private static final Map<Class<?>, Object> COMPONENTS = new HashMap<>();
21+
private final ComponentValidator componentValidator = new ComponentValidator();
22+
23+
public ComponentLoader() {
24+
try {
25+
loadComponents();
26+
} catch (Exception e) {
27+
LOGGER.error("An error occurred while loading components classes", e);
28+
}
29+
}
30+
31+
private void loadComponents() {
32+
List<File> classes = ClassFileUtil.getClassesInClassPath();
33+
for (File classFile : classes) {
34+
try {
35+
Class<?> clazz = Class.forName(ClassFileUtil.getClassName(classFile));
36+
if (componentValidator.validate(clazz)) {
37+
for (Method method : clazz.getMethods()) {
38+
if (method.isAnnotationPresent(Component.class)) {
39+
if (!COMPONENTS.containsKey(method.getReturnType())) {
40+
COMPONENTS.put(method.getReturnType(), method.invoke(null));
41+
LOGGER
42+
.info("Loaded component {}", method.getReturnType().getName());
43+
} else {
44+
LOGGER.error(
45+
"Component {} already loaded", method.getReturnType().getName()
46+
);
47+
}
48+
}
49+
}
50+
} else {
51+
LOGGER.error("{} failed validation", clazz.getName());
52+
}
53+
} catch (Exception | Error ignore) {
54+
/* Ignore */
55+
}
56+
}
57+
}
58+
59+
public static void injectComponents(Object component) {
60+
try {
61+
Class<?> clazz = component.getClass();
62+
for (Field field : clazz.getDeclaredFields()) {
63+
if (field.isAnnotationPresent(Inject.class)) {
64+
if (COMPONENTS.containsKey(field.getType())) {
65+
Object dependency = COMPONENTS.get(field.getType());
66+
if (dependency != null) {
67+
field.setAccessible(true);
68+
try {
69+
field.set(component, dependency);
70+
LOGGER.info(
71+
"Injected component {} into {}",
72+
dependency.getClass().getName(), field.getType()
73+
);
74+
} catch (IllegalAccessException e) {
75+
throw new RuntimeException(
76+
"Failed to inject dependency into field: " + field.getName(),
77+
e
78+
);
79+
}
80+
}
81+
} else {
82+
LOGGER.error(
83+
"No object {} was found in field {}", field.getType(), field.getName()
84+
);
85+
}
86+
}
87+
}
88+
} catch (Exception | Error ignore) {
89+
/* Ignore */
90+
}
91+
}
92+
}

annotations/src/main/java/com/javadiscord/jdi/core/processor/ListenerLoader.java renamed to annotations/src/main/java/com/javadiscord/jdi/core/processor/loader/ListenerLoader.java

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,12 @@
1-
package com.javadiscord.jdi.core.processor;
1+
package com.javadiscord.jdi.core.processor.loader;
22

33
import java.io.File;
44
import java.lang.reflect.Constructor;
55
import java.util.List;
66

77
import com.javadiscord.jdi.core.annotations.EventListener;
8+
import com.javadiscord.jdi.core.processor.ClassFileUtil;
9+
import com.javadiscord.jdi.core.processor.validator.EventListenerValidator;
810

911
import org.apache.logging.log4j.LogManager;
1012
import org.apache.logging.log4j.Logger;
@@ -43,7 +45,9 @@ public void loadListeners() {
4345

4446
private void registerListener(Class<?> clazz) {
4547
try {
46-
eventListeners.add(getZeroArgConstructor(clazz).newInstance());
48+
Object instance = getZeroArgConstructor(clazz).newInstance();
49+
ComponentLoader.injectComponents(instance);
50+
eventListeners.add(instance);
4751
LOGGER.info("Registered listener {}", clazz.getName());
4852
} catch (Exception e) {
4953
LOGGER.error("Failed to create {} instance", clazz.getName(), e);

annotations/src/main/java/com/javadiscord/jdi/core/processor/SlashCommandLoader.java renamed to annotations/src/main/java/com/javadiscord/jdi/core/processor/loader/SlashCommandLoader.java

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.javadiscord.jdi.core.processor;
1+
package com.javadiscord.jdi.core.processor.loader;
22

33
import java.io.File;
44
import java.lang.reflect.Constructor;
@@ -7,6 +7,9 @@
77
import java.util.Map;
88

99
import com.javadiscord.jdi.core.annotations.SlashCommand;
10+
import com.javadiscord.jdi.core.processor.ClassFileUtil;
11+
import com.javadiscord.jdi.core.processor.SlashCommandClassMethod;
12+
import com.javadiscord.jdi.core.processor.validator.SlashCommandValidator;
1013

1114
import org.apache.logging.log4j.LogManager;
1215
import org.apache.logging.log4j.Logger;
@@ -78,4 +81,8 @@ private boolean hasZeroArgsConstructor(Class<?> clazz) {
7881
return false;
7982
}
8083

84+
public void injectComponents(Object object) {
85+
ComponentLoader.injectComponents(object);
86+
}
87+
8188
}
Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,35 @@
1+
package com.javadiscord.jdi.core.processor.validator;
2+
3+
import java.lang.reflect.Method;
4+
import java.lang.reflect.Modifier;
5+
6+
import com.javadiscord.jdi.core.annotations.Component;
7+
8+
import org.apache.logging.log4j.LogManager;
9+
import org.apache.logging.log4j.Logger;
10+
11+
public class ComponentValidator {
12+
private static final Logger LOGGER = LogManager.getLogger(ComponentValidator.class);
13+
14+
public boolean validate(Class<?> clazz) {
15+
return validateMethods(clazz);
16+
}
17+
18+
private boolean validateMethods(Class<?> clazz) {
19+
Method[] methods = clazz.getMethods();
20+
for (Method method : methods) {
21+
if (method.isAnnotationPresent(Component.class)) {
22+
if (method.getParameterCount() != 0) {
23+
LOGGER.error("Methods annotated with @Component requires 0 parameters");
24+
return false;
25+
}
26+
if (!Modifier.isStatic(method.getModifiers())) {
27+
LOGGER.error("Methods annotated with @Component must be static");
28+
return false;
29+
}
30+
}
31+
}
32+
return true;
33+
}
34+
35+
}

annotations/src/main/java/com/javadiscord/jdi/core/processor/EventListenerValidator.java renamed to annotations/src/main/java/com/javadiscord/jdi/core/processor/validator/EventListenerValidator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.javadiscord.jdi.core.processor;
1+
package com.javadiscord.jdi.core.processor.validator;
22

33
import java.lang.annotation.Annotation;
44
import java.lang.reflect.Constructor;

annotations/src/main/java/com/javadiscord/jdi/core/processor/SlashCommandValidator.java renamed to annotations/src/main/java/com/javadiscord/jdi/core/processor/validator/SlashCommandValidator.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,4 @@
1-
package com.javadiscord.jdi.core.processor;
1+
package com.javadiscord.jdi.core.processor.validator;
22

33
import java.lang.annotation.Annotation;
44
import java.lang.reflect.Method;

annotations/src/test/unit/com/javadiscord/jdi/core/processor/EventListenerValidatorTest.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -10,6 +10,7 @@
1010
import com.javadiscord.jdi.core.models.channel.Channel;
1111
import com.javadiscord.jdi.core.models.message.Message;
1212

13+
import com.javadiscord.jdi.core.processor.validator.EventListenerValidator;
1314
import org.junit.jupiter.api.Test;
1415

1516
class EventListenerValidatorTest {

core/src/main/java/com/javadiscord/jdi/core/Discord.java

Lines changed: 19 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -118,6 +118,7 @@ public Discord(String botToken, IdentifyRequest identifyRequest, Cache cache) {
118118
this.cache = cache;
119119
if (annotationLibPresent()) {
120120
LOGGER.info("Annotation lib is present");
121+
loadComponents();
121122
loadAnnotations();
122123
loadSlashCommands();
123124
registerLoadedAnnotationsWithDiscord();
@@ -211,17 +212,31 @@ private void registerLoadedAnnotationsWithDiscord() {
211212

212213
private boolean annotationLibPresent() {
213214
try {
214-
Class.forName("com.javadiscord.jdi.core.processor.ListenerLoader");
215+
Class.forName("com.javadiscord.jdi.core.processor.loader.ListenerLoader");
215216
return true;
216217
} catch (Exception e) {
217218
return false;
218219
}
219220
}
220221

222+
private void loadComponents() {
223+
LOGGER.info("Loading Components");
224+
try {
225+
Class<?> clazz =
226+
Class.forName("com.javadiscord.jdi.core.processor.loader.ComponentLoader");
227+
for (Constructor<?> constructor : clazz.getConstructors()) {
228+
constructor.newInstance();
229+
}
230+
} catch (Exception | Error e) {
231+
/* Ignore */
232+
}
233+
}
234+
221235
private void loadAnnotations() {
222236
LOGGER.info("Loading EventListeners");
223237
try {
224-
Class<?> clazz = Class.forName("com.javadiscord.jdi.core.processor.ListenerLoader");
238+
Class<?> clazz =
239+
Class.forName("com.javadiscord.jdi.core.processor.loader.ListenerLoader");
225240
for (Constructor<?> constructor : clazz.getConstructors()) {
226241
if (constructor.getParameterCount() == 1) {
227242
Parameter parameters = constructor.getParameters()[0];
@@ -239,7 +254,8 @@ private void loadAnnotations() {
239254
private void loadSlashCommands() {
240255
LOGGER.info("Loading SlashCommands");
241256
try {
242-
Class<?> clazz = Class.forName("com.javadiscord.jdi.core.processor.SlashCommandLoader");
257+
Class<?> clazz =
258+
Class.forName("com.javadiscord.jdi.core.processor.loader.SlashCommandLoader");
243259
for (Constructor<?> constructor : clazz.getConstructors()) {
244260
if (constructor.getParameterCount() == 1) {
245261
Parameter parameters = constructor.getParameters()[0];

0 commit comments

Comments
 (0)