Skip to content

Commit ef8527b

Browse files
committed
Merge branch '3.5.x' into 4.0.x
Closes gh-50185
2 parents 4a7bd33 + f533a45 commit ef8527b

2 files changed

Lines changed: 58 additions & 15 deletions

File tree

core/spring-boot/src/main/java/org/springframework/boot/system/ApplicationPid.java

Lines changed: 17 additions & 15 deletions
Original file line numberDiff line numberDiff line change
@@ -18,9 +18,11 @@
1818

1919
import java.io.File;
2020
import java.io.FileNotFoundException;
21-
import java.io.FileWriter;
2221
import java.io.IOException;
2322
import java.nio.file.Files;
23+
import java.nio.file.LinkOption;
24+
import java.nio.file.Path;
25+
import java.nio.file.StandardOpenOption;
2426
import java.nio.file.attribute.PosixFilePermission;
2527
import java.util.Set;
2628

@@ -106,31 +108,31 @@ public String toString() {
106108
*/
107109
public void write(File file) throws IOException {
108110
Assert.state(this.pid != null, "No PID available");
109-
createParentDirectory(file);
110-
if (file.exists()) {
111-
assertCanOverwrite(file);
112-
}
113-
try (FileWriter writer = new FileWriter(file)) {
114-
writer.append(String.valueOf(this.pid));
111+
Path path = file.toPath();
112+
createParentDirectory(path);
113+
if (Files.exists(path, LinkOption.NOFOLLOW_LINKS)) {
114+
assertCanOverwrite(path);
115115
}
116+
Files.writeString(path, this.pid.toString(), StandardOpenOption.TRUNCATE_EXISTING, StandardOpenOption.CREATE,
117+
LinkOption.NOFOLLOW_LINKS);
116118
}
117119

118-
private void createParentDirectory(File file) {
119-
File parent = file.getParentFile();
120+
private void createParentDirectory(Path path) throws IOException {
121+
Path parent = path.getParent();
120122
if (parent != null) {
121-
parent.mkdirs();
123+
Files.createDirectories(parent);
122124
}
123125
}
124126

125-
private void assertCanOverwrite(File file) throws IOException {
126-
if (!file.canWrite() || !canWritePosixFile(file)) {
127-
throw new FileNotFoundException(file + " (permission denied)");
127+
private void assertCanOverwrite(Path file) throws IOException {
128+
if (!Files.isWritable(file) || !canWritePosixFile(file)) {
129+
throw new FileNotFoundException(file.toString() + " (permission denied)");
128130
}
129131
}
130132

131-
private boolean canWritePosixFile(File file) throws IOException {
133+
private boolean canWritePosixFile(Path file) throws IOException {
132134
try {
133-
Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(file.toPath());
135+
Set<PosixFilePermission> permissions = Files.getPosixFilePermissions(file, LinkOption.NOFOLLOW_LINKS);
134136
for (PosixFilePermission permission : WRITE_PERMISSIONS) {
135137
if (permissions.contains(permission)) {
136138
return true;

core/spring-boot/src/test/java/org/springframework/boot/system/ApplicationPidTests.java

Lines changed: 41 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -17,11 +17,18 @@
1717
package org.springframework.boot.system;
1818

1919
import java.io.File;
20+
import java.io.IOException;
21+
import java.nio.file.Files;
22+
import java.nio.file.Path;
23+
import java.nio.file.StandardOpenOption;
2024

2125
import org.junit.jupiter.api.Test;
26+
import org.junit.jupiter.api.condition.DisabledOnOs;
27+
import org.junit.jupiter.api.condition.OS;
2228
import org.junit.jupiter.api.io.TempDir;
2329

2430
import static org.assertj.core.api.Assertions.assertThat;
31+
import static org.assertj.core.api.Assertions.assertThatIOException;
2532
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
2633
import static org.assertj.core.api.Assertions.contentOf;
2734

@@ -71,6 +78,40 @@ void writeNewPid() throws Exception {
7178
assertThat(contentOf(file)).isEqualTo("123");
7279
}
7380

81+
@Test
82+
void overwriteExistingPid() throws Exception {
83+
File file = new File(this.tempDir, "pid");
84+
new ApplicationPid(123L).write(file);
85+
assertThat(contentOf(file)).isEqualTo("123");
86+
new ApplicationPid(456L).write(file);
87+
assertThat(contentOf(file)).isEqualTo("456");
88+
}
89+
90+
@Test
91+
@DisabledOnOs(OS.WINDOWS)
92+
void whenSymlinkToNonExistentTargetExistsAtPidFileLocationWriteThrows() throws IOException {
93+
File link = new File(this.tempDir, "pid");
94+
File target = new File(this.tempDir, "target");
95+
Files.createSymbolicLink(link.toPath(), target.toPath());
96+
ApplicationPid pid = new ApplicationPid(123L);
97+
assertThatIOException().isThrownBy(() -> pid.write(link));
98+
assertThat(Files.isSymbolicLink(link.toPath())).isTrue();
99+
assertThat(target).doesNotExist();
100+
}
101+
102+
@Test
103+
@DisabledOnOs(OS.WINDOWS)
104+
void whenSymlinkToTargetExistsAtPidFileLocationWriteThrows() throws IOException {
105+
File link = new File(this.tempDir, "pid");
106+
Path target = new File(this.tempDir, "target").toPath();
107+
Files.write(target, "target".getBytes(), StandardOpenOption.CREATE_NEW);
108+
Files.createSymbolicLink(link.toPath(), target);
109+
ApplicationPid pid = new ApplicationPid(123L);
110+
assertThatIOException().isThrownBy(() -> pid.write(link));
111+
assertThat(Files.isSymbolicLink(link.toPath())).isTrue();
112+
assertThat(target).hasContent("target");
113+
}
114+
74115
@Test
75116
void toLong() {
76117
ApplicationPid pid = new ApplicationPid(123L);

0 commit comments

Comments
 (0)