GH-164: Fix ZipTransformer deleteFile Mode
Fixes GH-164 (https://github.com/spring-projects/spring-integration-extensions/issues/164) * Move `deleteFile` logic to the end of of `ZipTransformer#doZipTransform()` * Add `deleteFile = true` for the `ZipTransformerTests` * Add `<request-handler-advice-chain>` to the transformers XSD definitions * Upgrade to Gradle 3.0 * Upgrade dependencies Move delete logic before reply message creation
This commit is contained in:
committed by
Gary Russell
parent
0ba841416b
commit
9a13e41d96
@@ -32,7 +32,6 @@ import org.springframework.integration.file.FileHeaders;
|
||||
import org.springframework.integration.transformer.Transformer;
|
||||
import org.springframework.integration.zip.ZipHeaders;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHandlingException;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -49,6 +48,7 @@ import org.springframework.util.StringUtils;
|
||||
* See also: https://blogs.oracle.com/xuemingshen/entry/zip64_support_for_4g_zipfile
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @author Artem Bilan
|
||||
* @since 1.0
|
||||
*
|
||||
*/
|
||||
@@ -98,90 +98,99 @@ public class ZipTransformer extends AbstractZipTransformer {
|
||||
*/
|
||||
@Override
|
||||
protected Object doZipTransform(Message<?> message) throws Exception {
|
||||
final Object payload = message.getPayload();
|
||||
final Object zippedData;
|
||||
final String baseFileName = this.fileNameGenerator.generateFileName(message);
|
||||
|
||||
try {
|
||||
final String zipEntryName;
|
||||
final String zipFileName;
|
||||
|
||||
final Object payload = message.getPayload();
|
||||
final Object zippedData;
|
||||
final String baseFileName = this.fileNameGenerator.generateFileName(message);
|
||||
|
||||
final String zipEntryName;
|
||||
final String zipFileName;
|
||||
|
||||
if (message.getHeaders().containsKey(ZipHeaders.ZIP_ENTRY_FILE_NAME)) {
|
||||
zipEntryName = (String) message.getHeaders().get(ZipHeaders.ZIP_ENTRY_FILE_NAME);
|
||||
}
|
||||
else {
|
||||
zipEntryName = baseFileName;
|
||||
}
|
||||
|
||||
if (message.getHeaders().containsKey(FileHeaders.FILENAME)) {
|
||||
zipFileName = baseFileName;
|
||||
}
|
||||
else {
|
||||
zipFileName = baseFileName + ZIP_EXTENSION;
|
||||
}
|
||||
|
||||
final Date lastModifiedDate;
|
||||
|
||||
if (message.getHeaders().containsKey(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE)) {
|
||||
lastModifiedDate = (Date) message.getHeaders().get(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE);
|
||||
}
|
||||
else {
|
||||
lastModifiedDate = new Date();
|
||||
}
|
||||
|
||||
java.util.List<ZipEntrySource> entries = new ArrayList<ZipEntrySource>();
|
||||
|
||||
if (payload instanceof Iterable<?>) {
|
||||
int counter = 1;
|
||||
|
||||
String baseName = FilenameUtils.getBaseName(zipEntryName);
|
||||
String fileExtension = FilenameUtils.getExtension(zipEntryName);
|
||||
|
||||
if (StringUtils.hasText(fileExtension)) {
|
||||
fileExtension = FilenameUtils.EXTENSION_SEPARATOR_STR + fileExtension;
|
||||
}
|
||||
|
||||
for (Object item : (Iterable<?>) payload) {
|
||||
|
||||
final ZipEntrySource zipEntrySource = createZipEntrySource(item, lastModifiedDate, baseName + "_"
|
||||
+ counter + fileExtension, this.useFileAttributes);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("ZipEntrySource path: '" + zipEntrySource.getPath() + "'");
|
||||
}
|
||||
entries.add(zipEntrySource);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
final ZipEntrySource zipEntrySource =
|
||||
createZipEntrySource(payload, lastModifiedDate, zipEntryName, this.useFileAttributes);
|
||||
entries.add(zipEntrySource);
|
||||
}
|
||||
|
||||
final byte[] zippedBytes = SpringZipUtils.pack(entries, this.compressionLevel);
|
||||
|
||||
if (ZipResultType.FILE.equals(this.zipResultType)) {
|
||||
final File zippedFile = new File(this.workDirectory, zipFileName);
|
||||
FileCopyUtils.copy(zippedBytes, zippedFile);
|
||||
zippedData = zippedFile;
|
||||
}
|
||||
else if (ZipResultType.BYTE_ARRAY.equals(this.zipResultType)) {
|
||||
zippedData = zippedBytes;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unsupported zipResultType " + this.zipResultType);
|
||||
}
|
||||
|
||||
return getMessageBuilderFactory()
|
||||
.withPayload(zippedData)
|
||||
.copyHeaders(message.getHeaders())
|
||||
.setHeader(FileHeaders.FILENAME, zipFileName)
|
||||
.build();
|
||||
if (message.getHeaders().containsKey(ZipHeaders.ZIP_ENTRY_FILE_NAME)) {
|
||||
zipEntryName = (String) message.getHeaders().get(ZipHeaders.ZIP_ENTRY_FILE_NAME);
|
||||
}
|
||||
catch (Exception e) {
|
||||
throw new MessageHandlingException(message, "Failed to apply Zip transformation.", e);
|
||||
else {
|
||||
zipEntryName = baseFileName;
|
||||
}
|
||||
|
||||
if (message.getHeaders().containsKey(FileHeaders.FILENAME)) {
|
||||
zipFileName = baseFileName;
|
||||
}
|
||||
else {
|
||||
zipFileName = baseFileName + ZIP_EXTENSION;
|
||||
}
|
||||
|
||||
final Date lastModifiedDate;
|
||||
|
||||
if (message.getHeaders().containsKey(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE)) {
|
||||
lastModifiedDate = (Date) message.getHeaders().get(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE);
|
||||
}
|
||||
else {
|
||||
lastModifiedDate = new Date();
|
||||
}
|
||||
|
||||
java.util.List<ZipEntrySource> entries = new ArrayList<ZipEntrySource>();
|
||||
|
||||
if (payload instanceof Iterable<?>) {
|
||||
int counter = 1;
|
||||
|
||||
String baseName = FilenameUtils.getBaseName(zipEntryName);
|
||||
String fileExtension = FilenameUtils.getExtension(zipEntryName);
|
||||
|
||||
if (StringUtils.hasText(fileExtension)) {
|
||||
fileExtension = FilenameUtils.EXTENSION_SEPARATOR_STR + fileExtension;
|
||||
}
|
||||
|
||||
for (Object item : (Iterable<?>) payload) {
|
||||
|
||||
final ZipEntrySource zipEntrySource = createZipEntrySource(item, lastModifiedDate, baseName + "_"
|
||||
+ counter + fileExtension, this.useFileAttributes);
|
||||
if (logger.isDebugEnabled()) {
|
||||
logger.debug("ZipEntrySource path: '" + zipEntrySource.getPath() + "'");
|
||||
}
|
||||
entries.add(zipEntrySource);
|
||||
counter++;
|
||||
}
|
||||
}
|
||||
else {
|
||||
final ZipEntrySource zipEntrySource =
|
||||
createZipEntrySource(payload, lastModifiedDate, zipEntryName, this.useFileAttributes);
|
||||
entries.add(zipEntrySource);
|
||||
}
|
||||
|
||||
final byte[] zippedBytes = SpringZipUtils.pack(entries, this.compressionLevel);
|
||||
|
||||
if (ZipResultType.FILE.equals(this.zipResultType)) {
|
||||
final File zippedFile = new File(this.workDirectory, zipFileName);
|
||||
FileCopyUtils.copy(zippedBytes, zippedFile);
|
||||
zippedData = zippedFile;
|
||||
}
|
||||
else if (ZipResultType.BYTE_ARRAY.equals(this.zipResultType)) {
|
||||
zippedData = zippedBytes;
|
||||
}
|
||||
else {
|
||||
throw new IllegalStateException("Unsupported zipResultType " + this.zipResultType);
|
||||
}
|
||||
|
||||
if (this.deleteFiles) {
|
||||
if (payload instanceof Iterable<?>) {
|
||||
for (Object item : (Iterable<?>) payload) {
|
||||
deleteFile(item);
|
||||
}
|
||||
}
|
||||
else {
|
||||
deleteFile(payload);
|
||||
}
|
||||
}
|
||||
return getMessageBuilderFactory()
|
||||
.withPayload(zippedData)
|
||||
.copyHeaders(message.getHeaders())
|
||||
.setHeader(FileHeaders.FILENAME, zipFileName)
|
||||
.build();
|
||||
}
|
||||
|
||||
private void deleteFile(Object fileToDelete) {
|
||||
if (fileToDelete instanceof File && !((File) fileToDelete).delete() && logger.isWarnEnabled()) {
|
||||
logger.warn("Failed to delete File '" + fileToDelete + "'");
|
||||
}
|
||||
}
|
||||
|
||||
@@ -197,15 +206,7 @@ public class ZipTransformer extends AbstractZipTransformer {
|
||||
throw new UnsupportedOperationException("Zipping of directories is not supported.");
|
||||
}
|
||||
|
||||
final FileSource fileSource = new FileSource(fileName, filePayload);
|
||||
|
||||
if (this.deleteFiles) {
|
||||
if (!filePayload.delete() && logger.isWarnEnabled()) {
|
||||
logger.warn("failed to delete File '" + filePayload + "'");
|
||||
}
|
||||
}
|
||||
|
||||
return fileSource;
|
||||
return new FileSource(fileName, filePayload);
|
||||
|
||||
}
|
||||
else if (item instanceof byte[] || item instanceof String) {
|
||||
@@ -223,7 +224,7 @@ public class ZipTransformer extends AbstractZipTransformer {
|
||||
}
|
||||
else {
|
||||
throw new IllegalArgumentException("Unsupported payload type. The only supported payloads are " +
|
||||
"java.io.File, java.lang.String, and byte[]");
|
||||
"java.io.File, java.lang.String, and byte[]");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -71,6 +71,7 @@
|
||||
<xsd:complexType name="transformerType">
|
||||
<xsd:sequence>
|
||||
<xsd:element ref="integration:poller" minOccurs="0" maxOccurs="1"/>
|
||||
<xsd:element name="request-handler-advice-chain" type="integration:handlerAdviceChainType" minOccurs="0" />
|
||||
</xsd:sequence>
|
||||
<xsd:attribute name="id" type="xsd:string">
|
||||
<xsd:annotation>
|
||||
|
||||
@@ -11,10 +11,14 @@
|
||||
http://www.springframework.org/schema/integration/zip http://www.springframework.org/schema/integration/zip/spring-integration-zip.xsd
|
||||
http://www.springframework.org/schema/integration http://www.springframework.org/schema/integration/spring-integration.xsd">
|
||||
|
||||
<int:channel id="input">
|
||||
</int:channel>
|
||||
<int:channel id="input"/>
|
||||
|
||||
<int-zip:zip-transformer input-channel="input" output-channel="write-file" result-type="BYTE_ARRAY">
|
||||
<int-zip:request-handler-advice-chain>
|
||||
<int:retry-advice/>
|
||||
</int-zip:request-handler-advice-chain>
|
||||
</int-zip:zip-transformer>
|
||||
|
||||
<int-zip:zip-transformer input-channel="input" output-channel="write-file" result-type="BYTE_ARRAY"/>
|
||||
<int-file:outbound-channel-adapter id="write-file" directory="${workDir}" auto-create-directory="true"/>
|
||||
|
||||
<context:property-placeholder properties-ref="properties"/>
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015 the original author or authors.
|
||||
* Copyright 2015-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.
|
||||
@@ -17,7 +17,6 @@
|
||||
package org.springframework.integration.zip;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
@@ -30,6 +29,7 @@ import org.junit.Before;
|
||||
import org.junit.Rule;
|
||||
import org.junit.Test;
|
||||
import org.junit.rules.TemporaryFolder;
|
||||
|
||||
import org.springframework.context.annotation.AnnotationConfigApplicationContext;
|
||||
import org.springframework.context.annotation.Bean;
|
||||
import org.springframework.context.annotation.Configuration;
|
||||
@@ -42,12 +42,14 @@ import org.springframework.messaging.MessageChannel;
|
||||
/**
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @author Artem Bilan
|
||||
* @since 1.0
|
||||
*
|
||||
*/
|
||||
public class Zip2FileTests {
|
||||
|
||||
private AnnotationConfigApplicationContext context;
|
||||
|
||||
private MessageChannel input;
|
||||
|
||||
private static final Properties properties = new Properties();
|
||||
@@ -61,7 +63,6 @@ public class Zip2FileTests {
|
||||
public void setup() throws IOException {
|
||||
this.workDir = testFolder.newFolder();
|
||||
properties.put("workDir", workDir);
|
||||
System.out.print(this.workDir.getAbsolutePath());
|
||||
|
||||
context = new AnnotationConfigApplicationContext();
|
||||
context.register(ContextConfiguration.class);
|
||||
@@ -77,7 +78,7 @@ public class Zip2FileTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zipStringWithDefaultFileName() throws FileNotFoundException, IOException, InterruptedException {
|
||||
public void zipStringWithDefaultFileName() throws IOException, InterruptedException {
|
||||
|
||||
final Message<String> message = MessageBuilder.withPayload("Zip me up.").build();
|
||||
|
||||
@@ -89,28 +90,33 @@ public class Zip2FileTests {
|
||||
|
||||
Assert.assertTrue(fileInWorkDir.isFile());
|
||||
Assert.assertTrue(fileInWorkDir.getName().contains(message.getHeaders().getId().toString()));
|
||||
Assert.assertTrue("The created file should have a 'zip' file extension.", fileInWorkDir.getName().endsWith(".zip"));
|
||||
Assert.assertTrue("The created file should have a 'zip' file extension.",
|
||||
fileInWorkDir.getName().endsWith(".zip"));
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zipStringWithExplicitFileName() throws FileNotFoundException, IOException, InterruptedException {
|
||||
input.send(MessageBuilder.withPayload("Zip me up.").setHeader(FileHeaders.FILENAME, "zipString.zip").build());
|
||||
public void zipStringWithExplicitFileName() throws IOException, InterruptedException {
|
||||
input.send(MessageBuilder.withPayload("Zip me up.")
|
||||
.setHeader(FileHeaders.FILENAME, "zipString.zip")
|
||||
.build());
|
||||
|
||||
Assert.assertTrue(this.workDir.list().length == 1);
|
||||
Assert.assertEquals("zipString.zip", this.workDir.listFiles()[0].getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zipBytesWithExplicitFileName() throws FileNotFoundException, IOException, InterruptedException {
|
||||
public void zipBytesWithExplicitFileName() throws IOException, InterruptedException {
|
||||
|
||||
input.send(MessageBuilder.withPayload("Zip me up.".getBytes()).setHeader(FileHeaders.FILENAME, "zipString.zip").build());
|
||||
input.send(MessageBuilder.withPayload("Zip me up.".getBytes())
|
||||
.setHeader(FileHeaders.FILENAME, "zipString.zip")
|
||||
.build());
|
||||
|
||||
Assert.assertTrue(this.workDir.list().length == 1);
|
||||
Assert.assertEquals("zipString.zip", this.workDir.listFiles()[0].getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zipFile() throws FileNotFoundException, IOException, InterruptedException {
|
||||
public void zipFile() throws IOException, InterruptedException {
|
||||
|
||||
final File fileToCompress = testFolder.newFile();
|
||||
FileUtils.writeStringToFile(fileToCompress, "hello world");
|
||||
@@ -122,7 +128,7 @@ public class Zip2FileTests {
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zipIterableWithMultipleStrings() throws FileNotFoundException, IOException, InterruptedException {
|
||||
public void zipIterableWithMultipleStrings() throws IOException, InterruptedException {
|
||||
|
||||
String stringToCompress1 = "String1";
|
||||
String stringToCompress2 = "String2";
|
||||
@@ -136,17 +142,19 @@ public class Zip2FileTests {
|
||||
stringsToCompress.add(stringToCompress3);
|
||||
stringsToCompress.add(stringToCompress4);
|
||||
|
||||
input.send(MessageBuilder.withPayload(stringsToCompress).setHeader(FileHeaders.FILENAME, "zipWith4Strings.zip").build());
|
||||
input.send(MessageBuilder.withPayload(stringsToCompress)
|
||||
.setHeader(FileHeaders.FILENAME, "zipWith4Strings.zip")
|
||||
.build());
|
||||
|
||||
Assert.assertTrue(this.workDir.list().length == 1);
|
||||
Assert.assertEquals("zipWith4Strings.zip", this.workDir.listFiles()[0].getName());
|
||||
}
|
||||
|
||||
@Test
|
||||
public void zipIterableWithDifferentTypes() throws FileNotFoundException, IOException, InterruptedException {
|
||||
public void zipIterableWithDifferentTypes() throws IOException, InterruptedException {
|
||||
|
||||
String stringToCompress = "String1";
|
||||
byte[] bytesToCompress = "String2".getBytes();
|
||||
byte[] bytesToCompress = "String2".getBytes();
|
||||
final File fileToCompress = testFolder.newFile();
|
||||
FileUtils.writeStringToFile(fileToCompress, "hello world");
|
||||
|
||||
@@ -156,7 +164,9 @@ public class Zip2FileTests {
|
||||
objectsToCompress.add(bytesToCompress);
|
||||
objectsToCompress.add(fileToCompress);
|
||||
|
||||
input.send(MessageBuilder.withPayload(objectsToCompress).setHeader(FileHeaders.FILENAME, "objects-to-compress.zip").build());
|
||||
input.send(MessageBuilder.withPayload(objectsToCompress)
|
||||
.setHeader(FileHeaders.FILENAME, "objects-to-compress.zip")
|
||||
.build());
|
||||
|
||||
Assert.assertTrue(this.workDir.list().length == 1);
|
||||
Assert.assertEquals("objects-to-compress.zip", this.workDir.listFiles()[0].getName());
|
||||
@@ -172,4 +182,5 @@ public class Zip2FileTests {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -20,7 +20,6 @@ import static org.mockito.Mockito.mock;
|
||||
|
||||
import java.io.ByteArrayInputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileNotFoundException;
|
||||
import java.io.IOException;
|
||||
import java.io.RandomAccessFile;
|
||||
import java.util.ArrayList;
|
||||
@@ -54,12 +53,6 @@ public class ZipTransformerTests {
|
||||
@Rule
|
||||
public TemporaryFolder testFolder = new TemporaryFolder();
|
||||
|
||||
/**
|
||||
* Compress a simple String. The result will be a byte array.
|
||||
*
|
||||
* @throws FileNotFoundException
|
||||
* @throws IOException
|
||||
*/
|
||||
@Test
|
||||
public void zipString() throws IOException {
|
||||
final ZipTransformer zipTransformer = new ZipTransformer();
|
||||
@@ -198,8 +191,9 @@ public class ZipTransformerTests {
|
||||
@Test
|
||||
public void zipFile() throws IOException {
|
||||
|
||||
final ZipTransformer zipTransformer = new ZipTransformer();
|
||||
ZipTransformer zipTransformer = new ZipTransformer();
|
||||
zipTransformer.setBeanFactory(mock(BeanFactory.class));
|
||||
zipTransformer.setDeleteFiles(true);
|
||||
zipTransformer.afterPropertiesSet();
|
||||
|
||||
final File testFile = createTestFile(10);
|
||||
|
||||
Reference in New Issue
Block a user