From eb3cb363e8f038c088d5090e0d45010761246c91 Mon Sep 17 00:00:00 2001 From: Oleg Zhurakousky Date: Tue, 8 Nov 2011 10:53:53 -0500 Subject: [PATCH] INT-2213 added support for specifying 'temporary-remote-directory' as well as 'temporary-remote-directory-expression' INT-2213 polishing INT-2213 polishing docs --- .../handler/AbstractMessageHandler.java | 5 -- ...emoteFileOutboundChannelAdapterParser.java | 68 ++++++++++++------- .../FileTransferringMessageHandler.java | 39 ++++++++--- .../ftp/config/spring-integration-ftp-2.1.xsd | 29 ++++++-- ...boundChannelAdapterParserTests-context.xml | 2 + .../FtpOutboundChannelAdapterParserTests.java | 2 + .../config/spring-integration-sftp-2.1.xsd | 27 ++++++-- ...boundChannelAdapterParserTests-context.xml | 1 + .../OutboundChannelAdapterParserTests.java | 4 ++ 9 files changed, 128 insertions(+), 49 deletions(-) diff --git a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageHandler.java b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageHandler.java index 8913ef5bf4..11c707421d 100644 --- a/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageHandler.java +++ b/spring-integration-core/src/main/java/org/springframework/integration/handler/AbstractMessageHandler.java @@ -16,9 +16,6 @@ package org.springframework.integration.handler; -import org.apache.commons.logging.Log; -import org.apache.commons.logging.LogFactory; - import org.springframework.core.Ordered; import org.springframework.integration.Message; import org.springframework.integration.MessageHandlingException; @@ -41,8 +38,6 @@ import org.springframework.util.Assert; */ public abstract class AbstractMessageHandler extends IntegrationObjectSupport implements MessageHandler, TrackableComponent, Orderable { - protected final Log logger = LogFactory.getLog(this.getClass()); - private volatile boolean shouldTrack = false; private volatile int order = Ordered.LOWEST_PRECEDENCE; diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/RemoteFileOutboundChannelAdapterParser.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/RemoteFileOutboundChannelAdapterParser.java index 7a3260fa9d..dd1e3ea1bc 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/RemoteFileOutboundChannelAdapterParser.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/RemoteFileOutboundChannelAdapterParser.java @@ -16,8 +16,6 @@ package org.springframework.integration.file.config; -import org.w3c.dom.Element; - import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; import org.springframework.beans.factory.BeanDefinitionStoreException; @@ -26,10 +24,15 @@ import org.springframework.beans.factory.support.AbstractBeanDefinition; import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.support.RootBeanDefinition; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.expression.common.LiteralExpression; +import org.springframework.integration.config.ExpressionFactoryBean; import org.springframework.integration.config.xml.AbstractOutboundChannelAdapterParser; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; +import org.springframework.integration.file.DefaultFileNameGenerator; +import org.springframework.integration.file.remote.handler.FileTransferringMessageHandler; import org.springframework.integration.file.remote.session.CachingSessionFactory; import org.springframework.util.StringUtils; +import org.w3c.dom.Element; /** * @author Oleg Zhurakousky @@ -40,8 +43,7 @@ public class RemoteFileOutboundChannelAdapterParser extends AbstractOutboundChan private final Log logger = LogFactory.getLog(this.getClass()); @Override protected AbstractBeanDefinition parseConsumer(Element element, ParserContext parserContext) { - BeanDefinitionBuilder handlerBuilder = BeanDefinitionBuilder.genericBeanDefinition( - "org.springframework.integration.file.remote.handler.FileTransferringMessageHandler"); + BeanDefinitionBuilder handlerBuilder = BeanDefinitionBuilder.genericBeanDefinition(FileTransferringMessageHandler.class); // This whole block must be refactored once cache-session attribute is removed String sessionFactoryName = element.getAttribute("session-factory"); @@ -70,26 +72,8 @@ public class RemoteFileOutboundChannelAdapterParser extends AbstractOutboundChan IntegrationNamespaceUtils.setValueIfAttributeDefined(handlerBuilder, element, "temporary-file-suffix"); IntegrationNamespaceUtils.setValueIfAttributeDefined(handlerBuilder, element, "auto-create-directory"); - // configure remote directory expression - String remoteDirectory = element.getAttribute("remote-directory"); - String remoteDirectoryExpression = element.getAttribute("remote-directory-expression"); - boolean hasRemoteDirectory = StringUtils.hasText(remoteDirectory); - boolean hasRemoteDirectoryExpression = StringUtils.hasText(remoteDirectoryExpression); - if (!(hasRemoteDirectory ^ hasRemoteDirectoryExpression)) { - throw new BeanDefinitionStoreException("exactly one of 'remote-directory' or 'remote-directory-expression' " + - "is required on a remote file outbound adapter"); - } - BeanDefinition remoteDirectoryExpressionDefinition = null; - if (hasRemoteDirectory) { - remoteDirectoryExpressionDefinition = new RootBeanDefinition("org.springframework.expression.common.LiteralExpression"); - remoteDirectoryExpressionDefinition.getConstructorArgumentValues().addGenericArgumentValue(remoteDirectory); - } - else if (hasRemoteDirectoryExpression) { - remoteDirectoryExpressionDefinition = new RootBeanDefinition("org.springframework.integration.config.ExpressionFactoryBean"); - remoteDirectoryExpressionDefinition.getConstructorArgumentValues().addGenericArgumentValue(remoteDirectoryExpression); - } - handlerBuilder.addPropertyValue("remoteDirectoryExpression", remoteDirectoryExpressionDefinition); - + this.configureRemoteDirectories(element, handlerBuilder); + // configure remote FileNameGenerator String remoteFileNameGenerator = element.getAttribute("remote-filename-generator"); String remoteFileNameGeneratorExpression = element.getAttribute("remote-filename-generator-expression"); @@ -104,8 +88,7 @@ public class RemoteFileOutboundChannelAdapterParser extends AbstractOutboundChan handlerBuilder.addPropertyReference("fileNameGenerator", remoteFileNameGenerator); } else { - BeanDefinitionBuilder fileNameGeneratorBuilder = BeanDefinitionBuilder.genericBeanDefinition( - "org.springframework.integration.file.DefaultFileNameGenerator"); + BeanDefinitionBuilder fileNameGeneratorBuilder = BeanDefinitionBuilder.genericBeanDefinition(DefaultFileNameGenerator.class); fileNameGeneratorBuilder.addPropertyValue("expression", remoteFileNameGeneratorExpression); handlerBuilder.addPropertyValue("fileNameGenerator", fileNameGeneratorBuilder.getBeanDefinition()); } @@ -114,5 +97,38 @@ public class RemoteFileOutboundChannelAdapterParser extends AbstractOutboundChan IntegrationNamespaceUtils.setValueIfAttributeDefined(handlerBuilder, element, "remote-file-separator"); return handlerBuilder.getBeanDefinition(); } + + private void configureRemoteDirectories(Element element, BeanDefinitionBuilder handlerBuilder){ + this.doConfigureRemoteDirectory(element, handlerBuilder, "remote-directory", "remote-directory-expression", "remoteDirectoryExpression", true); + this.doConfigureRemoteDirectory(element, handlerBuilder, "temporary-remote-directory", "temporary-remote-directory-expression", "temporaryRemoteDirectoryExpression", false); + } + + private void doConfigureRemoteDirectory(Element element, BeanDefinitionBuilder handlerBuilder, + String directoryAttribute, String directoryExpressionAttribute, + String directoryExpressionPropertyName, boolean atLeastOneRequired){ + String remoteDirectory = element.getAttribute(directoryAttribute); + String remoteDirectoryExpression = element.getAttribute(directoryExpressionAttribute); + boolean hasRemoteDirectory = StringUtils.hasText(remoteDirectory); + boolean hasRemoteDirectoryExpression = StringUtils.hasText(remoteDirectoryExpression); + if (atLeastOneRequired){ + if (!(hasRemoteDirectory ^ hasRemoteDirectoryExpression)) { + throw new BeanDefinitionStoreException("exactly one of '" + directoryAttribute + "' or '" + directoryExpressionAttribute + "' " + + "is required on a remote file outbound adapter"); + } + } + + BeanDefinition remoteDirectoryExpressionDefinition = null; + if (hasRemoteDirectory) { + remoteDirectoryExpressionDefinition = new RootBeanDefinition(LiteralExpression.class); + remoteDirectoryExpressionDefinition.getConstructorArgumentValues().addGenericArgumentValue(remoteDirectory); + } + else if (hasRemoteDirectoryExpression) { + remoteDirectoryExpressionDefinition = new RootBeanDefinition(ExpressionFactoryBean.class); + remoteDirectoryExpressionDefinition.getConstructorArgumentValues().addGenericArgumentValue(remoteDirectoryExpression); + } + if (remoteDirectoryExpressionDefinition != null){ + handlerBuilder.addPropertyValue(directoryExpressionPropertyName, remoteDirectoryExpressionDefinition); + } + } } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/handler/FileTransferringMessageHandler.java b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/handler/FileTransferringMessageHandler.java index 4ddb465355..8a58c095c9 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/remote/handler/FileTransferringMessageHandler.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/remote/handler/FileTransferringMessageHandler.java @@ -53,6 +53,8 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { private volatile boolean autoCreateDirectory = false; private volatile ExpressionEvaluatingMessageProcessor directoryExpressionProcessor; + + private volatile ExpressionEvaluatingMessageProcessor temporaryDirectoryExpressionProcessor; private volatile FileNameGenerator fileNameGenerator = new DefaultFileNameGenerator(); @@ -83,6 +85,11 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { this.directoryExpressionProcessor = new ExpressionEvaluatingMessageProcessor(remoteDirectoryExpression, String.class); } + public void setTemporaryRemoteDirectoryExpression(Expression temporaryRemoteDirectoryExpression) { + Assert.notNull(temporaryRemoteDirectoryExpression, "temporaryRemoteDirectoryExpression must not be null"); + this.temporaryDirectoryExpressionProcessor = new ExpressionEvaluatingMessageProcessor(temporaryRemoteDirectoryExpression, String.class); + } + protected String getTemporaryFileSuffix() { return this.temporaryFileSuffix; } @@ -116,8 +123,12 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { Session session = this.sessionFactory.getSession(); try { String remoteDirectory = this.directoryExpressionProcessor.processMessage(message); + String temporaryRemoteDirectory = remoteDirectory; + if (this.temporaryDirectoryExpressionProcessor != null){ + temporaryRemoteDirectory = this.directoryExpressionProcessor.processMessage(message); + } String fileName = this.fileNameGenerator.generateFileName(message); - this.sendFileToRemoteDirectory(file, remoteDirectory, fileName, session); + this.sendFileToRemoteDirectory(file, temporaryRemoteDirectory, remoteDirectory, fileName, session); } catch (FileNotFoundException e) { throw new MessageDeliveryException(message, @@ -180,19 +191,19 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { } } - private void sendFileToRemoteDirectory(File file, String remoteDirectory, String fileName, Session session) + private void sendFileToRemoteDirectory(File file, String temporaryRemoteDirectory, String remoteDirectory, String fileName, Session session) throws FileNotFoundException, IOException { + FileInputStream fileInputStream = new FileInputStream(file); - if (!StringUtils.hasText(remoteDirectory)) { - remoteDirectory = ""; - } - else if (!remoteDirectory.endsWith(this.remoteFileSeparator)) { - remoteDirectory += this.remoteFileSeparator; - } + + remoteDirectory = this.normalizeDirectoryPath(remoteDirectory); + temporaryRemoteDirectory = this.normalizeDirectoryPath(temporaryRemoteDirectory); + String remoteFilePath = remoteDirectory + fileName; + String tempRemoteFilePath = temporaryRemoteDirectory + fileName; // write remote file first with .writing extension - String tempFilePath = remoteFilePath + this.temporaryFileSuffix; + String tempFilePath = tempRemoteFilePath + this.temporaryFileSuffix; if (this.autoCreateDirectory) { session.mkdir(remoteDirectory); } @@ -208,5 +219,15 @@ public class FileTransferringMessageHandler extends AbstractMessageHandler { fileInputStream.close(); } } + + private String normalizeDirectoryPath(String directoryPath){ + if (!StringUtils.hasText(directoryPath)) { + directoryPath = ""; + } + else if (!directoryPath.endsWith(this.remoteFileSeparator)) { + directoryPath += this.remoteFileSeparator; + } + return directoryPath; + } } diff --git a/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.1.xsd b/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.1.xsd index 2473eb5e9c..ac2677d130 100644 --- a/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.1.xsd +++ b/spring-integration-ftp/src/main/resources/org/springframework/integration/ftp/config/spring-integration-ftp-2.1.xsd @@ -24,15 +24,26 @@ type="xsd:string"> - Allows you to provide SpEL expression which - will compute directory - path - where file will be transferred TO + Allows you to provide a SpEL expression which + will compute the directory + path where the files will be transferred to (e.g., "headers.['remote_dir'] + '/myTransfers'"); + + + + Allows you to provide a SpEL expression which + will compute the temporary directory + path where files will be transferred to before they are moved to the remote-directory + (e.g., "headers.['remote_dir'] + + '/temp/myTransfers'"); + + + @@ -365,7 +376,15 @@ use="optional"> - Identifies the directory path (e.g., "/temp/mytransfers") + Identifies the remote directory path (e.g., "/remote/mytransfers") + + + + + + + Identifies the remote temporary directory path (e.g., "/remote/temp/mytransfers") diff --git a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests-context.xml b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests-context.xml index 19250d1901..c0b0ff9bf3 100644 --- a/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests-context.xml +++ b/spring-integration-ftp/src/test/java/org/springframework/integration/ftp/config/FtpOutboundChannelAdapterParserTests-context.xml @@ -27,6 +27,7 @@ session-factory="ftpSessionFactory" cache-sessions="false" remote-directory="foo/bar" + temporary-remote-directory="baz/abc" charset="UTF-8" remote-file-separator="." temporary-file-suffix=".foo" @@ -42,6 +43,7 @@ temporary-file-suffix=".foo" remote-filename-generator="fileNameGenerator" order="12"/> + - Allows you to provide SpEL expression which - will compute directory + Allows you to provide a SpEL expression which + will compute the directory path - where file will be transferred TO + where files will be transferred to (e.g., "headers.['remote_dir'] + '/myTransfers'"); - + + + + Allows you to provide a SpEL expression which + will compute the temporary directory + path where files will be transferred to before they are moved to the remote-directory + (e.g., "headers.['remote_dir'] + + '/temp/myTransfers'"); + + + @@ -370,6 +381,14 @@ + + + + Identifies the remote temporary directory path (e.g., "/remote/temp/mytransfers") + + + diff --git a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests-context.xml b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests-context.xml index 2485cb1366..54b467ba08 100644 --- a/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests-context.xml +++ b/spring-integration-sftp/src/test/java/org/springframework/integration/sftp/config/OutboundChannelAdapterParserTests-context.xml @@ -27,6 +27,7 @@ remote-file-separator="." temporary-file-suffix=".bar" remote-directory="foo/bar" + temporary-remote-directory="foo/baz" order="23"/>