From 26ca3790b26b3153090462fbb9264e5fdda75153 Mon Sep 17 00:00:00 2001 From: Tomasz Maciejewski Date: Fri, 20 Dec 2024 20:39:11 +0100 Subject: [PATCH] Add support for symlinks in FileWatcher This commit allows using symlinks for SSL certificate hot reloading. See gh-43586 --- .../boot/autoconfigure/ssl/FileWatcher.java | 13 ++++++++++++- .../boot/autoconfigure/ssl/FileWatcherTests.java | 12 ++++++++++++ 2 files changed, 24 insertions(+), 1 deletion(-) diff --git a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/FileWatcher.java b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/FileWatcher.java index eecad97b3b4..3e590a55947 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/FileWatcher.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/FileWatcher.java @@ -86,7 +86,7 @@ class FileWatcher implements Closeable { this.thread = new WatcherThread(); this.thread.start(); } - this.thread.register(new Registration(paths, action)); + this.thread.register(new Registration(resolveSymlinks(paths), action)); } catch (IOException ex) { throw new UncheckedIOException("Failed to register paths for watching: " + paths, ex); @@ -94,6 +94,17 @@ class FileWatcher implements Closeable { } } + private Set resolveSymlinks(Set paths) throws IOException { + Set result = new HashSet<>(); + for (Path path : paths) { + result.add(path); + if (Files.isSymbolicLink(path)) { + result.add(Files.readSymbolicLink(path)); + } + } + return result; + } + @Override public void close() throws IOException { synchronized (this.lock) { diff --git a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/FileWatcherTests.java b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/FileWatcherTests.java index 5b3e18e3f79..f0a2cc8b167 100644 --- a/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/FileWatcherTests.java +++ b/spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/FileWatcherTests.java @@ -94,6 +94,18 @@ class FileWatcherTests { callback.expectChanges(); } + @Test + void shouldFollowSymlink(@TempDir Path tempDir) throws Exception { + Path realFile = tempDir.resolve("realFile.txt"); + Path symLink = tempDir.resolve("symlink.txt"); + Files.createFile(realFile); + Files.createSymbolicLink(symLink, realFile); + WaitingCallback callback = new WaitingCallback(); + this.fileWatcher.watch(Set.of(symLink), callback); + Files.writeString(realFile, "Some content"); + callback.expectChanges(); + } + @Test void shouldIgnoreNotWatchedFiles(@TempDir Path tempDir) throws Exception { Path watchedFile = tempDir.resolve("watched.txt");