INT-4303: (S)FTP MGET with FileExistsMode.IGNORE

JIRA: https://jira.spring.io/browse/INT-4303

Don't emit ignored files in the output message payload.

Also, always preserve the timestamp when using `FileExistsMode.REPLACE_IF_MODIFIED`.

Some code style polishing
This commit is contained in:
Gary Russell
2017-06-23 11:16:04 -04:00
committed by Artem Bilan
parent 4679c9bdbe
commit 0903df9676
5 changed files with 36 additions and 10 deletions

View File

@@ -1039,12 +1039,18 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
if (!appending && !tempFile.renameTo(localFile)) {
throw new MessagingException("Failed to rename local file");
}
if (this.options.contains(Option.PRESERVE_TIMESTAMP)) {
if (this.options.contains(Option.PRESERVE_TIMESTAMP)
|| FileExistsMode.REPLACE_IF_MODIFIED.equals(fileExistsMode)) {
localFile.setLastModified(getModified(fileInfo));
}
}
else if (FileExistsMode.REPLACE_IF_MODIFIED.equals(fileExistsMode)) {
logger.debug("Local file '" + localFile + "' has the same modified timestamp, ignored");
if (logger.isDebugEnabled()) {
logger.debug("Local file '" + localFile + "' has the same modified timestamp, ignored");
}
if (this.command.equals(Command.MGET)) {
localFile = null;
}
}
else if (!FileExistsMode.IGNORE.equals(fileExistsMode)) {
throw new MessageHandlingException(message, "Local file " + localFile + " already exists");
@@ -1053,6 +1059,9 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
if (logger.isDebugEnabled()) {
logger.debug("Existing file skipped: " + localFile);
}
if (this.command.equals(Command.MGET)) {
localFile = null;
}
}
return localFile;
}
@@ -1098,9 +1107,10 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
*/
String fileName = this.getRemoteFilename(fullFileName);
String actualRemoteDirectory = this.getRemoteDirectory(fullFileName, fileName);
File file = get(message, session, actualRemoteDirectory,
fullFileName, fileName, lsEntry.getFileInfo());
files.add(file);
File file = get(message, session, actualRemoteDirectory, fullFileName, fileName, lsEntry.getFileInfo());
if (file != null) {
files.add(file);
}
}
}
catch (Exception e) {
@@ -1141,9 +1151,10 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
*/
String fileName = this.getRemoteFilename(fullFileName);
String actualRemoteDirectory = this.getRemoteDirectory(fullFileName, fileName);
File file = get(message, session, actualRemoteDirectory,
fullFileName, fileName, lsEntry.getFileInfo());
files.add(file);
File file = get(message, session, actualRemoteDirectory, fullFileName, fileName, lsEntry.getFileInfo());
if (file != null) {
files.add(file);
}
}
}
catch (Exception e) {

View File

@@ -42,6 +42,7 @@
command="mget"
command-options="-f -P"
expression="payload"
mode="IGNORE"
local-directory-expression="@extraConfig.targetLocalDirectoryName + (#remoteDirectory ?: '')"
local-filename-generator-expression="#remoteFileName.replaceFirst('ftpSource', 'localTarget')"
reply-channel="output"/>

View File

@@ -228,6 +228,11 @@ public class FtpServerOutboundTests extends FtpTestSupport {
for (File file : localFiles) {
assertThat(file.getPath().replaceAll(Matcher.quoteReplacement(File.separator), "/"), containsString(dir));
}
this.inboundMGet.send(new GenericMessage<Object>(dir + "*.txt"));
result = this.output.receive(1000);
assertNotNull(result);
localFiles = (List<File>) result.getPayload();
assertThat(localFiles.size(), equalTo(0));
}
@Test

View File

@@ -886,7 +886,7 @@ You can either do that in your custom code, or route a copy of the message to a
*mget*
_mget_ retrieves multiple remote files based on a pattern and supports the following option:
_mget_ retrieves multiple remote files based on a pattern and supports the following options:
* -P - preserve the timestamps of the remote files
@@ -896,9 +896,13 @@ _mget_ retrieves multiple remote files based on a pattern and supports the follo
The message payload resulting from an _mget_ operation is a `List<File>` object - a List of File objects, each representing a retrieved file.
IMPORTANT: Startng with _version 5.0_, if the `FileExistsMode` is `IGNORE`, the payload of the output message will no longer contain files that were not fetched due to the file already existing.
Previously, the array contained all files, including those that already existed.
The expression used to determine the remote path should produce a result that ends with `*` - e.g. `foo/*` will fetch the complete tree under `foo`.
Starting with _version 5.0_, a recursive `MGET`, combined with the new `FileExistsMode.REPLACE_IF_MODIFIED` mode, can be used to periodically synchronize an entire remote directory tree locally.
This mode will set the local file last modified timestamp with the remote timestamp, regardless of the `-P` (preserve timestamp) option.
.Notes for when using recursion (`-R`)
[IMPORTANT]

View File

@@ -908,7 +908,7 @@ You can either do that in your custom code, or route a copy of the message to a
*mget*
_mget_ retrieves multiple remote files based on a pattern and supports the following option:
_mget_ retrieves multiple remote files based on a pattern and supports the following options:
* -P - preserve the timestamps of the remote files
@@ -918,9 +918,14 @@ _mget_ retrieves multiple remote files based on a pattern and supports the follo
The message payload resulting from an _mget_ operation is a `List<File>` object - a List of File objects, each representing a retrieved file.
IMPORTANT: Startng with _version 5.0_, if the `FileExistsMode` is `IGNORE`, the payload of the output message will no longer contain files that were not fetched due to the file already existing.
Previously, the array contained all files, including those that already existed.
The expression used to determine the remote path should produce a result that ends with `*` - e.g. `foo/*` will fetch the complete tree under `foo`.
Starting with _version 5.0_, a recursive `MGET`, combined with the new `FileExistsMode.REPLACE_IF_MODIFIED` mode, can be used to periodically synchronize an entire remote directory tree locally.
This mode will set the local file last modified timestamp to the remote file timestamp, regardless of the `-P` (preserve timestamp) option.
.Notes for when using recursion (`-R`)
[IMPORTANT]