diff --git a/.gitignore b/.gitignore index 742cbcc685..0b26911ab8 100644 --- a/.gitignore +++ b/.gitignore @@ -19,7 +19,9 @@ logs nohup.out out si.java.hsp +spring-integration-file/test/fileToAppend.txt +spring-integration-file/test/fileToAppendConcurrent.txt spring-integration-jms/activemq-data/ spring-integration-samples/loanshark/application.log* target -vf.gf.dmn-* \ No newline at end of file +vf.gf.dmn-* diff --git a/build.gradle b/build.gradle index 48504f5cfb..185246e859 100644 --- a/build.gradle +++ b/build.gradle @@ -255,6 +255,7 @@ project('spring-integration-file') { 'org.springframework.beans.*;version="[3.1.1, 4.0.0)"', 'org.springframework.expression.*;version="[3.1.1, 4.0.0)"', 'org.springframework.context;version="[3.1.1, 4.0.0)"', + 'org.springframework.context.expression.*;version="[3.1.1, 4.0.0)"', 'org.springframework.core.*;version="[3.1.1, 4.0.0)"', 'org.springframework.scheduling.*;version="[3.1.1, 4.0.0)"', 'org.springframework.transaction.*;version="[3.1.1, 4.0.0)"', diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java b/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java index 249683115b..7496ea433f 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/FileWritingMessageHandler.java @@ -26,6 +26,12 @@ import java.nio.charset.Charset; import org.apache.commons.logging.Log; import org.apache.commons.logging.LogFactory; +import org.springframework.beans.factory.BeanFactory; +import org.springframework.context.expression.BeanFactoryResolver; +import org.springframework.context.expression.MapAccessor; +import org.springframework.expression.Expression; +import org.springframework.expression.common.LiteralExpression; +import org.springframework.expression.spel.support.StandardEvaluationContext; import org.springframework.integration.Message; import org.springframework.integration.MessageHandlingException; import org.springframework.integration.core.MessageHandler; @@ -61,6 +67,7 @@ import org.springframework.util.FileCopyUtils; * @author Alex Peters * @author Oleg Zhurakousky * @author Artem Bilan + * @author Gunnar Hillert */ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHandler { @@ -74,7 +81,9 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand private volatile FileNameGenerator fileNameGenerator = new DefaultFileNameGenerator(); - private final File destinationDirectory; + private final StandardEvaluationContext evaluationContext = new StandardEvaluationContext(); + + private final Expression destinationDirectoryExpression; private volatile boolean autoCreateDirectory = true; @@ -86,11 +95,28 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand private volatile LockRegistry lockRegistry = new PassThruLockRegistry(); + /** + * Constructor which sets the {@link #destinationDirectoryExpression} using + * a {@link LiteralExpression}. + * + * @param destinationDirectory Must not be null + * @see #FileWritingMessageHandler(Expression) + */ public FileWritingMessageHandler(File destinationDirectory) { Assert.notNull(destinationDirectory, "Destination directory must not be null."); - this.destinationDirectory = destinationDirectory; + this.destinationDirectoryExpression = new LiteralExpression(destinationDirectory.getPath()); } + /** + * Constructor which sets the {@link #destinationDirectoryExpression}. + * + * @param destinationDirectoryExpression Must not be null + * @see #FileWritingMessageHandler(File) + */ + public FileWritingMessageHandler(Expression destinationDirectoryExpression) { + Assert.notNull(destinationDirectoryExpression, "Destination directory expression must not be null."); + this.destinationDirectoryExpression = destinationDirectoryExpression; + } /** * Specify whether to create the destination directory automatically if it @@ -103,6 +129,13 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand this.autoCreateDirectory = autoCreateDirectory; } + /** + * By default, every file that is in the process of being transferred will + * appear in the file system with an additional suffix, which by default is + * ".writing". This can be changed by setting this property. + * + * @param temporaryFileSuffix + */ public void setTemporaryFileSuffix(String temporaryFileSuffix) { Assert.notNull(temporaryFileSuffix, "'temporaryFileSuffix' must not be null"); // empty string is OK this.temporaryFileSuffix = temporaryFileSuffix; @@ -171,16 +204,35 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand @Override public final void onInit() { - if (!this.destinationDirectory.exists() && this.autoCreateDirectory) { - this.destinationDirectory.mkdirs(); + + this.evaluationContext.addPropertyAccessor(new MapAccessor()); + + final BeanFactory beanFactory = this.getBeanFactory(); + + if (beanFactory != null) { + this.evaluationContext.setBeanResolver(new BeanFactoryResolver(beanFactory)); } + + if (this.destinationDirectoryExpression instanceof LiteralExpression) { + final File directory = new File(this.destinationDirectoryExpression.getValue( + this.evaluationContext, null, String.class)); + validateDestinationDirectory(directory, this.autoCreateDirectory); + } + + } + + private void validateDestinationDirectory(File destinationDirectory, boolean autoCreateDirectory) { + + if (!destinationDirectory.exists() && autoCreateDirectory) { + destinationDirectory.mkdirs(); + } + Assert.isTrue(destinationDirectory.exists(), "Destination directory [" + destinationDirectory + "] does not exist."); - Assert.isTrue(this.destinationDirectory.isDirectory(), - "Destination path [" + this.destinationDirectory + "] does not point to a directory."); - Assert.isTrue(this.destinationDirectory.canWrite(), - "Destination directory [" + this.destinationDirectory + "] is not writable."); - + Assert.isTrue(destinationDirectory.isDirectory(), + "Destination path [" + destinationDirectory + "] does not point to a directory."); + Assert.isTrue(destinationDirectory.canWrite(), + "Destination directory [" + destinationDirectory + "] is not writable."); Assert.state(!(this.temporaryFileSuffixSet && this.append), "'temporaryFileSuffix' can not be set when appending to an existing file");; } @@ -192,8 +244,12 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand Assert.notNull(payload, "message payload must not be null"); String generatedFileName = this.fileNameGenerator.generateFileName(requestMessage); File originalFileFromHeader = this.retrieveOriginalFileFromHeader(requestMessage); - File tempFile = new File(this.destinationDirectory, generatedFileName + temporaryFileSuffix); - File resultFile = new File(this.destinationDirectory, generatedFileName); + + final File destinationDirectoryToUse = evaluateDestinationDirectoryExpression(requestMessage); + + File tempFile = new File(destinationDirectoryToUse, generatedFileName + temporaryFileSuffix); + File resultFile = new File(destinationDirectoryToUse, generatedFileName); + try { if (payload instanceof File) { resultFile = this.handleFileMessage((File) payload, tempFile, resultFile); @@ -348,4 +404,38 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand } } } + + private File evaluateDestinationDirectoryExpression(Message message) { + + final File destinationDirectory; + + final Object destinationDirectoryToUse = this.destinationDirectoryExpression.getValue( + this.evaluationContext, message); + + if (destinationDirectoryToUse == null) { + throw new IllegalStateException(String.format("The provided " + + "destinationDirectoryExpression (%s) must not resolve to null.", + this.destinationDirectoryExpression.getExpressionString())); + } + else if (destinationDirectoryToUse instanceof String) { + + final String destinationDirectoryPath = (String) destinationDirectoryToUse; + + Assert.hasText(destinationDirectoryPath, String.format( + "Unable to resolve destination directory name for the provided Expression '%s'.", + this.destinationDirectoryExpression.getExpressionString())); + destinationDirectory = new File(destinationDirectoryPath); + } + else if (destinationDirectoryToUse instanceof File) { + destinationDirectory = (File) destinationDirectoryToUse; + } else { + throw new IllegalStateException(String.format("The provided " + + "destinationDirectoryExpression (%s) must be of type " + + "java.io.File or be a String.", this.destinationDirectoryExpression.getExpressionString())); + } + + validateDestinationDirectory(destinationDirectory, this.autoCreateDirectory); + return destinationDirectory; + } + } diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerBeanDefinitionBuilder.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerBeanDefinitionBuilder.java index 3e5591d005..b48c989700 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerBeanDefinitionBuilder.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerBeanDefinitionBuilder.java @@ -17,9 +17,9 @@ package org.springframework.integration.file.config; import org.w3c.dom.Element; - import org.springframework.beans.factory.support.BeanDefinitionBuilder; import org.springframework.beans.factory.xml.ParserContext; +import org.springframework.integration.config.ExpressionFactoryBean; import org.springframework.integration.config.xml.IntegrationNamespaceUtils; import org.springframework.integration.file.DefaultFileNameGenerator; import org.springframework.util.StringUtils; @@ -31,19 +31,34 @@ import org.springframework.util.StringUtils; * * @author Mark Fisher * @author Artem Bilan + * @author Gunnar Hillert + * * @since 1.0.3 */ abstract class FileWritingMessageHandlerBeanDefinitionBuilder { static BeanDefinitionBuilder configure(Element element, boolean expectReply, ParserContext parserContext) { - String directory = element.getAttribute("directory"); - if (!StringUtils.hasText(directory)) { - parserContext.getReaderContext().error("directory is required", element); - } BeanDefinitionBuilder builder = BeanDefinitionBuilder.genericBeanDefinition(FileWritingMessageHandlerFactoryBean.class); - builder.addPropertyValue("directory", directory); + + String directory = element.getAttribute("directory"); + String directoryExpression = element.getAttribute("directory-expression"); + + if (!StringUtils.hasText(directory) && !StringUtils.hasText(directoryExpression)) { + parserContext.getReaderContext().error("directory or directory-expression is required", element); + } + else if (StringUtils.hasText(directory) && StringUtils.hasText(directoryExpression)) { + parserContext.getReaderContext().error("Either directory or directory-expression must be provided but not both", element); + } + + if (StringUtils.hasText(directoryExpression)) { + BeanDefinitionBuilder expressionBuilder = BeanDefinitionBuilder.genericBeanDefinition(ExpressionFactoryBean.class); + expressionBuilder.addConstructorArgValue(directoryExpression); + builder.addPropertyValue("directoryExpression", expressionBuilder.getBeanDefinition()); + } + builder.addPropertyValue("expectReply", expectReply); + IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "directory"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "auto-create-directory"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "delete-source-files"); IntegrationNamespaceUtils.setValueIfAttributeDefined(builder, element, "temporary-file-suffix"); diff --git a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerFactoryBean.java b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerFactoryBean.java index f82931b320..3c8877e1fd 100644 --- a/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerFactoryBean.java +++ b/spring-integration-file/src/main/java/org/springframework/integration/file/config/FileWritingMessageHandlerFactoryBean.java @@ -18,6 +18,7 @@ package org.springframework.integration.file.config; import java.io.File; +import org.springframework.expression.Expression; import org.springframework.integration.config.AbstractSimpleMessageHandlerFactoryBean; import org.springframework.integration.file.FileNameGenerator; import org.springframework.integration.file.FileWritingMessageHandler; @@ -30,12 +31,16 @@ import org.springframework.integration.file.FileWritingMessageHandler; * @author Oleg Zhurakousky * @author Gary Russell * @author Artem Bilan + * @author Gunnar Hillert + * * @since 1.0.3 */ public class FileWritingMessageHandlerFactoryBean extends AbstractSimpleMessageHandlerFactoryBean{ private volatile File directory; + private volatile Expression directoryExpression; + private volatile String charset; private volatile FileNameGenerator fileNameGenerator; @@ -66,6 +71,10 @@ public class FileWritingMessageHandlerFactoryBean extends AbstractSimpleMessageH this.charset = charset; } + public void setDirectoryExpression(Expression directoryExpression) { + this.directoryExpression = directoryExpression; + } + public void setFileNameGenerator(FileNameGenerator fileNameGenerator) { this.fileNameGenerator = fileNameGenerator; } @@ -96,7 +105,21 @@ public class FileWritingMessageHandlerFactoryBean extends AbstractSimpleMessageH @Override protected FileWritingMessageHandler createHandler() { - FileWritingMessageHandler handler = new FileWritingMessageHandler(this.directory); + + final FileWritingMessageHandler handler; + + if (this.directory != null && this.directoryExpression != null) { + throw new IllegalStateException("Cannot set both directory and directoryExpression"); + } + else if (this.directory != null) { + handler = new FileWritingMessageHandler(this.directory); + } + else if (this.directoryExpression != null) { + handler = new FileWritingMessageHandler(this.directoryExpression); + } else { + throw new IllegalStateException("Either directory or directoryExpression must not be null"); + } + if (this.charset != null) { handler.setCharset(this.charset); } diff --git a/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-2.2.xsd b/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-2.2.xsd index 712923fc9d..5c955f25b5 100644 --- a/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-2.2.xsd +++ b/spring-integration-file/src/main/resources/org/springframework/integration/file/config/spring-integration-file-2.2.xsd @@ -240,12 +240,26 @@ Only files matching this regular expression will be picked up by this adapter. - - - - - + + + + + + + + + + + + + diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/FileOutboundChannelAdapterIntegrationTests-context.xml b/spring-integration-file/src/test/java/org/springframework/integration/file/FileOutboundChannelAdapterIntegrationTests-context.xml new file mode 100644 index 0000000000..f4293be1f8 --- /dev/null +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/FileOutboundChannelAdapterIntegrationTests-context.xml @@ -0,0 +1,62 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/FileOutboundChannelAdapterIntegrationTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/FileOutboundChannelAdapterIntegrationTests.java new file mode 100644 index 0000000000..28afc8a1fb --- /dev/null +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/FileOutboundChannelAdapterIntegrationTests.java @@ -0,0 +1,218 @@ +/* + * Copyright 2002-2012 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.file; + +import java.io.File; +import java.io.FileOutputStream; + +import junit.framework.Assert; + +import org.junit.After; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.integration.Message; +import org.springframework.integration.MessageChannel; +import org.springframework.integration.MessageHandlingException; +import org.springframework.integration.support.MessageBuilder; +import org.springframework.test.context.ContextConfiguration; +import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; +import org.springframework.util.FileCopyUtils; + +/** + * @author Gunnar Hillert + */ +@ContextConfiguration +@RunWith(SpringJUnit4ClassRunner.class) +public class FileOutboundChannelAdapterIntegrationTests { + + static final String DEFAULT_ENCODING = "UTF-8"; + + static final String SAMPLE_CONTENT = "HelloWorld\nŠšŸ§"; + + static File workDir; + + FileWritingMessageHandler handler; + + @Autowired + MessageChannel inputChannelSaveToBaseDir; + + @Autowired + MessageChannel inputChannelSaveToBaseDirDeleteSource; + + @Autowired + MessageChannel inputChannelSaveToSubDir; + + @Autowired + MessageChannel inputChannelSaveToSubDirWithFile; + + @Autowired + MessageChannel inputChannelSaveToSubDirAutoCreateOff; + + @Autowired + MessageChannel inputChannelSaveToSubDirWrongExpression; + + @Autowired + MessageChannel inputChannelSaveToSubDirWithHeader; + + @Autowired + MessageChannel inputChannelSaveToSubDirEmptyStringExpression; + + Message message; + + File sourceFile; + @Before + public void setUp() throws Exception { + sourceFile = File.createTempFile("anyFile", ".txt"); + sourceFile.deleteOnExit(); + FileCopyUtils.copy(SAMPLE_CONTENT.getBytes(DEFAULT_ENCODING), + new FileOutputStream(sourceFile, false)); + message = MessageBuilder.withPayload(sourceFile).build(); + } + + @After + public void tearDown() { + sourceFile.delete(); + } + + @Test + public void saveToBaseDir() throws Exception { + this.inputChannelSaveToBaseDir.send(message); + + Assert.assertTrue(new File("target/base-directory/foo.txt").exists()); + + } + + @Test + public void saveToBaseDirDeleteSourceFile() throws Exception { + Assert.assertTrue(sourceFile.exists()); + this.inputChannelSaveToBaseDirDeleteSource.send(message); + Assert.assertTrue(new File("target/base-directory/foo.txt").exists()); + Assert.assertFalse(sourceFile.exists()); + } + + @Test + public void saveToSubDir() throws Exception { + this.inputChannelSaveToSubDir.send(message); + Assert.assertTrue(new File("target/base-directory/sub-directory/foo.txt").exists()); + } + + @Test + public void saveToSubDirWithWrongExpression() throws Exception { + + try { + this.inputChannelSaveToSubDirWrongExpression.send(message); + } catch (MessageHandlingException e) { + Assert.assertEquals("Destination path [target/base-directory/sub-directory/foo.txt] does not point to a directory.", e.getCause().getMessage()); + return; + } + + Assert.fail("Was expecting a MessageHandlingException to be thrown"); + } + + @Test + public void saveToSubDirWithEmptyStringExpression() throws Exception { + + try { + this.inputChannelSaveToSubDirEmptyStringExpression.send(message); + } catch (MessageHandlingException e) { + Assert.assertEquals("Unable to resolve destination directory name for the provided Expression '' ''.", e.getCause().getMessage()); + return; + } + + Assert.fail("Was expecting a MessageHandlingException to be thrown"); + } + + @Test + public void saveToSubDir2() throws Exception { + + final Message message2 = MessageBuilder.fromMessage(message) + .setHeader("myFileLocation", "target/base-directory/headerdir") + .build(); + + this.inputChannelSaveToSubDirWithHeader.send(message2); + Assert.assertTrue(new File("target/base-directory/headerdir/foo.txt").exists()); + } + + @Test + public void saveToSubDirAutoCreateOff() throws Exception { + + try { + this.inputChannelSaveToSubDirAutoCreateOff.send(message); + } catch (MessageHandlingException e) { + Assert.assertEquals("Destination directory [target/base-directory2/sub-directory2] does not exist.", e.getCause().getMessage()); + return; + } + + Assert.fail("Was expecting a MessageHandlingException to be thrown"); + } + + @Test + public void saveToSubWithFileExpression() throws Exception { + + final File directory = new File("target/base-directory/sub-directory"); + final Message messageWithFileHeader = MessageBuilder.fromMessage(message) + .setHeader("subDirectory", directory) + .build(); + this.inputChannelSaveToSubDirWithFile.send(messageWithFileHeader); + Assert.assertTrue(new File("target/base-directory/sub-directory/foo.txt").exists()); + } + + @Test + public void saveToSubWithFileExpressionNull() throws Exception { + + final File directory = null; + final Message messageWithFileHeader = MessageBuilder.fromMessage(message) + .setHeader("subDirectory", directory) + .build(); + + try { + this.inputChannelSaveToSubDirWithFile.send(messageWithFileHeader); + } catch (MessageHandlingException e) { + Assert.assertEquals("The provided destinationDirectoryExpression " + + "(headers['subDirectory']) must not resolve to null.", + e.getCause().getMessage()); + + return; + } + + Assert.fail("Was expecting a MessageHandlingException to be thrown"); + } + + @Test + public void saveToSubWithFileExpressionUnsupportedObjectType() throws Exception { + + final Integer unsupportedObject = Integer.valueOf(1234); + final Message messageWithFileHeader = MessageBuilder.fromMessage(message) + .setHeader("subDirectory", unsupportedObject) + .build(); + + try { + this.inputChannelSaveToSubDirWithFile.send(messageWithFileHeader); + } catch (MessageHandlingException e) { + Assert.assertEquals("The provided destinationDirectoryExpression" + + " (headers['subDirectory']) must be of type " + + "java.io.File or be a String.", + e.getCause().getMessage()); + + return; + } + + Assert.fail("Was expecting a MessageHandlingException to be thrown"); + } +} \ No newline at end of file diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundAdaptersWithClasspathInPropertiesTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundAdaptersWithClasspathInPropertiesTests.java index ee2e6e90bc..79b7834c7e 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundAdaptersWithClasspathInPropertiesTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundAdaptersWithClasspathInPropertiesTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2012 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. @@ -22,6 +22,7 @@ import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.core.io.ClassPathResource; +import org.springframework.expression.Expression; import org.springframework.integration.endpoint.EventDrivenConsumer; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; @@ -33,37 +34,45 @@ import static org.junit.Assert.assertEquals; /** * @author Iwein Fuld * @author Mark Fisher + * @author Gunnar Hillert + * * @since 1.0.3 */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class FileOutboundAdaptersWithClasspathInPropertiesTests { - @Autowired - @Qualifier("adapter") - private EventDrivenConsumer adapter; + @Autowired + @Qualifier("adapter") + private EventDrivenConsumer adapter; - @Autowired - @Qualifier("gateway") - private EventDrivenConsumer gateway; + @Autowired + @Qualifier("gateway") + private EventDrivenConsumer gateway; - @Test - public void outboundChannelAdapter() throws Exception { - DirectFieldAccessor accessor = new DirectFieldAccessor( - new DirectFieldAccessor(adapter).getPropertyValue("handler")); - File expected = new ClassPathResource("").getFile(); - File actual = (File) accessor.getPropertyValue("destinationDirectory"); - assertEquals("'destinationDirectory' should be set", expected, actual); - } + @Test + public void outboundChannelAdapter() throws Exception { + DirectFieldAccessor accessor = new DirectFieldAccessor( + new DirectFieldAccessor(adapter).getPropertyValue("handler")); + File expected = new ClassPathResource("").getFile(); - @Test - public void outboundGateway() throws Exception { - DirectFieldAccessor accessor = new DirectFieldAccessor( - new DirectFieldAccessor(gateway).getPropertyValue("handler")); - File expected = new ClassPathResource("").getFile(); - File actual = (File) accessor.getPropertyValue("destinationDirectory"); - assertEquals("'destinationDirectory' should be set", expected, actual); - } + Expression destinationDirectoryExpression = (Expression) accessor.getPropertyValue("destinationDirectoryExpression"); + File actual = new File(destinationDirectoryExpression.getExpressionString()); + + assertEquals("'destinationDirectory' should be set", expected, actual); + } + + @Test + public void outboundGateway() throws Exception { + DirectFieldAccessor accessor = new DirectFieldAccessor( + new DirectFieldAccessor(gateway).getPropertyValue("handler")); + File expected = new ClassPathResource("").getFile(); + + Expression destinationDirectoryExpression = (Expression) accessor.getPropertyValue("destinationDirectoryExpression"); + File actual = new File(destinationDirectoryExpression.getExpressionString()); + + assertEquals("'destinationDirectory' should be set", expected, actual); + } } diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserTests-context.xml b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserTests-context.xml index afb50deb98..3e3ec7f1fe 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserTests-context.xml +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserTests-context.xml @@ -24,6 +24,10 @@ filename-generator="customFileNameGenerator" directory="${java.io.tmpdir}"/> + + + + + + + + + + + diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserWithErrorsTests-context.xml b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserWithErrorsTests-context.xml new file mode 100644 index 0000000000..e847315ba9 --- /dev/null +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserWithErrorsTests-context.xml @@ -0,0 +1,27 @@ + + + + + + + + + + diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserWithErrorsTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserWithErrorsTests.java new file mode 100644 index 0000000000..fdec51f5ae --- /dev/null +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundChannelAdapterParserWithErrorsTests.java @@ -0,0 +1,68 @@ +/* + * Copyright 2002-2012 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.file.config; + +import static junit.framework.Assert.fail; +import static junit.framework.Assert.assertEquals; + +import org.junit.Test; +import org.springframework.beans.factory.parsing.BeanDefinitionParsingException; +import org.springframework.context.support.ClassPathXmlApplicationContext; + +/** + * + * @author Gunnar Hillert + * + */ +public class FileOutboundChannelAdapterParserWithErrorsTests { + + @Test + public void testSettingDirectoryAndDirectoryExpression() { + + try { + new ClassPathXmlApplicationContext("FileOutboundChannelAdapterParserWithErrorsTests-context.xml", getClass()); + } catch (BeanDefinitionParsingException e) { + assertEquals("Configuration problem: Either directory or " + + "directory-expression must be provided but not both\nOffending " + + "resource: class path " + + "resource [org/springframework/integration/file/config/FileOutboundChannelAdapterParserWithErrorsTests-context.xml]", + e.getMessage()); + return; + } + + fail("Expected a BeanDefinitionParsingException to be thrown"); + + } + + @Test + public void testNotSettingBothDirectoryAndDirectoryExpression() { + + try { + new ClassPathXmlApplicationContext("FileOutboundChannelAdapterParserWithErrors2Tests-context.xml", getClass()); + } catch (BeanDefinitionParsingException e) { + assertEquals("Configuration problem: directory or directory-expression " + + "is required\nOffending resource: class path resource " + + "[org/springframework/integration/file/config/FileOutboundChannelAdapterParserWithErrors2Tests-context.xml]", + e.getMessage()); + return; + } + + fail("Expected a BeanDefinitionParsingException to be thrown"); + + } + +} diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml index fc87bc3e33..61ac006886 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests-context.xml @@ -14,11 +14,18 @@ http://www.springframework.org/schema/integration/file/spring-integration-file.xsd"> + filename-generator-expression="'foo.txt'"/> + + diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests.java index 5d9663063f..6bbffc3e05 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/config/FileOutboundGatewayParserTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2009 the original author or authors. + * Copyright 2002-2012 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,45 +16,54 @@ package org.springframework.integration.file.config; +import static org.junit.Assert.assertEquals; +import static org.junit.Assert.assertNotNull; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.annotation.Autowired; -import org.springframework.context.ApplicationContext; +import org.springframework.expression.Expression; +import org.springframework.integration.endpoint.EventDrivenConsumer; import org.springframework.integration.file.DefaultFileNameGenerator; import org.springframework.integration.file.FileWritingMessageHandler; import org.springframework.integration.test.util.TestUtils; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; -import static org.junit.Assert.assertEquals; -import static org.junit.Assert.assertNotNull; - /** * @author Mark Fisher + * @author Gunnar Hillert */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class FileOutboundGatewayParserTests { - @Autowired - private ApplicationContext context; + @Autowired + private EventDrivenConsumer ordered; + @Autowired + private EventDrivenConsumer gatewayWithDirectoryExpression; - @Test - public void checkOrderedGateway() throws Exception { - Object gateway = context.getBean("ordered"); - DirectFieldAccessor gatewayAccessor = new DirectFieldAccessor(gateway); - FileWritingMessageHandler handler = (FileWritingMessageHandler) - gatewayAccessor.getPropertyValue("handler"); - assertEquals(Boolean.FALSE, gatewayAccessor.getPropertyValue("autoStartup")); - DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(handler); - assertEquals(777, handlerAccessor.getPropertyValue("order")); - DefaultFileNameGenerator fileNameGenerator = (DefaultFileNameGenerator) handlerAccessor.getPropertyValue("fileNameGenerator"); - assertNotNull(fileNameGenerator); - String expression = (String) TestUtils.getPropertyValue(fileNameGenerator, "expression"); - assertNotNull(expression); - assertEquals("'foo.txt'", expression); - } + @Test + public void checkOrderedGateway() throws Exception { + + DirectFieldAccessor gatewayAccessor = new DirectFieldAccessor(ordered); + FileWritingMessageHandler handler = (FileWritingMessageHandler) + gatewayAccessor.getPropertyValue("handler"); + assertEquals(Boolean.FALSE, gatewayAccessor.getPropertyValue("autoStartup")); + DirectFieldAccessor handlerAccessor = new DirectFieldAccessor(handler); + assertEquals(777, handlerAccessor.getPropertyValue("order")); + DefaultFileNameGenerator fileNameGenerator = (DefaultFileNameGenerator) handlerAccessor.getPropertyValue("fileNameGenerator"); + assertNotNull(fileNameGenerator); + String expression = (String) TestUtils.getPropertyValue(fileNameGenerator, "expression"); + assertNotNull(expression); + assertEquals("'foo.txt'", expression); + } + + @Test + public void testOutboundGatewayWithDirectoryExpression() throws Exception { + FileWritingMessageHandler handler = TestUtils.getPropertyValue(gatewayWithDirectoryExpression, "handler", FileWritingMessageHandler.class); + assertEquals("'build/foo'", TestUtils.getPropertyValue(handler, "destinationDirectoryExpression", Expression.class).getExpressionString()); + } }