Skip to content

Commit 3939c1e

Browse files
authored
Merge pull request #32 from Sandro642/feature/annotation
Add AnnotHandler class for managing connection event listeners with @…
2 parents af54a46 + 1110a6c commit 3939c1e

3 files changed

Lines changed: 144 additions & 3 deletions

File tree

build.gradle

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ plugins {
55
}
66

77
group = 'fr.sandro642.github'
8-
version = '0.2.7.2-STABLE'
8+
version = '0.2.8-STABLE'
99

1010
tasks.register('printVersion') {
1111
doLast {

readme.md

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@ And if you thought APIs were complicated, think again! With ConnectLib, it's lik
1717
---
1818

1919
```java
20-
Stable Version: 0.2.7.2-STABLE
20+
Stable Version: 0.2.8-STABLE
2121
```
2222

2323
---
@@ -106,7 +106,7 @@ repositories {
106106

107107
dependencies {
108108

109-
implementation("fr.sandro642.github:ConnectLib:0.2.7.2-STABLE")
109+
implementation("fr.sandro642.github:ConnectLib:0.2.8-STABLE")
110110

111111
}
112112

Lines changed: 141 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,141 @@
1+
package fr.sandro642.github.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+
import java.lang.reflect.InvocationTargetException;
8+
import java.lang.reflect.Method;
9+
import java.util.LinkedList;
10+
import java.util.List;
11+
import java.io.File;
12+
import java.net.URL;
13+
import java.util.ArrayList;
14+
15+
/**
16+
* AnnotHandler is a class that manages the discovery and execution of listeners annotated with @AnnotConnect.
17+
* It scans the package for classes that implement the ConnectListener interface and invokes methods annotated with @AnnotConnect.
18+
*
19+
* @author Sandro642
20+
* @version 1.0
21+
* @see ConnectListener
22+
* @see AnnotConnect
23+
*/
24+
25+
public class AnnotHandler {
26+
27+
/**
28+
* AnnotConnect is an annotation used to mark methods that should be executed when a connection event occurs.
29+
* Methods annotated with this annotation will be invoked by the AnnotHandler when it discovers them.
30+
*/
31+
@Retention(RetentionPolicy.RUNTIME)
32+
@Target(ElementType.METHOD)
33+
@interface AnnotConnect { }
34+
35+
/**
36+
* ConnectListener is an interface that should be implemented by classes that want to listen for connection events.
37+
* Classes implementing this interface can have methods annotated with @AnnotConnect to handle specific connection events.
38+
*/
39+
interface ConnectListener {
40+
<T> void onDebug(T type);
41+
}
42+
43+
/**
44+
* listeners is a list that holds instances of classes implementing the ConnectListener interface.
45+
* It is populated by the discoverListeners method, which scans the package for classes that implement ConnectListener.
46+
* The methods of these classes can be annotated with @AnnotConnect to indicate that they should be executed when a connection event occurs.
47+
*/
48+
private final List<ConnectListener> listeners = new LinkedList<>();
49+
50+
/**
51+
* discoverListeners is a method that scans the package of the AnnotHandler class for classes that implement the ConnectListener interface.
52+
* It creates instances of these classes and adds them to the listeners list.
53+
*/
54+
private void discoverListeners() {
55+
try {
56+
String packageName = this.getClass().getPackage().getName();
57+
List<Class<?>> classes = getClassesInPackage(packageName);
58+
59+
for (Class<?> clazz : classes) {
60+
if (ConnectListener.class.isAssignableFrom(clazz) && !clazz.isInterface()) {
61+
try {
62+
Object instance = clazz.getDeclaredConstructor().newInstance();
63+
listeners.add((ConnectListener) instance);
64+
} catch (Exception e) {
65+
}
66+
}
67+
}
68+
} catch (Exception e) {
69+
throw new RuntimeException("Error during listener discovery", e);
70+
}
71+
}
72+
73+
/**
74+
* getClassesInPackage is a helper method that retrieves all classes in a specified package.
75+
* It uses the class loader to find resources in the package and loads them as Class objects.
76+
*
77+
* @param packageName The name of the package to scan for classes.
78+
* @return A list of Class objects found in the specified package.
79+
*/
80+
private List<Class<?>> getClassesInPackage(String packageName) {
81+
List<Class<?>> classes = new ArrayList<>();
82+
try {
83+
ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
84+
String path = packageName.replace('.', '/');
85+
URL resource = classLoader.getResource(path);
86+
87+
if (resource != null) {
88+
File directory = new File(resource.getFile());
89+
if (directory.exists()) {
90+
for (File file : directory.listFiles()) {
91+
if (file.getName().endsWith(".class")) {
92+
String className = packageName + "." + file.getName().substring(0, file.getName().length() - 6);
93+
try {
94+
classes.add(Class.forName(className));
95+
} catch (ClassNotFoundException e) {
96+
}
97+
}
98+
}
99+
}
100+
}
101+
} catch (Exception e) {
102+
logger.warning("Failed to retrieve classes in package: " + packageName + ". Exception: " + e.getMessage());
103+
}
104+
return classes;
105+
}
106+
107+
/**
108+
* execListener is a method that executes all methods annotated with @AnnotConnect in the discovered listeners.
109+
* It first checks if the listeners list is empty and calls discoverListeners if it is.
110+
* Then, it iterates through each listener and invokes the annotated methods.
111+
*/
112+
public void execListener(){
113+
if (listeners.isEmpty()) {
114+
discoverListeners();
115+
}
116+
117+
for(ConnectListener listener : listeners){
118+
for(Method method : listener.getClass().getDeclaredMethods()){
119+
if(method.isAnnotationPresent(AnnotConnect.class)) {
120+
try {
121+
method.setAccessible(true);
122+
method.invoke(listener);
123+
} catch (IllegalAccessException | InvocationTargetException e) {
124+
throw new RuntimeException(e);
125+
}
126+
}
127+
}
128+
}
129+
}
130+
131+
/**
132+
* Main method to execute the AnnotHandler and trigger the execution of annotated methods.
133+
* This method serves as an entry point for testing the AnnotHandler functionality.
134+
*
135+
* @param args Command line arguments (not used).
136+
*/
137+
public static void main(String[] args) {
138+
AnnotHandler annotLogic = new AnnotHandler();
139+
annotLogic.execListener();
140+
}
141+
}

0 commit comments

Comments
 (0)