Tony CHEMIT pushed to branch develop at ultreiaio / ird-observe Commits: 2b2f14d4 by Tony Chemit at 2023-10-05T20:31:51+02:00 Problème de connexion au serveur IEO - Closes #2791 - - - - - e2385264 by Tony Chemit at 2023-10-06T09:52:51+02:00 Une incompatibilité empêche l'ouverture de l'application sous Java 21 - Closes #2792 - - - - - 11 changed files: - client/configuration/src/main/config/Client.ini - client/configuration/src/main/i18n/getters/config.getter - client/configuration/src/main/i18n/getters/java.getter - client/configuration/src/main/java/fr/ird/observe/client/configuration/ClientConfig.java - client/configuration/src/main/java/fr/ird/observe/client/configuration/ClientResources.java - + client/configuration/src/main/resources/observe.jks - client/core/src/main/java/fr/ird/observe/client/datasource/h2/backup/BackupsManager.java - client/core/src/main/java/fr/ird/observe/client/main/body/ClientConfigUI.java - client/runner/src/main/i18n/translations/client-runner_en_GB.properties - client/runner/src/main/i18n/translations/client-runner_es_ES.properties - client/runner/src/main/i18n/translations/client-runner_fr_FR.properties Changes: ===================================== client/configuration/src/main/config/Client.ini ===================================== @@ -331,6 +331,12 @@ type = file defaultValue = ${instance.resources.directory}/observe-log4j2.xml transient = true +[option useJvmKeyStore] +description = observe.config.useJvmKeyStore.description +key = instance.useJvmKeyStore +type = Boolean +defaultValue = false + [option longlineActivityPairingMaxDistance] description = observe.config.longlineActivityPairing.maxDistance key = instance.longlineActivityPairing.maxDistance ===================================== client/configuration/src/main/i18n/getters/config.getter ===================================== @@ -153,6 +153,7 @@ observe.config.ui.tree.node.disabled.color observe.config.ui.tree.node.empty.color observe.config.ui.tree.node.unloaded.color observe.config.ui.tree.node.unsaved.color +observe.config.useJvmKeyStore.description observe.config.validation.lengthWeightEnable observe.config.validation.speedEnable observe.config.validation.speedMaxValue ===================================== client/configuration/src/main/i18n/getters/java.getter ===================================== @@ -5,7 +5,9 @@ observe.runner.copy.default.map.file observe.runner.copy.default.report.file observe.runner.copy.default.swing.preferences.file observe.runner.copy.default.ui.file +observe.runner.copy.embedded.keystore.file observe.runner.loading.ui.configuration +observe.runner.use.embedded.keystore.file observe.ui.message.save.configuration observe.warning.nimbus.landf observe.warning.no.ui ===================================== client/configuration/src/main/java/fr/ird/observe/client/configuration/ClientConfig.java ===================================== @@ -430,6 +430,26 @@ public class ClientConfig extends GeneratedClientConfig implements TripMapConfig // 11 - export directory createDirectory(ClientConfigOption.EXPORT_DIRECTORY); + + // 12 - Add custom keystore (See https://gitlab.com/ultreiaio/ird-observe/-/issues/2791) + + Path keystore = resourcesDirectory.toPath().resolve("observe.jks"); + if (Files.notExists(keystore)) { + String message = t("observe.runner.copy.embedded.keystore.file", keystore); + log.info(message); + ClientResources.KEYSTORE.copyResource(keystore.toFile()); + } + + if (!isUseJvmKeyStore()) { + String message = t("observe.runner.use.embedded.keystore.file", keystore); + log.info(message); + System.setProperty("javax.net.ssl.trustStore", keystore.toString()); + System.setProperty("javax.net.ssl.trustStorePassword", "changeit"); + } else { + System.clearProperty("javax.net.ssl.trustStore"); + System.clearProperty("javax.net.ssl.trustStorePassword"); + } + } public void detectLocalDataBase() { ===================================== client/configuration/src/main/java/fr/ird/observe/client/configuration/ClientResources.java ===================================== @@ -42,4 +42,5 @@ public final class ClientResources { public static final ConfigResource LOG_CONFIGURATION_FILE = new ConfigResource("/observe-log4j2.xml"); public static final ConfigResource DCP_PRESETS = new ConfigResource("/dcp-presets.zip"); public static final ConfigResource mapLayers = new ConfigResource("/map.zip"); + public static final ConfigResource KEYSTORE = new ConfigResource("/observe.jks"); } ===================================== client/configuration/src/main/resources/observe.jks ===================================== Binary files /dev/null and b/client/configuration/src/main/resources/observe.jks differ ===================================== client/core/src/main/java/fr/ird/observe/client/datasource/h2/backup/BackupsManager.java ===================================== @@ -23,6 +23,7 @@ package fr.ird.observe.client.datasource.h2.backup; */ import com.google.gson.Gson; +import com.google.gson.GsonBuilder; import com.google.gson.reflect.TypeToken; import fr.ird.observe.client.configuration.ClientConfig; import fr.ird.observe.client.datasource.api.ObserveDataSourcesManager; @@ -30,10 +31,10 @@ import fr.ird.observe.client.datasource.api.ObserveSwingDataSource; import fr.ird.observe.client.datasource.api.event.ObserveSwingDataSourceEvent; import fr.ird.observe.client.datasource.api.event.ObserveSwingDataSourceListenerAdapter; import fr.ird.observe.client.util.ObserveSwingTechnicalException; -import io.ultreia.java4all.lang.Strings; +import io.ultreia.java4all.util.json.adapters.DateAdapter; +import io.ultreia.java4all.util.sql.SqlScript; import org.apache.logging.log4j.LogManager; import org.apache.logging.log4j.Logger; -import io.ultreia.java4all.util.sql.SqlScript; import java.io.BufferedReader; import java.io.BufferedWriter; @@ -41,12 +42,8 @@ import java.io.Closeable; import java.io.IOException; import java.lang.reflect.Type; import java.nio.charset.StandardCharsets; -import java.nio.file.FileVisitResult; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.SimpleFileVisitor; -import java.nio.file.attribute.BasicFileAttributes; -import java.util.ArrayList; import java.util.Comparator; import java.util.Date; import java.util.Iterator; @@ -69,11 +66,11 @@ public class BackupsManager implements Closeable { private static final Pattern AUTOMATIC_BACKUP_FILENAME_PATTERN = Pattern.compile("obs.+-([0-9-]+)\\.sql\\.gz"); - private final Path backupsPath; private final ObserveDataSourcesManager dataSourcesManager; private final Path storePath; private final List<BackupStorage> backups; private final BlockingDeque<BackupStorage> backupsToCheck = new LinkedBlockingDeque<>(); + private final Gson gson; private boolean run = true; private final Thread checkBackups = new Thread("Check-Backups") { @Override @@ -121,16 +118,21 @@ public class BackupsManager implements Closeable { public BackupsManager(ClientConfig config, ObserveDataSourcesManager dataSourcesManager) { this.storePath = config.getBackupsFile().toPath(); - this.backupsPath = config.getBackupDirectory().toPath(); this.dataSourcesManager = dataSourcesManager; - + this.gson = new GsonBuilder().registerTypeAdapter(Date.class, new DateAdapter()).create(); try { List<BackupStorage> backups; if (config.isBackupUse() && Files.exists(storePath)) { try (BufferedReader reader = Files.newBufferedReader(storePath, StandardCharsets.UTF_8)) { Type typeOfT = new TypeToken<List<BackupStorage>>() { }.getType(); - backups = new Gson().fromJson(reader, typeOfT); + + try { + backups = gson.fromJson(reader, typeOfT); + } catch (Exception e) { + log.error(String.format("Could not load %s file.", storePath), e); + backups = new LinkedList<>(); + } log.info(String.format("Loaded %d backups from %s", backups.size(), storePath)); } } else { @@ -160,36 +162,10 @@ public class BackupsManager implements Closeable { } } - private List<BackupStorage> discoverAutomaticBackups(Path backupsPath) throws IOException { - List<BackupStorage> backups = new ArrayList<>(); - Files.walkFileTree(backupsPath, new SimpleFileVisitor<>() { - @Override - public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException { - Matcher matcher = AUTOMATIC_BACKUP_FILENAME_PATTERN.matcher(file.toFile().getName()); - if (matcher.matches()) { - BackupStorage backupStorage = new BackupStorage(); - backupStorage.setDate(new Date(Files.getLastModifiedTime(file).toMillis())); - backupStorage.setFile(file.toFile()); - backupStorage.setAutomatic(true); - backupStorage.setVerified(false); - backupStorage.setName(matcher.group(1)); - backups.add(backupStorage); - } - return FileVisitResult.CONTINUE; - } - }); - log.info(String.format("Discovered %d automatic backups from %s", backups.size(), backupsPath)); - return backups; - } - public List<BackupStorage> getAutomaticBackups() { return backups.stream().filter(BackupStorage::isAutomatic).sorted(Comparator.comparing(BackupStorage::getDate).reversed()).collect(Collectors.toList()); } - public List<BackupStorage> getUserBackups() { - return backups.stream().filter(BackupStorage::isUser).sorted(Comparator.comparing(BackupStorage::getDate).reversed()).collect(Collectors.toList()); - } - public void addAutomaticBackup(Path backupPath) { Matcher matcher = AUTOMATIC_BACKUP_FILENAME_PATTERN.matcher(backupPath.toFile().getName()); if (!matcher.matches()) { @@ -204,21 +180,6 @@ public class BackupsManager implements Closeable { backupsToCheck.add(backupStorage); } - public void addUserBackup(Path backupPath) { - BackupStorage backupStorage = new BackupStorage(); - backupStorage.setDate(new Date()); - backupStorage.setFile(backupPath.toFile()); - backupStorage.setAutomatic(false); - backupStorage.setVerified(false); - String name = Strings.removeEnd(backupPath.toFile().getName(), ".sql.gz"); - backupStorage.setName(name); - backupsToCheck.add(backupStorage); - } - - public void sanityBackups() { - log.info("Sanity backups at " + backupsPath); - } - @Override public void close() { @@ -239,7 +200,7 @@ public class BackupsManager implements Closeable { private void storeBackups() throws IOException { log.info(String.format("Store %d backups to %s", backups.size(), storePath)); try (BufferedWriter writer = Files.newBufferedWriter(storePath, StandardCharsets.UTF_8)) { - new Gson().toJson(backups, writer); + gson.toJson(backups, writer); } } ===================================== client/core/src/main/java/fr/ird/observe/client/main/body/ClientConfigUI.java ===================================== @@ -406,6 +406,7 @@ public class ClientConfigUI extends JXTitledPanel implements WithClientUIContext helper.addOption(ClientConfigOption.AVDTH_FORCE_IMPORT); helper.addOption(ClientConfigOption.SHOW_SQL); + helper.addOption(ClientConfigOption.USE_JVM_KEY_STORE); } ===================================== client/runner/src/main/i18n/translations/client-runner_en_GB.properties ===================================== @@ -170,6 +170,7 @@ observe.config.ui.tree.node.disabled.color=Color for disabled node observe.config.ui.tree.node.empty.color=Color for empty node observe.config.ui.tree.node.unloaded.color=Color for unloaded node observe.config.ui.tree.node.unsaved.color=Color for unsaved node +observe.config.useJvmKeyStore.description=To use the Java «keystore», otherwise will use the embedded «keystore» (located at resources-xxx/observe.jks). observe.config.validation.lengthWeightEnable=Force validation of species length max observe.config.validation.speedEnable=Force validation of activities speed observe.config.validation.speedMaxValue=Max speed value used in activities speed validation @@ -283,6 +284,7 @@ observe.runner.copy.default.map.file=Création des cartes %1$s. observe.runner.copy.default.report.file=Création du fichier de reports %1$s. observe.runner.copy.default.swing.preferences.file=Création du fichier de préférence Swing %1$s. observe.runner.copy.default.ui.file=Création du fichier de cosmétique %1$s. +observe.runner.copy.embedded.keystore.file=Copy embedded keystore (%s). observe.runner.i18n.loaded=Service de traduction chargé dans la langue %1$s. observe.runner.init=Initialisation d'ObServe %1$s %2$s observe.runner.initStorage.choice.createLocalStorage=Create local storage @@ -305,6 +307,7 @@ observe.runner.quit.without.ui=Close application without opening ui observe.runner.start=Start ObServe %1$s %2$s observe.runner.title.error.dialog=An error occurs\! observe.runner.ui.loaded=Graphical interface is ready. +observe.runner.use.embedded.keystore.file=Use embedded keystore (%s). observe.runner.user.directories.loaded=User directory is ready (%1$s). observe.security.role=Role observe.security.role.administrator=Owner of database ===================================== client/runner/src/main/i18n/translations/client-runner_es_ES.properties ===================================== @@ -170,6 +170,7 @@ observe.config.ui.tree.node.disabled.color=Color for disabled node observe.config.ui.tree.node.empty.color=Color for empty node observe.config.ui.tree.node.unloaded.color=Color for unloaded node observe.config.ui.tree.node.unsaved.color=Color for unsaved node +observe.config.useJvmKeyStore.description=To use the Java «keystore», otherwise will use the embedded «keystore» (located at resources-xxx/observe.jks). \#TODO observe.config.validation.lengthWeightEnable=Forzar la validación de la talla de especies min/max observe.config.validation.speedEnable=Forzar la validación de las velocidades de las actividades observe.config.validation.speedMaxValue=Velocidad máxima autorizada en el control de las velocidades de las actividades @@ -283,6 +284,7 @@ observe.runner.copy.default.map.file=Creación de los mapas %1$s. observe.runner.copy.default.report.file=Creación del archivo de informes %1$s. observe.runner.copy.default.swing.preferences.file=Création du fichier de préférence Swing %1$s. observe.runner.copy.default.ui.file=Creación del archivo de cosmético %1$s. +observe.runner.copy.embedded.keystore.file=Copy embedded keystore (%s). \#TODO observe.runner.i18n.loaded=Servicio de traducción cargado en el idioma %1$s. observe.runner.init=Inicialización de ObServe %1$s %2$s observe.runner.initStorage.choice.createLocalStorage=Crear la base local @@ -305,6 +307,7 @@ observe.runner.quit.without.ui=Cierre de la aplicación sin abrir la interfaz gr observe.runner.start=Inicio de ObServe %1$s %2$s observe.runner.title.error.dialog=Un error se ha producido\! observe.runner.ui.loaded=Finalizada la inicialización de la interfaz gráfica +observe.runner.use.embedded.keystore.file=Use embedded keystore (%s). \#TODO observe.runner.user.directories.loaded=Se ha inicializado el directorio del usuario (%1$s). observe.security.role=Rol observe.security.role.administrator=Propietario de la base ===================================== client/runner/src/main/i18n/translations/client-runner_fr_FR.properties ===================================== @@ -170,6 +170,7 @@ observe.config.ui.tree.node.disabled.color=Couleur pour un nœud désactivé observe.config.ui.tree.node.empty.color=Couleur pour un nœud vide observe.config.ui.tree.node.unloaded.color=Couleur pour un nœud non chargé observe.config.ui.tree.node.unsaved.color=Couleur pour un nœud non persisté +observe.config.useJvmKeyStore.description=Pour utiliser le «keystore» fourni par Java, sinon pour utiliser le keystore fourni par l'application (localisé ici \: resources-xxx/observe.jks). observe.config.validation.lengthWeightEnable=Forcer la validation des bornes min/max de taille d'espèce observe.config.validation.speedEnable=Forcer la validation des vitesses d'activités observe.config.validation.speedMaxValue=Vitesse maximale autorisée dans le contrôle des vitesses d'activités @@ -283,6 +284,7 @@ observe.runner.copy.default.map.file=Création des cartes %1$s. observe.runner.copy.default.report.file=Création du fichier de reports %1$s. observe.runner.copy.default.swing.preferences.file=Création du fichier de préférence Swing %1$s. observe.runner.copy.default.ui.file=Création du fichier de cosmétique %1$s. +observe.runner.copy.embedded.keystore.file=Recopie du «keystore» embarqué par l'application (%s). observe.runner.i18n.loaded=Service de traduction chargé dans la langue %1$s. observe.runner.init=Initialisation d'ObServe %1$s %2$s observe.runner.initStorage.choice.createLocalStorage=Créer la base locale @@ -305,6 +307,7 @@ observe.runner.quit.without.ui=Fermeture de l'application sans ouvrir l'interfac observe.runner.start=Démarrage d'ObServe %1$s %2$s observe.runner.title.error.dialog=Une erreur est survenue\! observe.runner.ui.loaded=Initialisation de l'interface graphique terminée. +observe.runner.use.embedded.keystore.file=Utilisation du «keystore» embarqué (%s). observe.runner.user.directories.loaded=Le répertoire utilisateur a été initialisé (%1$s). observe.security.role=Rôle observe.security.role.administrator=Propriétaire de la base View it on GitLab: https://gitlab.com/ultreiaio/ird-observe/-/compare/c3e2e386a47721ccc624fc3ad... -- View it on GitLab: https://gitlab.com/ultreiaio/ird-observe/-/compare/c3e2e386a47721ccc624fc3ad... You're receiving this email because of your account on gitlab.com.