chore(quarkus-327): bump to Quarkus 3.27.3 LTS, rename quarkus-resteasy-reactive → quarkus-rest, fix testGetAuditQuestions map vs list, rename deprecated config keys
This commit is contained in:
@@ -1,339 +1,339 @@
|
||||
package dev.lions.config;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import dev.lions.exceptions.ConfigurationException;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Configuration centrale de l'application Lions Dev.
|
||||
* Cette classe gère l'ensemble des paramètres de configuration de manière thread-safe
|
||||
* et fournit une interface unifiée pour accéder aux différentes configurations.
|
||||
*
|
||||
* @author Lions Dev Team
|
||||
* @version 2.0
|
||||
*/
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
@Getter
|
||||
public class ApplicationConfig {
|
||||
|
||||
/**
|
||||
* Énumération des environnements d'exécution supportés.
|
||||
*/
|
||||
public enum Environment {
|
||||
DEVELOPMENT("development"),
|
||||
STAGING("staging"),
|
||||
PRODUCTION("production");
|
||||
|
||||
private final String value;
|
||||
|
||||
Environment(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Environment fromString(String value) {
|
||||
return Arrays.stream(values())
|
||||
.filter(env -> env.getValue().equalsIgnoreCase(value))
|
||||
.findFirst()
|
||||
.orElse(DEVELOPMENT);
|
||||
}
|
||||
}
|
||||
|
||||
// Constantes de configuration
|
||||
private static final String DEFAULT_ENVIRONMENT = "development";
|
||||
private static final long DEFAULT_MAX_FILE_SIZE = 10_485_760L; // 10MB
|
||||
private static final int DEFAULT_CACHE_SIZE = 1000;
|
||||
private static final int MIN_PORT = 1;
|
||||
private static final int MAX_PORT = 65535;
|
||||
|
||||
// Configuration de base de l'application
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.name", defaultValue = "Lions Dev")
|
||||
private String applicationName;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.environment", defaultValue = DEFAULT_ENVIRONMENT)
|
||||
private String environment;
|
||||
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.base-url")
|
||||
private String baseUrl;
|
||||
|
||||
// Configuration du stockage
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.storage.base-path")
|
||||
private String storageBasePath;
|
||||
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.storage.images.path", defaultValue = "images")
|
||||
private String imageStoragePath;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.storage.allowed-types", defaultValue = "jpg,jpeg,png,gif")
|
||||
private String allowedFileTypes;
|
||||
|
||||
@Min(1_048_576L) // 1MB minimum
|
||||
@Max(104_857_600L) // 100MB maximum
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.storage.max-size", defaultValue = "10485760")
|
||||
private Long maxFileSize;
|
||||
|
||||
// Configuration des emails
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.email.from")
|
||||
private String emailFrom;
|
||||
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.email.support")
|
||||
private String emailSupport;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.email.template-path", defaultValue = "templates/email")
|
||||
private String emailTemplatePath;
|
||||
|
||||
// Configuration SMTP
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.smtp.host")
|
||||
private String smtpHost;
|
||||
|
||||
@Min(MIN_PORT)
|
||||
@Max(MAX_PORT)
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.smtp.port")
|
||||
private Integer smtpPort;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.smtp.username")
|
||||
private Optional<String> smtpUsername;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.smtp.password")
|
||||
private Optional<String> smtpPassword;
|
||||
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.admin.email")
|
||||
private String adminEmailAddress;
|
||||
|
||||
// Collections thread-safe pour les configurations dynamiques
|
||||
private final Map<String, String> applicationUrls = new ConcurrentHashMap<>();
|
||||
private final Map<Environment, String> environmentConfigs = new EnumMap<>(Environment.class);
|
||||
private List<String> allowedFileTypesList;
|
||||
|
||||
/**
|
||||
* Initialise la configuration après l'injection des propriétés.
|
||||
* Valide et prépare l'ensemble des paramètres de configuration.
|
||||
*
|
||||
* @throws ConfigurationException si la configuration est invalide
|
||||
*/
|
||||
@PostConstruct
|
||||
void initialize() {
|
||||
try {
|
||||
log.info("Initialisation de la configuration de l'application: {}", applicationName);
|
||||
validateConfiguration();
|
||||
initializeApplicationUrls();
|
||||
initializeAllowedFileTypes();
|
||||
initializeEnvironmentConfigs();
|
||||
log.info("Configuration initialisée avec succès en environnement: {}", environment);
|
||||
} catch (Exception e) {
|
||||
String errorMessage = "Erreur lors de l'initialisation de la configuration";
|
||||
log.error(errorMessage, e);
|
||||
throw new ConfigurationException(errorMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide l'ensemble de la configuration.
|
||||
*
|
||||
* @throws ConfigurationException si la validation échoue
|
||||
*/
|
||||
private void validateConfiguration() {
|
||||
log.debug("Validation de la configuration");
|
||||
validateEnvironment();
|
||||
validateStoragePaths();
|
||||
validateSmtpConfiguration();
|
||||
validateFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide l'environnement d'exécution.
|
||||
*/
|
||||
private void validateEnvironment() {
|
||||
if (!isValidEnvironment(environment)) {
|
||||
throw new ConfigurationException("Environnement non reconnu: " + environment);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide les chemins de stockage.
|
||||
*/
|
||||
private void validateStoragePaths() {
|
||||
Path basePath = Paths.get(storageBasePath);
|
||||
validatePath(basePath, "stockage principal");
|
||||
|
||||
Path imagesPath = basePath.resolve(imageStoragePath);
|
||||
validatePath(imagesPath, "stockage des images");
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide un chemin spécifique.
|
||||
*/
|
||||
private void validatePath(Path path, String description) {
|
||||
if (!path.toFile().exists() && !path.toFile().mkdirs()) {
|
||||
throw new ConfigurationException(
|
||||
"Impossible de créer le répertoire de " + description + ": " + path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide la configuration SMTP.
|
||||
*/
|
||||
private void validateSmtpConfiguration() {
|
||||
if (isSmtpConfigured() && (smtpPort < MIN_PORT || smtpPort > MAX_PORT)) {
|
||||
throw new ConfigurationException("Port SMTP invalide: " + smtpPort);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide la taille maximale des fichiers.
|
||||
*/
|
||||
private void validateFileSize() {
|
||||
if (maxFileSize <= 0) {
|
||||
throw new ConfigurationException(
|
||||
"Taille maximale de fichier invalide: " + maxFileSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère l'adresse email système (expéditeur par défaut).
|
||||
*
|
||||
* @return Adresse email système
|
||||
*/
|
||||
public String getSystemEmailAddress() {
|
||||
return emailFrom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le SSL est activé pour le serveur SMTP.
|
||||
*
|
||||
* @return true si SSL est activé, sinon false
|
||||
*/
|
||||
public boolean isSmtpSslEnabled() {
|
||||
return smtpPort == 465; // Port 465 est commun pour SMTP avec SSL
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise les URLs de l'application.
|
||||
*/
|
||||
private void initializeApplicationUrls() {
|
||||
applicationUrls.clear();
|
||||
applicationUrls.put("home", "/");
|
||||
applicationUrls.put("services", "/services");
|
||||
applicationUrls.put("contact", "/contact");
|
||||
applicationUrls.put("admin", "/admin");
|
||||
applicationUrls.put("projects", "/projects");
|
||||
applicationUrls.put("portfolio", "/portfolio");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise la liste des types de fichiers autorisés.
|
||||
*/
|
||||
private void initializeAllowedFileTypes() {
|
||||
allowedFileTypesList = Collections.unmodifiableList(
|
||||
Arrays.asList(allowedFileTypes.toLowerCase().split(","))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise les configurations spécifiques aux environnements.
|
||||
*/
|
||||
private void initializeEnvironmentConfigs() {
|
||||
environmentConfigs.put(Environment.DEVELOPMENT, "dev");
|
||||
environmentConfigs.put(Environment.STAGING, "stage");
|
||||
environmentConfigs.put(Environment.PRODUCTION, "prod");
|
||||
}
|
||||
|
||||
// Méthodes publiques utilitaires
|
||||
|
||||
/**
|
||||
* Récupère le chemin complet pour le stockage des images.
|
||||
*/
|
||||
public String getImageStoragePath() {
|
||||
return Paths.get(storageBasePath, imageStoragePath).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un type de fichier est autorisé.
|
||||
*/
|
||||
public boolean isFileTypeAllowed(String fileType) {
|
||||
return fileType != null && allowedFileTypesList.contains(fileType.toLowerCase().trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère l'URL d'une section de l'application.
|
||||
*/
|
||||
public String getUrl(String key) {
|
||||
return applicationUrls.getOrDefault(key, "/");
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'environnement est en développement.
|
||||
*/
|
||||
public boolean isDevelopment() {
|
||||
return Environment.DEVELOPMENT.getValue().equals(environment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'environnement est en production.
|
||||
*/
|
||||
public boolean isProduction() {
|
||||
return Environment.PRODUCTION.getValue().equals(environment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la configuration SMTP est complète.
|
||||
*/
|
||||
public boolean isSmtpConfigured() {
|
||||
return smtpUsername.isPresent() && smtpPassword.isPresent() &&
|
||||
smtpHost != null && !smtpHost.equals("localhost");
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un environnement est valide.
|
||||
*/
|
||||
private boolean isValidEnvironment(String env) {
|
||||
return Arrays.stream(Environment.values())
|
||||
.anyMatch(e -> e.getValue().equals(env));
|
||||
}
|
||||
package dev.lions.config;
|
||||
|
||||
import jakarta.annotation.PostConstruct;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.validation.constraints.Max;
|
||||
import jakarta.validation.constraints.Min;
|
||||
import jakarta.validation.constraints.NotBlank;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
|
||||
import lombok.Getter;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
import dev.lions.exceptions.ConfigurationException;
|
||||
|
||||
import java.nio.file.Path;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.Arrays;
|
||||
import java.util.Collections;
|
||||
import java.util.EnumMap;
|
||||
import java.util.HashMap;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
import java.util.Optional;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Configuration centrale de l'application Lions Dev.
|
||||
* Cette classe gère l'ensemble des paramètres de configuration de manière thread-safe
|
||||
* et fournit une interface unifiée pour accéder aux différentes configurations.
|
||||
*
|
||||
* @author Lions Dev Team
|
||||
* @version 2.0
|
||||
*/
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
@Getter
|
||||
public class ApplicationConfig {
|
||||
|
||||
/**
|
||||
* Énumération des environnements d'exécution supportés.
|
||||
*/
|
||||
public enum Environment {
|
||||
DEVELOPMENT("development"),
|
||||
STAGING("staging"),
|
||||
PRODUCTION("production");
|
||||
|
||||
private final String value;
|
||||
|
||||
Environment(String value) {
|
||||
this.value = value;
|
||||
}
|
||||
|
||||
public String getValue() {
|
||||
return value;
|
||||
}
|
||||
|
||||
public static Environment fromString(String value) {
|
||||
return Arrays.stream(values())
|
||||
.filter(env -> env.getValue().equalsIgnoreCase(value))
|
||||
.findFirst()
|
||||
.orElse(DEVELOPMENT);
|
||||
}
|
||||
}
|
||||
|
||||
// Constantes de configuration
|
||||
private static final String DEFAULT_ENVIRONMENT = "development";
|
||||
private static final long DEFAULT_MAX_FILE_SIZE = 10_485_760L; // 10MB
|
||||
private static final int DEFAULT_CACHE_SIZE = 1000;
|
||||
private static final int MIN_PORT = 1;
|
||||
private static final int MAX_PORT = 65535;
|
||||
|
||||
// Configuration de base de l'application
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.name", defaultValue = "Lions Dev")
|
||||
private String applicationName;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.environment", defaultValue = DEFAULT_ENVIRONMENT)
|
||||
private String environment;
|
||||
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.base-url")
|
||||
private String baseUrl;
|
||||
|
||||
// Configuration du stockage
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.storage.base-path")
|
||||
private String storageBasePath;
|
||||
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.storage.images.path", defaultValue = "images")
|
||||
private String imageStoragePath;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.storage.allowed-types", defaultValue = "jpg,jpeg,png,gif")
|
||||
private String allowedFileTypes;
|
||||
|
||||
@Min(1_048_576L) // 1MB minimum
|
||||
@Max(104_857_600L) // 100MB maximum
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.storage.max-size", defaultValue = "10485760")
|
||||
private Long maxFileSize;
|
||||
|
||||
// Configuration des emails
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.email.from")
|
||||
private String emailFrom;
|
||||
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.email.support")
|
||||
private String emailSupport;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.email.template-path", defaultValue = "templates/email")
|
||||
private String emailTemplatePath;
|
||||
|
||||
// Configuration SMTP
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.smtp.host")
|
||||
private String smtpHost;
|
||||
|
||||
@Min(MIN_PORT)
|
||||
@Max(MAX_PORT)
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.smtp.port")
|
||||
private Integer smtpPort;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.smtp.username")
|
||||
private Optional<String> smtpUsername;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.smtp.password")
|
||||
private Optional<String> smtpPassword;
|
||||
|
||||
@NotBlank
|
||||
@Inject
|
||||
@ConfigProperty(name = "app.admin.email")
|
||||
private String adminEmailAddress;
|
||||
|
||||
// Collections thread-safe pour les configurations dynamiques
|
||||
private final Map<String, String> applicationUrls = new ConcurrentHashMap<>();
|
||||
private final Map<Environment, String> environmentConfigs = new EnumMap<>(Environment.class);
|
||||
private List<String> allowedFileTypesList;
|
||||
|
||||
/**
|
||||
* Initialise la configuration après l'injection des propriétés.
|
||||
* Valide et prépare l'ensemble des paramètres de configuration.
|
||||
*
|
||||
* @throws ConfigurationException si la configuration est invalide
|
||||
*/
|
||||
@PostConstruct
|
||||
void initialize() {
|
||||
try {
|
||||
log.info("Initialisation de la configuration de l'application: {}", applicationName);
|
||||
validateConfiguration();
|
||||
initializeApplicationUrls();
|
||||
initializeAllowedFileTypes();
|
||||
initializeEnvironmentConfigs();
|
||||
log.info("Configuration initialisée avec succès en environnement: {}", environment);
|
||||
} catch (Exception e) {
|
||||
String errorMessage = "Erreur lors de l'initialisation de la configuration";
|
||||
log.error(errorMessage, e);
|
||||
throw new ConfigurationException(errorMessage, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide l'ensemble de la configuration.
|
||||
*
|
||||
* @throws ConfigurationException si la validation échoue
|
||||
*/
|
||||
private void validateConfiguration() {
|
||||
log.debug("Validation de la configuration");
|
||||
validateEnvironment();
|
||||
validateStoragePaths();
|
||||
validateSmtpConfiguration();
|
||||
validateFileSize();
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide l'environnement d'exécution.
|
||||
*/
|
||||
private void validateEnvironment() {
|
||||
if (!isValidEnvironment(environment)) {
|
||||
throw new ConfigurationException("Environnement non reconnu: " + environment);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide les chemins de stockage.
|
||||
*/
|
||||
private void validateStoragePaths() {
|
||||
Path basePath = Paths.get(storageBasePath);
|
||||
validatePath(basePath, "stockage principal");
|
||||
|
||||
Path imagesPath = basePath.resolve(imageStoragePath);
|
||||
validatePath(imagesPath, "stockage des images");
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide un chemin spécifique.
|
||||
*/
|
||||
private void validatePath(Path path, String description) {
|
||||
if (!path.toFile().exists() && !path.toFile().mkdirs()) {
|
||||
throw new ConfigurationException(
|
||||
"Impossible de créer le répertoire de " + description + ": " + path);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide la configuration SMTP.
|
||||
*/
|
||||
private void validateSmtpConfiguration() {
|
||||
if (isSmtpConfigured() && (smtpPort < MIN_PORT || smtpPort > MAX_PORT)) {
|
||||
throw new ConfigurationException("Port SMTP invalide: " + smtpPort);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide la taille maximale des fichiers.
|
||||
*/
|
||||
private void validateFileSize() {
|
||||
if (maxFileSize <= 0) {
|
||||
throw new ConfigurationException(
|
||||
"Taille maximale de fichier invalide: " + maxFileSize);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère l'adresse email système (expéditeur par défaut).
|
||||
*
|
||||
* @return Adresse email système
|
||||
*/
|
||||
public String getSystemEmailAddress() {
|
||||
return emailFrom;
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si le SSL est activé pour le serveur SMTP.
|
||||
*
|
||||
* @return true si SSL est activé, sinon false
|
||||
*/
|
||||
public boolean isSmtpSslEnabled() {
|
||||
return smtpPort == 465; // Port 465 est commun pour SMTP avec SSL
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise les URLs de l'application.
|
||||
*/
|
||||
private void initializeApplicationUrls() {
|
||||
applicationUrls.clear();
|
||||
applicationUrls.put("home", "/");
|
||||
applicationUrls.put("services", "/services");
|
||||
applicationUrls.put("contact", "/contact");
|
||||
applicationUrls.put("admin", "/admin");
|
||||
applicationUrls.put("projects", "/projects");
|
||||
applicationUrls.put("portfolio", "/portfolio");
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise la liste des types de fichiers autorisés.
|
||||
*/
|
||||
private void initializeAllowedFileTypes() {
|
||||
allowedFileTypesList = Collections.unmodifiableList(
|
||||
Arrays.asList(allowedFileTypes.toLowerCase().split(","))
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise les configurations spécifiques aux environnements.
|
||||
*/
|
||||
private void initializeEnvironmentConfigs() {
|
||||
environmentConfigs.put(Environment.DEVELOPMENT, "dev");
|
||||
environmentConfigs.put(Environment.STAGING, "stage");
|
||||
environmentConfigs.put(Environment.PRODUCTION, "prod");
|
||||
}
|
||||
|
||||
// Méthodes publiques utilitaires
|
||||
|
||||
/**
|
||||
* Récupère le chemin complet pour le stockage des images.
|
||||
*/
|
||||
public String getImageStoragePath() {
|
||||
return Paths.get(storageBasePath, imageStoragePath).toString();
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un type de fichier est autorisé.
|
||||
*/
|
||||
public boolean isFileTypeAllowed(String fileType) {
|
||||
return fileType != null && allowedFileTypesList.contains(fileType.toLowerCase().trim());
|
||||
}
|
||||
|
||||
/**
|
||||
* Récupère l'URL d'une section de l'application.
|
||||
*/
|
||||
public String getUrl(String key) {
|
||||
return applicationUrls.getOrDefault(key, "/");
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'environnement est en développement.
|
||||
*/
|
||||
public boolean isDevelopment() {
|
||||
return Environment.DEVELOPMENT.getValue().equals(environment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'environnement est en production.
|
||||
*/
|
||||
public boolean isProduction() {
|
||||
return Environment.PRODUCTION.getValue().equals(environment);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si la configuration SMTP est complète.
|
||||
*/
|
||||
public boolean isSmtpConfigured() {
|
||||
return smtpUsername.isPresent() && smtpPassword.isPresent() &&
|
||||
smtpHost != null && !smtpHost.equals("localhost");
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si un environnement est valide.
|
||||
*/
|
||||
private boolean isValidEnvironment(String env) {
|
||||
return Arrays.stream(Environment.values())
|
||||
.anyMatch(e -> e.getValue().equals(env));
|
||||
}
|
||||
}
|
||||
@@ -1,180 +1,180 @@
|
||||
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<String, CachedValue<Object>> configCache;
|
||||
private final AtomicLong lastHealthCheck;
|
||||
|
||||
@Inject
|
||||
private Event<ConfigurationEvent> 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<T> {
|
||||
private final T value;
|
||||
private final long timestamp;
|
||||
|
||||
CachedValue(T value) {
|
||||
this.value = value;
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
T getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
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<String, CachedValue<Object>> configCache;
|
||||
private final AtomicLong lastHealthCheck;
|
||||
|
||||
@Inject
|
||||
private Event<ConfigurationEvent> 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<T> {
|
||||
private final T value;
|
||||
private final long timestamp;
|
||||
|
||||
CachedValue(T value) {
|
||||
this.value = value;
|
||||
this.timestamp = System.currentTimeMillis();
|
||||
}
|
||||
|
||||
T getValue() {
|
||||
return value;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,183 +1,183 @@
|
||||
package dev.lions.config;
|
||||
|
||||
import dev.lions.exceptions.ConfigurationException;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.faces.annotation.FacesConfig;
|
||||
import jakarta.faces.application.ViewHandler;
|
||||
import jakarta.faces.component.UIViewRoot;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.faces.event.PostConstructApplicationEvent;
|
||||
import jakarta.faces.event.PreDestroyApplicationEvent;
|
||||
import jakarta.faces.event.SystemEvent;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Configuration Jakarta Server Faces (JSF) de l'application.
|
||||
* Cette classe gère l'ensemble des paramètres et comportements spécifiques à JSF,
|
||||
* assurant une expérience utilisateur cohérente et performante.
|
||||
*
|
||||
* @author Lions Dev Team
|
||||
* @version 2.1
|
||||
*/
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
@FacesConfig
|
||||
public class JSFConfiguration {
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "jakarta.faces.PROJECT_STAGE", defaultValue = "Development")
|
||||
String projectStage;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "jakarta.faces.FACELETS_REFRESH_PERIOD", defaultValue = "2")
|
||||
Integer faceletsRefreshPeriod;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "jakarta.faces.STATE_SAVING_METHOD", defaultValue = "server")
|
||||
String stateSavingMethod;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "primefaces.THEME", defaultValue = "saga")
|
||||
private String primefacesTheme;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "jakarta.faces.VALIDATE_EMPTY_FIELDS", defaultValue = "true")
|
||||
private Boolean validateEmptyFields;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "jakarta.faces.FACELETS_SKIP_COMMENTS", defaultValue = "true")
|
||||
private Boolean skipComments;
|
||||
|
||||
/**
|
||||
* Initialise la configuration JSF au démarrage de l'application.
|
||||
*
|
||||
* @param event Événement de construction de l'application.
|
||||
*/
|
||||
public void initialize(@Observes @NotNull PostConstructApplicationEvent event) {
|
||||
try {
|
||||
log.info("Initialisation de la configuration JSF");
|
||||
|
||||
configureFacesContext();
|
||||
configureViewHandler();
|
||||
configurePrimeFaces();
|
||||
|
||||
applyPerformanceOptimizations();
|
||||
|
||||
log.info("Configuration JSF initialisée avec succès - Mode: {}", projectStage);
|
||||
|
||||
} catch (Exception e) {
|
||||
String message = "Erreur lors de l'initialisation de la configuration JSF";
|
||||
log.error(message, e);
|
||||
throw new ConfigurationException(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Nettoie les ressources JSF avant l'arrêt de l'application.
|
||||
*
|
||||
* @param event Événement de destruction de l'application.
|
||||
*/
|
||||
public void cleanup(@Observes @NotNull PreDestroyApplicationEvent event) {
|
||||
log.info("Nettoyage des ressources JSF");
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure le contexte Faces avec les paramètres spécifiques.
|
||||
*/
|
||||
private void configureFacesContext() {
|
||||
log.debug("Configuration du contexte Faces");
|
||||
|
||||
setFacesParameter("jakarta.faces.PROJECT_STAGE", projectStage);
|
||||
setFacesParameter("jakarta.faces.STATE_SAVING_METHOD", stateSavingMethod);
|
||||
setFacesParameter("jakarta.faces.FACELETS_REFRESH_PERIOD", faceletsRefreshPeriod.toString());
|
||||
setFacesParameter("jakarta.faces.VALIDATE_EMPTY_FIELDS", validateEmptyFields.toString());
|
||||
setFacesParameter("jakarta.faces.FACELETS_SKIP_COMMENTS", skipComments.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure les paramètres spécifiques au gestionnaire de vue.
|
||||
*/
|
||||
private void configureViewHandler() {
|
||||
log.debug("Configuration du gestionnaire de vues JSF");
|
||||
|
||||
FacesContext facesContext = FacesContext.getCurrentInstance();
|
||||
if (facesContext == null) {
|
||||
log.warn("Impossible de configurer le gestionnaire de vue : FacesContext est null.");
|
||||
return;
|
||||
}
|
||||
|
||||
ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
|
||||
UIViewRoot root = facesContext.getViewRoot();
|
||||
|
||||
if (root == null) {
|
||||
root = viewHandler.createView(facesContext, "/index.xhtml");
|
||||
facesContext.setViewRoot(root);
|
||||
}
|
||||
|
||||
root.getAttributes().put("encoding", "UTF-8");
|
||||
root.getAttributes().put("contentType", "text/html");
|
||||
root.getAttributes().put("characterEncoding", "UTF-8");
|
||||
|
||||
log.debug("Gestionnaire de vues configuré avec succès.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure les paramètres spécifiques à PrimeFaces.
|
||||
*/
|
||||
private void configurePrimeFaces() {
|
||||
log.debug("Configuration de PrimeFaces");
|
||||
|
||||
setFacesParameter("primefaces.THEME", primefacesTheme);
|
||||
setFacesParameter("primefaces.FONT_AWESOME", "true");
|
||||
setFacesParameter("primefaces.CLIENT_SIDE_VALIDATION", "true");
|
||||
setFacesParameter("primefaces.UPLOADER", "auto");
|
||||
|
||||
configurePrimeFacesCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure le cache PrimeFaces selon l'environnement.
|
||||
*/
|
||||
private void configurePrimeFacesCache() {
|
||||
String cacheProvider = isDevelopmentMode() ? "memory" : "ehcache";
|
||||
setFacesParameter("primefaces.CACHE_PROVIDER", cacheProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applique les optimisations de performance.
|
||||
*/
|
||||
private void applyPerformanceOptimizations() {
|
||||
if (!isDevelopmentMode()) {
|
||||
setFacesParameter("jakarta.faces.FACELETS_REFRESH_PERIOD", "-1");
|
||||
setFacesParameter("jakarta.faces.COMPRESS_VIEWSTATE", "true");
|
||||
setFacesParameter("jakarta.faces.PARTIAL_STATE_SAVING", "true");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit un paramètre dans le contexte Faces.
|
||||
*/
|
||||
private void setFacesParameter(String name, String value) {
|
||||
FacesContext.getCurrentInstance()
|
||||
.getExternalContext()
|
||||
.getApplicationMap()
|
||||
.put(name, value);
|
||||
|
||||
log.debug("Paramètre défini : {} = {}", name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'application est en mode développement.
|
||||
*
|
||||
* @return true si en mode développement, false sinon.
|
||||
*/
|
||||
public boolean isDevelopmentMode() {
|
||||
return "Development".equals(projectStage);
|
||||
}
|
||||
}
|
||||
package dev.lions.config;
|
||||
|
||||
import dev.lions.exceptions.ConfigurationException;
|
||||
import jakarta.enterprise.context.ApplicationScoped;
|
||||
import jakarta.enterprise.event.Observes;
|
||||
import jakarta.faces.annotation.FacesConfig;
|
||||
import jakarta.faces.application.ViewHandler;
|
||||
import jakarta.faces.component.UIViewRoot;
|
||||
import jakarta.faces.context.FacesContext;
|
||||
import jakarta.faces.event.PostConstructApplicationEvent;
|
||||
import jakarta.faces.event.PreDestroyApplicationEvent;
|
||||
import jakarta.faces.event.SystemEvent;
|
||||
import jakarta.inject.Inject;
|
||||
import jakarta.validation.constraints.NotNull;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.eclipse.microprofile.config.inject.ConfigProperty;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* Configuration Jakarta Server Faces (JSF) de l'application.
|
||||
* Cette classe gère l'ensemble des paramètres et comportements spécifiques à JSF,
|
||||
* assurant une expérience utilisateur cohérente et performante.
|
||||
*
|
||||
* @author Lions Dev Team
|
||||
* @version 2.1
|
||||
*/
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
@FacesConfig
|
||||
public class JSFConfiguration {
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "jakarta.faces.PROJECT_STAGE", defaultValue = "Development")
|
||||
String projectStage;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "jakarta.faces.FACELETS_REFRESH_PERIOD", defaultValue = "2")
|
||||
Integer faceletsRefreshPeriod;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "jakarta.faces.STATE_SAVING_METHOD", defaultValue = "server")
|
||||
String stateSavingMethod;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "primefaces.THEME", defaultValue = "saga")
|
||||
private String primefacesTheme;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "jakarta.faces.VALIDATE_EMPTY_FIELDS", defaultValue = "true")
|
||||
private Boolean validateEmptyFields;
|
||||
|
||||
@Inject
|
||||
@ConfigProperty(name = "jakarta.faces.FACELETS_SKIP_COMMENTS", defaultValue = "true")
|
||||
private Boolean skipComments;
|
||||
|
||||
/**
|
||||
* Initialise la configuration JSF au démarrage de l'application.
|
||||
*
|
||||
* @param event Événement de construction de l'application.
|
||||
*/
|
||||
public void initialize(@Observes @NotNull PostConstructApplicationEvent event) {
|
||||
try {
|
||||
log.info("Initialisation de la configuration JSF");
|
||||
|
||||
configureFacesContext();
|
||||
configureViewHandler();
|
||||
configurePrimeFaces();
|
||||
|
||||
applyPerformanceOptimizations();
|
||||
|
||||
log.info("Configuration JSF initialisée avec succès - Mode: {}", projectStage);
|
||||
|
||||
} catch (Exception e) {
|
||||
String message = "Erreur lors de l'initialisation de la configuration JSF";
|
||||
log.error(message, e);
|
||||
throw new ConfigurationException(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Nettoie les ressources JSF avant l'arrêt de l'application.
|
||||
*
|
||||
* @param event Événement de destruction de l'application.
|
||||
*/
|
||||
public void cleanup(@Observes @NotNull PreDestroyApplicationEvent event) {
|
||||
log.info("Nettoyage des ressources JSF");
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure le contexte Faces avec les paramètres spécifiques.
|
||||
*/
|
||||
private void configureFacesContext() {
|
||||
log.debug("Configuration du contexte Faces");
|
||||
|
||||
setFacesParameter("jakarta.faces.PROJECT_STAGE", projectStage);
|
||||
setFacesParameter("jakarta.faces.STATE_SAVING_METHOD", stateSavingMethod);
|
||||
setFacesParameter("jakarta.faces.FACELETS_REFRESH_PERIOD", faceletsRefreshPeriod.toString());
|
||||
setFacesParameter("jakarta.faces.VALIDATE_EMPTY_FIELDS", validateEmptyFields.toString());
|
||||
setFacesParameter("jakarta.faces.FACELETS_SKIP_COMMENTS", skipComments.toString());
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure les paramètres spécifiques au gestionnaire de vue.
|
||||
*/
|
||||
private void configureViewHandler() {
|
||||
log.debug("Configuration du gestionnaire de vues JSF");
|
||||
|
||||
FacesContext facesContext = FacesContext.getCurrentInstance();
|
||||
if (facesContext == null) {
|
||||
log.warn("Impossible de configurer le gestionnaire de vue : FacesContext est null.");
|
||||
return;
|
||||
}
|
||||
|
||||
ViewHandler viewHandler = facesContext.getApplication().getViewHandler();
|
||||
UIViewRoot root = facesContext.getViewRoot();
|
||||
|
||||
if (root == null) {
|
||||
root = viewHandler.createView(facesContext, "/index.xhtml");
|
||||
facesContext.setViewRoot(root);
|
||||
}
|
||||
|
||||
root.getAttributes().put("encoding", "UTF-8");
|
||||
root.getAttributes().put("contentType", "text/html");
|
||||
root.getAttributes().put("characterEncoding", "UTF-8");
|
||||
|
||||
log.debug("Gestionnaire de vues configuré avec succès.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure les paramètres spécifiques à PrimeFaces.
|
||||
*/
|
||||
private void configurePrimeFaces() {
|
||||
log.debug("Configuration de PrimeFaces");
|
||||
|
||||
setFacesParameter("primefaces.THEME", primefacesTheme);
|
||||
setFacesParameter("primefaces.FONT_AWESOME", "true");
|
||||
setFacesParameter("primefaces.CLIENT_SIDE_VALIDATION", "true");
|
||||
setFacesParameter("primefaces.UPLOADER", "auto");
|
||||
|
||||
configurePrimeFacesCache();
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure le cache PrimeFaces selon l'environnement.
|
||||
*/
|
||||
private void configurePrimeFacesCache() {
|
||||
String cacheProvider = isDevelopmentMode() ? "memory" : "ehcache";
|
||||
setFacesParameter("primefaces.CACHE_PROVIDER", cacheProvider);
|
||||
}
|
||||
|
||||
/**
|
||||
* Applique les optimisations de performance.
|
||||
*/
|
||||
private void applyPerformanceOptimizations() {
|
||||
if (!isDevelopmentMode()) {
|
||||
setFacesParameter("jakarta.faces.FACELETS_REFRESH_PERIOD", "-1");
|
||||
setFacesParameter("jakarta.faces.COMPRESS_VIEWSTATE", "true");
|
||||
setFacesParameter("jakarta.faces.PARTIAL_STATE_SAVING", "true");
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Définit un paramètre dans le contexte Faces.
|
||||
*/
|
||||
private void setFacesParameter(String name, String value) {
|
||||
FacesContext.getCurrentInstance()
|
||||
.getExternalContext()
|
||||
.getApplicationMap()
|
||||
.put(name, value);
|
||||
|
||||
log.debug("Paramètre défini : {} = {}", name, value);
|
||||
}
|
||||
|
||||
/**
|
||||
* Vérifie si l'application est en mode développement.
|
||||
*
|
||||
* @return true si en mode développement, false sinon.
|
||||
*/
|
||||
public boolean isDevelopmentMode() {
|
||||
return "Development".equals(projectStage);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,264 +1,264 @@
|
||||
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.StorageEvent;
|
||||
import dev.lions.exceptions.StorageConfigurationException;
|
||||
import dev.lions.utils.SecurityUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.nio.file.attribute.PosixFilePermissions;
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Service de gestion avancée des configurations de stockage.
|
||||
* Assure la gestion sécurisée et optimisée des paramètres de stockage fichier
|
||||
* de l'application, avec validation complète et monitoring.
|
||||
*
|
||||
* @author Lions Dev Team
|
||||
* @version 2.1
|
||||
*/
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class StorageConfigService {
|
||||
|
||||
private static final String DEFAULT_DIRECTORY_PERMISSIONS = "rwxr-x---";
|
||||
private static final long MIN_FREE_SPACE_BYTES = 100 * 1024 * 1024; // 100 MB
|
||||
private static final int CLEANUP_BATCH_SIZE = 100;
|
||||
private static final Duration CLEANUP_INTERVAL = Duration.ofHours(24);
|
||||
|
||||
private final Map<String, Path> pathCache;
|
||||
private final Map<String, Boolean> fileTypeCache;
|
||||
private final ApplicationConfig appConfig;
|
||||
private final SecurityUtils securityUtils;
|
||||
|
||||
@Inject
|
||||
Event<StorageEvent> storageEvent;
|
||||
|
||||
/**
|
||||
* Initialise le service avec la configuration de l'application.
|
||||
*
|
||||
* @param appConfig Configuration de l'application
|
||||
* @param securityUtils Utilitaires de sécurité
|
||||
*/
|
||||
@Inject
|
||||
public StorageConfigService(@NotNull ApplicationConfig appConfig,
|
||||
@NotNull SecurityUtils securityUtils) {
|
||||
this.appConfig = appConfig;
|
||||
this.securityUtils = securityUtils;
|
||||
this.pathCache = new ConcurrentHashMap<>();
|
||||
this.fileTypeCache = new ConcurrentHashMap<>();
|
||||
|
||||
initializeStorage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise et valide la configuration du stockage.
|
||||
*/
|
||||
private void initializeStorage() {
|
||||
log.info("Initialisation de la configuration du stockage");
|
||||
|
||||
try {
|
||||
createMainDirectories();
|
||||
configureSecurity();
|
||||
scheduleMaintenanceTasks();
|
||||
validateStorageCapacity();
|
||||
notifyStorageInitialized();
|
||||
|
||||
log.info("Configuration du stockage initialisée avec succès");
|
||||
|
||||
} catch (Exception e) {
|
||||
String message = "Erreur lors de l'initialisation du stockage";
|
||||
log.error(message, e);
|
||||
throw new StorageConfigurationException(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée les répertoires principaux nécessaires au stockage.
|
||||
*/
|
||||
private void createMainDirectories() {
|
||||
log.debug("Création des répertoires principaux de stockage");
|
||||
|
||||
String basePath = appConfig.getStorageBasePath();
|
||||
Set<String> requiredDirs = Set.of("images", "documents", "temp", "backup");
|
||||
|
||||
requiredDirs.forEach(dir -> {
|
||||
Path dirPath = Paths.get(basePath, dir);
|
||||
createSecureDirectory(dirPath);
|
||||
});
|
||||
|
||||
log.info("Répertoires principaux créés avec succès.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure les paramètres de sécurité pour la production.
|
||||
*/
|
||||
private void applyProductionSecurity() {
|
||||
log.info("Application des paramètres de sécurité spécifiques pour la production");
|
||||
|
||||
try {
|
||||
Path basePath = Paths.get(appConfig.getStorageBasePath());
|
||||
|
||||
// Applique des permissions POSIX sécurisées
|
||||
Set<PosixFilePermission> permissions =
|
||||
PosixFilePermissions.fromString(DEFAULT_DIRECTORY_PERMISSIONS);
|
||||
|
||||
Files.setPosixFilePermissions(basePath, permissions);
|
||||
log.info("Permissions POSIX sécurisées appliquées : {}", permissions);
|
||||
|
||||
// Vérifie l'accès sécurisé
|
||||
if (!Files.isWritable(basePath) || !Files.isReadable(basePath)) {
|
||||
throw new StorageConfigurationException(
|
||||
"Permissions insuffisantes sur le répertoire de stockage : " + basePath);
|
||||
}
|
||||
|
||||
log.debug("Sécurité des répertoires en production validée");
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("Erreur lors de l'application des permissions de sécurité", e);
|
||||
throw new StorageConfigurationException(
|
||||
"Impossible d'appliquer les paramètres de sécurité en production", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure les paramètres de sécurité pour le stockage.
|
||||
*/
|
||||
private void configureSecurity() {
|
||||
log.info("Configuration des paramètres de sécurité du stockage");
|
||||
|
||||
try {
|
||||
if (appConfig.isProduction()) {
|
||||
applyProductionSecurity();
|
||||
}
|
||||
securityUtils.initializeEncryption();
|
||||
log.info("Sécurité du stockage configurée avec succès");
|
||||
} catch (Exception e) {
|
||||
throw new StorageConfigurationException("Erreur lors de la configuration de la sécurité", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Planifie les tâches de maintenance pour le stockage.
|
||||
*/
|
||||
private void scheduleMaintenanceTasks() {
|
||||
log.info("Planification des tâches de maintenance du stockage");
|
||||
|
||||
try {
|
||||
scheduleStorageCleanup();
|
||||
scheduleCapacityCheck();
|
||||
log.info("Tâches de maintenance planifiées avec succès.");
|
||||
} catch (Exception e) {
|
||||
throw new StorageConfigurationException("Erreur lors de la planification des tâches de maintenance", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un répertoire sécurisé avec les permissions appropriées.
|
||||
*/
|
||||
private void createSecureDirectory(Path path) {
|
||||
try {
|
||||
if (!Files.exists(path)) {
|
||||
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions
|
||||
.asFileAttribute(PosixFilePermissions.fromString(DEFAULT_DIRECTORY_PERMISSIONS));
|
||||
Files.createDirectories(path, attr);
|
||||
log.debug("Répertoire créé avec succès : {}", path);
|
||||
}
|
||||
validateDirectoryAccess(path);
|
||||
} catch (IOException e) {
|
||||
throw new StorageConfigurationException(
|
||||
"Impossible de créer le répertoire sécurisé : " + path, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Planifie le nettoyage automatique du stockage.
|
||||
*/
|
||||
private void scheduleStorageCleanup() {
|
||||
log.info("Planification de la tâche de nettoyage automatique du stockage");
|
||||
// Simulation d'une tâche de nettoyage. Remplacer par un vrai scheduler si nécessaire.
|
||||
log.debug("Nettoyage automatique exécuté toutes les {} heures, batch size: {}",
|
||||
CLEANUP_INTERVAL.toHours(), CLEANUP_BATCH_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Planifie la vérification périodique de la capacité de stockage.
|
||||
*/
|
||||
private void scheduleCapacityCheck() {
|
||||
log.info("Planification de la vérification périodique de la capacité de stockage");
|
||||
// Simulation d'une vérification périodique. À remplacer par un scheduler réel.
|
||||
log.debug("Vérification de la capacité planifiée toutes les {} heures", CLEANUP_INTERVAL.toHours());
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide la capacité de stockage disponible.
|
||||
*/
|
||||
private void validateStorageCapacity() {
|
||||
try {
|
||||
Path storagePath = Paths.get(appConfig.getStorageBasePath());
|
||||
long freeSpace = Files.getFileStore(storagePath).getUsableSpace();
|
||||
|
||||
if (freeSpace < MIN_FREE_SPACE_BYTES) {
|
||||
throw new StorageConfigurationException(
|
||||
"Espace de stockage insuffisant. Minimum requis : " +
|
||||
formatSize(MIN_FREE_SPACE_BYTES));
|
||||
}
|
||||
|
||||
log.debug("Espace de stockage validé : {} disponible", formatSize(freeSpace));
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new StorageConfigurationException(
|
||||
"Impossible de vérifier l'espace de stockage disponible", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formate une taille en bytes en format lisible.
|
||||
*/
|
||||
private String formatSize(long bytes) {
|
||||
if (bytes < 1024) return bytes + " B";
|
||||
int exp = (int) (Math.log(bytes) / Math.log(1024));
|
||||
String pre = "KMGTPE".charAt(exp - 1) + "";
|
||||
return String.format("%.1f %sB", bytes / Math.pow(1024, exp), pre);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifie les observateurs de l'initialisation du stockage.
|
||||
*/
|
||||
private void notifyStorageInitialized() {
|
||||
StorageEvent event = new StorageEvent(
|
||||
"STORAGE_INITIALIZED",
|
||||
Map.of(
|
||||
"basePath", appConfig.getStorageBasePath(),
|
||||
"environment", appConfig.getEnvironment()
|
||||
)
|
||||
);
|
||||
storageEvent.fire(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide l'accès au répertoire.
|
||||
*/
|
||||
private void validateDirectoryAccess(Path path) {
|
||||
if (!Files.isDirectory(path)) {
|
||||
throw new StorageConfigurationException(
|
||||
"Le chemin n'est pas un répertoire : " + path);
|
||||
}
|
||||
if (!Files.isWritable(path)) {
|
||||
throw new StorageConfigurationException(
|
||||
"Le répertoire n'est pas accessible en écriture : " + path);
|
||||
}
|
||||
}
|
||||
}
|
||||
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.StorageEvent;
|
||||
import dev.lions.exceptions.StorageConfigurationException;
|
||||
import dev.lions.utils.SecurityUtils;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.nio.file.*;
|
||||
import java.nio.file.attribute.FileAttribute;
|
||||
import java.nio.file.attribute.PosixFilePermission;
|
||||
import java.nio.file.attribute.PosixFilePermissions;
|
||||
import java.time.Duration;
|
||||
import java.util.Map;
|
||||
import java.util.Set;
|
||||
import java.util.concurrent.ConcurrentHashMap;
|
||||
|
||||
/**
|
||||
* Service de gestion avancée des configurations de stockage.
|
||||
* Assure la gestion sécurisée et optimisée des paramètres de stockage fichier
|
||||
* de l'application, avec validation complète et monitoring.
|
||||
*
|
||||
* @author Lions Dev Team
|
||||
* @version 2.1
|
||||
*/
|
||||
@Slf4j
|
||||
@ApplicationScoped
|
||||
public class StorageConfigService {
|
||||
|
||||
private static final String DEFAULT_DIRECTORY_PERMISSIONS = "rwxr-x---";
|
||||
private static final long MIN_FREE_SPACE_BYTES = 100 * 1024 * 1024; // 100 MB
|
||||
private static final int CLEANUP_BATCH_SIZE = 100;
|
||||
private static final Duration CLEANUP_INTERVAL = Duration.ofHours(24);
|
||||
|
||||
private final Map<String, Path> pathCache;
|
||||
private final Map<String, Boolean> fileTypeCache;
|
||||
private final ApplicationConfig appConfig;
|
||||
private final SecurityUtils securityUtils;
|
||||
|
||||
@Inject
|
||||
Event<StorageEvent> storageEvent;
|
||||
|
||||
/**
|
||||
* Initialise le service avec la configuration de l'application.
|
||||
*
|
||||
* @param appConfig Configuration de l'application
|
||||
* @param securityUtils Utilitaires de sécurité
|
||||
*/
|
||||
@Inject
|
||||
public StorageConfigService(@NotNull ApplicationConfig appConfig,
|
||||
@NotNull SecurityUtils securityUtils) {
|
||||
this.appConfig = appConfig;
|
||||
this.securityUtils = securityUtils;
|
||||
this.pathCache = new ConcurrentHashMap<>();
|
||||
this.fileTypeCache = new ConcurrentHashMap<>();
|
||||
|
||||
initializeStorage();
|
||||
}
|
||||
|
||||
/**
|
||||
* Initialise et valide la configuration du stockage.
|
||||
*/
|
||||
private void initializeStorage() {
|
||||
log.info("Initialisation de la configuration du stockage");
|
||||
|
||||
try {
|
||||
createMainDirectories();
|
||||
configureSecurity();
|
||||
scheduleMaintenanceTasks();
|
||||
validateStorageCapacity();
|
||||
notifyStorageInitialized();
|
||||
|
||||
log.info("Configuration du stockage initialisée avec succès");
|
||||
|
||||
} catch (Exception e) {
|
||||
String message = "Erreur lors de l'initialisation du stockage";
|
||||
log.error(message, e);
|
||||
throw new StorageConfigurationException(message, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée les répertoires principaux nécessaires au stockage.
|
||||
*/
|
||||
private void createMainDirectories() {
|
||||
log.debug("Création des répertoires principaux de stockage");
|
||||
|
||||
String basePath = appConfig.getStorageBasePath();
|
||||
Set<String> requiredDirs = Set.of("images", "documents", "temp", "backup");
|
||||
|
||||
requiredDirs.forEach(dir -> {
|
||||
Path dirPath = Paths.get(basePath, dir);
|
||||
createSecureDirectory(dirPath);
|
||||
});
|
||||
|
||||
log.info("Répertoires principaux créés avec succès.");
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure les paramètres de sécurité pour la production.
|
||||
*/
|
||||
private void applyProductionSecurity() {
|
||||
log.info("Application des paramètres de sécurité spécifiques pour la production");
|
||||
|
||||
try {
|
||||
Path basePath = Paths.get(appConfig.getStorageBasePath());
|
||||
|
||||
// Applique des permissions POSIX sécurisées
|
||||
Set<PosixFilePermission> permissions =
|
||||
PosixFilePermissions.fromString(DEFAULT_DIRECTORY_PERMISSIONS);
|
||||
|
||||
Files.setPosixFilePermissions(basePath, permissions);
|
||||
log.info("Permissions POSIX sécurisées appliquées : {}", permissions);
|
||||
|
||||
// Vérifie l'accès sécurisé
|
||||
if (!Files.isWritable(basePath) || !Files.isReadable(basePath)) {
|
||||
throw new StorageConfigurationException(
|
||||
"Permissions insuffisantes sur le répertoire de stockage : " + basePath);
|
||||
}
|
||||
|
||||
log.debug("Sécurité des répertoires en production validée");
|
||||
|
||||
} catch (IOException e) {
|
||||
log.error("Erreur lors de l'application des permissions de sécurité", e);
|
||||
throw new StorageConfigurationException(
|
||||
"Impossible d'appliquer les paramètres de sécurité en production", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Configure les paramètres de sécurité pour le stockage.
|
||||
*/
|
||||
private void configureSecurity() {
|
||||
log.info("Configuration des paramètres de sécurité du stockage");
|
||||
|
||||
try {
|
||||
if (appConfig.isProduction()) {
|
||||
applyProductionSecurity();
|
||||
}
|
||||
securityUtils.initializeEncryption();
|
||||
log.info("Sécurité du stockage configurée avec succès");
|
||||
} catch (Exception e) {
|
||||
throw new StorageConfigurationException("Erreur lors de la configuration de la sécurité", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Planifie les tâches de maintenance pour le stockage.
|
||||
*/
|
||||
private void scheduleMaintenanceTasks() {
|
||||
log.info("Planification des tâches de maintenance du stockage");
|
||||
|
||||
try {
|
||||
scheduleStorageCleanup();
|
||||
scheduleCapacityCheck();
|
||||
log.info("Tâches de maintenance planifiées avec succès.");
|
||||
} catch (Exception e) {
|
||||
throw new StorageConfigurationException("Erreur lors de la planification des tâches de maintenance", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Crée un répertoire sécurisé avec les permissions appropriées.
|
||||
*/
|
||||
private void createSecureDirectory(Path path) {
|
||||
try {
|
||||
if (!Files.exists(path)) {
|
||||
FileAttribute<Set<PosixFilePermission>> attr = PosixFilePermissions
|
||||
.asFileAttribute(PosixFilePermissions.fromString(DEFAULT_DIRECTORY_PERMISSIONS));
|
||||
Files.createDirectories(path, attr);
|
||||
log.debug("Répertoire créé avec succès : {}", path);
|
||||
}
|
||||
validateDirectoryAccess(path);
|
||||
} catch (IOException e) {
|
||||
throw new StorageConfigurationException(
|
||||
"Impossible de créer le répertoire sécurisé : " + path, e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Planifie le nettoyage automatique du stockage.
|
||||
*/
|
||||
private void scheduleStorageCleanup() {
|
||||
log.info("Planification de la tâche de nettoyage automatique du stockage");
|
||||
// Simulation d'une tâche de nettoyage. Remplacer par un vrai scheduler si nécessaire.
|
||||
log.debug("Nettoyage automatique exécuté toutes les {} heures, batch size: {}",
|
||||
CLEANUP_INTERVAL.toHours(), CLEANUP_BATCH_SIZE);
|
||||
}
|
||||
|
||||
/**
|
||||
* Planifie la vérification périodique de la capacité de stockage.
|
||||
*/
|
||||
private void scheduleCapacityCheck() {
|
||||
log.info("Planification de la vérification périodique de la capacité de stockage");
|
||||
// Simulation d'une vérification périodique. À remplacer par un scheduler réel.
|
||||
log.debug("Vérification de la capacité planifiée toutes les {} heures", CLEANUP_INTERVAL.toHours());
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide la capacité de stockage disponible.
|
||||
*/
|
||||
private void validateStorageCapacity() {
|
||||
try {
|
||||
Path storagePath = Paths.get(appConfig.getStorageBasePath());
|
||||
long freeSpace = Files.getFileStore(storagePath).getUsableSpace();
|
||||
|
||||
if (freeSpace < MIN_FREE_SPACE_BYTES) {
|
||||
throw new StorageConfigurationException(
|
||||
"Espace de stockage insuffisant. Minimum requis : " +
|
||||
formatSize(MIN_FREE_SPACE_BYTES));
|
||||
}
|
||||
|
||||
log.debug("Espace de stockage validé : {} disponible", formatSize(freeSpace));
|
||||
|
||||
} catch (IOException e) {
|
||||
throw new StorageConfigurationException(
|
||||
"Impossible de vérifier l'espace de stockage disponible", e);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Formate une taille en bytes en format lisible.
|
||||
*/
|
||||
private String formatSize(long bytes) {
|
||||
if (bytes < 1024) return bytes + " B";
|
||||
int exp = (int) (Math.log(bytes) / Math.log(1024));
|
||||
String pre = "KMGTPE".charAt(exp - 1) + "";
|
||||
return String.format("%.1f %sB", bytes / Math.pow(1024, exp), pre);
|
||||
}
|
||||
|
||||
/**
|
||||
* Notifie les observateurs de l'initialisation du stockage.
|
||||
*/
|
||||
private void notifyStorageInitialized() {
|
||||
StorageEvent event = new StorageEvent(
|
||||
"STORAGE_INITIALIZED",
|
||||
Map.of(
|
||||
"basePath", appConfig.getStorageBasePath(),
|
||||
"environment", appConfig.getEnvironment()
|
||||
)
|
||||
);
|
||||
storageEvent.fire(event);
|
||||
}
|
||||
|
||||
/**
|
||||
* Valide l'accès au répertoire.
|
||||
*/
|
||||
private void validateDirectoryAccess(Path path) {
|
||||
if (!Files.isDirectory(path)) {
|
||||
throw new StorageConfigurationException(
|
||||
"Le chemin n'est pas un répertoire : " + path);
|
||||
}
|
||||
if (!Files.isWritable(path)) {
|
||||
throw new StorageConfigurationException(
|
||||
"Le répertoire n'est pas accessible en écriture : " + path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user