diff --git a/spring-core/src/main/java/org/springframework/core/io/FileSystemResource.java b/spring-core/src/main/java/org/springframework/core/io/FileSystemResource.java index ec51f4cefd3..6e3a9b4411d 100644 --- a/spring-core/src/main/java/org/springframework/core/io/FileSystemResource.java +++ b/spring-core/src/main/java/org/springframework/core/io/FileSystemResource.java @@ -179,7 +179,7 @@ public class FileSystemResource extends AbstractResource implements WritableReso */ @Override public boolean isReadable() { - return (this.file != null ? this.file.canRead() && !this.file.isDirectory() : + return (this.file != null ? this.file.exists() && this.file.canRead() && !this.file.isDirectory() : Files.isReadable(this.filePath) && !Files.isDirectory(this.filePath)); } diff --git a/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java b/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java index 9385a210f99..71cb785abcc 100644 --- a/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java +++ b/spring-core/src/test/java/org/springframework/core/io/ResourceTests.java @@ -270,6 +270,50 @@ class ResourceTests { assertThat(relative).isEqualTo(new FileSystemResource("dir/subdir")); } + @Test + void isReadableChecksExistsFirst() { + AtomicBoolean existsCalled = new AtomicBoolean(); + AtomicBoolean canReadCalled = new AtomicBoolean(); + File file = new File("/dev/my.txt") { + @Override + public boolean exists() { + existsCalled.set(true); + return false; + } + @Override + public boolean canRead() { + canReadCalled.set(true); + return false; + } + }; + Resource resource = new FileSystemResource(file); + assertThat(resource.isReadable()).isFalse(); + assertThat(existsCalled).isTrue(); + assertThat(canReadCalled).isFalse(); + } + + @Test + void isReadableChecksCanReadAfterExists() { + AtomicBoolean existsCalled = new AtomicBoolean(); + AtomicBoolean canReadCalled = new AtomicBoolean(); + File file = new File("/dev/my.txt") { + @Override + public boolean exists() { + existsCalled.set(true); + return true; + } + @Override + public boolean canRead() { + canReadCalled.set(true); + return false; + } + }; + Resource resource = new FileSystemResource(file); + assertThat(resource.isReadable()).isFalse(); + assertThat(existsCalled).isTrue(); + assertThat(canReadCalled).isTrue(); + } + @Test void getFilePath() throws Exception { Path path = mock();