#91: Lock-File relativer Pfad – zweistufige Fallback-Strategie

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 <noreply@anthropic.com>
This commit is contained in:
2026-05-05 11:38:03 +02:00
parent 9c49fc61c0
commit 38b2d8c3b2
@@ -2,6 +2,7 @@ package de.gecheckt.pdf.umbenenner.bootstrap;
import java.io.IOException; import java.io.IOException;
import java.io.StringReader; import java.io.StringReader;
import java.net.URL;
import java.nio.charset.StandardCharsets; import java.nio.charset.StandardCharsets;
import java.nio.file.Files; import java.nio.file.Files;
import java.nio.file.Path; 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.
* <p>
* 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 * @param config die validierte Startkonfiguration
* @return the resolved lock file path; never {@code null} and never blank * @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) { private Path resolveLockFilePath(StartConfiguration config) {
Path lockFilePath = config.runtimeLockFile(); Path configuredPath = config.runtimeLockFile();
if (lockFilePath == null || lockFilePath.toString().isBlank()) {
lockFilePath = Paths.get("pdf-umbenenner.lock"); // Absoluter Pfad: direkt verwenden, kein Fallback
LOG.info("runtime.lock.file not configured, using default lock path: {}", if (configuredPath != null && !configuredPath.toString().isBlank() && configuredPath.isAbsolute()) {
lockFilePath.toAbsolutePath()); 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;
} }
/** /**