Skip to content

Commit a5b917f

Browse files
committed
Merge pull request #43586 from tmaciejewski
* pr/43586: Polish "Add support for symlinks in FileWatcher" Add support for symlinks in FileWatcher Closes gh-43586
2 parents 0035569 + 9167055 commit a5b917f

File tree

2 files changed

+41
-3
lines changed
  • spring-boot-project/spring-boot-autoconfigure/src

2 files changed

+41
-3
lines changed

spring-boot-project/spring-boot-autoconfigure/src/main/java/org/springframework/boot/autoconfigure/ssl/FileWatcher.java

+14-2
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -86,14 +86,26 @@ void watch(Set<Path> paths, Runnable action) {
8686
this.thread = new WatcherThread();
8787
this.thread.start();
8888
}
89-
this.thread.register(new Registration(paths, action));
89+
Set<Path> actualPaths = new HashSet<>();
90+
for (Path path : paths) {
91+
actualPaths.add(resolveSymlinkIfNecessary(path));
92+
}
93+
this.thread.register(new Registration(actualPaths, action));
9094
}
9195
catch (IOException ex) {
9296
throw new UncheckedIOException("Failed to register paths for watching: " + paths, ex);
9397
}
9498
}
9599
}
96100

101+
private static Path resolveSymlinkIfNecessary(Path path) throws IOException {
102+
if (Files.isSymbolicLink(path)) {
103+
Path target = Files.readSymbolicLink(path);
104+
return resolveSymlinkIfNecessary(target);
105+
}
106+
return path;
107+
}
108+
97109
@Override
98110
public void close() throws IOException {
99111
synchronized (this.lock) {

spring-boot-project/spring-boot-autoconfigure/src/test/java/org/springframework/boot/autoconfigure/ssl/FileWatcherTests.java

+27-1
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2012-2023 the original author or authors.
2+
* Copyright 2012-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -94,6 +94,32 @@ void shouldWatchFile(@TempDir Path tempDir) throws Exception {
9494
callback.expectChanges();
9595
}
9696

97+
@Test
98+
void shouldFollowSymlink(@TempDir Path tempDir) throws Exception {
99+
Path realFile = tempDir.resolve("realFile.txt");
100+
Path symLink = tempDir.resolve("symlink.txt");
101+
Files.createFile(realFile);
102+
Files.createSymbolicLink(symLink, realFile);
103+
WaitingCallback callback = new WaitingCallback();
104+
this.fileWatcher.watch(Set.of(symLink), callback);
105+
Files.writeString(realFile, "Some content");
106+
callback.expectChanges();
107+
}
108+
109+
@Test
110+
void shouldFollowSymlinkRecursively(@TempDir Path tempDir) throws Exception {
111+
Path realFile = tempDir.resolve("realFile.txt");
112+
Path symLink = tempDir.resolve("symlink.txt");
113+
Path symLink2 = tempDir.resolve("symlink2.txt");
114+
Files.createFile(realFile);
115+
Files.createSymbolicLink(symLink, symLink2);
116+
Files.createSymbolicLink(symLink2, realFile);
117+
WaitingCallback callback = new WaitingCallback();
118+
this.fileWatcher.watch(Set.of(symLink), callback);
119+
Files.writeString(realFile, "Some content");
120+
callback.expectChanges();
121+
}
122+
97123
@Test
98124
void shouldIgnoreNotWatchedFiles(@TempDir Path tempDir) throws Exception {
99125
Path watchedFile = tempDir.resolve("watched.txt");

0 commit comments

Comments
 (0)