From b83c0d5e9e85d01c064a6fff5a8be6e14c60c512 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Melaine=20G=C3=A9rard?= Date: Thu, 28 Nov 2024 10:20:23 +0100 Subject: [PATCH] :sparkles: Patch Reflection --- .../gachamelia/utils/ReflectionUtils.java | 100 +++++++++--------- 1 file changed, 48 insertions(+), 52 deletions(-) diff --git a/src/main/java/org/camelia/studio/gachamelia/utils/ReflectionUtils.java b/src/main/java/org/camelia/studio/gachamelia/utils/ReflectionUtils.java index b730317..4aba8af 100644 --- a/src/main/java/org/camelia/studio/gachamelia/utils/ReflectionUtils.java +++ b/src/main/java/org/camelia/studio/gachamelia/utils/ReflectionUtils.java @@ -4,41 +4,36 @@ import org.slf4j.Logger; import org.slf4j.LoggerFactory; import java.io.File; -import java.lang.reflect.Modifier; +import java.io.IOException; import java.net.URL; +import java.net.URLDecoder; +import java.nio.charset.StandardCharsets; import java.util.ArrayList; +import java.util.Enumeration; import java.util.List; +import java.util.jar.JarEntry; +import java.util.jar.JarFile; public class ReflectionUtils { private static final Logger logger = LoggerFactory.getLogger(ReflectionUtils.class); - /** - * Charge toutes les classes d'un type spécifique depuis un package - * - * @param packageName Le package à scanner - * @param targetType Le type de classe à charger - * @return Liste des instances des classes trouvées - */ public static List loadClasses(String packageName, Class targetType) { List instances = new ArrayList<>(); + String path = packageName.replace('.', '/'); try { - // Convertit le nom du package en chemin - String path = packageName.replace('.', '/'); ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); + Enumeration resources = classLoader.getResources(path); - // Récupère toutes les ressources du package - var resources = classLoader.getResources(path); - - // Parcourt toutes les ressources trouvées while (resources.hasMoreElements()) { URL resource = resources.nextElement(); - File directory = new File(resource.toURI()); - // Charge les classes du répertoire et ses sous-répertoires - scanDirectory(directory, packageName, targetType, instances); + if (resource.getProtocol().equals("jar")) { + processJarFile(resource, path, packageName, targetType, instances); + } else { + processDirectory(new File(resource.toURI()), packageName, targetType, instances); + } } - } catch (Exception e) { logger.error("Erreur lors du scan du package {} : {}", packageName, e.getMessage()); } @@ -46,60 +41,61 @@ public class ReflectionUtils { return instances; } - /** - * Scanne récursivement un répertoire pour trouver les classes - */ - private static void scanDirectory(File directory, String packageName, Class targetType, List instances) { - // Vérifie si le répertoire existe + private static void processJarFile(URL resource, String path, String packageName, + Class targetType, List instances) throws IOException { + String jarPath = resource.getPath().substring(5, resource.getPath().indexOf("!")); + jarPath = URLDecoder.decode(jarPath, StandardCharsets.UTF_8); + + try (JarFile jar = new JarFile(jarPath)) { + Enumeration entries = jar.entries(); + + while (entries.hasMoreElements()) { + JarEntry entry = entries.nextElement(); + String entryName = entry.getName(); + + if (entryName.startsWith(path) && entryName.endsWith(".class")) { + String className = entryName.substring(0, entryName.length() - 6) + .replace('/', '.'); + loadClass(className, targetType, instances); + } + } + } + } + + private static void processDirectory(File directory, String packageName, + Class targetType, List instances) { if (!directory.exists()) { return; } - // Récupère tous les fichiers du répertoire File[] files = directory.listFiles(); if (files != null) { for (File file : files) { - // Si c'est un répertoire, on le scanne récursivement if (file.isDirectory()) { - scanDirectory( - file, - packageName + "." + file.getName(), - targetType, - instances - ); - } - // Si c'est un fichier .class, on essaie de le charger - else if (file.getName().endsWith(".class")) { - loadClass(packageName, file.getName(), targetType, instances); + processDirectory(file, packageName + "." + file.getName(), + targetType, instances); + } else if (file.getName().endsWith(".class")) { + String className = packageName + '.' + + file.getName().substring(0, file.getName().length() - 6); + loadClass(className, targetType, instances); } } } } - /** - * Charge une classe spécifique - */ @SuppressWarnings("unchecked") - private static void loadClass(String packageName, String fileName, Class targetType, List instances) { + private static void loadClass(String className, Class targetType, List instances) { try { - // Convertit le nom de fichier en nom de classe - String className = packageName + '.' + fileName.substring(0, fileName.length() - 6); Class clazz = Class.forName(className); - // Vérifie si la classe correspond au type recherché - if (targetType.isAssignableFrom(clazz) && - !clazz.isInterface() && - !Modifier.isAbstract(clazz.getModifiers())) { - - // Crée une instance de la classe - T instance = (T) clazz.getDeclaredConstructor().newInstance(); - instances.add(instance); - + if (targetType.isAssignableFrom(clazz) && !clazz.isInterface() && + !java.lang.reflect.Modifier.isAbstract(clazz.getModifiers())) { + instances.add((T) clazz.getDeclaredConstructor().newInstance()); logger.debug("Classe chargée : {}", className); } - } catch (Exception e) { - logger.error("Erreur lors du chargement d'une classe : {}", e.getMessage()); + logger.error("Erreur lors du chargement de la classe {} : {}", + className, e.getMessage()); } } } \ No newline at end of file