From 38b2d8c3b20266c37c93cb64342a03d4f1f3cdc7 Mon Sep 17 00:00:00 2001 From: Marcus van Elst Date: Tue, 5 May 2026 11:38:03 +0200 Subject: [PATCH] =?UTF-8?q?#91:=20Lock-File=20relativer=20Pfad=20=E2=80=93?= =?UTF-8?q?=20zweistufige=20Fallback-Strategie?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Absoluter konfigurierter Pfad wird direkt verwendet (kein Fallback). Relativer oder fehlender Pfad wird zweistufig aufgeloest: 1. Relativ zum JAR-Verzeichnis (CodeSource.getLocation()) 2. Fallback auf user.home Der final verwendete Pfad wird auf INFO-Ebene geloggt. Co-Authored-By: Claude Sonnet 4.6 --- .../umbenenner/bootstrap/BootstrapRunner.java | 76 ++++++++++++++++--- 1 file changed, 67 insertions(+), 9 deletions(-) diff --git a/pdf-umbenenner-bootstrap/src/main/java/de/gecheckt/pdf/umbenenner/bootstrap/BootstrapRunner.java b/pdf-umbenenner-bootstrap/src/main/java/de/gecheckt/pdf/umbenenner/bootstrap/BootstrapRunner.java index c0b1cec..9d15f9b 100644 --- a/pdf-umbenenner-bootstrap/src/main/java/de/gecheckt/pdf/umbenenner/bootstrap/BootstrapRunner.java +++ b/pdf-umbenenner-bootstrap/src/main/java/de/gecheckt/pdf/umbenenner/bootstrap/BootstrapRunner.java @@ -2,6 +2,7 @@ package de.gecheckt.pdf.umbenenner.bootstrap; import java.io.IOException; import java.io.StringReader; +import java.net.URL; import java.nio.charset.StandardCharsets; import java.nio.file.Files; import java.nio.file.Path; @@ -1747,19 +1748,76 @@ public class BootstrapRunner { } /** - * Resolves the run-lock file path from the configuration, applying a default when not set. + * Löst den Lock-Datei-Pfad aus der Konfiguration auf. + *

+ * Ist der konfigurierte Pfad absolut, wird er unverändert verwendet (kein Fallback). + * Ist er relativ oder nicht konfiguriert, wird zweistufig aufgelöst: + * zuerst relativ zum JAR-Verzeichnis, dann relativ zu {@code user.home}. + * Der final verwendete absolute Pfad wird auf INFO-Ebene geloggt. * - * @param config the startup configuration - * @return the resolved lock file path; never {@code null} and never blank + * @param config die validierte Startkonfiguration + * @return der absolut aufgelöste Lock-Datei-Pfad; niemals {@code null} + * @throws IllegalStateException wenn weder JAR-Verzeichnis noch {@code user.home} auflösbar sind */ private Path resolveLockFilePath(StartConfiguration config) { - Path lockFilePath = config.runtimeLockFile(); - if (lockFilePath == null || lockFilePath.toString().isBlank()) { - lockFilePath = Paths.get("pdf-umbenenner.lock"); - LOG.info("runtime.lock.file not configured, using default lock path: {}", - lockFilePath.toAbsolutePath()); + Path configuredPath = config.runtimeLockFile(); + + // Absoluter Pfad: direkt verwenden, kein Fallback + if (configuredPath != null && !configuredPath.toString().isBlank() && configuredPath.isAbsolute()) { + LOG.info("Lock-Datei: {}", configuredPath); + return configuredPath; + } + + // Dateiname aus Konfiguration oder Standard + String lockFileName; + if (configuredPath != null && !configuredPath.toString().isBlank()) { + lockFileName = configuredPath.toString(); + } else { + lockFileName = "pdf-umbenenner.lock"; + } + + // Stufe 1: JAR-Verzeichnis + Path jarDir = resolveJarDirectory(); + if (jarDir != null) { + Path resolved = jarDir.resolve(lockFileName).normalize().toAbsolutePath(); + LOG.info("Lock-Datei: {}", resolved); + return resolved; + } + + // Stufe 2: user.home als Fallback + String userHome = System.getProperty("user.home"); + if (userHome != null && !userHome.isBlank()) { + Path resolved = Path.of(userHome).resolve(lockFileName).normalize().toAbsolutePath(); + LOG.info("Lock-Datei (Fallback auf user.home): {}", resolved); + return resolved; + } + + // Beide Stufen gescheitert + throw new IllegalStateException( + "Lock-Datei-Pfad konnte nicht aufgelöst werden: JAR-Verzeichnis nicht bestimmbar" + + " und system property 'user.home' nicht gesetzt."); + } + + /** + * Ermittelt das Verzeichnis der aktuell ausgeführten JAR-Datei über {@code CodeSource.getLocation()}. + * + * @return das JAR-Verzeichnis als {@link Path}, oder {@code null} wenn nicht bestimmbar + */ + private Path resolveJarDirectory() { + try { + URL codeSource = BootstrapRunner.class.getProtectionDomain() + .getCodeSource().getLocation(); + if (codeSource == null) { + LOG.debug("CodeSource.getLocation() lieferte null – JAR-Verzeichnis nicht bestimmbar."); + return null; + } + Path jarPath = Path.of(codeSource.toURI()); + // Bei einer JAR-Datei: übergeordnetes Verzeichnis; bei Klassen-Verzeichnis: direkt verwenden + return Files.isDirectory(jarPath) ? jarPath : jarPath.getParent(); + } catch (Exception e) { + LOG.debug("JAR-Verzeichnis konnte nicht bestimmt werden: {}", e.getMessage()); + return null; } - return lockFilePath; } /**