package dev.lions.config; import jakarta.enterprise.context.ApplicationScoped; import jakarta.enterprise.event.Event; import jakarta.inject.Inject; import jakarta.validation.constraints.NotNull; import lombok.extern.slf4j.Slf4j; import dev.lions.events.ConfigurationEvent; import dev.lions.exceptions.ConfigurationException; import dev.lions.utils.EncryptionUtils; import java.nio.file.Files; import java.nio.file.Path; import java.nio.file.Paths; import java.util.Map; import java.util.concurrent.ConcurrentHashMap; import java.util.concurrent.atomic.AtomicLong; /** * Service de gestion avancée de la configuration de l'application. * Fournit une interface enrichie pour accéder et gérer les paramètres de configuration * de manière thread-safe, sécurisée et optimisée. * * @author Lions Dev Team * @version 2.1 */ @Slf4j @ApplicationScoped public class ApplicationConfigService { private static final long CACHE_DURATION_MS = 300_000; // 5 minutes private static final long MIN_DISK_SPACE_BYTES = 100 * 1024 * 1024; // 100 MB private static final String[] MANDATORY_DIRECTORIES = {"logs", "data", "temp"}; private final ApplicationConfig applicationConfig; private final Map> configCache; private final AtomicLong lastHealthCheck; @Inject private Event configurationEvent; @Inject private EncryptionUtils encryptionUtils; @Inject public ApplicationConfigService(@NotNull ApplicationConfig applicationConfig) { this.applicationConfig = applicationConfig; this.configCache = new ConcurrentHashMap<>(); this.lastHealthCheck = new AtomicLong(0); initializeService(); } /** * Valide la configuration actuelle de l'application. * Vérifie les chemins de stockage, les répertoires obligatoires et les paramètres critiques. */ private void validateConfiguration() { log.info("Validation de la configuration de l'application..."); try { validateStorageBasePath(); validateMandatoryDirectories(); validateSecuritySettings(); log.info("Configuration de l'application validée avec succès."); } catch (ConfigurationException e) { log.error("Validation échouée : {}", e.getMessage()); throw e; // Relancer l'exception après log } catch (Exception e) { log.error("Erreur inattendue lors de la validation de la configuration", e); throw new ConfigurationException("Erreur inattendue lors de la validation", e); } } /** * Vérifie l'existence et l'accessibilité du chemin de stockage. */ private void validateStorageBasePath() { Path storagePath = Paths.get(applicationConfig.getStorageBasePath()); if (!Files.exists(storagePath) || !Files.isDirectory(storagePath)) { throw new ConfigurationException("Le chemin de stockage est invalide : " + storagePath); } log.debug("Chemin de stockage validé : {}", storagePath); } /** * Vérifie l'existence des répertoires obligatoires. */ private void validateMandatoryDirectories() { String basePath = applicationConfig.getStorageBasePath(); for (String directory : MANDATORY_DIRECTORIES) { Path directoryPath = Paths.get(basePath, directory); if (!Files.exists(directoryPath) || !Files.isWritable(directoryPath)) { throw new ConfigurationException("Répertoire obligatoire manquant ou inaccessible : " + directoryPath); } log.debug("Répertoire valide : {}", directoryPath); } } /** * Valide les paramètres de sécurité essentiels. */ private void validateSecuritySettings() { if (applicationConfig.isProduction()) { if (!applicationConfig.isSmtpConfigured()) { throw new ConfigurationException("La configuration SMTP est obligatoire en production"); } log.debug("Paramètres SMTP validés pour l'environnement production"); } log.debug("Paramètres de sécurité validés"); } private void initializeService() { try { log.info("Initialisation du service de configuration"); createMandatoryDirectories(); validateConfiguration(); initializeCache(); notifyServiceInitialized(); log.info("Service de configuration initialisé avec succès"); } catch (Exception e) { log.error("Erreur lors de l'initialisation du service de configuration", e); throw new ConfigurationException("Échec de l'initialisation du service", e); } } private void createMandatoryDirectories() { String basePath = applicationConfig.getStorageBasePath(); for (String directory : MANDATORY_DIRECTORIES) { Path directoryPath = Paths.get(basePath, directory); if (!Files.exists(directoryPath)) { try { Files.createDirectories(directoryPath); log.debug("Répertoire créé : {}", directoryPath); } catch (Exception e) { throw new ConfigurationException("Impossible de créer le répertoire : " + directoryPath, e); } } } } private void initializeCache() { log.info("Initialisation du cache de configuration..."); configCache.clear(); } private void notifyServiceInitialized() { ConfigurationEvent event = new ConfigurationEvent( "SERVICE_INITIALIZED", Map.of("timestamp", System.currentTimeMillis(), "environment", applicationConfig.getEnvironment()) ); configurationEvent.fire(event); } /** * Classe interne représentant une valeur mise en cache. */ private static class CachedValue { private final T value; private final long timestamp; CachedValue(T value) { this.value = value; this.timestamp = System.currentTimeMillis(); } T getValue() { return value; } } }