Skip to content

Commit 59d0f51

Browse files
committed
GH-3076: Add file existence check
Fixes #3076
1 parent 3366788 commit 59d0f51

File tree

4 files changed

+92
-1
lines changed

4 files changed

+92
-1
lines changed

spring-integration-file/src/main/java/org/springframework/integration/file/locking/FileChannelCache.java

+8-1
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.integration.file.locking;
1818

1919
import java.io.File;
20+
import java.io.FileNotFoundException;
2021
import java.io.IOException;
2122
import java.io.RandomAccessFile;
2223
import java.nio.channels.FileChannel;
@@ -30,6 +31,7 @@
3031
*
3132
* @author Iwein Fuld
3233
* @author Gary Russell
34+
* @author Emmanuel Roux
3335
* @since 2.0
3436
*/
3537
final class FileChannelCache {
@@ -43,13 +45,18 @@ private FileChannelCache() {
4345

4446
/**
4547
* Try to get a lock for this file while guaranteeing that the same channel will be used for all file locks in this
46-
* VM. If the lock could not be acquired this method will return <code>null</code>.
48+
* VM. If the lock could not be acquired this method will return <code>null</code>. If the file does not exist this
49+
* method will throw a {@link FileNotFoundException}.
4750
* <p>
4851
* Locks acquired through this method should be passed back to #closeChannelFor to prevent memory leaks.
4952
* <p>
5053
* Thread safe.
5154
*/
5255
public static FileLock tryLockFor(File fileToLock) throws IOException {
56+
if (!fileToLock.exists()) {
57+
throw new FileNotFoundException("Unable to get lock for non-existent file: " + fileToLock.getAbsolutePath());
58+
}
59+
5360
FileChannel channel = channelCache.get(fileToLock);
5461
if (channel == null) {
5562
@SuppressWarnings("resource")

spring-integration-file/src/main/java/org/springframework/integration/file/locking/NioFileLocker.java

+5
Original file line numberDiff line numberDiff line change
@@ -17,6 +17,7 @@
1717
package org.springframework.integration.file.locking;
1818

1919
import java.io.File;
20+
import java.io.FileNotFoundException;
2021
import java.io.IOException;
2122
import java.nio.channels.FileLock;
2223
import java.util.concurrent.ConcurrentHashMap;
@@ -36,6 +37,7 @@
3637
* @author Iwein Fuld
3738
* @author Mark Fisher
3839
* @author Gary Russell
40+
* @author Emmanuel Roux
3941
* @since 2.0
4042
*/
4143
public class NioFileLocker extends AbstractFileLockerFilter {
@@ -50,6 +52,9 @@ public boolean lock(File fileToLock) {
5052
try {
5153
newLock = FileChannelCache.tryLockFor(fileToLock);
5254
}
55+
catch (FileNotFoundException e) {
56+
// Consider lock failed
57+
}
5358
catch (IOException e) {
5459
throw new MessagingException("Failed to lock file: " + fileToLock, e);
5560
}
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,62 @@
1+
/*
2+
* Copyright 2002-2019 the original author or authors.
3+
*
4+
* Licensed under the Apache License, Version 2.0 (the "License");
5+
* you may not use this file except in compliance with the License.
6+
* You may obtain a copy of the License at
7+
*
8+
* https://www.apache.org/licenses/LICENSE-2.0
9+
*
10+
* Unless required by applicable law or agreed to in writing, software
11+
* distributed under the License is distributed on an "AS IS" BASIS,
12+
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13+
* See the License for the specific language governing permissions and
14+
* limitations under the License.
15+
*/
16+
17+
package org.springframework.integration.file.locking;
18+
19+
import static org.assertj.core.api.Assertions.assertThat;
20+
21+
import java.io.File;
22+
import java.io.FileNotFoundException;
23+
import java.io.IOException;
24+
import java.nio.channels.FileLock;
25+
26+
import org.junit.Rule;
27+
import org.junit.Test;
28+
import org.junit.rules.TemporaryFolder;
29+
30+
/**
31+
* @author Emmanuel Roux
32+
*/
33+
public class FileChannelCacheTests {
34+
35+
private File workdir;
36+
37+
@Rule
38+
public TemporaryFolder temp = new TemporaryFolder() {
39+
40+
@Override
41+
public void create() throws IOException {
42+
super.create();
43+
workdir = temp.newFolder(FileChannelCacheTests.class.getSimpleName());
44+
}
45+
};
46+
47+
@Test(expected = FileNotFoundException.class)
48+
public void throwsExceptionWhenFileNotExists() throws IOException {
49+
File testFile = new File(workdir, "test0");
50+
assertThat(testFile.exists()).isFalse();
51+
FileChannelCache.tryLockFor(testFile);
52+
}
53+
54+
@Test
55+
public void fileLocked() throws IOException {
56+
File testFile = new File(workdir, "test1");
57+
testFile.createNewFile();
58+
assertThat(testFile.exists()).isTrue();
59+
assertThat(FileChannelCache.tryLockFor(testFile)).isNotNull();
60+
FileChannelCache.closeChannelFor(testFile);
61+
}
62+
}

spring-integration-file/src/test/java/org/springframework/integration/file/locking/NioFileLockerTests.java

+17
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
/**
3535
* @author Iwein Fuld
3636
* @author Gary Russell
37+
* @author Emmanuel Roux
3738
*/
3839
public class NioFileLockerTests {
3940

@@ -76,4 +77,20 @@ public void fileNotListedWhenLockedByOtherFilter() throws IOException {
7677
filter1.unlock(testFile);
7778
}
7879

80+
@Test
81+
public void fileLockedWhenNotAlreadyLockedAndExists() throws IOException {
82+
NioFileLocker locker = new NioFileLocker();
83+
File testFile = new File(workdir, "test2");
84+
testFile.createNewFile();
85+
assertThat(locker.lock(testFile)).isTrue();
86+
locker.unlock(testFile);
87+
}
88+
89+
@Test
90+
public void fileNotLockedWhenNotExists() throws IOException {
91+
NioFileLocker locker = new NioFileLocker();
92+
File testFile = new File(workdir, "test3");
93+
assertThat(locker.lock(testFile)).isFalse();
94+
assertThat(testFile.exists()).isFalse();
95+
}
7996
}

0 commit comments

Comments
 (0)