GH-9452: Expose ZipTransformer.setFileNameGenerator()
Fixes: #9452 Issue link: https://github.com/spring-projects/spring-integration/issues/9452 * Move the logic about `fileNameGenerator` configuration out of `AbstractZipTransformer` since this property is not used by `UnZipTransformer` implementation * Add more docs about `ZipTransformer` logic
This commit is contained in:
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2023 the original author or authors.
|
||||
* Copyright 2015-2024 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.
|
||||
@@ -19,8 +19,6 @@ package org.springframework.integration.zip.transformer;
|
||||
import java.io.File;
|
||||
import java.nio.charset.Charset;
|
||||
|
||||
import org.springframework.integration.file.DefaultFileNameGenerator;
|
||||
import org.springframework.integration.file.FileNameGenerator;
|
||||
import org.springframework.integration.transformer.AbstractTransformer;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.util.Assert;
|
||||
@@ -37,8 +35,6 @@ public abstract class AbstractZipTransformer extends AbstractTransformer {
|
||||
|
||||
protected Charset charset = Charset.defaultCharset();
|
||||
|
||||
protected FileNameGenerator fileNameGenerator;
|
||||
|
||||
protected ZipResultType zipResultType = ZipResultType.FILE;
|
||||
|
||||
protected File workDirectory =
|
||||
@@ -91,11 +87,6 @@ public abstract class AbstractZipTransformer extends AbstractTransformer {
|
||||
logger.info(() -> "Creating work directory: " + this.workDirectory);
|
||||
Assert.isTrue(this.workDirectory.mkdirs(), () -> "Can't create the 'workDirectory': " + this.workDirectory);
|
||||
}
|
||||
DefaultFileNameGenerator defaultFileNameGenerator = new DefaultFileNameGenerator();
|
||||
defaultFileNameGenerator.setBeanFactory(getBeanFactory());
|
||||
defaultFileNameGenerator.setConversionService(getConversionService());
|
||||
this.fileNameGenerator = defaultFileNameGenerator;
|
||||
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2023 the original author or authors.
|
||||
* Copyright 2015-2024 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.
|
||||
@@ -29,10 +29,13 @@ import org.zeroturnaround.zip.ByteSource;
|
||||
import org.zeroturnaround.zip.FileSource;
|
||||
import org.zeroturnaround.zip.ZipEntrySource;
|
||||
|
||||
import org.springframework.integration.file.DefaultFileNameGenerator;
|
||||
import org.springframework.integration.file.FileHeaders;
|
||||
import org.springframework.integration.file.FileNameGenerator;
|
||||
import org.springframework.integration.transformer.Transformer;
|
||||
import org.springframework.integration.zip.ZipHeaders;
|
||||
import org.springframework.messaging.Message;
|
||||
import org.springframework.messaging.MessageHeaders;
|
||||
import org.springframework.util.Assert;
|
||||
import org.springframework.util.FileCopyUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
@@ -43,9 +46,6 @@ import org.springframework.util.StringUtils;
|
||||
* <p>
|
||||
* See also: <a href="https://www.mindprod.com/jgloss/zip.html"/>
|
||||
* <p>
|
||||
* If you want to generate Zip files larger than {@code 4GB}, you must use Java 7:
|
||||
* <p>
|
||||
* See also: <a href="https://blogs.oracle.com/xuemingshen/entry/zip64_support_for_4g_zipfile"/>
|
||||
*
|
||||
* @author Gunnar Hillert
|
||||
* @author Artem Bilan
|
||||
@@ -56,9 +56,11 @@ public class ZipTransformer extends AbstractZipTransformer {
|
||||
|
||||
private static final String ZIP_EXTENSION = ".zip";
|
||||
|
||||
private volatile int compressionLevel = Deflater.DEFAULT_COMPRESSION;
|
||||
private int compressionLevel = Deflater.DEFAULT_COMPRESSION;
|
||||
|
||||
private volatile boolean useFileAttributes = true;
|
||||
private boolean useFileAttributes = true;
|
||||
|
||||
private FileNameGenerator fileNameGenerator;
|
||||
|
||||
/**
|
||||
* Set the compression level. Default is {@link Deflater#DEFAULT_COMPRESSION}.
|
||||
@@ -77,6 +79,31 @@ public class ZipTransformer extends AbstractZipTransformer {
|
||||
this.useFileAttributes = useFileAttributes;
|
||||
}
|
||||
|
||||
/**
|
||||
* Set a {@link FileNameGenerator} for zip file base name: the {@code .zip} extension is added to this name.
|
||||
* Unless it already comes with {@code .zip} extension.
|
||||
* Defaults to the {@link org.springframework.integration.file.DefaultFileNameGenerator}.
|
||||
* The result of this generator is also used for zip entry(ies) if {@link ZipHeaders#ZIP_ENTRY_FILE_NAME}
|
||||
* header is not provided in the request message.
|
||||
* @param fileNameGenerator the {@link FileNameGenerator} to use.
|
||||
* @since 6.4
|
||||
*/
|
||||
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
|
||||
Assert.notNull(fileNameGenerator, "'fileNameGenerator' must not be null");
|
||||
this.fileNameGenerator = fileNameGenerator;
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onInit() {
|
||||
super.onInit();
|
||||
if (this.fileNameGenerator == null) {
|
||||
DefaultFileNameGenerator defaultFileNameGenerator = new DefaultFileNameGenerator();
|
||||
defaultFileNameGenerator.setBeanFactory(getBeanFactory());
|
||||
defaultFileNameGenerator.setConversionService(getConversionService());
|
||||
this.fileNameGenerator = defaultFileNameGenerator;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The payload may encompass the following types:
|
||||
* <ul>
|
||||
@@ -91,39 +118,19 @@ public class ZipTransformer extends AbstractZipTransformer {
|
||||
@Override
|
||||
protected Object doZipTransform(Message<?> message) {
|
||||
Object payload = message.getPayload();
|
||||
Object zippedData;
|
||||
MessageHeaders messageHeaders = message.getHeaders();
|
||||
|
||||
String baseFileName = this.fileNameGenerator.generateFileName(message);
|
||||
String zipFileName = baseFileName.endsWith(ZIP_EXTENSION) ? baseFileName : baseFileName + ZIP_EXTENSION;
|
||||
|
||||
String zipEntryName;
|
||||
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 = (String) message.getHeaders().get(FileHeaders.FILENAME);
|
||||
}
|
||||
else {
|
||||
zipFileName = baseFileName + ZIP_EXTENSION;
|
||||
}
|
||||
|
||||
Date lastModifiedDate;
|
||||
|
||||
if (message.getHeaders().containsKey(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE)) {
|
||||
lastModifiedDate = message.getHeaders().get(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE, Date.class);
|
||||
}
|
||||
else {
|
||||
lastModifiedDate = new Date();
|
||||
}
|
||||
String zipEntryName = (String) messageHeaders.getOrDefault(ZipHeaders.ZIP_ENTRY_FILE_NAME, baseFileName);
|
||||
Date lastModifiedDate = (Date) messageHeaders.getOrDefault(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE, new Date());
|
||||
|
||||
List<ZipEntrySource> entries = createZipEntries(payload, zipEntryName, lastModifiedDate);
|
||||
|
||||
byte[] zippedBytes = SpringZipUtils.pack(entries, this.compressionLevel);
|
||||
|
||||
Object zippedData;
|
||||
if (ZipResultType.FILE.equals(this.zipResultType)) {
|
||||
final File zippedFile = new File(this.workDirectory, zipFileName);
|
||||
try {
|
||||
@@ -145,7 +152,7 @@ public class ZipTransformer extends AbstractZipTransformer {
|
||||
|
||||
return getMessageBuilderFactory()
|
||||
.withPayload(zippedData)
|
||||
.copyHeaders(message.getHeaders())
|
||||
.copyHeaders(messageHeaders)
|
||||
.setHeader(FileHeaders.FILENAME, zipFileName)
|
||||
.build();
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/*
|
||||
* Copyright 2015-2023 the original author or authors.
|
||||
* Copyright 2015-2024 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.
|
||||
@@ -25,8 +25,6 @@ import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.context.ConfigurableApplicationContext;
|
||||
import org.springframework.integration.channel.AbstractMessageChannel;
|
||||
import org.springframework.integration.endpoint.EventDrivenConsumer;
|
||||
import org.springframework.integration.file.DefaultFileNameGenerator;
|
||||
import org.springframework.integration.file.FileNameGenerator;
|
||||
import org.springframework.integration.test.util.TestUtils;
|
||||
import org.springframework.integration.transformer.MessageTransformingHandler;
|
||||
import org.springframework.integration.zip.transformer.UnZipTransformer;
|
||||
@@ -64,21 +62,18 @@ public class UnZipTransformerParserTests {
|
||||
final UnZipTransformer unZipTransformer = TestUtils.getPropertyValue(handler, "transformer", UnZipTransformer.class);
|
||||
|
||||
final Charset charset = TestUtils.getPropertyValue(unZipTransformer, "charset", Charset.class);
|
||||
final FileNameGenerator fileNameGenerator = TestUtils.getPropertyValue(unZipTransformer, "fileNameGenerator", FileNameGenerator.class);
|
||||
final ZipResultType zipResultType = TestUtils.getPropertyValue(unZipTransformer, "zipResultType", ZipResultType.class);
|
||||
final File workDirectory = TestUtils.getPropertyValue(unZipTransformer, "workDirectory", File.class);
|
||||
final Boolean deleteFiles = TestUtils.getPropertyValue(unZipTransformer, "deleteFiles", Boolean.class);
|
||||
final Boolean expectSingleResult = TestUtils.getPropertyValue(unZipTransformer, "expectSingleResult", Boolean.class);
|
||||
|
||||
assertThat(charset).isNotNull();
|
||||
assertThat(fileNameGenerator).isNotNull();
|
||||
assertThat(zipResultType).isNotNull();
|
||||
assertThat(workDirectory).isNotNull();
|
||||
assertThat(deleteFiles).isNotNull();
|
||||
assertThat(expectSingleResult).isNotNull();
|
||||
|
||||
assertThat(charset).isEqualTo(Charset.defaultCharset());
|
||||
assertThat(fileNameGenerator).isInstanceOf(DefaultFileNameGenerator.class);
|
||||
assertThat(zipResultType).isEqualTo(ZipResultType.FILE);
|
||||
assertThat(workDirectory)
|
||||
.isEqualTo(new File(System.getProperty("java.io.tmpdir") + File.separator + "ziptransformer"));
|
||||
@@ -102,21 +97,18 @@ public class UnZipTransformerParserTests {
|
||||
final UnZipTransformer unZipTransformer = TestUtils.getPropertyValue(handler, "transformer", UnZipTransformer.class);
|
||||
|
||||
final Charset charset = TestUtils.getPropertyValue(unZipTransformer, "charset", Charset.class);
|
||||
final FileNameGenerator fileNameGenerator = TestUtils.getPropertyValue(unZipTransformer, "fileNameGenerator", FileNameGenerator.class);
|
||||
final ZipResultType zipResultType = TestUtils.getPropertyValue(unZipTransformer, "zipResultType", ZipResultType.class);
|
||||
final File workDirectory = TestUtils.getPropertyValue(unZipTransformer, "workDirectory", File.class);
|
||||
final Boolean deleteFiles = TestUtils.getPropertyValue(unZipTransformer, "deleteFiles", Boolean.class);
|
||||
final Boolean expectSingleResult = TestUtils.getPropertyValue(unZipTransformer, "expectSingleResult", Boolean.class);
|
||||
|
||||
assertThat(charset).isNotNull();
|
||||
assertThat(fileNameGenerator).isNotNull();
|
||||
assertThat(zipResultType).isNotNull();
|
||||
assertThat(workDirectory).isNotNull();
|
||||
assertThat(deleteFiles).isNotNull();
|
||||
assertThat(expectSingleResult).isNotNull();
|
||||
|
||||
assertThat(charset).isEqualTo(Charset.defaultCharset());
|
||||
assertThat(fileNameGenerator).isInstanceOf(DefaultFileNameGenerator.class);
|
||||
assertThat(zipResultType).isEqualTo(ZipResultType.FILE);
|
||||
assertThat(workDirectory)
|
||||
.isEqualTo(new File(System.getProperty("java.io.tmpdir") + File.separator + "ziptransformer"));
|
||||
|
||||
@@ -78,3 +78,9 @@ See xref:sftp/session-factory.adoc[SFTP Session Factory] for more information.
|
||||
Multiple instances of `MqttPahoMessageDrivenChannelAdapter` and `Mqttv5PahoMessageDrivenChannelAdapter` can now be added at runtime using corresponding `ClientManager` through `IntegrationFlowContext`
|
||||
Also a `MqttMessageNotDeliveredEvent` event has been introduced to emit when action callback reacts to the delivery failure.
|
||||
See xref:mqtt.adoc[MQTT Support] for more information.
|
||||
|
||||
[[x6.4-zip-support-changes]]
|
||||
=== Zip Support Changes
|
||||
|
||||
The `ZipTransformer` now exposes a `fileNameGenerator` property to customize a target zip file (and optional zip entry) name generation.
|
||||
See xref:zip.adoc[Zip Support] for more information.
|
||||
|
||||
@@ -69,6 +69,14 @@ The `ZipTransformer` can be customized by setting several properties:
|
||||
Default is `Deflater#DEFAULT_COMPRESSION`.
|
||||
|
||||
* `useFileAttributes` - specifies whether the name of the file shall be used for the zip entry.
|
||||
* `fileNameGenerator` - uses to generate an original file name based on the request message.
|
||||
Defaults to `DefaultFileNameGenerator`.
|
||||
The `.zip` extension is added into this name for the target zip file name.
|
||||
Unless it is already present as a result of this generator.
|
||||
|
||||
In addition, a `ZipHeaders.ZIP_ENTRY_FILE_NAME` and `ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE` can be supplied for the name of zip entry and its `lastmodified` attribute.
|
||||
If not provided, the entry name is exact result of the `fileNameGenerator` and `lastmodified` falls back to the current date and time.
|
||||
If the payload of request message is an `Iterable`, then this entry name is modified with an index starting `1`.
|
||||
|
||||
For example to zip a simple `test.txt` file into a `test.txt.zip`, only this configuration is enough:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user