/* * Copyright 2002-2017 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 org.junit.Assert.assertEquals; import static org.junit.Assert.assertFalse; import static org.junit.Assert.assertNotNull; import static org.junit.Assert.assertTrue; import static org.junit.Assert.fail; import java.io.File; import org.junit.Test; import org.junit.runner.RunWith; import org.springframework.beans.DirectFieldAccessor; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Qualifier; import org.springframework.expression.Expression; import org.springframework.integration.core.MessagingTemplate; import org.springframework.integration.endpoint.EventDrivenConsumer; import org.springframework.integration.file.DefaultFileNameGenerator; import org.springframework.integration.file.FileWritingMessageHandler; import org.springframework.integration.handler.advice.AbstractRequestHandlerAdvice; import org.springframework.integration.test.util.TestUtils; import org.springframework.messaging.Message; import org.springframework.messaging.MessageChannel; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessageHandlingException; import org.springframework.messaging.support.GenericMessage; import org.springframework.test.context.ContextConfiguration; import org.springframework.test.context.junit4.SpringJUnit4ClassRunner; import org.springframework.util.FileCopyUtils; /** * @author Mark Fisher * @author Gunnar Hillert * @author Artem Bilan * @author Tony Falabella */ @ContextConfiguration @RunWith(SpringJUnit4ClassRunner.class) public class FileOutboundGatewayParserTests { @Autowired private EventDrivenConsumer ordered; @Autowired private EventDrivenConsumer gatewayWithDirectoryExpression; @Autowired MessageChannel gatewayWithIgnoreModeChannel; @Autowired MessageChannel gatewayWithFailModeChannel; @Autowired MessageChannel gatewayWithAppendModeChannel; @Autowired MessageChannel gatewayWithReplaceModeChannel; @Autowired @Qualifier("gatewayWithReplaceMode.handler") MessageHandler gatewayWithReplaceModeHandler; @Autowired MessageChannel gatewayWithFailModeLowercaseChannel; @Autowired EventDrivenConsumer gatewayWithAppendNewLine; private volatile static int adviceCalled; @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")); assertEquals(Boolean.TRUE, handlerAccessor.getPropertyValue("requiresReply")); DefaultFileNameGenerator fileNameGenerator = (DefaultFileNameGenerator) handlerAccessor.getPropertyValue("fileNameGenerator"); assertNotNull(fileNameGenerator); Expression expression = TestUtils.getPropertyValue(fileNameGenerator, "expression", Expression.class); assertNotNull(expression); assertEquals("'foo.txt'", expression.getExpressionString()); Long sendTimeout = TestUtils.getPropertyValue(handler, "messagingTemplate.sendTimeout", Long.class); assertEquals(Long.valueOf(777), sendTimeout); } @Test public void testOutboundGatewayWithDirectoryExpression() throws Exception { FileWritingMessageHandler handler = TestUtils.getPropertyValue(gatewayWithDirectoryExpression, "handler", FileWritingMessageHandler.class); assertEquals("'build/foo'", TestUtils.getPropertyValue(handler, "destinationDirectoryExpression", Expression.class) .getExpressionString()); handler.handleMessage(new GenericMessage<String>("foo")); assertEquals(1, adviceCalled); } /** * Test uses the Ignore Mode of the File OutboundGateway. When persisting * a payload using the File Outbound Gateway and the mode is set to IGNORE, * then the destination file will be created and written if it does not yet exist, * BUT if it exists it will not be overwritten. Instead the Message Payload will * be silently ignored. The reply message will contain the pre-existing destination * {@link File} as its payload. * */ @Test public void gatewayWithIgnoreMode() throws Exception { final MessagingTemplate messagingTemplate = new MessagingTemplate(); messagingTemplate.setDefaultDestination(this.gatewayWithIgnoreModeChannel); final String expectedFileContent = "Initial File Content:"; final File testFile = new File("test/fileToAppend.txt"); if (testFile.exists()) { testFile.delete(); } messagingTemplate.sendAndReceive(new GenericMessage<String>("Initial File Content:")); Message<?> replyMessage = messagingTemplate.sendAndReceive(new GenericMessage<String>("String content:")); String actualFileContent = new String(FileCopyUtils.copyToByteArray(testFile)); assertEquals(expectedFileContent, actualFileContent); assertTrue(replyMessage.getPayload() instanceof File); File replyPayload = (File) replyMessage.getPayload(); assertEquals(expectedFileContent, new String(FileCopyUtils.copyToByteArray(replyPayload))); } /** * Test uses the Fail mode of the File Outbound Gateway. When persisting * a payload using the File Outbound Gateway and the mode is set to Fail, * then the destination {@link File} will be created and written if it does * not yet exist. BUT if the destination {@link File} already exists, a * {@link MessageHandlingException} will be thrown. * */ @Test public void gatewayWithFailMode() throws Exception { final MessagingTemplate messagingTemplate = new MessagingTemplate(); messagingTemplate.setDefaultDestination(this.gatewayWithFailModeChannel); String expectedFileContent = "Initial File Content:"; File testFile = new File("test/fileToAppend.txt"); if (testFile.exists()) { testFile.delete(); } messagingTemplate.sendAndReceive(new GenericMessage<String>("Initial File Content:")); final String actualFileContent = new String(FileCopyUtils.copyToByteArray(testFile)); assertEquals(expectedFileContent, actualFileContent); try { messagingTemplate.sendAndReceive(new GenericMessage<String>("String content:")); } catch (MessageHandlingException e) { assertTrue(e.getMessage().startsWith("The destination file already exists at '")); return; } fail("Was expecting a MessageHandlingException to be thrown."); } /** * Test is exactly the same as {@link #gatewayWithFailMode()}. However, the * mode is provided in lower-case ensuring that the mode can be provided * in an case-insensitive fashion. * * Instead a {@link MessageHandlingException} will be thrown. * */ @Test public void gatewayWithFailModeLowercase() throws Exception { final MessagingTemplate messagingTemplate = new MessagingTemplate(); messagingTemplate.setDefaultDestination(this.gatewayWithFailModeLowercaseChannel); String expectedFileContent = "Initial File Content:"; File testFile = new File("test/fileToAppend.txt"); if (testFile.exists()) { testFile.delete(); } messagingTemplate.sendAndReceive(new GenericMessage<String>("Initial File Content:")); final String actualFileContent = new String(FileCopyUtils.copyToByteArray(testFile)); assertEquals(expectedFileContent, actualFileContent); try { messagingTemplate.sendAndReceive(new GenericMessage<String>("String content:")); } catch (MessageHandlingException e) { assertTrue(e.getMessage().startsWith("The destination file already exists at '")); return; } fail("Was expecting a MessageHandlingException to be thrown."); } /** * Test uses the Append Mode of the File Outbound Gateway. When persisting * a payload using the File Outbound Gateway and the mode is set to APPEND, * then the destination file will be created and written, if it does not yet * exist. BUT if it exists it will be appended to the existing file. * * The reply message will contain the concatenated destination * {@link File} as its payload. * */ @Test public void gatewayWithAppendMode() throws Exception { final MessagingTemplate messagingTemplate = new MessagingTemplate(); messagingTemplate.setDefaultDestination(this.gatewayWithAppendModeChannel); String expectedFileContent = "Initial File Content:String content:"; File testFile = new File("test/fileToAppend.txt"); if (testFile.exists()) { testFile.delete(); } messagingTemplate.sendAndReceive(new GenericMessage<String>("Initial File Content:")); Message<?> m = messagingTemplate.sendAndReceive(new GenericMessage<String>("String content:")); String actualFileContent = new String(FileCopyUtils.copyToByteArray(testFile)); assertEquals(expectedFileContent, actualFileContent); assertTrue(m.getPayload() instanceof File); File replyPayload = (File) m.getPayload(); assertEquals(expectedFileContent, new String(FileCopyUtils.copyToByteArray(replyPayload))); } /** * Test uses the Replace Mode of the File OutboundGateway. When persisting * a payload using the File Outbound Gateway and the mode is set to REPLACE, * then the destination file will be created and written if it does not yet exist. * If the destination file exists, it will be replaced. * * The reply message will contain the concatenated destination * {@link File} as its payload. * */ @Test public void gatewayWithReplaceMode() throws Exception { assertFalse(TestUtils.getPropertyValue(this.gatewayWithReplaceModeHandler, "requiresReply", Boolean.class)); final MessagingTemplate messagingTemplate = new MessagingTemplate(); messagingTemplate.setDefaultDestination(this.gatewayWithReplaceModeChannel); String expectedFileContent = "String content:"; File testFile = new File("test/fileToAppend.txt"); if (testFile.exists()) { testFile.delete(); } messagingTemplate.sendAndReceive(new GenericMessage<String>("Initial File Content:")); Message<?> m = messagingTemplate.sendAndReceive(new GenericMessage<String>("String content:")); String actualFileContent = new String(FileCopyUtils.copyToByteArray(testFile)); assertEquals(expectedFileContent, actualFileContent); assertTrue(m.getPayload() instanceof File); File replyPayload = (File) m.getPayload(); assertEquals(expectedFileContent, new String(FileCopyUtils.copyToByteArray(replyPayload))); } /** * Test that the underlying {@link FileWritingMessageHandler} bean of the File Outbound Gateway * gets it's {@link FileWritingMessageHandler#setAppendNewLine(boolean)} called when XML * config file has <code>append-new-line="true"</code>. */ @Test public void gatewayWithAppendNewLine() { assertEquals(Boolean.TRUE, TestUtils.getPropertyValue(this.gatewayWithAppendNewLine, "handler.appendNewLine")); } public static class FooAdvice extends AbstractRequestHandlerAdvice { @Override protected Object doInvoke(ExecutionCallback callback, Object target, Message<?> message) throws Exception { adviceCalled++; return null; } } }