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