GH-3092: Refactor (S)FTP outbound specs, handlers

Fixes https://github.com/spring-projects/spring-integration/issues/3092
This commit is contained in:
DEEPAK GUNASEKARAN
2020-06-15 13:27:24 -07:00
committed by GitHub
parent 2419c03b25
commit 7cefd53e10
7 changed files with 204 additions and 4 deletions

View File

@@ -34,6 +34,7 @@ import org.springframework.integration.ftp.session.FtpRemoteFileTemplate;
*
* @author Artem Bilan
* @author Gary Russell
* @author Deepak Gunasekaran
*
* @since 5.0
*/
@@ -111,7 +112,9 @@ public final class Ftp {
* A {@link FtpMessageHandlerSpec} factory for an outbound channel adapter spec.
* @param remoteFileTemplate the remote file template.
* @return the spec.
* @deprecated in favor of {@link #outboundAdapter(FtpRemoteFileTemplate)}
*/
@Deprecated
public static FtpMessageHandlerSpec outboundAdapter(RemoteFileTemplate<FTPFile> remoteFileTemplate) {
return new FtpMessageHandlerSpec(remoteFileTemplate);
}
@@ -121,13 +124,38 @@ public final class Ftp {
* @param remoteFileTemplate the remote file template.
* @param fileExistsMode the file exists mode.
* @return the spec.
* @deprecated in favor of {@link #outboundAdapter(FtpRemoteFileTemplate, FileExistsMode)}
*/
@Deprecated
public static FtpMessageHandlerSpec outboundAdapter(RemoteFileTemplate<FTPFile> remoteFileTemplate,
FileExistsMode fileExistsMode) {
return new FtpMessageHandlerSpec(remoteFileTemplate, fileExistsMode);
}
/**
* A {@link FtpMessageHandlerSpec} factory for an outbound channel adapter spec.
* @param ftpRemoteFileTemplate the remote file template.
* @return the spec.
* @since 5.4
*/
public static FtpMessageHandlerSpec outboundAdapter(FtpRemoteFileTemplate ftpRemoteFileTemplate) {
return new FtpMessageHandlerSpec(ftpRemoteFileTemplate);
}
/**
* A {@link FtpMessageHandlerSpec} factory for an outbound channel adapter spec.
* @param ftpRemoteFileTemplate the remote file template.
* @param fileExistsMode the file exists mode.
* @return the spec.
* @since 5.4
*/
public static FtpMessageHandlerSpec outboundAdapter(FtpRemoteFileTemplate ftpRemoteFileTemplate,
FileExistsMode fileExistsMode) {
return new FtpMessageHandlerSpec(ftpRemoteFileTemplate, fileExistsMode);
}
/**
* Produce a {@link FtpOutboundGatewaySpec} based on the {@link SessionFactory},
* {@link AbstractRemoteFileOutboundGateway.Command} and {@code expression} for the

View File

@@ -23,12 +23,14 @@ import org.springframework.integration.file.remote.RemoteFileTemplate;
import org.springframework.integration.file.remote.session.SessionFactory;
import org.springframework.integration.file.support.FileExistsMode;
import org.springframework.integration.ftp.outbound.FtpMessageHandler;
import org.springframework.integration.ftp.session.FtpRemoteFileTemplate;
/**
* A {@link FileTransferringMessageHandlerSpec} for FTP.
*
* @author Artem Bilan
* @author Joaquin Santana
* @author Deepak Gunasekaran
*
* @since 5.0
*/
@@ -38,12 +40,22 @@ public class FtpMessageHandlerSpec extends FileTransferringMessageHandlerSpec<FT
this.target = new FtpMessageHandler(sessionFactory);
}
@Deprecated
protected FtpMessageHandlerSpec(RemoteFileTemplate<FTPFile> remoteFileTemplate) {
this.target = new FtpMessageHandler(remoteFileTemplate.getSessionFactory());
}
@Deprecated
protected FtpMessageHandlerSpec(RemoteFileTemplate<FTPFile> remoteFileTemplate, FileExistsMode fileExistsMode) {
this.target = new FtpMessageHandler(remoteFileTemplate, fileExistsMode);
}
protected FtpMessageHandlerSpec(FtpRemoteFileTemplate ftpRemoteFileTemplate) {
this.target = new FtpMessageHandler(ftpRemoteFileTemplate);
}
protected FtpMessageHandlerSpec(FtpRemoteFileTemplate ftpRemoteFileTemplate, FileExistsMode fileExistsMode) {
this.target = new FtpMessageHandler(ftpRemoteFileTemplate, fileExistsMode);
}
}

View File

@@ -30,10 +30,12 @@ import org.springframework.integration.file.support.FileExistsMode;
import org.springframework.integration.ftp.session.FtpRemoteFileTemplate;
/**
* The FTP specific {@link FileTransferringMessageHandler} extension.
* Based on the {@link FtpRemoteFileTemplate}.
* The FTP specific {@link FileTransferringMessageHandler} extension. Based on the
* {@link FtpRemoteFileTemplate}.
*
* @author Artem Bilan
* @author Deepak Gunasekaran
*
* @since 4.1.9
* @see FtpRemoteFileTemplate
*/
@@ -48,10 +50,28 @@ public class FtpMessageHandler extends FileTransferringMessageHandler<FTPFile> {
super(remoteFileTemplate);
}
/**
* Constructor which sets the RemoteFileTemplate and FileExistsMode.
* @param remoteFileTemplate the remote file template.
* @param mode the file exists mode.
* @deprecated in favor of
* {@link #FtpMessageHandler(FtpRemoteFileTemplate, FileExistsMode)}
*/
@Deprecated
public FtpMessageHandler(RemoteFileTemplate<FTPFile> remoteFileTemplate, FileExistsMode mode) {
super(remoteFileTemplate, mode);
}
/**
* Constructor which sets the FtpRemoteFileTemplate and FileExistsMode.
* @param ftpRemoteFileTemplate the remote file template.
* @param mode the file exists mode.
* @since 5.4
*/
public FtpMessageHandler(FtpRemoteFileTemplate ftpRemoteFileTemplate, FileExistsMode mode) {
super(ftpRemoteFileTemplate, mode);
}
@Override
public boolean isChmodCapable() {
return true;

View File

@@ -70,6 +70,7 @@ import org.springframework.util.FileCopyUtils;
* @author Artem Bilan
* @author Gary Russell
* @author Joaquin Santana
* @author Deepak Gunasekaran
*
* @since 5.0
*/
@@ -203,6 +204,59 @@ public class FtpTests extends FtpTestSupport {
registration.destroy();
}
@Test
public void testFtpOutboundFlowWithFtpRemoteTemplate() {
FtpRemoteFileTemplate ftpTemplate = new FtpRemoteFileTemplate(sessionFactory());
IntegrationFlow flow = f -> f
.handle(Ftp.outboundAdapter(ftpTemplate)
.useTemporaryFileName(false)
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
.remoteDirectory("ftpTarget"));
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
String fileName = "foo.file";
Message<ByteArrayInputStream> message = MessageBuilder
.withPayload(new ByteArrayInputStream("foo".getBytes(StandardCharsets.UTF_8)))
.setHeader(FileHeaders.FILENAME, fileName)
.build();
registration.getInputChannel().send(message);
FTPFile[] files = ftpTemplate.execute(session ->
session.list(getTargetRemoteDirectory().getName() + "/" + fileName));
assertThat(files.length).isEqualTo(1);
assertThat(files[0].getSize()).isEqualTo(3);
registration.destroy();
}
@Test
public void testFtpOutboundFlowWithFtpRemoteTemplateAndMode() {
FtpRemoteFileTemplate ftpTemplate = new FtpRemoteFileTemplate(sessionFactory());
IntegrationFlow flow = f -> f
.handle(Ftp.outboundAdapter(ftpTemplate, FileExistsMode.APPEND)
.useTemporaryFileName(false)
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
.remoteDirectory("ftpTarget"));
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
String fileName = "foo.file";
Message<ByteArrayInputStream> message1 = MessageBuilder
.withPayload(new ByteArrayInputStream("foo".getBytes(StandardCharsets.UTF_8)))
.setHeader(FileHeaders.FILENAME, fileName)
.build();
Message<ByteArrayInputStream> message2 = MessageBuilder
.withPayload(new ByteArrayInputStream("foo".getBytes(StandardCharsets.UTF_8)))
.setHeader(FileHeaders.FILENAME, fileName)
.build();
registration.getInputChannel().send(message1);
registration.getInputChannel().send(message2);
FTPFile[] files = ftpTemplate.execute(session ->
session.list(getTargetRemoteDirectory().getName() + "/" + fileName));
assertThat(files.length).isEqualTo(1);
assertThat(files[0].getSize()).isEqualTo(6);
registration.destroy();
}
@Test
public void testFtpOutboundFlowWithChmod() {
IntegrationFlow flow = f -> f

View File

@@ -1,5 +1,5 @@
/*
* Copyright 2014-2019 the original author or authors.
* Copyright 2014-2020 the original author or authors.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
@@ -35,6 +35,7 @@ import com.jcraft.jsch.ChannelSftp.LsEntry;
*
* @author Artem Bilan
* @author Gary Russell
* @author Deepak Gunasekaran
*
* @since 5.0
*/
@@ -112,7 +113,9 @@ public final class Sftp {
* An {@link SftpMessageHandlerSpec} factory for an outbound channel adapter spec.
* @param remoteFileTemplate the remote file template.
* @return the spec.
* @deprecated in favor of {@link #outboundAdapter(SftpRemoteFileTemplate)}
*/
@Deprecated
public static SftpMessageHandlerSpec outboundAdapter(RemoteFileTemplate<ChannelSftp.LsEntry> remoteFileTemplate) {
return new SftpMessageHandlerSpec(remoteFileTemplate);
}
@@ -122,13 +125,39 @@ public final class Sftp {
* @param remoteFileTemplate the remote file template.
* @param fileExistsMode the file exists mode.
* @return the spec.
* @deprecated in favor of
* {@link #outboundAdapter(SftpRemoteFileTemplate,FileExistsMode)}
*/
@Deprecated
public static SftpMessageHandlerSpec outboundAdapter(RemoteFileTemplate<ChannelSftp.LsEntry> remoteFileTemplate,
FileExistsMode fileExistsMode) {
return new SftpMessageHandlerSpec(remoteFileTemplate, fileExistsMode);
}
/**
* An {@link SftpMessageHandlerSpec} factory for an outbound channel adapter spec.
* @param sftpRemoteFileTemplate the remote file template.
* @return the spec.
* @since 5.4
*/
public static SftpMessageHandlerSpec outboundAdapter(SftpRemoteFileTemplate sftpRemoteFileTemplate) {
return new SftpMessageHandlerSpec(sftpRemoteFileTemplate);
}
/**
* An {@link SftpMessageHandlerSpec} factory for an outbound channel adapter spec.
* @param sftpRemoteFileTemplate the remote file template.
* @param fileExistsMode the file exists mode.
* @return the spec.
* @since 5.4
*/
public static SftpMessageHandlerSpec outboundAdapter(SftpRemoteFileTemplate sftpRemoteFileTemplate,
FileExistsMode fileExistsMode) {
return new SftpMessageHandlerSpec(sftpRemoteFileTemplate, fileExistsMode);
}
/**
* Produce a {@link SftpOutboundGatewaySpec} based on the {@link SessionFactory},
* {@link AbstractRemoteFileOutboundGateway.Command} and {@code expression} for the

View File

@@ -28,6 +28,7 @@ import com.jcraft.jsch.ChannelSftp;
/**
* @author Artem Bilan
* @author Joaquin Santana
* @author Deepak Gunasekaran
*
* @since 5.0
*/
@@ -38,10 +39,12 @@ public class SftpMessageHandlerSpec
this.target = new SftpMessageHandler(sessionFactory);
}
@Deprecated
protected SftpMessageHandlerSpec(RemoteFileTemplate<ChannelSftp.LsEntry> remoteFileTemplate) {
this.target = new SftpMessageHandler(remoteFileTemplate.getSessionFactory());
}
@Deprecated
protected SftpMessageHandlerSpec(RemoteFileTemplate<ChannelSftp.LsEntry> remoteFileTemplate,
FileExistsMode fileExistsMode) {
@@ -50,4 +53,13 @@ public class SftpMessageHandlerSpec
fileExistsMode);
}
protected SftpMessageHandlerSpec(SftpRemoteFileTemplate sftpRemoteFileTemplate) {
this.target = new SftpMessageHandler(sftpRemoteFileTemplate);
}
protected SftpMessageHandlerSpec(SftpRemoteFileTemplate sftpRemoteFileTemplate, FileExistsMode fileExistsMode) {
this.target = new SftpMessageHandler(sftpRemoteFileTemplate, fileExistsMode);
}
}

View File

@@ -56,9 +56,9 @@ import com.jcraft.jsch.ChannelSftp;
* @author Artem Bilan
* @author Gary Russell
* @author Joaquin Santana
* @author Deepak Gunasekaran
*
* @since 5.0
*
*/
@SpringJUnitConfig
@DirtiesContext
@@ -148,6 +148,51 @@ public class SftpTests extends SftpTestSupport {
registration.destroy();
}
@Test
public void testSftpOutboundFlowSftpTemplate() {
SftpRemoteFileTemplate sftpTemplate = new SftpRemoteFileTemplate(sessionFactory());
IntegrationFlow flow = f -> f.handle(Sftp.outboundAdapter(sftpTemplate)
.useTemporaryFileName(false)
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
.remoteDirectory("sftpTarget"));
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
String fileName = "foo.file";
registration.getInputChannel().send(MessageBuilder.withPayload("foo")
.setHeader(FileHeaders.FILENAME, fileName)
.build());
ChannelSftp.LsEntry[] files = sftpTemplate.execute(session ->
session.list(getTargetRemoteDirectory().getName() + "/" + fileName));
assertThat(files.length).isEqualTo(1);
assertThat(files[0].getAttrs().getSize()).isEqualTo(3);
registration.destroy();
}
@Test
public void testSftpOutboundFlowSftpTemplateAndMode() {
SftpRemoteFileTemplate sftpTemplate = new SftpRemoteFileTemplate(sessionFactory());
IntegrationFlow flow = f -> f.handle(Sftp.outboundAdapter(sftpTemplate, FileExistsMode.APPEND)
.useTemporaryFileName(false)
.fileNameExpression("headers['" + FileHeaders.FILENAME + "']")
.remoteDirectory("sftpTarget"));
IntegrationFlowRegistration registration = this.flowContext.registration(flow).register();
String fileName = "foo.file";
registration.getInputChannel().send(MessageBuilder.withPayload("foo")
.setHeader(FileHeaders.FILENAME, fileName)
.build());
registration.getInputChannel().send(MessageBuilder.withPayload("foo")
.setHeader(FileHeaders.FILENAME, fileName)
.build());
ChannelSftp.LsEntry[] files = sftpTemplate.execute(session ->
session.list(getTargetRemoteDirectory().getName() + "/" + fileName));
assertThat(files.length).isEqualTo(1);
assertThat(files[0].getAttrs().getSize()).isEqualTo(6);
registration.destroy();
}
@Test
@DisabledOnOs(OS.WINDOWS)