Patch Reflection
All checks were successful
Build and Push Docker Image / build (push) Successful in 2m38s

This commit is contained in:
Melaine Gérard 2024-11-28 10:20:23 +01:00
parent 8f610fe94a
commit b83c0d5e9e

View File

@ -4,41 +4,36 @@ import org.slf4j.Logger;
import org.slf4j.LoggerFactory; import org.slf4j.LoggerFactory;
import java.io.File; import java.io.File;
import java.lang.reflect.Modifier; import java.io.IOException;
import java.net.URL; import java.net.URL;
import java.net.URLDecoder;
import java.nio.charset.StandardCharsets;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List; import java.util.List;
import java.util.jar.JarEntry;
import java.util.jar.JarFile;
public class ReflectionUtils { public class ReflectionUtils {
private static final Logger logger = LoggerFactory.getLogger(ReflectionUtils.class); 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 <T> List<T> loadClasses(String packageName, Class<T> targetType) { public static <T> List<T> loadClasses(String packageName, Class<T> targetType) {
List<T> instances = new ArrayList<>(); List<T> instances = new ArrayList<>();
String path = packageName.replace('.', '/');
try { try {
// Convertit le nom du package en chemin
String path = packageName.replace('.', '/');
ClassLoader classLoader = Thread.currentThread().getContextClassLoader(); ClassLoader classLoader = Thread.currentThread().getContextClassLoader();
Enumeration<URL> 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()) { while (resources.hasMoreElements()) {
URL resource = resources.nextElement(); URL resource = resources.nextElement();
File directory = new File(resource.toURI());
// Charge les classes du répertoire et ses sous-répertoires if (resource.getProtocol().equals("jar")) {
scanDirectory(directory, packageName, targetType, instances); processJarFile(resource, path, packageName, targetType, instances);
} else {
processDirectory(new File(resource.toURI()), packageName, targetType, instances);
}
} }
} catch (Exception e) { } catch (Exception e) {
logger.error("Erreur lors du scan du package {} : {}", packageName, e.getMessage()); logger.error("Erreur lors du scan du package {} : {}", packageName, e.getMessage());
} }
@ -46,60 +41,61 @@ public class ReflectionUtils {
return instances; return instances;
} }
/** private static <T> void processJarFile(URL resource, String path, String packageName,
* Scanne récursivement un répertoire pour trouver les classes Class<T> targetType, List<T> instances) throws IOException {
*/ String jarPath = resource.getPath().substring(5, resource.getPath().indexOf("!"));
private static <T> void scanDirectory(File directory, String packageName, Class<T> targetType, List<T> instances) { jarPath = URLDecoder.decode(jarPath, StandardCharsets.UTF_8);
// Vérifie si le répertoire existe
try (JarFile jar = new JarFile(jarPath)) {
Enumeration<JarEntry> 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 <T> void processDirectory(File directory, String packageName,
Class<T> targetType, List<T> instances) {
if (!directory.exists()) { if (!directory.exists()) {
return; return;
} }
// Récupère tous les fichiers du répertoire
File[] files = directory.listFiles(); File[] files = directory.listFiles();
if (files != null) { if (files != null) {
for (File file : files) { for (File file : files) {
// Si c'est un répertoire, on le scanne récursivement
if (file.isDirectory()) { if (file.isDirectory()) {
scanDirectory( processDirectory(file, packageName + "." + file.getName(),
file, targetType, instances);
packageName + "." + file.getName(), } else if (file.getName().endsWith(".class")) {
targetType, String className = packageName + '.' +
instances file.getName().substring(0, file.getName().length() - 6);
); loadClass(className, 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);
} }
} }
} }
} }
/**
* Charge une classe spécifique
*/
@SuppressWarnings("unchecked") @SuppressWarnings("unchecked")
private static <T> void loadClass(String packageName, String fileName, Class<T> targetType, List<T> instances) { private static <T> void loadClass(String className, Class<T> targetType, List<T> instances) {
try { try {
// Convertit le nom de fichier en nom de classe
String className = packageName + '.' + fileName.substring(0, fileName.length() - 6);
Class<?> clazz = Class.forName(className); Class<?> clazz = Class.forName(className);
// Vérifie si la classe correspond au type recherché if (targetType.isAssignableFrom(clazz) && !clazz.isInterface() &&
if (targetType.isAssignableFrom(clazz) && !java.lang.reflect.Modifier.isAbstract(clazz.getModifiers())) {
!clazz.isInterface() && instances.add((T) clazz.getDeclaredConstructor().newInstance());
!Modifier.isAbstract(clazz.getModifiers())) {
// Crée une instance de la classe
T instance = (T) clazz.getDeclaredConstructor().newInstance();
instances.add(instance);
logger.debug("Classe chargée : {}", className); logger.debug("Classe chargée : {}", className);
} }
} catch (Exception e) { } 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());
} }
} }
} }