1
|
/**
|
2
|
* Copyright (C) 2017 EDIT
|
3
|
* European Distributed Institute of Taxonomy
|
4
|
* http://www.e-taxonomy.eu
|
5
|
*
|
6
|
* The contents of this file are subject to the Mozilla Public License Version 1.1
|
7
|
* See LICENSE.TXT at the top of this package for the full license terms.
|
8
|
*/
|
9
|
package eu.etaxonomy.cdm.io.common;
|
10
|
|
11
|
import java.io.File;
|
12
|
import java.io.FileOutputStream;
|
13
|
import java.io.IOException;
|
14
|
import java.io.OutputStream;
|
15
|
import java.util.HashMap;
|
16
|
import java.util.Map;
|
17
|
|
18
|
import org.apache.commons.io.output.DeferredFileOutputStream;
|
19
|
import org.apache.tools.zip.ZipEntry;
|
20
|
import org.apache.tools.zip.ZipOutputStream;
|
21
|
|
22
|
/**
|
23
|
* Writing to zip files is not possible in parallel.
|
24
|
* This class buffers streams into the zip file in
|
25
|
* {@link DeferredFileOutputStream}s which store data in
|
26
|
* memory or, if a certain threshold size is exceeded in
|
27
|
* temporary files.
|
28
|
* Calling {@link #close()} will write all data into the
|
29
|
* given defined zip file.
|
30
|
* Each entry offers its own {@link OutputStream} to write
|
31
|
* into in parallel.
|
32
|
*
|
33
|
* @author a.mueller
|
34
|
* @since 29.06.2017
|
35
|
*
|
36
|
*/
|
37
|
public class ZipWriter {
|
38
|
|
39
|
|
40
|
public static final int DEFAULT_THRESHOLD = 2000000;
|
41
|
|
42
|
private int threshold = DEFAULT_THRESHOLD;
|
43
|
|
44
|
private Map<String, DeferredFileOutputStream> entryMap = new HashMap<>();
|
45
|
|
46
|
private File tmpFolder = new File(System.getProperty("java.io.tmpdir"));
|
47
|
|
48
|
private File targetFile;
|
49
|
|
50
|
/**
|
51
|
* {@link ZipWriter} with default values.
|
52
|
*
|
53
|
* @param targetFile final zip file to be filled
|
54
|
*/
|
55
|
|
56
|
public ZipWriter(File targetFile) {
|
57
|
this(targetFile, null, null);
|
58
|
}
|
59
|
|
60
|
/**
|
61
|
* @param targetFile final zip file to be filled
|
62
|
* @param threshold the threshold when to start writing to file,
|
63
|
* uses default (2MB) if <code>null</code>
|
64
|
* @param tmpFolder the folder to write the temporary file to
|
65
|
*/
|
66
|
public ZipWriter(File targetFile, Integer threshold, File tmpFolder) {
|
67
|
super();
|
68
|
this.targetFile = targetFile;
|
69
|
this.threshold = threshold == null ? DEFAULT_THRESHOLD : threshold;
|
70
|
this.tmpFolder = tmpFolder == null ? this.tmpFolder : tmpFolder;
|
71
|
}
|
72
|
|
73
|
|
74
|
|
75
|
public OutputStream getEntryStream(String entryName){
|
76
|
DeferredFileOutputStream result = entryMap.get(entryName);
|
77
|
if (result == null){
|
78
|
result = new DeferredFileOutputStream(threshold, "tmp", "_zip_buffer", tmpFolder);
|
79
|
entryMap.put(entryName, result);
|
80
|
}
|
81
|
return result;
|
82
|
}
|
83
|
|
84
|
public void close() throws IOException{
|
85
|
FileOutputStream fos = new FileOutputStream(targetFile);
|
86
|
ZipOutputStream zos = new ZipOutputStream(fos);
|
87
|
for (String key: entryMap.keySet()){
|
88
|
ZipEntry zipEntry = new ZipEntry(key);
|
89
|
zos.putNextEntry(zipEntry);
|
90
|
DeferredFileOutputStream os = entryMap.get(key);
|
91
|
os.close();
|
92
|
// zos.setComment(comment);
|
93
|
os.writeTo(zos);
|
94
|
zos.closeEntry();
|
95
|
}
|
96
|
try {
|
97
|
zos.finish();
|
98
|
zos.close();
|
99
|
} catch (IOException e) {
|
100
|
throw e;
|
101
|
}
|
102
|
for (String key: entryMap.keySet()){
|
103
|
DeferredFileOutputStream os = entryMap.get(key);
|
104
|
cleanupFile(os);
|
105
|
}
|
106
|
}
|
107
|
|
108
|
/**
|
109
|
* @param os
|
110
|
*/
|
111
|
private boolean cleanupFile(DeferredFileOutputStream os) {
|
112
|
try {
|
113
|
boolean deleted = true;
|
114
|
File file = os.getFile();
|
115
|
if (file != null){
|
116
|
deleted = file.delete();
|
117
|
}
|
118
|
return deleted;
|
119
|
} catch (Exception e) {
|
120
|
//no matter, it should be in temp folder
|
121
|
e.printStackTrace();
|
122
|
return false;
|
123
|
}
|
124
|
}
|
125
|
|
126
|
}
|