GH-3038: Delegate more RemoteFileTempalte options

Fixes https://github.com/spring-projects/spring-integration/issues/3038

* Add more delegating setters into the `AbstractRemoteFileOutboundGateway`
for its `RemoteFileTemplate` property
* Restrict externally provided `RemoteFileTemplate` from modifications
in the `AbstractRemoteFileOutboundGateway`: those options must be
configured on that external `RemoteFileTemplate`
* Expose new options in the Java DSL specs
This commit is contained in:
Artem Bilan
2019-08-28 16:20:35 -04:00
committed by Gary Russell
parent 1b892fc7a4
commit 075086775d
6 changed files with 327 additions and 30 deletions

View File

@@ -25,6 +25,7 @@ import org.springframework.expression.Expression;
import org.springframework.integration.dsl.ComponentsRegistration;
import org.springframework.integration.dsl.MessageHandlerSpec;
import org.springframework.integration.expression.FunctionExpression;
import org.springframework.integration.file.FileNameGenerator;
import org.springframework.integration.file.filters.CompositeFileListFilter;
import org.springframework.integration.file.filters.ExpressionFileListFilter;
import org.springframework.integration.file.filters.FileListFilter;
@@ -313,8 +314,21 @@ public abstract class RemoteFileOutboundGatewaySpec<F, S extends RemoteFileOutbo
* @param localFilenameFunction the {@link Function} to use.
* @param <P> the expected payload type.
* @return the Spec.
* @deprecated since 5.2 in favor of {@link #localFilenameFunction(Function)}
*/
@Deprecated
public <P> S localFilename(Function<Message<P>, String> localFilenameFunction) {
return localFilenameFunction(localFilenameFunction);
}
/**
* Specify a {@link Function} for local files renaming after downloading.
* @param localFilenameFunction the {@link Function} to use.
* @param <P> the expected payload type.
* @return the Spec.
* @since 5.2
*/
public <P> S localFilenameFunction(Function<Message<P>, String> localFilenameFunction) {
return localFilenameExpression(new FunctionExpression<>(localFilenameFunction));
}
@@ -351,6 +365,167 @@ public abstract class RemoteFileOutboundGatewaySpec<F, S extends RemoteFileOutbo
return _this();
}
/**
* Determine whether the remote directory should automatically be created when
* sending files to the remote system.
* @param autoCreateDirectory true to create the directory.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setAutoCreateDirectory(boolean)
*/
public S autoCreateDirectory(boolean autoCreateDirectory) {
this.target.setAutoCreateDirectory(autoCreateDirectory);
return _this();
}
/**
* Set the remote directory expression used to determine the remote directory to which
* files will be sent.
* @param remoteDirectoryExpression the remote directory expression.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setRemoteDirectoryExpression
*/
public S remoteDirectoryExpression(String remoteDirectoryExpression) {
return remoteDirectoryExpression(PARSER.parseExpression(remoteDirectoryExpression));
}
/**
* Specify a {@link Function} for remote directory.
* @param remoteDirectoryFunction the {@link Function} to use.
* @param <P> the expected payload type.
* @return the Spec.
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setRemoteDirectoryExpression
* @see FunctionExpression
*/
public <P> S remoteDirectoryFunction(Function<Message<P>, String> remoteDirectoryFunction) {
return remoteDirectoryExpression(new FunctionExpression<>(remoteDirectoryFunction));
}
/**
* Set the remote directory expression used to determine the remote directory to which
* files will be sent.
* @param remoteDirectoryExpression the remote directory expression.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setRemoteDirectoryExpression
*/
public S remoteDirectoryExpression(Expression remoteDirectoryExpression) {
this.target.setRemoteDirectoryExpression(remoteDirectoryExpression);
return _this();
}
/**
* Set a temporary remote directory expression; used when transferring files to the remote
* system.
* @param temporaryRemoteDirectoryExpression the temporary remote directory expression.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setRemoteDirectoryExpression
*/
public S temporaryRemoteDirectoryExpression(String temporaryRemoteDirectoryExpression) {
return temporaryRemoteDirectoryExpression(PARSER.parseExpression(temporaryRemoteDirectoryExpression));
}
/**
* Set a temporary remote directory function; used when transferring files to the remote
* system.
* @param temporaryRemoteDirectoryFunction the file name expression.
* @param <P> the expected payload type.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setRemoteDirectoryExpression
*/
public <P> S temporaryRemoteDirectoryFunction(Function<Message<P>, String> temporaryRemoteDirectoryFunction) {
return temporaryRemoteDirectoryExpression(new FunctionExpression<>(temporaryRemoteDirectoryFunction));
}
/**
* Set a temporary remote directory expression; used when transferring files to the remote
* system.
* @param temporaryRemoteDirectoryExpression the temporary remote directory expression.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setRemoteDirectoryExpression
*/
public S temporaryRemoteDirectoryExpression(Expression temporaryRemoteDirectoryExpression) {
this.target.setTemporaryRemoteDirectoryExpression(temporaryRemoteDirectoryExpression);
return _this();
}
/**
* Set the file name expression to determine the full path to the remote file.
* @param fileNameExpression the file name expression.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setFileNameExpression
*/
public S fileNameExpression(String fileNameExpression) {
return fileNameExpression(PARSER.parseExpression(fileNameExpression));
}
/**
* Set the file name function to determine the full path to the remote file.
* @param fileNameFunction the file name expression.
* @param <P> the expected payload type.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setFileNameExpression
*/
public <P> S fileNameFunction(Function<Message<P>, String> fileNameFunction) {
return fileNameExpression(new FunctionExpression<>(fileNameFunction));
}
/**
* Set the file name expression to determine the full path to the remote file.
* @param fileNameExpression the file name expression.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setFileNameExpression
*/
public S fileNameExpression(Expression fileNameExpression) {
this.target.setFileNameExpression(fileNameExpression);
return _this();
}
/**
* Set whether a temporary file name is used when sending files to the remote system.
* @param useTemporaryFileName true to use a temporary file name.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setUseTemporaryFileName
*/
public S useTemporaryFileName(boolean useTemporaryFileName) {
this.target.setUseTemporaryFileName(useTemporaryFileName);
return _this();
}
/**
* Set the file name generator used to generate the remote filename to be used when transferring
* files to the remote system.
* @param fileNameGenerator the file name generator.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setFileNameGenerator
*/
public S fileNameGenerator(FileNameGenerator fileNameGenerator) {
this.target.setFileNameGenerator(fileNameGenerator);
return _this();
}
/**
* Set the charset to use when converting String payloads to bytes as the content of the
* remote file. Default {@code UTF-8}.
* @param charset the charset.
* @return the current Spec
* @since 5.2
* @see AbstractRemoteFileOutboundGateway#setCharset
*/
public S charset(String charset) {
this.target.setCharset(charset);
return _this();
}
@Override
public Map<Object, String> getComponentsToRegister() {

View File

@@ -41,6 +41,7 @@ import org.springframework.integration.expression.ExpressionUtils;
import org.springframework.integration.expression.FunctionExpression;
import org.springframework.integration.expression.ValueExpression;
import org.springframework.integration.file.FileHeaders;
import org.springframework.integration.file.FileNameGenerator;
import org.springframework.integration.file.filters.FileListFilter;
import org.springframework.integration.file.remote.AbstractFileInfo;
import org.springframework.integration.file.remote.MessageSessionCallback;
@@ -108,6 +109,8 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
private Integer chmod;
private boolean remoteFileTemplateExplicitlySet;
/**
* Construct an instance using the provided session factory and callback for
* performing operations on the session.
@@ -135,6 +138,7 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
this.messageSessionCallback = messageSessionCallback;
this.fileNameProcessor = null;
this.command = null;
remoteFileTemplateExplicitlySet(true);
}
/**
@@ -204,6 +208,16 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
setPrimaryExpression(parsedExpression);
}
this.messageSessionCallback = null;
remoteFileTemplateExplicitlySet(true);
}
protected final void remoteFileTemplateExplicitlySet(boolean remoteFileTemplateExplicitlySet) {
this.remoteFileTemplateExplicitlySet = remoteFileTemplateExplicitlySet;
}
protected void assertRemoteFileTemplateMutability(String propertyName) {
Assert.state(!this.remoteFileTemplateExplicitlySet,
() -> "The '" + propertyName + "' must be set on the externally provided: " + this.remoteFileTemplate);
}
/**
@@ -242,6 +256,7 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
* @see RemoteFileTemplate#setRemoteFileSeparator(String)
*/
public void setRemoteFileSeparator(String remoteFileSeparator) {
assertRemoteFileTemplateMutability("remoteFileSeparator");
this.remoteFileTemplate.setRemoteFileSeparator(remoteFileSeparator);
}
@@ -290,9 +305,93 @@ public abstract class AbstractRemoteFileOutboundGateway<F> extends AbstractReply
* @see RemoteFileTemplate#setTemporaryFileSuffix(String)
*/
public void setTemporaryFileSuffix(String temporaryFileSuffix) {
assertRemoteFileTemplateMutability("temporaryFileSuffix");
this.remoteFileTemplate.setTemporaryFileSuffix(temporaryFileSuffix);
}
/**
* Determine whether the remote directory should automatically be created when
* sending files to the remote system.
* @param autoCreateDirectory true to create the directory.
* @since 5.2
* @see RemoteFileTemplate#setAutoCreateDirectory(boolean)
*/
public void setAutoCreateDirectory(boolean autoCreateDirectory) {
assertRemoteFileTemplateMutability("autoCreateDirectory");
this.remoteFileTemplate.setAutoCreateDirectory(autoCreateDirectory);
}
/**
* Set the remote directory expression used to determine the remote directory to which
* files will be sent.
* @param remoteDirectoryExpression the remote directory expression.
* @since 5.2
* @see RemoteFileTemplate#setRemoteDirectoryExpression
*/
public void setRemoteDirectoryExpression(Expression remoteDirectoryExpression) {
assertRemoteFileTemplateMutability("remoteDirectoryExpression");
this.remoteFileTemplate.setRemoteDirectoryExpression(remoteDirectoryExpression);
}
/**
* Set a temporary remote directory expression; used when transferring files to the remote
* system. After a successful transfer the file is renamed using the
* {@link #setRemoteDirectoryExpression(Expression) remoteDirectoryExpression}.
* @param temporaryRemoteDirectoryExpression the temporary remote directory expression.
* @since 5.2
* @see RemoteFileTemplate#setTemporaryRemoteDirectoryExpression
*/
public void setTemporaryRemoteDirectoryExpression(Expression temporaryRemoteDirectoryExpression) {
assertRemoteFileTemplateMutability("temporaryRemoteDirectoryExpression");
this.remoteFileTemplate.setTemporaryRemoteDirectoryExpression(temporaryRemoteDirectoryExpression);
}
/**
* Set the file name expression to determine the full path to the remote file.
* @param fileNameExpression the file name expression.
* @since 5.2
* @see RemoteFileTemplate#setFileNameExpression
*/
public void setFileNameExpression(Expression fileNameExpression) {
assertRemoteFileTemplateMutability("fileNameExpression");
this.remoteFileTemplate.setFileNameExpression(fileNameExpression);
}
/**
* Set whether a temporary file name is used when sending files to the remote system.
* @param useTemporaryFileName true to use a temporary file name.
* @since 5.2
* @see RemoteFileTemplate#setUseTemporaryFileName
*/
public void setUseTemporaryFileName(boolean useTemporaryFileName) {
assertRemoteFileTemplateMutability("useTemporaryFileName");
this.remoteFileTemplate.setUseTemporaryFileName(useTemporaryFileName);
}
/**
* Set the file name generator used to generate the remote filename to be used when transferring
* files to the remote system.
* @param fileNameGenerator the file name generator.
* @since 5.2
* @see RemoteFileTemplate#setFileNameGenerator
*/
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
assertRemoteFileTemplateMutability("fileNameGenerator");
this.remoteFileTemplate.setFileNameGenerator(fileNameGenerator);
}
/**
* Set the charset to use when converting String payloads to bytes as the content of the
* remote file. Default {@code UTF-8}.
* @param charset the charset.
* @since 5.2
* @see RemoteFileTemplate#setCharset
*/
public void setCharset(String charset) {
assertRemoteFileTemplateMutability("charset");
this.remoteFileTemplate.setCharset(charset);
}
/**
* Set a {@link FileListFilter} to filter remote files.
* @param filter the filter to set

View File

@@ -19,6 +19,7 @@ package org.springframework.integration.file.remote.gateway;
import static org.assertj.core.api.Assertions.assertThat;
import static org.assertj.core.api.Assertions.assertThatExceptionOfType;
import static org.assertj.core.api.Assertions.assertThatIllegalArgumentException;
import static org.assertj.core.api.Assertions.assertThatIllegalStateException;
import static org.mockito.ArgumentMatchers.any;
import static org.mockito.ArgumentMatchers.anyString;
import static org.mockito.Mockito.doAnswer;
@@ -124,7 +125,8 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<TestLsEntry>> out = (MessageBuilder<List<TestLsEntry>>) gw
.handleRequestMessage(new GenericMessage<>("testremote/x"));
assertThat(out.getPayload().size()).isEqualTo(2);
assertThat(out).isNotNull();
assertThat(out.getPayload()).hasSize(2);
assertThat(out.getPayload().get(0)).isSameAs(files[1]); // sort by default
assertThat(out.getPayload().get(1)).isSameAs(files[0]);
assertThat(out.getHeaders().get(FileHeaders.REMOTE_DIRECTORY)).isEqualTo("testremote/x/");
@@ -175,7 +177,8 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<File>> out = (MessageBuilder<List<File>>) gw
.handleRequestMessage(new GenericMessage<>("testremote/*"));
assertThat(out.getPayload().size()).isEqualTo(2);
assertThat(out).isNotNull();
assertThat(out.getPayload()).hasSize(2);
assertThat(out.getPayload().get(0).getName()).isEqualTo("f1");
assertThat(out.getPayload().get(1).getName()).isEqualTo("f2");
assertThat(out.getHeaders().get(FileHeaders.REMOTE_DIRECTORY)).isEqualTo("testremote/");
@@ -205,7 +208,8 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<File>> out = (MessageBuilder<List<File>>) gw
.handleRequestMessage(new GenericMessage<>("testremote/f1"));
assertThat(out.getPayload().size()).isEqualTo(1);
assertThat(out).isNotNull();
assertThat(out.getPayload()).hasSize(1);
assertThat(out.getPayload().get(0).getName()).isEqualTo("f1");
assertThat(out.getHeaders().get(FileHeaders.REMOTE_DIRECTORY)).isEqualTo("testremote/");
}
@@ -329,7 +333,8 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<TestLsEntry>> out = (MessageBuilder<List<TestLsEntry>>) gw
.handleRequestMessage(new GenericMessage<>("testremote/x"));
assertThat(out.getPayload().size()).isEqualTo(2);
assertThat(out).isNotNull();
assertThat(out.getPayload()).hasSize(2);
assertThat(out.getPayload().get(0)).isSameAs(files[0]);
assertThat(out.getPayload().get(1)).isSameAs(files[1]);
assertThat(out.getHeaders().get(FileHeaders.REMOTE_DIRECTORY)).isEqualTo("testremote/x/");
@@ -373,7 +378,8 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<TestLsEntry>> out = (MessageBuilder<List<TestLsEntry>>) gw
.handleRequestMessage(new GenericMessage<>("testremote/x"));
assertThat(out.getPayload().size()).isEqualTo(4);
assertThat(out).isNotNull();
assertThat(out.getPayload()).hasSize(4);
assertThat(out.getPayload().get(0).getFilename()).isEqualTo("f1");
assertThat(out.getPayload().get(1).getFilename()).isEqualTo("d1/d2/f4");
assertThat(out.getPayload().get(2).getFilename()).isEqualTo("d1/f3");
@@ -398,7 +404,8 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<TestLsEntry>> out = (MessageBuilder<List<TestLsEntry>>) gw
.handleRequestMessage(new GenericMessage<>("testremote/x"));
assertThat(out.getPayload().size()).isEqualTo(5);
assertThat(out).isNotNull();
assertThat(out.getPayload()).hasSize(5);
assertThat(out.getPayload().get(0).getFilename()).isEqualTo("f1");
assertThat(out.getPayload().get(1).getFilename()).isEqualTo("d1");
assertThat(out.getPayload().get(2).getFilename()).isEqualTo("d1/d2");
@@ -419,7 +426,8 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<TestLsEntry>> out = (MessageBuilder<List<TestLsEntry>>) gw
.handleRequestMessage(new GenericMessage<>("testremote"));
assertThat(out.getPayload().size()).isEqualTo(0);
assertThat(out).isNotNull();
assertThat(out.getPayload()).hasSize(0);
}
@Test
@@ -435,7 +443,8 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<String>> out = (MessageBuilder<List<String>>) gw
.handleRequestMessage(new GenericMessage<>("testremote"));
assertThat(out.getPayload().size()).isEqualTo(2);
assertThat(out).isNotNull();
assertThat(out.getPayload()).hasSize(2);
assertThat(out.getPayload().get(0)).isEqualTo("f1");
assertThat(out.getPayload().get(1)).isEqualTo("f2");
}
@@ -453,7 +462,7 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<String>> out = (MessageBuilder<List<String>>) gw
.handleRequestMessage(new GenericMessage<>("testremote"));
assertThat(out.getPayload().size()).isEqualTo(2);
assertThat(out.getPayload()).hasSize(2);
assertThat(out.getPayload().get(0)).isEqualTo("f2");
assertThat(out.getPayload().get(1)).isEqualTo("f1");
}
@@ -471,7 +480,7 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<String>> out = (MessageBuilder<List<String>>) gw
.handleRequestMessage(new GenericMessage<>("testremote"));
assertThat(out.getPayload().size()).isEqualTo(3);
assertThat(out.getPayload()).hasSize(3);
assertThat(out.getPayload().get(0)).isEqualTo("f1");
assertThat(out.getPayload().get(1)).isEqualTo("f2");
assertThat(out.getPayload().get(2)).isEqualTo("f3");
@@ -490,7 +499,7 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<String>> out = (MessageBuilder<List<String>>) gw
.handleRequestMessage(new GenericMessage<>("testremote"));
assertThat(out.getPayload().size()).isEqualTo(4);
assertThat(out.getPayload()).hasSize(4);
assertThat(out.getPayload().get(0)).isEqualTo("f1");
assertThat(out.getPayload().get(1)).isEqualTo("f2");
assertThat(out.getPayload().get(2)).isEqualTo("f3");
@@ -510,7 +519,7 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<String>> out = (MessageBuilder<List<String>>) gw
.handleRequestMessage(new GenericMessage<>("testremote"));
assertThat(out.getPayload().size()).isEqualTo(6);
assertThat(out.getPayload()).hasSize(6);
assertThat(out.getPayload().get(0)).isEqualTo("f2");
assertThat(out.getPayload().get(1)).isEqualTo("f1");
assertThat(out.getPayload().get(2)).isEqualTo("f3");
@@ -533,7 +542,7 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<List<String>> out = (MessageBuilder<List<String>>) gw
.handleRequestMessage(new GenericMessage<>("testremote"));
assertThat(out.getPayload().size()).isEqualTo(1);
assertThat(out.getPayload()).hasSize(1);
assertThat(out.getPayload().get(0)).isEqualTo("f4");
}
@@ -748,7 +757,7 @@ public class RemoteFileOutboundGatewayTests {
@SuppressWarnings("unchecked")
MessageBuilder<Boolean> out = (MessageBuilder<Boolean>) gw
.handleRequestMessage(new GenericMessage<>("testremote/x/f1"));
assertThat(out.getPayload()).isEqualTo(Boolean.TRUE);
assertThat(out.getPayload()).isTrue();
verify(session).remove("testremote/x/f1");
assertThat(out.getHeaders().get(FileHeaders.REMOTE_DIRECTORY)).isEqualTo("testremote/x/");
assertThat(out.getHeaders().get(FileHeaders.REMOTE_FILE)).isEqualTo("f1");
@@ -876,7 +885,7 @@ public class RemoteFileOutboundGatewayTests {
Message<File> requestMessage = MessageBuilder.withPayload(tempFolder.getRoot())
.build();
List<String> out = (List<String>) gw.handleRequestMessage(requestMessage);
assertThat(out.size()).isEqualTo(2);
assertThat(out).hasSize(2);
assertThat(out.get(0)).isNotEqualTo(out.get(1));
assertThat(out.get(0)).isIn("foo/baz.txt", "foo/qux.txt");
assertThat(out.get(1)).isIn("foo/baz.txt", "foo/qux.txt");
@@ -908,23 +917,31 @@ public class RemoteFileOutboundGatewayTests {
Message<File> requestMessage = MessageBuilder.withPayload(tempFolder.getRoot())
.build();
List<String> out = (List<String>) gw.handleRequestMessage(requestMessage);
assertThat(out.size()).isEqualTo(3);
assertThat(out).hasSize(3);
assertThat(out.get(0)).isNotEqualTo(out.get(1));
assertThat(out.get(0)).isIn("foo/baz.txt", "foo/qux.txt", "foo/" + dir1.getName() + "/" + file3.getName());
assertThat(out.get(1)).isIn("foo/baz.txt", "foo/qux.txt", "foo/" + dir1.getName() + "/" + file3.getName());
assertThat(out.get(2)).isIn("foo/baz.txt", "foo/qux.txt", "foo/" + dir1.getName() + "/" + file3.getName());
}
@Test
@SuppressWarnings("unchecked")
public void testRemoteFileTemplateImmutability() {
SessionFactory<TestLsEntry> sessionFactory = mock(SessionFactory.class);
RemoteFileTemplate<TestLsEntry> template = new RemoteFileTemplate<>(sessionFactory);
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(template, "mput", null);
assertThatIllegalStateException()
.isThrownBy(() -> gw.setRemoteDirectoryExpression(new LiteralExpression("testRemoteDirectory")))
.withMessageContaining("The 'remoteDirectoryExpression' must be set on the externally provided");
}
@Test
@SuppressWarnings("unchecked")
public void testMputCollection() throws Exception {
SessionFactory<TestLsEntry> sessionFactory = mock(SessionFactory.class);
Session<TestLsEntry> session = mock(Session.class);
RemoteFileTemplate<TestLsEntry> template = new RemoteFileTemplate<>(sessionFactory);
template.setRemoteDirectoryExpression(new LiteralExpression("foo/"));
template.setBeanFactory(mock(BeanFactory.class));
template.afterPropertiesSet();
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(template, "mput", "payload");
TestRemoteFileOutboundGateway gw = new TestRemoteFileOutboundGateway(sessionFactory, "mput", "payload");
gw.setRemoteDirectoryExpression(new LiteralExpression("foo/"));
gw.afterPropertiesSet();
when(sessionFactory.getSession()).thenReturn(session);
final AtomicReference<String> written = new AtomicReference<>();
@@ -938,7 +955,7 @@ public class RemoteFileOutboundGatewayTests {
Message<List<File>> requestMessage = MessageBuilder.withPayload(files)
.build();
List<String> out = (List<String>) gw.handleRequestMessage(requestMessage);
assertThat(out.size()).isEqualTo(2);
assertThat(out).isNotNull().hasSize(2);
assertThat(out.get(0)).isNotEqualTo(out.get(1));
assertThat(out.get(0)).isEqualTo("foo/fiz.txt");
assertThat(out.get(1)).isEqualTo("foo/buz.txt");
@@ -1038,6 +1055,7 @@ public class RemoteFileOutboundGatewayTests {
String command, String expression) {
super(sessionFactory, Command.toCommand(command), expression);
this.setBeanFactory(mock(BeanFactory.class));
remoteFileTemplateExplicitlySet(false);
}
TestRemoteFileOutboundGateway(RemoteFileTemplate<TestLsEntry> remoteFileTemplate, String command,
@@ -1046,7 +1064,6 @@ public class RemoteFileOutboundGatewayTests {
this.setBeanFactory(mock(BeanFactory.class));
}
@Override
protected boolean isDirectory(TestLsEntry file) {
return file.isDirectory();

View File

@@ -68,6 +68,7 @@ public class FtpOutboundGateway extends AbstractRemoteFileOutboundGateway<FTPFil
this(new FtpRemoteFileTemplate(sessionFactory), messageSessionCallback);
((FtpRemoteFileTemplate) getRemoteFileTemplate()).setExistsMode(FtpRemoteFileTemplate.ExistsMode.NLST);
remoteFileTemplateExplicitlySet(false);
}
/**
@@ -92,6 +93,7 @@ public class FtpOutboundGateway extends AbstractRemoteFileOutboundGateway<FTPFil
public FtpOutboundGateway(SessionFactory<FTPFile> sessionFactory, String command, String expression) {
this(new FtpRemoteFileTemplate(sessionFactory), command, expression);
((FtpRemoteFileTemplate) getRemoteFileTemplate()).setExistsMode(FtpRemoteFileTemplate.ExistsMode.NLST);
remoteFileTemplateExplicitlySet(false);
}
/**

View File

@@ -197,13 +197,15 @@ public class FtpTests extends FtpTestSupport {
public void testFtpMgetFlow() {
QueueChannel out = new QueueChannel();
IntegrationFlow flow = f -> f
.handle(Ftp.outboundGateway(sessionFactory(),
AbstractRemoteFileOutboundGateway.Command.MGET, "payload")
.options(AbstractRemoteFileOutboundGateway.Option.RECURSIVE)
.fileExistsMode(FileExistsMode.IGNORE)
.filterExpression("name matches 'subFtpSource|.*1.txt'")
.localDirectoryExpression("'" + getTargetLocalDirectoryName() + "' + #remoteDirectory")
.localFilenameExpression("#remoteFileName.replaceFirst('ftpSource', 'localTarget')"))
.handle(
Ftp.outboundGateway(sessionFactory(), AbstractRemoteFileOutboundGateway.Command.MGET, "payload")
.options(AbstractRemoteFileOutboundGateway.Option.RECURSIVE)
.fileExistsMode(FileExistsMode.IGNORE)
.filterExpression("name matches 'subFtpSource|.*1.txt'")
.localDirectoryExpression("'" + getTargetLocalDirectoryName() + "' + #remoteDirectory")
.localFilenameExpression("#remoteFileName.replaceFirst('ftpSource', 'localTarget')")
.charset(StandardCharsets.UTF_8.name())
.useTemporaryFileName(true))
.channel(out);
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
String dir = "ftpSource/";

View File

@@ -66,6 +66,7 @@ public class SftpOutboundGateway extends AbstractRemoteFileOutboundGateway<LsEnt
MessageSessionCallback<LsEntry, ?> messageSessionCallback) {
this(new SftpRemoteFileTemplate(sessionFactory), messageSessionCallback);
remoteFileTemplateExplicitlySet(false);
}
/**
@@ -89,6 +90,7 @@ public class SftpOutboundGateway extends AbstractRemoteFileOutboundGateway<LsEnt
*/
public SftpOutboundGateway(SessionFactory<LsEntry> sessionFactory, String command, String expression) {
this(new SftpRemoteFileTemplate(sessionFactory), command, expression);
remoteFileTemplateExplicitlySet(false);
}
/**