Skip to content

Commit a6c3a30

Browse files
committed
GH-9452: Expose ZipTransformer.setFileNameGenerator()
Fixes: #9452 Issue link: #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
1 parent e3a46ca commit a6c3a30

File tree

5 files changed

+56
-52
lines changed

5 files changed

+56
-52
lines changed

spring-integration-zip/src/main/java/org/springframework/integration/zip/transformer/AbstractZipTransformer.java

Lines changed: 1 addition & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2023 the original author or authors.
2+
* Copyright 2015-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -19,8 +19,6 @@
1919
import java.io.File;
2020
import java.nio.charset.Charset;
2121

22-
import org.springframework.integration.file.DefaultFileNameGenerator;
23-
import org.springframework.integration.file.FileNameGenerator;
2422
import org.springframework.integration.transformer.AbstractTransformer;
2523
import org.springframework.messaging.Message;
2624
import org.springframework.util.Assert;
@@ -37,8 +35,6 @@ public abstract class AbstractZipTransformer extends AbstractTransformer {
3735

3836
protected Charset charset = Charset.defaultCharset();
3937

40-
protected FileNameGenerator fileNameGenerator;
41-
4238
protected ZipResultType zipResultType = ZipResultType.FILE;
4339

4440
protected File workDirectory =
@@ -91,11 +87,6 @@ protected void onInit() {
9187
logger.info(() -> "Creating work directory: " + this.workDirectory);
9288
Assert.isTrue(this.workDirectory.mkdirs(), () -> "Can't create the 'workDirectory': " + this.workDirectory);
9389
}
94-
DefaultFileNameGenerator defaultFileNameGenerator = new DefaultFileNameGenerator();
95-
defaultFileNameGenerator.setBeanFactory(getBeanFactory());
96-
defaultFileNameGenerator.setConversionService(getConversionService());
97-
this.fileNameGenerator = defaultFileNameGenerator;
98-
9990
}
10091

10192
/**

spring-integration-zip/src/main/java/org/springframework/integration/zip/transformer/ZipTransformer.java

Lines changed: 40 additions & 33 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2023 the original author or authors.
2+
* Copyright 2015-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -29,10 +29,13 @@
2929
import org.zeroturnaround.zip.FileSource;
3030
import org.zeroturnaround.zip.ZipEntrySource;
3131

32+
import org.springframework.integration.file.DefaultFileNameGenerator;
3233
import org.springframework.integration.file.FileHeaders;
34+
import org.springframework.integration.file.FileNameGenerator;
3335
import org.springframework.integration.transformer.Transformer;
3436
import org.springframework.integration.zip.ZipHeaders;
3537
import org.springframework.messaging.Message;
38+
import org.springframework.messaging.MessageHeaders;
3639
import org.springframework.util.Assert;
3740
import org.springframework.util.FileCopyUtils;
3841
import org.springframework.util.StringUtils;
@@ -43,9 +46,6 @@
4346
* <p>
4447
* See also: <a href="https://www.mindprod.com/jgloss/zip.html"/>
4548
* <p>
46-
* If you want to generate Zip files larger than {@code 4GB}, you must use Java 7:
47-
* <p>
48-
* See also: <a href="https://blogs.oracle.com/xuemingshen/entry/zip64_support_for_4g_zipfile"/>
4949
*
5050
* @author Gunnar Hillert
5151
* @author Artem Bilan
@@ -56,9 +56,11 @@ public class ZipTransformer extends AbstractZipTransformer {
5656

5757
private static final String ZIP_EXTENSION = ".zip";
5858

59-
private volatile int compressionLevel = Deflater.DEFAULT_COMPRESSION;
59+
private int compressionLevel = Deflater.DEFAULT_COMPRESSION;
60+
61+
private boolean useFileAttributes = true;
6062

61-
private volatile boolean useFileAttributes = true;
63+
private FileNameGenerator fileNameGenerator;
6264

6365
/**
6466
* Set the compression level. Default is {@link Deflater#DEFAULT_COMPRESSION}.
@@ -77,6 +79,31 @@ public void setUseFileAttributes(boolean useFileAttributes) {
7779
this.useFileAttributes = useFileAttributes;
7880
}
7981

82+
/**
83+
* Set a {@link FileNameGenerator} for zip file base name: the {@code .zip} extension is added to this name.
84+
* Unless it already comes with {@code .zip} extension.
85+
* Defaults to the {@link org.springframework.integration.file.DefaultFileNameGenerator}.
86+
* The result of this generator is also used for zip entry(ies) if {@link ZipHeaders#ZIP_ENTRY_FILE_NAME}
87+
* header is not provided in the request message.
88+
* @param fileNameGenerator the {@link FileNameGenerator} to use.
89+
* @since 6.4
90+
*/
91+
public void setFileNameGenerator(FileNameGenerator fileNameGenerator) {
92+
Assert.notNull(fileNameGenerator, "'fileNameGenerator' must not be null");
93+
this.fileNameGenerator = fileNameGenerator;
94+
}
95+
96+
@Override
97+
protected void onInit() {
98+
super.onInit();
99+
if (this.fileNameGenerator == null) {
100+
DefaultFileNameGenerator defaultFileNameGenerator = new DefaultFileNameGenerator();
101+
defaultFileNameGenerator.setBeanFactory(getBeanFactory());
102+
defaultFileNameGenerator.setConversionService(getConversionService());
103+
this.fileNameGenerator = defaultFileNameGenerator;
104+
}
105+
}
106+
80107
/**
81108
* The payload may encompass the following types:
82109
* <ul>
@@ -91,39 +118,19 @@ public void setUseFileAttributes(boolean useFileAttributes) {
91118
@Override
92119
protected Object doZipTransform(Message<?> message) {
93120
Object payload = message.getPayload();
94-
Object zippedData;
95-
String baseFileName = this.fileNameGenerator.generateFileName(message);
96-
97-
String zipEntryName;
98-
String zipFileName;
121+
MessageHeaders messageHeaders = message.getHeaders();
99122

100-
if (message.getHeaders().containsKey(ZipHeaders.ZIP_ENTRY_FILE_NAME)) {
101-
zipEntryName = (String) message.getHeaders().get(ZipHeaders.ZIP_ENTRY_FILE_NAME);
102-
}
103-
else {
104-
zipEntryName = baseFileName;
105-
}
106-
107-
if (message.getHeaders().containsKey(FileHeaders.FILENAME)) {
108-
zipFileName = (String) message.getHeaders().get(FileHeaders.FILENAME);
109-
}
110-
else {
111-
zipFileName = baseFileName + ZIP_EXTENSION;
112-
}
113-
114-
Date lastModifiedDate;
123+
String baseFileName = this.fileNameGenerator.generateFileName(message);
124+
String zipFileName = baseFileName.endsWith(ZIP_EXTENSION) ? baseFileName : baseFileName + ZIP_EXTENSION;
115125

116-
if (message.getHeaders().containsKey(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE)) {
117-
lastModifiedDate = message.getHeaders().get(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE, Date.class);
118-
}
119-
else {
120-
lastModifiedDate = new Date();
121-
}
126+
String zipEntryName = (String) messageHeaders.getOrDefault(ZipHeaders.ZIP_ENTRY_FILE_NAME, baseFileName);
127+
Date lastModifiedDate = (Date) messageHeaders.getOrDefault(ZipHeaders.ZIP_ENTRY_LAST_MODIFIED_DATE, new Date());
122128

123129
List<ZipEntrySource> entries = createZipEntries(payload, zipEntryName, lastModifiedDate);
124130

125131
byte[] zippedBytes = SpringZipUtils.pack(entries, this.compressionLevel);
126132

133+
Object zippedData;
127134
if (ZipResultType.FILE.equals(this.zipResultType)) {
128135
final File zippedFile = new File(this.workDirectory, zipFileName);
129136
try {
@@ -145,7 +152,7 @@ else if (ZipResultType.BYTE_ARRAY.equals(this.zipResultType)) {
145152

146153
return getMessageBuilderFactory()
147154
.withPayload(zippedData)
148-
.copyHeaders(message.getHeaders())
155+
.copyHeaders(messageHeaders)
149156
.setHeader(FileHeaders.FILENAME, zipFileName)
150157
.build();
151158
}

spring-integration-zip/src/test/java/org/springframework/integration/zip/config/xml/UnZipTransformerParserTests.java

Lines changed: 1 addition & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,5 @@
11
/*
2-
* Copyright 2015-2023 the original author or authors.
2+
* Copyright 2015-2024 the original author or authors.
33
*
44
* Licensed under the Apache License, Version 2.0 (the "License");
55
* you may not use this file except in compliance with the License.
@@ -25,8 +25,6 @@
2525
import org.springframework.context.ConfigurableApplicationContext;
2626
import org.springframework.integration.channel.AbstractMessageChannel;
2727
import org.springframework.integration.endpoint.EventDrivenConsumer;
28-
import org.springframework.integration.file.DefaultFileNameGenerator;
29-
import org.springframework.integration.file.FileNameGenerator;
3028
import org.springframework.integration.test.util.TestUtils;
3129
import org.springframework.integration.transformer.MessageTransformingHandler;
3230
import org.springframework.integration.zip.transformer.UnZipTransformer;
@@ -64,21 +62,18 @@ public void testUnZipTransformerParserWithDefaults() {
6462
final UnZipTransformer unZipTransformer = TestUtils.getPropertyValue(handler, "transformer", UnZipTransformer.class);
6563

6664
final Charset charset = TestUtils.getPropertyValue(unZipTransformer, "charset", Charset.class);
67-
final FileNameGenerator fileNameGenerator = TestUtils.getPropertyValue(unZipTransformer, "fileNameGenerator", FileNameGenerator.class);
6865
final ZipResultType zipResultType = TestUtils.getPropertyValue(unZipTransformer, "zipResultType", ZipResultType.class);
6966
final File workDirectory = TestUtils.getPropertyValue(unZipTransformer, "workDirectory", File.class);
7067
final Boolean deleteFiles = TestUtils.getPropertyValue(unZipTransformer, "deleteFiles", Boolean.class);
7168
final Boolean expectSingleResult = TestUtils.getPropertyValue(unZipTransformer, "expectSingleResult", Boolean.class);
7269

7370
assertThat(charset).isNotNull();
74-
assertThat(fileNameGenerator).isNotNull();
7571
assertThat(zipResultType).isNotNull();
7672
assertThat(workDirectory).isNotNull();
7773
assertThat(deleteFiles).isNotNull();
7874
assertThat(expectSingleResult).isNotNull();
7975

8076
assertThat(charset).isEqualTo(Charset.defaultCharset());
81-
assertThat(fileNameGenerator).isInstanceOf(DefaultFileNameGenerator.class);
8277
assertThat(zipResultType).isEqualTo(ZipResultType.FILE);
8378
assertThat(workDirectory)
8479
.isEqualTo(new File(System.getProperty("java.io.tmpdir") + File.separator + "ziptransformer"));
@@ -102,21 +97,18 @@ public void testUnZipTransformerParserWithExplicitSettings() {
10297
final UnZipTransformer unZipTransformer = TestUtils.getPropertyValue(handler, "transformer", UnZipTransformer.class);
10398

10499
final Charset charset = TestUtils.getPropertyValue(unZipTransformer, "charset", Charset.class);
105-
final FileNameGenerator fileNameGenerator = TestUtils.getPropertyValue(unZipTransformer, "fileNameGenerator", FileNameGenerator.class);
106100
final ZipResultType zipResultType = TestUtils.getPropertyValue(unZipTransformer, "zipResultType", ZipResultType.class);
107101
final File workDirectory = TestUtils.getPropertyValue(unZipTransformer, "workDirectory", File.class);
108102
final Boolean deleteFiles = TestUtils.getPropertyValue(unZipTransformer, "deleteFiles", Boolean.class);
109103
final Boolean expectSingleResult = TestUtils.getPropertyValue(unZipTransformer, "expectSingleResult", Boolean.class);
110104

111105
assertThat(charset).isNotNull();
112-
assertThat(fileNameGenerator).isNotNull();
113106
assertThat(zipResultType).isNotNull();
114107
assertThat(workDirectory).isNotNull();
115108
assertThat(deleteFiles).isNotNull();
116109
assertThat(expectSingleResult).isNotNull();
117110

118111
assertThat(charset).isEqualTo(Charset.defaultCharset());
119-
assertThat(fileNameGenerator).isInstanceOf(DefaultFileNameGenerator.class);
120112
assertThat(zipResultType).isEqualTo(ZipResultType.FILE);
121113
assertThat(workDirectory)
122114
.isEqualTo(new File(System.getProperty("java.io.tmpdir") + File.separator + "ziptransformer"));

src/reference/antora/modules/ROOT/pages/whats-new.adoc

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -78,3 +78,9 @@ See xref:sftp/session-factory.adoc[SFTP Session Factory] for more information.
7878
Multiple instances of `MqttPahoMessageDrivenChannelAdapter` and `Mqttv5PahoMessageDrivenChannelAdapter` can now be added at runtime using corresponding `ClientManager` through `IntegrationFlowContext`
7979
Also a `MqttMessageNotDeliveredEvent` event has been introduced to emit when action callback reacts to the delivery failure.
8080
See xref:mqtt.adoc[MQTT Support] for more information.
81+
82+
[[x6.4-zip-support-changes]]
83+
=== Zip Support Changes
84+
85+
The `ZipTransformer` now exposes a `fileNameGenerator` property to customize a target zip file (and optional zip entry) name generation.
86+
See xref:zip.adoc[Zip Support] for more information.

src/reference/antora/modules/ROOT/pages/zip.adoc

Lines changed: 8 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,14 @@ The `ZipTransformer` can be customized by setting several properties:
6969
Default is `Deflater#DEFAULT_COMPRESSION`.
7070

7171
* `useFileAttributes` - specifies whether the name of the file shall be used for the zip entry.
72+
* `fileNameGenerator` - uses to generate an original file name based on the request message.
73+
Defaults to `DefaultFileNameGenerator`.
74+
The `.zip` extension is added into this name for the target zip file name.
75+
Unless it is already present as a result of this generator.
76+
77+
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.
78+
If not provided, the entry name is exact result of the `fileNameGenerator` and `lastmodified` falls back to the current date and time.
79+
If the payload of request message is an `Iterable`, then this entry name is modified with an index starting `1`.
7280

7381
For example to zip a simple `test.txt` file into a `test.txt.zip`, only this configuration is enough:
7482

0 commit comments

Comments
 (0)