Migrated FTP Channel Adapter code from the 'org.springframework.integration.adapter' module to the new 'org.springframework.integration.ftp' module.

This commit is contained in:
Mark Fisher
2008-09-22 14:25:08 +00:00
parent 5260e8b1ac
commit a97b767d56
33 changed files with 363 additions and 483 deletions

View File

@@ -16,55 +16,6 @@
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="file-source">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines a file-based source channel adapter.
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="directory" type="xsd:string" use="required"/>
<xsd:attribute name="type" type="fileSourceType" use="optional"/>
<xsd:attribute name="message-creator" type="xsd:string" use="optional"/>
<xsd:attribute name="file-filter" type="xsd:string"/>
<xsd:attribute name="filename-filter" type="xsd:string"/>
<xsd:attribute name="filename-pattern" type="xsd:string"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="file-target">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines a file-based target.
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="directory" type="xsd:string" use="required"/>
<xsd:attribute name="name-generator" type="xsd:string" use="optional"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="ftp-source">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines an ftp-receiving target channel adapter.
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="username" type="xsd:string" use="optional"/>
<xsd:attribute name="password" type="xsd:string" use="optional"/>
<xsd:attribute name="host" type="xsd:string" use="required"/>
<xsd:attribute name="port" type="xsd:int" use="optional"/>
<xsd:attribute name="local-working-directory" type="xsd:string" use="required"/>
<xsd:attribute name="remote-working-directory" type="xsd:string" use="optional"/>
<xsd:attribute name="type" type="fileSourceType" use="optional"/>
<xsd:attribute name="message-creator" type="xsd:string" use="optional"/>
</xsd:complexType>
</xsd:element>
<xsd:element name="mail-target">
<xsd:complexType>
<xsd:annotation>
@@ -108,12 +59,4 @@
</xsd:complexType>
</xsd:element>
<xsd:simpleType name="fileSourceType">
<xsd:restriction base="xsd:string">
<xsd:enumeration value="text"/>
<xsd:enumeration value="binary"/>
<xsd:enumeration value="file"/>
</xsd:restriction>
</xsd:simpleType>
</xsd:schema>

View File

@@ -1,45 +0,0 @@
/*
* Copyright 2002-2008 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.adapter.ftp.config;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.util.StringUtils;
import org.w3c.dom.Element;
/**
* Base class for directory-based sources.
*
* @author Marius Bogoevici
*/
public abstract class AbstractDirectorySourceParser extends AbstractSimpleBeanDefinitionParser {
public static final String MESSAGE_CREATOR_REFERENCE_ATTRIBUTE = "message-creator";
@Override
protected boolean isEligibleAttribute(String attributeName) {
return !MESSAGE_CREATOR_REFERENCE_ATTRIBUTE.equals(attributeName) && super.isEligibleAttribute(attributeName);
}
@Override
protected void postProcess(BeanDefinitionBuilder beanDefinition, Element element) {
String messageCreatorReference = element.getAttribute(MESSAGE_CREATOR_REFERENCE_ATTRIBUTE);
if (StringUtils.hasText(messageCreatorReference)) {
beanDefinition.addConstructorArgReference(messageCreatorReference);
}
}
}

View File

@@ -1,77 +0,0 @@
/*
* Copyright 2002-2008 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.adapter.ftp.config;
import org.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.integration.adapter.ftp.FtpSource;
import org.springframework.integration.adapter.ftp.QueuedFTPClientPool;
/**
* Parser for the &lt;ftp-source/&gt; element.
*
* @author Mark Fisher
* @author Marius Bogoevici
* @author Iwein Fuld
*/
public class FtpSourceParser extends AbstractDirectorySourceParser {
private static final String POOL_ATTRIBUTE_USER = "username";
private static final String POOL_ATTRIBUTE_PASS = "password";
private static final String POOL_ATTRIBUTE_HOST = "host";
private static final String POOL_ATTRIBUTE_PORT = "port";
private static final String POOL_ATTRIBUTE_REMOTEDIR = "remote-working-directory";
@Override
protected Class<?> getBeanClass(Element element) {
return FtpSource.class;
}
@Override
protected boolean isEligibleAttribute(String attributeName) {
return !POOL_ATTRIBUTE_HOST.equals(attributeName)
&& !POOL_ATTRIBUTE_PASS.equals(attributeName)
&& !POOL_ATTRIBUTE_PORT.equals(attributeName)
&& !POOL_ATTRIBUTE_USER.equals(attributeName)
&& !POOL_ATTRIBUTE_REMOTEDIR.equals(attributeName)
&& super.isEligibleAttribute(attributeName);
}
@Override
protected void postProcess(BeanDefinitionBuilder beanDefinition, Element element) {
super.postProcess(beanDefinition, element);
String user = element.getAttribute(POOL_ATTRIBUTE_USER);
String pass = element.getAttribute(POOL_ATTRIBUTE_PASS);
String host = element.getAttribute(POOL_ATTRIBUTE_HOST);
String port = element.getAttribute(POOL_ATTRIBUTE_PORT);
String remoteWorkingDirectory = element.getAttribute(POOL_ATTRIBUTE_REMOTEDIR);
QueuedFTPClientPool queuedFTPClientPool = new QueuedFTPClientPool();
queuedFTPClientPool.setUsername(user);
queuedFTPClientPool.setPassword(pass);
queuedFTPClientPool.setHost(host);
queuedFTPClientPool.setPort(Integer.parseInt(port));
queuedFTPClientPool.setRemoteWorkingDirectory(remoteWorkingDirectory);
beanDefinition.addConstructorArgValue(queuedFTPClientPool);
}
}

View File

@@ -1,73 +0,0 @@
/*
* Copyright 2002-2008 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.adapter.ftp.config;
import java.io.File;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.xml.AbstractSimpleBeanDefinitionParser;
import org.springframework.integration.adapter.ftp.FtpTarget;
import org.springframework.integration.adapter.ftp.QueuedFTPClientPool;
import org.springframework.integration.message.DefaultMessageMapper;
import org.w3c.dom.Element;
public class FtpTargetParser extends AbstractSimpleBeanDefinitionParser {
private static final String POOL_ATTRIBUTE_USER = "username";
private static final String POOL_ATTRIBUTE_PASS = "password";
private static final String POOL_ATTRIBUTE_HOST = "host";
private static final String POOL_ATTRIBUTE_PORT = "port";
private static final String POOL_ATTRIBUTE_REMOTEDIR = "remote-working-directory";
@Override
protected Class<FtpTarget> getBeanClass(Element element) {
return FtpTarget.class;
}
@Override
protected boolean isEligibleAttribute(String attributeName) {
return !POOL_ATTRIBUTE_HOST.equals(attributeName) && !POOL_ATTRIBUTE_PASS.equals(attributeName)
&& !POOL_ATTRIBUTE_PORT.equals(attributeName) && !POOL_ATTRIBUTE_USER.equals(attributeName)
&& !POOL_ATTRIBUTE_REMOTEDIR.equals(attributeName) && super.isEligibleAttribute(attributeName);
}
@Override
protected void postProcess(BeanDefinitionBuilder beanDefinition, Element element) {
super.postProcess(beanDefinition, element);
QueuedFTPClientPool queuedFTPClientPool = constructFTPClientPool(element);
beanDefinition.addConstructorArgValue(queuedFTPClientPool);
beanDefinition.addConstructorArgValue(new DefaultMessageMapper<File>());
}
private QueuedFTPClientPool constructFTPClientPool(Element element) {
String user = element.getAttribute(POOL_ATTRIBUTE_USER);
String pass = element.getAttribute(POOL_ATTRIBUTE_PASS);
String host = element.getAttribute(POOL_ATTRIBUTE_HOST);
String port = element.getAttribute(POOL_ATTRIBUTE_PORT);
String remoteWorkingDirectory = element.getAttribute(POOL_ATTRIBUTE_REMOTEDIR);
QueuedFTPClientPool queuedFTPClientPool = new QueuedFTPClientPool();
queuedFTPClientPool.setUsername(user);
queuedFTPClientPool.setPassword(pass);
queuedFTPClientPool.setHost(host);
queuedFTPClientPool.setPort(Integer.parseInt(port));
queuedFTPClientPool.setRemoteWorkingDirectory(remoteWorkingDirectory);
return queuedFTPClientPool;
}
}

View File

@@ -1,4 +1,3 @@
ftp-source=org.springframework.integration.adapter.ftp.config.FtpSourceParser
mail-target=org.springframework.integration.adapter.mail.config.MailTargetParser
polling-mail-source=org.springframework.integration.adapter.mail.config.PollingMailSourceParser
imap-idle-mail-source=org.springframework.integration.adapter.mail.config.SubscribableImapIdleMailSourceParser

View File

@@ -1,57 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:si="http://www.springframework.org/schema/integration"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-1.0.xsd">
<si:ftp-source id="ftpSourceDefault"
host="testHost"
port="2121"
local-working-directory="/local"
remote-working-directory="/remote"
username="testUser"
password="testPassword"/>
<si:ftp-source id="ftpSourceText"
host="testHost"
port="2121"
local-working-directory="/local"
remote-working-directory="/remote"
username="testUser"
password="testPassword"
/>
<si:ftp-source id="ftpSourceBinary"
host="testHost"
port="2121"
local-working-directory="/local"
remote-working-directory="/remote"
username="testUser"
password="testPassword"
/>
<si:ftp-source id="ftpSourceFile"
host="testHost"
port="2121"
local-working-directory="/local"
remote-working-directory="/remote"
username="testUser"
password="testPassword"
/>
<si:ftp-source id="ftpSourceCustom"
host="testHost"
port="2121"
local-working-directory="/local"
remote-working-directory="/remote"
username="testUser"
password="testPassword"
message-creator="customMessageCreator"/>
<bean id="customMessageCreator"
class="org.springframework.integration.adapter.ftp.config.CustomMessageCreator"/>
</beans>

View File

@@ -1,36 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:si="http://www.springframework.org/schema/integration"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:p="http://www.springframework.org/schema/p"
xsi:schemaLocation="
http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans.xsd
http://www.springframework.org/schema/integration
http://www.springframework.org/schema/integration/spring-integration-1.0.xsd">
<si:message-bus />
<bean id="ftpSource"
class="org.springframework.integration.adapter.ftp.FtpSource">
<constructor-arg>
<bean
class="org.springframework.integration.message.DefaultMessageCreator" />
</constructor-arg>
<constructor-arg>
<bean
class="org.springframework.integration.adapter.ftp.QueuedFTPClientPool"
p:host="localhost" p:password="kaas" p:username="ftp-user"
p:remoteWorkingDirectory="ftp-test" />
</constructor-arg>
</bean>
<si:channel-adapter id="input" source="ftpSource" />
<bean id="splitter"
class="org.springframework.integration.adapter.ftp.config.CollectionSplitter" />
<si:splitter output-channel="output" input-channel="input"
ref="splitter" method="split" />
<si:channel id="output" />
</beans>

View File

@@ -26,9 +26,7 @@
<dependency org="org.easymock" name="com.springsource.org.easymock" rev="2.3.0" conf="test->runtime"/>
<dependency org="org.easymock" name="com.springsource.org.easymock.classextension" rev="2.3.0" conf="test->runtime"/>
<dependency org="org.junit" name="com.springsource.org.junit" rev="4.4.0" conf="test->runtime"/>
<dependency org="org.springframework" name="org.springframework.context" rev="2.5.5.A" conf="compile->runtime"/>
<dependency org="org.springframework" name="org.springframework.context.support" rev="2.5.5.A" conf="compile->runtime"/>
<dependency org="org.springframework" name="org.springframework.test" rev="2.5.5.A" conf="test->runtime"/>
<dependency org="org.springframework.integration" name="org.springframework.integration" rev="latest.integration" conf="compile->compile"/>
</dependencies>

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import java.io.IOException;
import java.util.ArrayList;
@@ -48,6 +48,7 @@ public abstract class AbstractDirectorySource<T> implements PollableSource<T>, M
private final MessageCreator<T, T> messageCreator;
public AbstractDirectorySource(MessageCreator<T, T> messageCreator) {
this(messageCreator, null);
}
@@ -58,6 +59,7 @@ public abstract class AbstractDirectorySource<T> implements PollableSource<T>, M
this.messageCreator = messageCreator;
}
protected Backlog<FileSnapshot> getBacklog() {
return this.backlog;
}
@@ -117,21 +119,16 @@ public abstract class AbstractDirectorySource<T> implements PollableSource<T>, M
/**
* Constructs the snapshot by iterating files.
*
* @param snapshot
* @throws IOException
*/
protected abstract void populateSnapshot(List<FileSnapshot> snapshot) throws IOException;
/**
* Returns the next file, based on the backlog data.
*
* @return
* @throws IOException
*/
protected abstract T retrieveNextPayload() throws IOException;
protected final void filesProcessed() {
this.backlog.processed();
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import java.util.ArrayList;
import java.util.Collection;
@@ -33,7 +33,6 @@ import org.springframework.util.Assert;
* Keeps track of a backlog in a threadsafe, stateful manner.
*
* @author Marius Bogoevici
* @author Mark Fisher
* @author Iwein Fuld
*/
public class Backlog<T extends Comparable<T>> {

View File

@@ -13,16 +13,18 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import java.io.IOException;
import java.net.SocketException;
import org.apache.commons.net.ftp.FTPClient;
/**
* Factory for {@link FTPClient}.
*
* @author Iwein Fuld
*
*/
public interface FTPClientFactory {

View File

@@ -13,15 +13,16 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import org.apache.commons.net.ftp.FTPClient;
/**
* A pool of {@link FTPClient} instances. The pool can be used to control the
* number of open ftp connections and reuse these connections efficiently.
* @author Iwein Fuld
* number of open FTP connections and reuse these connections efficiently.
*
* @author Iwein Fuld
*/
public interface FTPClientPool extends FTPClientFactory {
@@ -30,9 +31,9 @@ public interface FTPClientPool extends FTPClientFactory {
* is no longer responsible for the connection. The pool is free to do with
* it as it sees fit, which means either recycling or disconnecting it most
* probably.
*
* <P>
* The caller should NOT disconnect the client before calling this method.
*
* <p>
* The caller is NOT expected to use the client after calling this method.
* Doing so can lead to unexpected behavior.
*
@@ -40,4 +41,4 @@ public interface FTPClientPool extends FTPClientFactory {
*/
void releaseClient(FTPClient client);
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import java.io.File;
@@ -22,7 +22,7 @@ import org.springframework.util.Assert;
/**
* Information about a file.
*
* <p>
* The FileSnapshot takes a snapshot of certain mutable properties of a file and
* stores them in an immutable way. This can be useful to determine if files
* have been changed.

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import java.io.File;
import java.io.FileInputStream;
@@ -24,40 +24,43 @@ import java.io.IOException;
import org.apache.commons.net.ftp.FTPClient;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageConsumer;
import org.springframework.integration.message.MessageDeliveryException;
import org.springframework.integration.message.MessageMapper;
import org.springframework.integration.message.MessageTarget;
import org.springframework.util.Assert;
/**
* Target adapter for sending files to an FTP server.
* A {@link MessageConsumer} implementation that sends files to an FTP server.
*
* @author Iwein Fuld
* @author Mark Fisher
*/
public class FtpTarget implements MessageTarget {
private final MessageMapper<?, File> messageMapper;
public class FtpSendingMessageConsumer implements MessageConsumer {
private final FTPClientPool ftpClientPool;
public FtpTarget(MessageMapper<?, File> messageMapper, FTPClientPool ftpClientPool) {
Assert.notNull(messageMapper, "messageMapper must not be null");
public FtpSendingMessageConsumer(FTPClientPool ftpClientPool) {
Assert.notNull(ftpClientPool, "ftpClientPool must not be null");
this.ftpClientPool = ftpClientPool;
this.messageMapper = messageMapper;
}
public boolean send(Message message) {
boolean sent = false;
File file = this.messageMapper.mapMessage(message);
public void onMessage(Message<?> message) {
Assert.notNull(message, "message must not be null");
Object payload = message.getPayload();
Assert.notNull(payload, "message payload must not be null");
Assert.isInstanceOf(File.class, payload, "Message payload must be an instance of [java.io.File]");
File file = (File) payload;
if (file != null && file.exists()) {
FTPClient client = null;
try {
FileInputStream fileInputStream = new FileInputStream(file);
client = this.ftpClientPool.getClient();
sent = client.storeFile(file.getName(), fileInputStream);
boolean sent = client.storeFile(file.getName(), fileInputStream);
fileInputStream.close();
if (!sent) {
throw new MessageDeliveryException(message, "Failed to store file '" + file + "'");
}
}
catch (FileNotFoundException e) {
throw new MessageDeliveryException(message, "File [" + file + "] lost from local working directory", e);
@@ -70,7 +73,6 @@ public class FtpTarget implements MessageTarget {
ftpClientPool.releaseClient(client);
}
}
return sent;
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import java.io.File;
import java.io.FileOutputStream;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import java.io.IOException;
import java.net.SocketException;
@@ -35,7 +35,7 @@ import org.springframework.util.StringUtils;
/**
* FTPClientPool implementation based on a Queue. This implementation has a
* default pool size of 5, but this is configurable with a constructor argument.
*
* <p>
* This implementation pools released clients, but gives no guarantee to the
* number of clients open at the same time.
*

View File

@@ -0,0 +1,63 @@
/*
* Copyright 2002-2008 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.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.AbstractPollingInboundChannelAdapterParser;
import org.springframework.integration.config.IntegrationNamespaceUtils;
import org.springframework.integration.ftp.FtpSource;
import org.springframework.integration.ftp.QueuedFTPClientPool;
import org.springframework.util.StringUtils;
/**
* Parser for the &lt;inbound-channel-adapter/&gt; element of the 'ftp' namespace.
*
* @author Mark Fisher
* @author Marius Bogoevici
* @author Iwein Fuld
*/
public class FtpInboundChannelAdapterParser extends AbstractPollingInboundChannelAdapterParser {
@Override
protected String parseSource(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FtpSource.class);
String messageCreatorReference = element.getAttribute("message-creator");
if (StringUtils.hasText(messageCreatorReference)) {
builder.addConstructorArgReference(messageCreatorReference);
}
IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "local-working-directory");
String username = element.getAttribute("username");
String password = element.getAttribute("password");
String host = element.getAttribute("host");
String port = element.getAttribute("port");
String remoteWorkingDirectory = element.getAttribute("remote-working-directory");
QueuedFTPClientPool queuedFTPClientPool = new QueuedFTPClientPool();
queuedFTPClientPool.setUsername(username);
queuedFTPClientPool.setPassword(password);
queuedFTPClientPool.setHost(host);
queuedFTPClientPool.setPort(Integer.parseInt(port));
queuedFTPClientPool.setRemoteWorkingDirectory(remoteWorkingDirectory);
builder.addConstructorArgValue(queuedFTPClientPool);
return BeanDefinitionReaderUtils.registerWithGeneratedName(
builder.getBeanDefinition(), parserContext.getRegistry());
}
}

View File

@@ -0,0 +1,32 @@
/*
* Copyright 2002-2008 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.beans.factory.xml.NamespaceHandlerSupport;
/**
* Namespace handler for the 'ftp' namespace.
*
* @author Mark Fisher
*/
public class FtpNamespaceHandler extends NamespaceHandlerSupport {
public void init() {
this.registerBeanDefinitionParser("inbound-channel-adapter", new FtpInboundChannelAdapterParser());
}
}

View File

@@ -0,0 +1,55 @@
/*
* Copyright 2002-2008 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.w3c.dom.Element;
import org.springframework.beans.factory.support.BeanDefinitionBuilder;
import org.springframework.beans.factory.support.BeanDefinitionReaderUtils;
import org.springframework.beans.factory.xml.ParserContext;
import org.springframework.integration.config.AbstractOutboundChannelAdapterParser;
import org.springframework.integration.ftp.FtpSendingMessageConsumer;
import org.springframework.integration.ftp.QueuedFTPClientPool;
/**
* Parser for the &lt;outbound-channel-adapter/&gt; element of the 'ftp' namespace.
*
* @author Iwein Fuld
* @author Mark Fisher
*/
public class FtpOutboundChannelAdapterParser extends AbstractOutboundChannelAdapterParser {
@Override
protected String parseConsumer(Element element, ParserContext parserContext) {
BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FtpSendingMessageConsumer.class);
String username = element.getAttribute("username");
String password = element.getAttribute("password");
String host = element.getAttribute("host");
String port = element.getAttribute("port");
String remoteWorkingDirectory = element.getAttribute("remote-working-directory");
QueuedFTPClientPool queuedFTPClientPool = new QueuedFTPClientPool();
queuedFTPClientPool.setUsername(username);
queuedFTPClientPool.setPassword(password);
queuedFTPClientPool.setHost(host);
queuedFTPClientPool.setPort(Integer.parseInt(port));
queuedFTPClientPool.setRemoteWorkingDirectory(remoteWorkingDirectory);
builder.addConstructorArgValue(queuedFTPClientPool);
return BeanDefinitionReaderUtils.registerWithGeneratedName(
builder.getBeanDefinition(), parserContext.getRegistry());
}
}

View File

@@ -0,0 +1,37 @@
<?xml version="1.0" encoding="UTF-8"?>
<xsd:schema xmlns="http://www.springframework.org/schema/integration/ftp"
xmlns:xsd="http://www.w3.org/2001/XMLSchema"
xmlns:beans="http://www.springframework.org/schema/beans"
xmlns:tool="http://www.springframework.org/schema/tool"
targetNamespace="http://www.springframework.org/schema/integration/ftp"
elementFormDefault="qualified"
attributeFormDefault="unqualified">
<xsd:import namespace="http://www.springframework.org/schema/beans"/>
<xsd:import namespace="http://www.springframework.org/schema/tool"/>
<xsd:annotation>
<xsd:documentation><![CDATA[
Defines the configuration elements for Spring Integration's FTP Channel Adapters.
]]></xsd:documentation>
</xsd:annotation>
<xsd:element name="inbound-channel-adapter">
<xsd:complexType>
<xsd:annotation>
<xsd:documentation>
Defines an inbound FTP-polling Channel Adapter.
</xsd:documentation>
</xsd:annotation>
<xsd:attribute name="id" type="xsd:string"/>
<xsd:attribute name="username" type="xsd:string" use="optional"/>
<xsd:attribute name="password" type="xsd:string" use="optional"/>
<xsd:attribute name="host" type="xsd:string" use="required"/>
<xsd:attribute name="port" type="xsd:int" use="optional"/>
<xsd:attribute name="local-working-directory" type="xsd:string" use="required"/>
<xsd:attribute name="remote-working-directory" type="xsd:string" use="optional"/>
<xsd:attribute name="message-creator" type="xsd:string" use="optional"/>
</xsd:complexType>
</xsd:element>
</xsd:schema>

View File

@@ -0,0 +1 @@
http\://www.springframework.org/schema/integration/ftp=org.springframework.integration.ftp.config.FtpNamespaceHandler

View File

@@ -0,0 +1 @@
http\://www.springframework.org/schema/integration/ftp/spring-integration-ftp-1.0.xsd=org/springframework/integration/ftp/config/spring-integration-ftp-1.0.xsd

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import java.util.ArrayList;
import java.util.concurrent.PriorityBlockingQueue;
@@ -24,8 +24,8 @@ import org.junit.Before;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.integration.adapter.ftp.Backlog;
import org.springframework.integration.adapter.ftp.FileSnapshot;
import org.springframework.integration.ftp.Backlog;
import org.springframework.integration.ftp.FileSnapshot;
/**
* @author Marius Bogoevici

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import static org.junit.Assert.assertTrue;
@@ -27,12 +27,13 @@ import java.util.concurrent.atomic.AtomicBoolean;
import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.integration.ftp.Backlog;
@SuppressWarnings("unchecked")
public class ConcurrentBacklogTests {
@Test(timeout = 1000)
public void simultaniousPreparation() throws Exception {
public void simultaneousPreparation() throws Exception {
final Backlog backlog = new Backlog();
backlog.processSnapshot(Arrays.asList(new String[] { "bert", "ernie", "pino", "whatsherface" }));
Runnable todo = new Runnable() {

View File

@@ -13,10 +13,15 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
import static org.easymock.classextension.EasyMock.*;
import static org.junit.Assert.*;
package org.springframework.integration.ftp;
import static org.easymock.EasyMock.expect;
import static org.easymock.EasyMock.isA;
import static org.easymock.classextension.EasyMock.createMock;
import static org.easymock.classextension.EasyMock.createNiceMock;
import static org.easymock.classextension.EasyMock.replay;
import static org.easymock.classextension.EasyMock.verify;
import java.io.File;
import java.io.FileInputStream;
@@ -24,23 +29,19 @@ import java.io.FileInputStream;
import org.apache.commons.net.ftp.FTPClient;
import org.junit.Before;
import org.junit.Test;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageMapper;
import org.springframework.integration.message.MessageDeliveryException;
/**
*
* @author Iwein Fuld
*
* @author Mark Fisher
*/
@SuppressWarnings("unchecked")
public class FtpTargetTest {
public class FtpSendingMessageConsumerTests {
private FtpTarget ftpTarget;
// Mocks and initialization
private MessageMapper<?, File> messageMapper = createMock(MessageMapper.class);
private Message message = createMock(Message.class);
private FtpSendingMessageConsumer consumer;
private FTPClient ftpClient = createMock(FTPClient.class);
@@ -51,45 +52,42 @@ public class FtpTargetTest {
*/
private FTPClientPool ftpClientPool = createNiceMock(FTPClientPool.class);
/*
* Handle to all mocks in this test so you can't forget to include one in a
* replay, verify or reset call.
*/
private Object[] allMocks = new Object[] { ftpClient, ftpClientPool };
@Before
public void liberalPool() throws Exception {
expect(ftpClientPool.getClient()).andReturn(ftpClient).anyTimes();
}
/*
* Handle to all mocks in this test so you can't forget to include one in a
* replay, verify or reset call.
*/
private Object[] allMocks = new Object[] { messageMapper, message, ftpClient, ftpClientPool };
@Before
public void intitializeSubject() {
this.ftpTarget = new FtpTarget(messageMapper, ftpClientPool);
this.consumer = new FtpSendingMessageConsumer(ftpClientPool);
}
// Tests
@Test
public void send() throws Exception {
expect(messageMapper.mapMessage(message)).andReturn(File.createTempFile("test", ".tmp"));
Message<?> message = new GenericMessage<File>(File.createTempFile("test", ".tmp"));
expect(ftpClient.storeFile(isA(String.class), isA(FileInputStream.class))).andReturn(true);
replay(allMocks);
boolean sent = ftpTarget.send(message);
assertTrue(sent);
consumer.onMessage(message);
verify(allMocks);
}
@Test
@Test(expected = MessageDeliveryException.class)
public void sendFailed_negative() throws Exception {
expect(messageMapper.mapMessage(message)).andReturn(File.createTempFile("test", ".tmp"));
Message<?> message = new GenericMessage<File>(File.createTempFile("test", ".tmp"));
expect(ftpClient.storeFile(isA(String.class), isA(FileInputStream.class))).andReturn(false);
replay(allMocks);
boolean sent = ftpTarget.send(message);
assertFalse(sent);
consumer.onMessage(message);
verify(allMocks);
}
@Test
public void sendFailed_() throws Exception {
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import static org.easymock.EasyMock.eq;
import static org.easymock.EasyMock.expect;
@@ -46,6 +46,9 @@ import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.integration.ftp.FTPClientPool;
import org.springframework.integration.ftp.FtpSource;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageCreator;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp;
package org.springframework.integration.ftp;
import static junit.framework.Assert.assertEquals;
import static junit.framework.Assert.assertSame;
@@ -32,10 +32,13 @@ import org.apache.commons.net.ftp.FTPClient;
import org.junit.Before;
import org.junit.Test;
import org.springframework.integration.ftp.FTPClientFactory;
import org.springframework.integration.ftp.QueuedFTPClientPool;
/**
* @author Iwein Fuld
*/
public class QueuedFTPClientPoolTest {
public class QueuedFTPClientPoolTests {
private QueuedFTPClientPool pool;

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp.config;
package org.springframework.integration.ftp.config;
import java.io.File;
@@ -25,10 +25,10 @@ import org.springframework.integration.message.MessageCreator;
/**
* @author Marius Bogoevici
*/
public class CustomMessageCreator implements MessageCreator<File, String>{
public class CustomMessageCreator implements MessageCreator<File, String> {
public Message<String> createMessage(File object) {
return new GenericMessage<String> (object.getAbsolutePath());
return new GenericMessage<String>(object.getAbsolutePath());
}
}

View File

@@ -14,7 +14,7 @@
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp.config;
package org.springframework.integration.ftp.config;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertTrue;
@@ -26,7 +26,6 @@ import org.junit.Test;
import org.springframework.beans.DirectFieldAccessor;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.adapter.ftp.FtpSource;
import org.springframework.integration.message.DefaultMessageCreator;
/**
@@ -34,36 +33,42 @@ import org.springframework.integration.message.DefaultMessageCreator;
* @author Marius Bogoevici
* @author Iwein Fuld
*/
public class FtpSourceParserTests {
public class FtpInboundChannelAdapterParserTests {
@Test
public void testFtpSourceAdapterParser() {
ApplicationContext context = new ClassPathXmlApplicationContext("ftpSourceParserTests.xml", this.getClass());
FtpSource ftpSource = (FtpSource) context.getBean("ftpSourceDefault");
DirectFieldAccessor sourceAccessor = new DirectFieldAccessor(ftpSource);
DirectFieldAccessor accessor = new DirectFieldAccessor(sourceAccessor.getPropertyValue("clientPool"));
assertEquals("testHost", accessor.getPropertyValue("host"));
assertEquals(2121, accessor.getPropertyValue("port"));
public void ftpSourceWithDefaultMessageCreator() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"ftpInboundChannelAdapterParserTests.xml", this.getClass());
Object adapter = context.getBean("default.adapter");
DirectFieldAccessor sourceAccessor = new DirectFieldAccessor(
new DirectFieldAccessor(adapter).getPropertyValue("source"));
DirectFieldAccessor poolAccessor = new DirectFieldAccessor(
sourceAccessor.getPropertyValue("clientPool"));
assertEquals("testHost", poolAccessor.getPropertyValue("host"));
assertEquals(2121, poolAccessor.getPropertyValue("port"));
assertEquals(new File("/local"), sourceAccessor.getPropertyValue("localWorkingDirectory"));
assertEquals("/remote", accessor.getPropertyValue("remoteWorkingDirectory"));
assertEquals("testUser", accessor.getPropertyValue("username"));
assertEquals("testPassword", accessor.getPropertyValue("password"));
assertEquals("/remote", poolAccessor.getPropertyValue("remoteWorkingDirectory"));
assertEquals("testUser", poolAccessor.getPropertyValue("username"));
assertEquals("testPassword", poolAccessor.getPropertyValue("password"));
Object messageCreator = sourceAccessor.getPropertyValue("messageCreator");
assertTrue(messageCreator instanceof DefaultMessageCreator);
}
@Test
public void testFtpSourceCustomType() {
ApplicationContext context = new ClassPathXmlApplicationContext("ftpSourceParserTests.xml", this.getClass());
FtpSource ftpSource = (FtpSource) context.getBean("ftpSourceCustom");
DirectFieldAccessor sourceAccessor = new DirectFieldAccessor(ftpSource);
DirectFieldAccessor accessor = new DirectFieldAccessor(sourceAccessor.getPropertyValue("clientPool"));
assertEquals("testHost", accessor.getPropertyValue("host"));
assertEquals(2121, accessor.getPropertyValue("port"));
public void ftpSourceWithCustomMessageCreator() {
ApplicationContext context = new ClassPathXmlApplicationContext(
"ftpInboundChannelAdapterParserTests.xml", this.getClass());
Object adapter = context.getBean("custom.adapter");
DirectFieldAccessor sourceAccessor = new DirectFieldAccessor(
new DirectFieldAccessor(adapter).getPropertyValue("source"));
DirectFieldAccessor poolAccessor = new DirectFieldAccessor(
sourceAccessor.getPropertyValue("clientPool"));
assertEquals("testHost", poolAccessor.getPropertyValue("host"));
assertEquals(2121, poolAccessor.getPropertyValue("port"));
assertEquals(new File("/local"), sourceAccessor.getPropertyValue("localWorkingDirectory"));
assertEquals("/remote", accessor.getPropertyValue("remoteWorkingDirectory"));
assertEquals("testUser", accessor.getPropertyValue("username"));
assertEquals("testPassword", accessor.getPropertyValue("password"));
assertEquals("/remote", poolAccessor.getPropertyValue("remoteWorkingDirectory"));
assertEquals("testUser", poolAccessor.getPropertyValue("username"));
assertEquals("testPassword", poolAccessor.getPropertyValue("password"));
Object messageCreator = sourceAccessor.getPropertyValue("messageCreator");
assertTrue(messageCreator instanceof CustomMessageCreator);
}

View File

@@ -13,9 +13,8 @@
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.springframework.integration.adapter.ftp.config;
import static org.junit.Assert.assertTrue;
package org.springframework.integration.ftp.config;
import java.io.File;
import java.io.FilenameFilter;
@@ -25,18 +24,18 @@ import org.junit.AfterClass;
import org.junit.Before;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.integration.adapter.ftp.FtpTarget;
import org.springframework.integration.adapter.ftp.QueuedFTPClientPool;
import org.springframework.integration.message.DefaultMessageMapper;
import org.springframework.integration.ftp.FtpSendingMessageConsumer;
import org.springframework.integration.ftp.QueuedFTPClientPool;
import org.springframework.integration.message.GenericMessage;
/**
* @author Iwein Fuld
*/
@Ignore
public class FtpTargetIntegrationTest {
public class FtpSendingMessageConsumerIntegrationTests {
private FtpTarget ftpTarget;
private FtpSendingMessageConsumer consumer;
@Before
public void initFtpTarget() {
@@ -45,13 +44,13 @@ public class FtpTargetIntegrationTest {
clientPool.setUsername("ftp-user");
clientPool.setPassword("kaas");
clientPool.setRemoteWorkingDirectory("ftp-test");
ftpTarget = new FtpTarget(new DefaultMessageMapper<File>(), clientPool);
consumer = new FtpSendingMessageConsumer(clientPool);
}
@Test
public void send() throws Exception {
File file = File.createTempFile("test", "");
assertTrue(ftpTarget.send(new GenericMessage<File>(file)));
consumer.onMessage(new GenericMessage<File>(file));
}
@AfterClass
@@ -62,4 +61,5 @@ public class FtpTargetIntegrationTest {
file.delete();
}
}
}

View File

@@ -1,23 +1,33 @@
package org.springframework.integration.adapter.ftp.config;
/*
* Copyright 2002-2008 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 static org.junit.Assert.assertTrue;
import java.io.File;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import org.junit.Before;
import org.junit.BeforeClass;
import org.junit.Ignore;
import org.junit.Test;
import org.springframework.context.ApplicationContext;
import org.springframework.context.support.ClassPathXmlApplicationContext;
import org.springframework.integration.adapter.ftp.FtpSource;
import org.springframework.integration.adapter.ftp.QueuedFTPClientPool;
import org.springframework.integration.channel.ChannelRegistry;
import org.springframework.integration.channel.PollableChannel;
import org.springframework.integration.config.MessageBusParser;
import org.springframework.integration.ftp.FtpSource;
import org.springframework.integration.ftp.QueuedFTPClientPool;
import org.springframework.integration.message.GenericMessage;
import org.springframework.integration.message.Message;
import org.springframework.integration.message.MessageCreator;
@@ -39,16 +49,16 @@ import org.springframework.integration.message.MessageCreator;
@Ignore
public class FtpSourceIntegrationTests {
private static File localWorkDir;
private FtpSource ftpSource;
private MessageCreator<List<File>, List<File>> messageCreator = new MessageCreator<List<File>, List<File>>() {
public Message<List<File>> createMessage(List<File> object) {
return new GenericMessage<List<File>>(object);
}
};
private static File localWorkDir;
@BeforeClass
public static void initializeEnvironment() {
@@ -72,15 +82,5 @@ public class FtpSourceIntegrationTests {
Message<List<File>> received = ftpSource.receive();
assertTrue(received.getPayload().iterator().next().exists());
}
@Test public void withChannelAdapter() {
ApplicationContext context = new ClassPathXmlApplicationContext("ftpSourceWithChannelAdapter.xml", this.getClass());
ChannelRegistry channelRegistry = (ChannelRegistry) context.getBean(MessageBusParser.MESSAGE_BUS_BEAN_NAME);
PollableChannel input = (PollableChannel) channelRegistry.lookupChannel("output");
List<File> files = new ArrayList<File>();
files.add((File) input.receive().getPayload());
files.add((File) input.receive().getPayload());
assertTrue(files.containsAll(Arrays.asList(new File("file1"), new File("file2"))));
}
}

View File

@@ -0,0 +1,30 @@
<?xml version="1.0" encoding="UTF-8"?>
<beans:beans xmlns="http://www.springframework.org/schema/integration/ftp"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns:beans="http://www.springframework.org/schema/beans"
xsi:schemaLocation="http://www.springframework.org/schema/beans
http://www.springframework.org/schema/beans/spring-beans-2.5.xsd
http://www.springframework.org/schema/integration/ftp
http://www.springframework.org/schema/integration/ftp/spring-integration-ftp-1.0.xsd">
<inbound-channel-adapter id="default"
host="testHost"
port="2121"
local-working-directory="/local"
remote-working-directory="/remote"
username="testUser"
password="testPassword"/>
<inbound-channel-adapter id="custom"
host="testHost"
port="2121"
local-working-directory="/local"
remote-working-directory="/remote"
username="testUser"
password="testPassword"
message-creator="customMessageCreator"/>
<beans:bean id="customMessageCreator"
class="org.springframework.integration.ftp.config.CustomMessageCreator"/>
</beans:beans>

View File

@@ -5,8 +5,6 @@ Bundle-ManifestVersion: 2
Import-Template:
org.springframework.integration.*;version="[1.0.0, 1.0.1)",
org.springframework.beans.*;version="[2.5.5.A, 3.0.0)",
org.springframework.context;version="[2.5.5.A, 3.0.0)",
org.springframework.core.*;version="[2.5.5.A, 3.0.0)",
org.springframework.util;version="[2.5.5.A, 3.0.0)",
org.apache.commons.logging;version="[1.1.1, 2.0.0)",
org.apache.commons.net.ftp;version="[1.4.1, 2.0.0)";resolution:=optional