1 package fr.ifremer.quadrige3.core.dao.technical;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26 import com.google.common.collect.ImmutableList;
27 import fr.ifremer.quadrige3.core.ProgressionCoreModel;
28 import org.apache.commons.io.FileUtils;
29 import org.apache.commons.io.FilenameUtils;
30 import org.apache.commons.lang3.StringUtils;
31
32 import java.io.File;
33 import java.io.IOException;
34 import java.io.InputStream;
35 import java.io.OutputStream;
36 import java.nio.charset.Charset;
37 import java.nio.file.Path;
38 import java.util.*;
39 import java.util.zip.ZipEntry;
40 import java.util.zip.ZipFile;
41 import java.util.zip.ZipOutputStream;
42
43
44
45
46 public class ZipUtils {
47
48 public static List<String> COMPRESSED_EXTENSION_LIST;
49
50 static {
51 COMPRESSED_EXTENSION_LIST = new ArrayList<>();
52 COMPRESSED_EXTENSION_LIST.addAll(Images.AVAILABLE_EXTENSION_LIST);
53
54 COMPRESSED_EXTENSION_LIST.addAll(ImmutableList.of("zip", "7z", "rar"));
55 }
56
57
58
59
60 protected ZipUtils() {
61
62 }
63
64 public static boolean isZipFile(File file) {
65 boolean result = false;
66 try {
67 ZipFile zipFile = new ZipFile(file);
68 zipFile.close();
69 result = true;
70 } catch (IOException ignored) {
71 }
72 return result;
73 }
74
75 public static ZipFile open(Path file) throws IOException {
76 if (!isZipFile(file.toFile()))
77 throw new IOException("this file is not a zip archive : " + file);
78
79
80 return new ZipFile(file.toFile(), Charset.forName("IBM437"));
81 }
82
83 public static List<? extends ZipEntry> getEntries(Path file) throws IOException {
84 try (ZipFile zipFile = open(file)) {
85 return Collections.list(zipFile.entries());
86 }
87 }
88
89 public static void compressFilesInPath(Path source, Path target, boolean deleteAfterCompress) throws IOException {
90 compressFilesInPath(source, target, null, deleteAfterCompress, false);
91 }
92
93 public static void compressFilesInPath(Path source, Path target, ProgressionCoreModel progressionModel, boolean deleteAfterCompress) throws IOException {
94 compressFilesInPath(source, target, progressionModel, deleteAfterCompress, false);
95 }
96
97 public static void compressFilesInPath(Path source, Path target, ProgressionCoreModel progressionModel, boolean deleteAfterCompress, boolean includeRoot) throws IOException {
98 Assert.notNull(source);
99 Assert.isTrue(java.nio.file.Files.isDirectory(source), "source must be a directory");
100 Assert.notNull(target);
101 java.nio.file.Files.createDirectories(target.getParent());
102
103 if (progressionModel != null) {
104 progressionModel.adaptTotal(Files.getSize(source));
105 }
106
107 try (ZipOutputStream outputStream = new ZipOutputStream(java.nio.file.Files.newOutputStream(target))) {
108
109 outputStream.setLevel(1);
110 compressDirectory(includeRoot ? source.getParent() : source, source, target, outputStream, progressionModel, deleteAfterCompress);
111 outputStream.finish();
112 }
113 }
114
115 public static void uncompressFileToPath(Path compressedFile, Path destDir, boolean deleteAfterUncompress) throws IOException {
116 uncompressFileToPath(compressedFile, destDir, null, deleteAfterUncompress);
117 }
118
119 public static void uncompressFileToPath(Path compressedFile, Path destDir, ProgressionCoreModel progressionModel, boolean deleteAfterUncompress) throws IOException {
120 uncompressFileToPath(compressedFile, destDir, null, progressionModel, deleteAfterUncompress);
121 }
122
123 public static void uncompressFileToPath(Path compressedFile, Path destDir, String rootDirName, ProgressionCoreModel progressionModel, boolean deleteAfterUncompress) throws IOException {
124 Assert.notNull(compressedFile, "compressed file is null");
125 Assert.notNull(destDir, "destination directory is null");
126 Assert.isTrue(java.nio.file.Files.exists(compressedFile), "compressed file must exists");
127 Assert.isTrue(java.nio.file.Files.isRegularFile(compressedFile), "compressed file must be a regular file");
128 if (progressionModel != null) {
129 progressionModel.adaptTotal(Files.getSize(compressedFile));
130 }
131 rootDirName = StringUtils.appendIfMissing(rootDirName, "/");
132
133 try (ZipFile zipFile = open(compressedFile)) {
134 Enumeration<? extends ZipEntry> entries = zipFile.entries();
135 while (entries.hasMoreElements()) {
136 ZipEntry zipEntry = entries.nextElement();
137 if (rootDirName != null && !zipEntry.getName().startsWith(rootDirName))
138 continue;
139 Path destFile = destDir.resolve(StringUtils.removeStartIgnoreCase(zipEntry.getName(), rootDirName));
140 if (zipEntry.isDirectory()) {
141 java.nio.file.Files.createDirectories(destFile);
142 } else {
143 java.nio.file.Files.createDirectories(destFile.getParent());
144 try (InputStream in = zipFile.getInputStream(zipEntry);
145 OutputStream out = java.nio.file.Files.newOutputStream(destFile)) {
146 Files.copyStream(in, out, progressionModel);
147 }
148 }
149 }
150 }
151 if (deleteAfterUncompress) {
152 java.nio.file.Files.delete(compressedFile);
153 }
154 }
155
156
157
158 private static void compressDirectory(Path rootSource, Path source, Path target,
159 ZipOutputStream zipOutputStream,
160 ProgressionCoreModel progressionModel,
161 boolean deleteAfterCompress) throws IOException {
162
163 List<Path> sourceContent = Files.getDirectoryContent(source);
164 for (Path path : Objects.requireNonNull(sourceContent)) {
165 if (path.equals(target)) {
166 continue;
167 }
168 if (java.nio.file.Files.isDirectory(path)) {
169 String zipEntryName = toZipEntryName(rootSource, path);
170 zipOutputStream.putNextEntry(new ZipEntry(zipEntryName));
171 compressDirectory(rootSource, path, target, zipOutputStream, progressionModel, deleteAfterCompress);
172 zipOutputStream.closeEntry();
173 if (deleteAfterCompress) {
174 java.nio.file.Files.delete(path);
175 }
176 continue;
177 }
178 try (InputStream in = java.nio.file.Files.newInputStream(path)) {
179 String zipEntryName = toZipEntryName(rootSource, path);
180 ZipEntry zipEntry = new ZipEntry(zipEntryName);
181 if (FilenameUtils.isExtension(path.getFileName().toString(), COMPRESSED_EXTENSION_LIST)) {
182 zipEntry.setMethod(ZipEntry.STORED);
183 zipEntry.setSize(java.nio.file.Files.size(path));
184 zipEntry.setCrc(FileUtils.checksumCRC32(path.toFile()));
185 }
186 zipOutputStream.putNextEntry(zipEntry);
187 Files.copyStream(in, zipOutputStream, progressionModel);
188 zipOutputStream.closeEntry();
189 }
190 if (deleteAfterCompress) {
191 java.nio.file.Files.delete(path);
192 }
193 }
194 }
195
196 private static String toZipEntryName(Path root, Path file) {
197 String result = file.toString();
198 if (root != null) {
199 String rootPath = root.toString();
200 if (result.startsWith(rootPath)) {
201 result = result.substring(rootPath.length());
202 }
203 }
204
205 result = result.replace('\\', '/');
206 if (java.nio.file.Files.isDirectory(file)) {
207 result = result + '/';
208 }
209
210 while (result.startsWith("/")) {
211 result = result.substring(1);
212 }
213
214 return result;
215 }
216
217 }