INT-3412 (S)FTP Append, rmdir, Client Access
JIRA: https://jira.spring.io/browse/INT-3412 Initial commit - review only. TODO: - SFTP Tests - Namespace/Adapter support for file append - Docs INT-3412 Polishing - Addressed PR comments - Completed SFTP implementation - Added namespace/parser support for `FileExistsMode` (append, etc) - Added SFTP Tests - Created Embedded SFTP server for tests (similar to FTP) - Converted tests that needed a real server to use the embedded server INT-3412 Docs and Polish (PR Comments)
This commit is contained in:
committed by
Artem Bilan
parent
bc3db5d4a9
commit
403c91801d
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.integration.ftp.config;
|
||||
|
||||
import org.springframework.integration.config.xml.AbstractIntegrationNamespaceHandler;
|
||||
import org.springframework.integration.file.config.RemoteFileOutboundChannelAdapterParser;
|
||||
|
||||
/**
|
||||
* Provides namespace support for using FTP
|
||||
@@ -26,13 +25,15 @@ import org.springframework.integration.file.config.RemoteFileOutboundChannelAdap
|
||||
*
|
||||
* @author Josh Long
|
||||
* @author Oleg Zhurakousky
|
||||
* @author Gary Russell
|
||||
* @since 2.0
|
||||
*/
|
||||
public class FtpNamespaceHandler extends AbstractIntegrationNamespaceHandler {
|
||||
|
||||
@Override
|
||||
public void init() {
|
||||
registerBeanDefinitionParser("inbound-channel-adapter", new FtpInboundChannelAdapterParser());
|
||||
registerBeanDefinitionParser("outbound-channel-adapter", new RemoteFileOutboundChannelAdapterParser());
|
||||
registerBeanDefinitionParser("outbound-channel-adapter", new FtpOutboundChannelAdapterParser());
|
||||
registerBeanDefinitionParser("outbound-gateway", new FtpOutboundGatewayParser());
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,36 @@
|
||||
/*
|
||||
* Copyright 2014 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.integration.ftp.config;
|
||||
|
||||
import org.springframework.integration.file.config.RemoteFileOutboundChannelAdapterParser;
|
||||
import org.springframework.integration.file.remote.RemoteFileOperations;
|
||||
import org.springframework.integration.ftp.session.FtpRemoteFileTemplate;
|
||||
|
||||
/**
|
||||
* Parser for FTP Outbound Channel Adapters.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 4.1
|
||||
*
|
||||
*/
|
||||
public class FtpOutboundChannelAdapterParser extends RemoteFileOutboundChannelAdapterParser {
|
||||
|
||||
@Override
|
||||
protected Class<? extends RemoteFileOperations<?>> getTemplateClass() {
|
||||
return FtpRemoteFileTemplate.class;
|
||||
}
|
||||
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2013 the original author or authors.
|
||||
* Copyright 2002-2014 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.
|
||||
@@ -16,9 +16,11 @@
|
||||
package org.springframework.integration.ftp.config;
|
||||
|
||||
import org.springframework.integration.file.config.AbstractRemoteFileOutboundGatewayParser;
|
||||
import org.springframework.integration.file.remote.RemoteFileOperations;
|
||||
import org.springframework.integration.ftp.filters.FtpRegexPatternFileListFilter;
|
||||
import org.springframework.integration.ftp.filters.FtpSimplePatternFileListFilter;
|
||||
import org.springframework.integration.ftp.gateway.FtpOutboundGateway;
|
||||
import org.springframework.integration.ftp.session.FtpRemoteFileTemplate;
|
||||
|
||||
/**
|
||||
* @author Gary Russell
|
||||
@@ -28,6 +30,7 @@ import org.springframework.integration.ftp.gateway.FtpOutboundGateway;
|
||||
*/
|
||||
public class FtpOutboundGatewayParser extends AbstractRemoteFileOutboundGatewayParser {
|
||||
|
||||
@Override
|
||||
public String getGatewayClassName() {
|
||||
return FtpOutboundGateway.class.getName();
|
||||
}
|
||||
@@ -42,4 +45,9 @@ public class FtpOutboundGatewayParser extends AbstractRemoteFileOutboundGatewayP
|
||||
return FtpRegexPatternFileListFilter.class.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
protected Class<? extends RemoteFileOperations<?>> getTemplateClass() {
|
||||
return FtpRemoteFileTemplate.class;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -26,7 +26,6 @@ import org.apache.commons.net.ftp.FTPClientConfig;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
import org.apache.commons.net.ftp.FTPReply;
|
||||
|
||||
import org.springframework.integration.file.remote.session.Session;
|
||||
import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -164,7 +163,7 @@ public abstract class AbstractFtpSessionFactory<T extends FTPClient> implements
|
||||
}
|
||||
|
||||
@Override
|
||||
public Session<FTPFile> getSession() {
|
||||
public FtpSession getSession() {
|
||||
try {
|
||||
return new FtpSession(this.createClient());
|
||||
}
|
||||
|
||||
@@ -0,0 +1,77 @@
|
||||
/*
|
||||
* Copyright 2014 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.
|
||||
* You may obtain a copy of the License at
|
||||
*
|
||||
* http://www.apache.org/licenses/LICENSE-2.0
|
||||
*
|
||||
* Unless required by applicable law or agreed to in writing, software
|
||||
* distributed under the License is distributed on an "AS IS" BASIS,
|
||||
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
*/
|
||||
package org.springframework.integration.ftp.session;
|
||||
|
||||
import java.io.IOException;
|
||||
|
||||
import org.apache.commons.net.ftp.FTPClient;
|
||||
import org.apache.commons.net.ftp.FTPFile;
|
||||
|
||||
import org.springframework.integration.file.remote.ClientCallback;
|
||||
import org.springframework.integration.file.remote.RemoteFileTemplate;
|
||||
import org.springframework.integration.file.remote.SessionCallback;
|
||||
import org.springframework.integration.file.remote.session.Session;
|
||||
import org.springframework.integration.file.remote.session.SessionFactory;
|
||||
import org.springframework.messaging.MessagingException;
|
||||
|
||||
/**
|
||||
* FTP version of {@code RemoteFileTemplate} providing type-safe access to
|
||||
* the underlying FTPClient object.
|
||||
*
|
||||
* @author Gary Russell
|
||||
* @since 4.1
|
||||
*
|
||||
*/
|
||||
public class FtpRemoteFileTemplate extends RemoteFileTemplate<FTPFile> {
|
||||
|
||||
public FtpRemoteFileTemplate(SessionFactory<FTPFile> sessionFactory) {
|
||||
super(sessionFactory);
|
||||
}
|
||||
|
||||
@SuppressWarnings("unchecked")
|
||||
@Override
|
||||
public <T, C> T executeWithClient(final ClientCallback<C, T> callback) {
|
||||
return doExecuteWithClient((ClientCallback<FTPClient, T>) callback);
|
||||
}
|
||||
|
||||
protected <T> T doExecuteWithClient(final ClientCallback<FTPClient, T> callback) {
|
||||
return execute(new SessionCallback<FTPFile, T>() {
|
||||
|
||||
@Override
|
||||
public T doInSession(Session<FTPFile> session) throws IOException {
|
||||
return callback.doWithClient((FTPClient) session.getClientInstance());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean exists(final String path) {
|
||||
return executeWithClient(new ClientCallback<FTPClient, Boolean>() {
|
||||
|
||||
@Override
|
||||
public Boolean doWithClient(FTPClient client) {
|
||||
try {
|
||||
return client.getStatus(path) != null;
|
||||
}
|
||||
catch (IOException e) {
|
||||
throw new MessagingException("Failed to stat " + path, e);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -116,7 +116,7 @@ public class FtpSession implements Session<FTPFile> {
|
||||
@Override
|
||||
public void write(InputStream inputStream, String path) throws IOException {
|
||||
Assert.notNull(inputStream, "inputStream must not be null");
|
||||
Assert.hasText(path, "path must not be null");
|
||||
Assert.hasText(path, "path must not be null or empty");
|
||||
boolean completed = this.client.storeFile(path, inputStream);
|
||||
if (!completed) {
|
||||
throw new IOException("Failed to write to '" + path
|
||||
@@ -127,6 +127,20 @@ public class FtpSession implements Session<FTPFile> {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void append(InputStream inputStream, String path) throws IOException {
|
||||
Assert.notNull(inputStream, "inputStream must not be null");
|
||||
Assert.hasText(path, "path must not be null or empty");
|
||||
boolean completed = this.client.appendFile(path, inputStream);
|
||||
if (!completed) {
|
||||
throw new IOException("Failed to append to '" + path
|
||||
+ "'. Server replied with: " + this.client.getReplyString());
|
||||
}
|
||||
if (logger.isInfoEnabled()) {
|
||||
logger.info("File has been successfully appended to: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void close() {
|
||||
try {
|
||||
@@ -168,6 +182,12 @@ public class FtpSession implements Session<FTPFile> {
|
||||
return this.client.makeDirectory(remoteDirectory);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean rmdir(String directory) throws IOException {
|
||||
return this.client.removeDirectory(directory);
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
public boolean exists(String path) throws IOException{
|
||||
Assert.hasText(path, "'path' must not be empty");
|
||||
@@ -187,4 +207,10 @@ public class FtpSession implements Session<FTPFile> {
|
||||
|
||||
return exists;
|
||||
}
|
||||
|
||||
@Override
|
||||
public FTPClient getClientInstance() {
|
||||
return this.client;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user