INT-3960: File Outbound - Preserve Timestamp
JIRA: https://jira.spring.io/browse/INT-3960 Polishing - PR Comments Fix errors according Checkstyle report. Wrap `warn()` to `isWarnEnable()`. Polishing for `setPreserveTimestamp()` JavaDocs.
This commit is contained in:
committed by
Artem Bilan
parent
ad0839da8b
commit
516846b750
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2002-2015 the original author or authors.
|
||||
* Copyright 2002-2016 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.
|
||||
@@ -39,4 +39,6 @@ public abstract class FileHeaders {
|
||||
|
||||
public static final String RENAME_TO = PREFIX + "renameTo";
|
||||
|
||||
public static final String SET_MODIFIED = PREFIX + "setModified";
|
||||
|
||||
}
|
||||
|
||||
@@ -152,6 +152,8 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
|
||||
|
||||
private volatile MessageFlushPredicate flushPredicate = new DefaultFlushPredicate();
|
||||
|
||||
private volatile boolean preserveTimestamp;
|
||||
|
||||
/**
|
||||
* Constructor which sets the {@link #destinationDirectoryExpression} using
|
||||
* a {@link LiteralExpression}.
|
||||
@@ -327,6 +329,19 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
|
||||
this.flushPredicate = flushPredicate;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set to true to preserve the destination file timestamp. If true and
|
||||
* the payload is a {@link File}, the payload's {@code lastModified} time will be
|
||||
* transferred to the destination file. For other payloads, the
|
||||
* {@link FileHeaders#SET_MODIFIED} header {@value FileHeaders#SET_MODIFIED}
|
||||
* will be used if present and it's a {@link Number}.
|
||||
* @param preserveTimestamp the preserveTimestamp to set.
|
||||
* @since 4.3
|
||||
*/
|
||||
public void setPreserveTimestamp(boolean preserveTimestamp) {
|
||||
this.preserveTimestamp = preserveTimestamp;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void doInit() {
|
||||
this.evaluationContext = ExpressionUtils.createStandardEvaluationContext(getBeanFactory());
|
||||
@@ -408,6 +423,7 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
|
||||
|
||||
if (!ignore) {
|
||||
try {
|
||||
Object timestamp = requestMessage.getHeaders().get(FileHeaders.SET_MODIFIED);
|
||||
if (!resultFile.exists() &&
|
||||
generatedFileName.replaceAll("/", Matcher.quoteReplacement(File.separator))
|
||||
.contains(File.separator)) {
|
||||
@@ -415,6 +431,7 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
|
||||
}
|
||||
if (payload instanceof File) {
|
||||
resultFile = handleFileMessage((File) payload, tempFile, resultFile);
|
||||
timestamp = ((File) payload).lastModified();
|
||||
}
|
||||
else if (payload instanceof InputStream) {
|
||||
resultFile = handleInputStreamMessage((InputStream) payload, originalFileFromHeader, tempFile,
|
||||
@@ -432,6 +449,17 @@ public class FileWritingMessageHandler extends AbstractReplyProducingMessageHand
|
||||
throw new IllegalArgumentException(
|
||||
"unsupported Message payload type [" + payload.getClass().getName() + "]");
|
||||
}
|
||||
if (this.preserveTimestamp) {
|
||||
if (timestamp instanceof Number) {
|
||||
resultFile.setLastModified(((Number) timestamp).longValue());
|
||||
}
|
||||
else {
|
||||
if (this.logger.isWarnEnabled()) {
|
||||
this.logger.warn("Could not set lastModified, header " + FileHeaders.SET_MODIFIED
|
||||
+ " must be a Number, not " + timestamp.getClass());
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MessageHandlingException(requestMessage, "failed to write Message payload to file", e);
|
||||
|
||||
@@ -509,6 +509,17 @@ Only files matching this regular expression will be picked up by this adapter.
|
||||
</xsd:appinfo>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attribute name="preserve-timestamp" type="xsd:string" default="false">
|
||||
<xsd:annotation>
|
||||
<xsd:documentation>
|
||||
Specify whether to preserve the modified timestamp from the source
|
||||
file on the destination file after copying. Applies to 'java.io.File' payloads.
|
||||
For other payload types, the optional 'file_setModified' header will be used,
|
||||
if present (and a 'Number'), to set the lastModified time.
|
||||
By default, the timestamp will NOT be preserved.
|
||||
</xsd:documentation>
|
||||
</xsd:annotation>
|
||||
</xsd:attribute>
|
||||
<xsd:attributeGroup ref="integration:smartLifeCycleAttributeGroup"/>
|
||||
</xsd:complexType>
|
||||
|
||||
|
||||
@@ -120,13 +120,18 @@ public class FileWritingMessageHandlerTests {
|
||||
|
||||
@Test
|
||||
public void stringPayloadCopiedToNewFile() throws Exception {
|
||||
Message<?> message = MessageBuilder.withPayload(SAMPLE_CONTENT).build();
|
||||
long lastModified = 1234000L;
|
||||
Message<?> message = MessageBuilder.withPayload(SAMPLE_CONTENT)
|
||||
.setHeader(FileHeaders.SET_MODIFIED, lastModified)
|
||||
.build();
|
||||
QueueChannel output = new QueueChannel();
|
||||
handler.setCharset(DEFAULT_ENCODING);
|
||||
handler.setOutputChannel(output);
|
||||
handler.setPreserveTimestamp(true);
|
||||
handler.handleMessage(message);
|
||||
Message<?> result = output.receive(0);
|
||||
assertFileContentIsMatching(result);
|
||||
assertLastModifiedIs(result, lastModified);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -184,11 +189,15 @@ public class FileWritingMessageHandlerTests {
|
||||
@Test
|
||||
public void filePayloadCopiedToNewFile() throws Exception {
|
||||
Message<?> message = MessageBuilder.withPayload(sourceFile).build();
|
||||
long lastModified = 12345000L;
|
||||
sourceFile.setLastModified(lastModified);
|
||||
QueueChannel output = new QueueChannel();
|
||||
handler.setOutputChannel(output);
|
||||
handler.setPreserveTimestamp(true);
|
||||
handler.handleMessage(message);
|
||||
Message<?> result = output.receive(0);
|
||||
assertFileContentIsMatching(result);
|
||||
assertLastModifiedIs(result, lastModified);
|
||||
}
|
||||
|
||||
@Test
|
||||
@@ -512,10 +521,11 @@ public class FileWritingMessageHandlerTests {
|
||||
}
|
||||
|
||||
void assertFileContentIs(Message<?> result, String expected) throws IOException {
|
||||
assertThat(result, is(notNullValue()));
|
||||
assertThat(result.getPayload(), is(instanceOf(File.class)));
|
||||
File destFile = (File) result.getPayload();
|
||||
assertFileContentIs(destFile, expected);
|
||||
assertFileContentIs(messageToFile(result), expected);
|
||||
}
|
||||
|
||||
void assertLastModifiedIs(Message<?> result, long expected) {
|
||||
assertThat(messageToFile(result).lastModified(), is(expected));
|
||||
}
|
||||
|
||||
void assertFileContentIs(File destFile, String expected) throws IOException {
|
||||
@@ -525,4 +535,11 @@ public class FileWritingMessageHandlerTests {
|
||||
assertThat(new String(destFileContent, DEFAULT_ENCODING), is(expected));
|
||||
}
|
||||
|
||||
protected File messageToFile(Message<?> result) {
|
||||
assertThat(result, is(notNullValue()));
|
||||
assertThat(result.getPayload(), is(instanceOf(File.class)));
|
||||
File destFile = (File) result.getPayload();
|
||||
return destFile;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user