Skip to content

Commit 44d035f

Browse files
artembilanspring-builds
authored andcommitted
GH-9594: Fix FileReadingMessageSource for FileHeaders.RELATIVE_PATH
Fixes: #9594 Issue link: #9594 The `String.replaceFirst()` for directory with `[]` or `()` leads to a regex execution which does not really replace the root path because of mismatch between regex and file path. Essentially, the `Matcher.quoteReplacement()` does not do the trick we would expect from it. * Use `Path.relativize()` API instead which works in canonical paths and proper file separators (cherry picked from commit 9149409)
1 parent eab39c0 commit 44d035f

File tree

2 files changed

+26
-36
lines changed

2 files changed

+26
-36
lines changed

spring-integration-file/src/main/java/org/springframework/integration/file/FileReadingMessageSource.java

Lines changed: 1 addition & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,6 @@
4242
import java.util.concurrent.PriorityBlockingQueue;
4343
import java.util.concurrent.atomic.AtomicBoolean;
4444
import java.util.function.Predicate;
45-
import java.util.regex.Matcher;
4645

4746
import org.springframework.context.Lifecycle;
4847
import org.springframework.integration.endpoint.AbstractMessageSource;
@@ -388,10 +387,7 @@ protected AbstractIntegrationMessageBuilder<File> doReceive() {
388387
if (file != null) {
389388
return getMessageBuilderFactory()
390389
.withPayload(file)
391-
.setHeader(FileHeaders.RELATIVE_PATH,
392-
file.getAbsolutePath()
393-
.replaceFirst(Matcher.quoteReplacement(
394-
this.directory.getAbsolutePath() + File.separator), ""))
390+
.setHeader(FileHeaders.RELATIVE_PATH, this.directory.toPath().relativize(file.toPath()).toString())
395391
.setHeader(FileHeaders.FILENAME, file.getName())
396392
.setHeader(FileHeaders.ORIGINAL_FILE, file);
397393
}

spring-integration-file/src/test/java/org/springframework/integration/file/FileReadingMessageSourceTests.java

Lines changed: 25 additions & 31 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2002-2022 the original author or authors.
2+
* Copyright 2002-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.
@@ -17,15 +17,12 @@
1717
package org.springframework.integration.file;
1818

1919
import java.io.File;
20+
import java.nio.file.Path;
2021
import java.util.Comparator;
2122

22-
import org.junit.Before;
23-
import org.junit.Test;
24-
import org.junit.runner.RunWith;
25-
import org.mockito.Mock;
26-
import org.mockito.junit.MockitoJUnitRunner;
23+
import org.junit.jupiter.api.BeforeEach;
24+
import org.junit.jupiter.api.Test;
2725

28-
import org.springframework.beans.factory.BeanFactory;
2926
import org.springframework.messaging.Message;
3027

3128
import static org.assertj.core.api.Assertions.assertThat;
@@ -42,43 +39,40 @@
4239
* @author Artem Bilan
4340
* @author Gary Russell
4441
*/
45-
@RunWith(MockitoJUnitRunner.class)
46-
public class FileReadingMessageSourceTests {
42+
class FileReadingMessageSourceTests {
4743

4844
private FileReadingMessageSource source;
4945

50-
@Mock
51-
private File inputDirectoryMock;
46+
private final File inputDirectoryMock = mock();
5247

53-
@Mock
54-
private File fileMock;
48+
private final File fileMock = mock();
5549

56-
@Mock
57-
private FileLocker locker;
50+
private final FileLocker locker = mock();
5851

59-
@Mock
60-
private Comparator<File> comparator;
52+
private final Comparator<File> comparator = mock();
6153

6254
public void prepResource() {
63-
when(inputDirectoryMock.getAbsolutePath()).thenReturn("foo/bar");
64-
when(fileMock.getAbsolutePath()).thenReturn("foo/bar/fileMock");
55+
when(inputDirectoryMock.toPath()).thenReturn(Path.of("[dir]"));
56+
when(fileMock.toPath()).thenReturn(Path.of("[dir]/fileMock"));
6557
when(locker.lock(isA(File.class))).thenReturn(true);
6658
}
6759

68-
@Before
60+
@BeforeEach
6961
public void initialize() {
7062
prepResource();
7163
this.source = new FileReadingMessageSource(comparator);
7264
this.source.setDirectory(inputDirectoryMock);
7365
this.source.setLocker(locker);
74-
this.source.setBeanFactory(mock(BeanFactory.class));
66+
this.source.setBeanFactory(mock());
7567
this.source.afterPropertiesSet();
7668
}
7769

7870
@Test
7971
public void straightProcess() {
8072
when(inputDirectoryMock.listFiles()).thenReturn(new File[] {fileMock});
81-
assertThat(source.receive().getPayload()).isEqualTo(fileMock);
73+
Message<File> fileMessage = source.receive();
74+
assertThat(fileMessage.getPayload()).isEqualTo(fileMock);
75+
assertThat(fileMessage.getHeaders()).containsEntry(FileHeaders.RELATIVE_PATH, "fileMock");
8276
}
8377

8478
@Test
@@ -88,13 +82,13 @@ public void requeueOnFailure() {
8882
assertThat(received).isNotNull();
8983
source.onFailure(received);
9084
assertThat(source.receive().getPayload()).isEqualTo(received.getPayload());
91-
verify(inputDirectoryMock, times(1)).listFiles();
85+
verify(inputDirectoryMock).listFiles();
9286
}
9387

9488
@Test
9589
public void scanEachPoll() {
96-
File anotherFileMock = mock(File.class);
97-
when(anotherFileMock.getAbsolutePath()).thenReturn("foo/bar/anotherFileMock");
90+
File anotherFileMock = mock();
91+
when(anotherFileMock.toPath()).thenReturn(Path.of("[dir]/anotherFileMock"));
9892
when(inputDirectoryMock.listFiles()).thenReturn(new File[] {fileMock, anotherFileMock});
9993
source.setScanEachPoll(true);
10094
assertThat(source.receive()).isNotNull();
@@ -139,12 +133,12 @@ public void lockedFilesAreIgnored() {
139133

140134
@Test
141135
public void orderedReception() {
142-
File file1 = mock(File.class);
143-
when(file1.getAbsolutePath()).thenReturn("foo/bar/file1");
144-
File file2 = mock(File.class);
145-
when(file2.getAbsolutePath()).thenReturn("foo/bar/file2");
146-
File file3 = mock(File.class);
147-
when(file3.getAbsolutePath()).thenReturn("foo/bar/file3");
136+
File file1 = mock();
137+
when(file1.toPath()).thenReturn(Path.of("[dir]/file1"));
138+
File file2 = mock();
139+
when(file2.toPath()).thenReturn(Path.of("[dir]/file2"));
140+
File file3 = mock();
141+
when(file3.toPath()).thenReturn(Path.of("[dir]/file3"));
148142

149143
// record the comparator to reverse order the files
150144
when(comparator.compare(file1, file2)).thenReturn(1);

0 commit comments

Comments
 (0)