GH-3026 Support chmod with FTP
Resolves https://github.com/spring-projects/spring-integration/issues/3026 * Fix exception messages; remove test TODOs; test works on Windows # Conflicts: # spring-integration-ftp/src/test/java/org/springframework/integration/ftp/outbound/FtpServerOutboundTests.java # src/reference/asciidoc/whats-new.adoc
This commit is contained in:
committed by
Artem Bilan
parent
f7032c7127
commit
b04a8576fa
@@ -20,6 +20,7 @@ import org.w3c.dom.Element;
|
||||
|
||||
import org.springframework.beans.factory.config.BeanDefinition;
|
||||
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
|
||||
import org.springframework.integration.config.xml.IntegrationNamespaceUtils;
|
||||
import org.springframework.integration.file.config.RemoteFileOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.file.remote.RemoteFileOperations;
|
||||
import org.springframework.integration.ftp.outbound.FtpMessageHandler;
|
||||
@@ -56,6 +57,7 @@ public class FtpOutboundChannelAdapterParser extends RemoteFileOutboundChannelAd
|
||||
.getValue();
|
||||
templateDefinition.getPropertyValues() // NOSONAR never null
|
||||
.add("existsMode", FtpRemoteFileTemplate.ExistsMode.NLST);
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "chmod", "chmodOctal");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -71,6 +71,7 @@ public class FtpOutboundGatewayParser extends AbstractRemoteFileOutboundGatewayP
|
||||
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "working-dir-expression",
|
||||
"workingDirExpressionString");
|
||||
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "chmod", "chmodOctal");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -18,6 +18,7 @@ package org.springframework.integration.ftp.gateway;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
@@ -31,7 +32,9 @@ import org.springframework.expression.Expression;
|
||||
import org.springframework.expression.spel.support.StandardEvaluationContext;
|
||||
import org.springframework.integration.expression.ExpressionUtils;
|
||||
import org.springframework.integration.file.remote.AbstractFileInfo;
|
||||
import org.springframework.integration.file.remote.ClientCallbackWithoutResult;
|
||||
import org.springframework.integration.file.remote.MessageSessionCallback;
|
||||
import org.springframework.integration.file.remote.RemoteFileOperations;
|
||||
import org.springframework.integration.file.remote.RemoteFileTemplate;
|
||||
import org.springframework.integration.file.remote.gateway.AbstractRemoteFileOutboundGateway;
|
||||
import org.springframework.integration.file.remote.session.Session;
|
||||
@@ -296,4 +299,22 @@ public class FtpOutboundGateway extends AbstractRemoteFileOutboundGateway<FTPFil
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChmodCapable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doChmod(RemoteFileOperations<FTPFile> remoteFileOperations, final String path, final int chmod) {
|
||||
remoteFileOperations.executeWithClient((ClientCallbackWithoutResult<FTPClient>) client -> {
|
||||
String chModCommand = "chmod " + Integer.toOctalString(chmod) + " " + path;
|
||||
try {
|
||||
client.sendSiteCommand(chModCommand);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to execute '" + chModCommand + "'", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -16,8 +16,13 @@
|
||||
|
||||
package org.springframework.integration.ftp.outbound;
|
||||
|
||||
import java.io.IOException;
|
||||
import java.io.UncheckedIOException;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
|
||||
import org.springframework.integration.file.remote.ClientCallbackWithoutResult;
|
||||
import org.springframework.integration.file.remote.RemoteFileTemplate;
|
||||
import org.springframework.integration.file.remote.handler.FileTransferringMessageHandler;
|
||||
import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
@@ -47,4 +52,22 @@ public class FtpMessageHandler extends FileTransferringMessageHandler<FTPFile> {
|
||||
super(remoteFileTemplate, mode);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isChmodCapable() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doChmod(RemoteFileTemplate<FTPFile> remoteFileTemplate, final String path, final int chmod) {
|
||||
remoteFileTemplate.executeWithClient((ClientCallbackWithoutResult<FTPClient>) client -> {
|
||||
String chModCommand = "chmod " + Integer.toOctalString(chmod) + " " + path;
|
||||
try {
|
||||
client.sendSiteCommand(chModCommand);
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new UncheckedIOException("Failed to execute '" + chModCommand + "'", e);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -63,6 +63,7 @@
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="int-file:remoteOutboundAttributeGroup" />
|
||||
<xsd:attributeGroup ref="int-file:chmod" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
@@ -517,6 +518,7 @@
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="int-file:remoteOutboundAttributeGroup" />
|
||||
<xsd:attributeGroup ref="int-file:chmod" />
|
||||
</xsd:extension>
|
||||
</xsd:complexContent>
|
||||
</xsd:complexType>
|
||||
|
||||
@@ -86,6 +86,7 @@
|
||||
auto-create-directory="true"
|
||||
filename-pattern="*.txt"
|
||||
expression="payload"
|
||||
chmod="600"
|
||||
remote-directory="ftpTarget"
|
||||
mput-filter="sortingFilter"
|
||||
reply-channel="output"/>
|
||||
@@ -141,6 +142,7 @@
|
||||
session-factory="ftpSessionFactory"
|
||||
channel="appending"
|
||||
mode="APPEND"
|
||||
chmod="600"
|
||||
use-temporary-file-name="false"
|
||||
remote-directory="ftpTarget"
|
||||
auto-create-directory="true"
|
||||
|
||||
@@ -34,6 +34,8 @@ import static org.junit.Assert.fail;
|
||||
import static org.mockito.Mockito.doAnswer;
|
||||
import static org.mockito.Mockito.mock;
|
||||
import static org.mockito.Mockito.spy;
|
||||
import static org.mockito.Mockito.times;
|
||||
import static org.mockito.Mockito.verify;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.ByteArrayOutputStream;
|
||||
@@ -58,6 +60,7 @@ import org.junit.Test;
|
||||
import org.junit.runner.RunWith;
|
||||
import org.mockito.Mockito;
|
||||
|
||||
import org.springframework.beans.DirectFieldAccessor;
|
||||
import org.springframework.beans.factory.BeanFactory;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.beans.factory.annotation.Qualifier;
|
||||
@@ -395,7 +398,12 @@ public class FtpServerOutboundTests extends FtpTestSupport {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt3088MPutNotRecursive() {
|
||||
public void testInt3088MPutNotRecursive() throws IOException {
|
||||
Session<?> session = ftpSessionFactory.getSession();
|
||||
session.close();
|
||||
session = TestUtils.getPropertyValue(session, "targetSession", Session.class);
|
||||
FTPClient client = spy(TestUtils.getPropertyValue(session, "client", FTPClient.class));
|
||||
new DirectFieldAccessor(session).setPropertyValue("client", client);
|
||||
this.inboundMPut.send(new GenericMessage<File>(getSourceLocalDirectory()));
|
||||
@SuppressWarnings("unchecked")
|
||||
Message<List<String>> out = (Message<List<String>>) this.output.receive(1000);
|
||||
@@ -409,6 +417,8 @@ public class FtpServerOutboundTests extends FtpTestSupport {
|
||||
assertThat(
|
||||
out.getPayload().get(1),
|
||||
anyOf(equalTo("ftpTarget/localSource1.txt"), equalTo("ftpTarget/localSource2.txt")));
|
||||
verify(client).sendSiteCommand("chmod 600 ftpTarget/localSource1.txt");
|
||||
verify(client).sendSiteCommand("chmod 600 ftpTarget/localSource1.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -454,7 +464,12 @@ public class FtpServerOutboundTests extends FtpTestSupport {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void testInt3412FileMode() {
|
||||
public void testInt3412FileMode() throws IOException {
|
||||
Session<?> session = ftpSessionFactory.getSession();
|
||||
session.close();
|
||||
session = TestUtils.getPropertyValue(session, "targetSession", Session.class);
|
||||
FTPClient client = spy(TestUtils.getPropertyValue(session, "client", FTPClient.class));
|
||||
new DirectFieldAccessor(session).setPropertyValue("client", client);
|
||||
FtpRemoteFileTemplate template = new FtpRemoteFileTemplate(ftpSessionFactory);
|
||||
assertFalse(template.exists("ftpTarget/appending.txt"));
|
||||
Message<String> m = MessageBuilder.withPayload("foo")
|
||||
@@ -474,7 +489,7 @@ public class FtpServerOutboundTests extends FtpTestSupport {
|
||||
catch (MessagingException e) {
|
||||
assertThat(e.getCause().getCause().getMessage(), containsString("The destination file already exists"));
|
||||
}
|
||||
|
||||
verify(client, times(2)).sendSiteCommand("chmod 600 ftpTarget/appending.txt");
|
||||
}
|
||||
|
||||
@Test
|
||||
|
||||
Reference in New Issue
Block a user