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 742626f75c..afe877b51b 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 @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -24,7 +24,6 @@ import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.io.OutputStreamWriter; -import java.io.Writer; import java.nio.charset.Charset; import org.apache.commons.logging.Log; @@ -45,7 +44,7 @@ import org.springframework.messaging.Message; import org.springframework.messaging.MessageHandler; import org.springframework.messaging.MessageHandlingException; import org.springframework.util.Assert; -import org.springframework.util.FileCopyUtils; +import org.springframework.util.StreamUtils; import org.springframework.util.StringUtils; /** @@ -55,6 +54,9 @@ import org.springframework.util.StringUtils; * it directly. Otherwise, the payload type is unsupported, and an Exception * will be thrown. *
+ * To append a new-line after each write, set the + * {@link #setAppendNewLine(boolean) appendNewLine} flag to 'true'. It is 'false' by default. + *
* If the 'deleteSourceFiles' flag is set to true, the original Files will be * deleted. The default value for that flag is false. See the * {@link #setDeleteSourceFiles(boolean)} method javadoc for more information. @@ -73,9 +75,12 @@ import org.springframework.util.StringUtils; * @author Artem Bilan * @author Gunnar Hillert * @author Gary Russell + * @author Tony Falabella */ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHandler { + private static final String LINE_SEPARATOR = System.getProperty("line.separator"); + private volatile String temporaryFileSuffix =".writing"; private volatile boolean temporaryFileSuffixSet = false; @@ -100,6 +105,8 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand private volatile boolean expectReply = true; + private volatile boolean appendNewLine = false; + private volatile LockRegistry lockRegistry = new PassThruLockRegistry(); /** @@ -189,6 +196,15 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand this.expectReply = expectReply; } + /** + * If 'true' will append a new-line after each write. It is 'false' by default. + * @param appendNewLine true if a new-line should be written to the file after payload is written + * @since 4.0.7 + */ + public void setAppendNewLine(boolean appendNewLine) { + this.appendNewLine = appendNewLine; + } + protected String getTemporaryFileSuffix() { return temporaryFileSuffix; } @@ -341,14 +357,36 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand } private File handleFileMessage(final File sourceFile, File tempFile, final File resultFile) throws IOException { - if (FileExistsMode.APPEND.equals(this.fileExistsMode)){ + if (FileExistsMode.APPEND.equals(this.fileExistsMode)) { File fileToWriteTo = this.determineFileToWrite(resultFile, tempFile); final BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(fileToWriteTo, true)); final BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile)); WhileLockedProcessor whileLockedProcessor = new WhileLockedProcessor(this.lockRegistry, fileToWriteTo.getAbsolutePath()){ @Override protected void whileLocked() throws IOException { - FileCopyUtils.copy(bis, bos); + try { + byte[] buffer = new byte[StreamUtils.BUFFER_SIZE]; + int bytesRead = -1; + while ((bytesRead = bis.read(buffer)) != -1) { + bos.write(buffer, 0, bytesRead); + } + if (FileWritingMessageHandler.this.appendNewLine) { + bos.write(LINE_SEPARATOR.getBytes()); + } + bos.flush(); + } + finally { + try { + bis.close(); + } + catch (IOException ex) { + } + try { + bos.close(); + } + catch (IOException ex) { + } + } } }; whileLockedProcessor.doWhileLocked(); @@ -365,7 +403,33 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand sourceFile.getAbsolutePath())); } } - FileCopyUtils.copy(sourceFile, tempFile); + + BufferedOutputStream bos = new BufferedOutputStream(new FileOutputStream(tempFile)); + BufferedInputStream bis = new BufferedInputStream(new FileInputStream(sourceFile)); + + try { + byte[] buffer = new byte[StreamUtils.BUFFER_SIZE]; + int bytesRead = -1; + while ((bytesRead = bis.read(buffer)) != -1) { + bos.write(buffer, 0, bytesRead); + } + if (this.appendNewLine) { + bos.write(LINE_SEPARATOR.getBytes()); + } + bos.flush(); + } + finally { + try { + bis.close(); + } + catch (IOException ex) { + } + try { + bos.close(); + } + catch (IOException ex) { + } + } this.cleanUpAfterCopy(tempFile, resultFile, sourceFile); return resultFile; } @@ -380,7 +444,19 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand WhileLockedProcessor whileLockedProcessor = new WhileLockedProcessor(this.lockRegistry, fileToWriteTo.getAbsolutePath()){ @Override protected void whileLocked() throws IOException { - FileCopyUtils.copy(bytes, bos); + try { + bos.write(bytes); + if (FileWritingMessageHandler.this.appendNewLine) { + bos.write(LINE_SEPARATOR.getBytes()); + } + } + finally { + try { + bos.close(); + } + catch (IOException ex) { + } + } } }; @@ -394,11 +470,24 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand final boolean append = FileExistsMode.APPEND.equals(this.fileExistsMode); - final Writer writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileToWriteTo, append), this.charset)); + final BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(new FileOutputStream(fileToWriteTo, append), this.charset)); WhileLockedProcessor whileLockedProcessor = new WhileLockedProcessor(this.lockRegistry, fileToWriteTo.getAbsolutePath()){ @Override protected void whileLocked() throws IOException { - FileCopyUtils.copy(content, writer); + try { + writer.write(content); + if (FileWritingMessageHandler.this.appendNewLine) { + writer.newLine(); + } + } + finally { + try { + writer.close(); + } + catch (IOException ex) { + } + } + } }; diff --git a/spring-integration-file/src/test/java/org/springframework/integration/file/FileWritingMessageHandlerTests.java b/spring-integration-file/src/test/java/org/springframework/integration/file/FileWritingMessageHandlerTests.java index 9b3ed83258..2a697f8241 100644 --- a/spring-integration-file/src/test/java/org/springframework/integration/file/FileWritingMessageHandlerTests.java +++ b/spring-integration-file/src/test/java/org/springframework/integration/file/FileWritingMessageHandlerTests.java @@ -1,5 +1,5 @@ /* - * Copyright 2002-2014 the original author or authors. + * Copyright 2002-2015 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. @@ -54,6 +54,7 @@ import org.springframework.util.FileCopyUtils; * @author Iwein Fuld * @author Alex Peters * @author Gary Russell + * @author Tony Falabella */ public class FileWritingMessageHandlerTests { @@ -112,6 +113,19 @@ public class FileWritingMessageHandlerTests { assertFileContentIsMatching(result); } + @Test + public void stringPayloadCopiedToNewFileWithNewLines() throws Exception { + Message> message = MessageBuilder.withPayload(SAMPLE_CONTENT).build(); + QueueChannel output = new QueueChannel(); + String newLine = System.getProperty("line.separator"); + handler.setCharset(DEFAULT_ENCODING); + handler.setOutputChannel(output); + handler.setAppendNewLine(true); + handler.handleMessage(message); + Message> result = output.receive(0); + assertFileContentIs(result, SAMPLE_CONTENT + newLine); + } + @Test public void byteArrayPayloadCopiedToNewFile() throws Exception { Message> message = MessageBuilder.withPayload( @@ -123,6 +137,19 @@ public class FileWritingMessageHandlerTests { assertFileContentIsMatching(result); } + @Test + public void byteArrayPayloadCopiedToNewFileWithNewLines() throws Exception { + Message> message = MessageBuilder.withPayload( + SAMPLE_CONTENT.getBytes(DEFAULT_ENCODING)).build(); + QueueChannel output = new QueueChannel(); + String newLine = System.getProperty("line.separator"); + handler.setOutputChannel(output); + handler.setAppendNewLine(true); + handler.handleMessage(message); + Message> result = output.receive(0); + assertFileContentIs(result, SAMPLE_CONTENT + newLine); + } + @Test public void filePayloadCopiedToNewFile() throws Exception { Message> message = MessageBuilder.withPayload(sourceFile).build(); @@ -133,6 +160,17 @@ public class FileWritingMessageHandlerTests { assertFileContentIsMatching(result); } + @Test + public void filePayloadCopiedToNewFileWithNewLines() throws Exception { + Message> message = MessageBuilder.withPayload(sourceFile).build(); + QueueChannel output = new QueueChannel(); + handler.setOutputChannel(output); + handler.setAppendNewLine(true); + handler.handleMessage(message); + Message> result = output.receive(0); + assertFileContentIs(result, SAMPLE_CONTENT + System.getProperty("line.separator")); + } + @Test @Ignore // INT-3289 ignored because it won't fail on all OS public void testCreateDirFail() { File dir = new File("/foo");