1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.rolling.helper;
15
16 import java.io.BufferedInputStream;
17 import java.io.File;
18 import java.io.FileInputStream;
19 import java.io.FileOutputStream;
20 import java.util.concurrent.ExecutorService;
21 import java.util.concurrent.Future;
22 import java.util.zip.GZIPOutputStream;
23 import java.util.zip.ZipEntry;
24 import java.util.zip.ZipOutputStream;
25
26 import ch.qos.logback.core.rolling.RolloverFailure;
27 import ch.qos.logback.core.spi.ContextAwareBase;
28 import ch.qos.logback.core.status.ErrorStatus;
29 import ch.qos.logback.core.status.WarnStatus;
30 import ch.qos.logback.core.util.FileUtil;
31
32
33
34
35
36
37
38 public class Compressor extends ContextAwareBase {
39
40 final CompressionMode compressionMode;
41
42 static final int BUFFER_SIZE = 8192;
43
44 public Compressor(CompressionMode compressionMode) {
45 this.compressionMode = compressionMode;
46 }
47
48
49
50
51
52
53
54 public void compress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) {
55 switch (compressionMode) {
56 case GZ:
57 gzCompress(nameOfFile2Compress, nameOfCompressedFile);
58 break;
59 case ZIP:
60 zipCompress(nameOfFile2Compress, nameOfCompressedFile, innerEntryName);
61 break;
62 case NONE:
63 throw new UnsupportedOperationException("compress method called in NONE compression mode");
64 }
65 }
66
67 private void zipCompress(String nameOfFile2zip, String nameOfZippedFile, String innerEntryName) {
68 File file2zip = new File(nameOfFile2zip);
69
70 if (!file2zip.exists()) {
71 addStatus(new WarnStatus("The file to compress named [" + nameOfFile2zip + "] does not exist.", this));
72
73 return;
74 }
75
76 if (innerEntryName == null) {
77 addStatus(new WarnStatus("The innerEntryName parameter cannot be null", this));
78 return;
79 }
80
81 if (!nameOfZippedFile.endsWith(".zip")) {
82 nameOfZippedFile = nameOfZippedFile + ".zip";
83 }
84
85 File zippedFile = new File(nameOfZippedFile);
86
87 if (zippedFile.exists()) {
88 addStatus(
89 new WarnStatus("The target compressed file named [" + nameOfZippedFile + "] exist already.", this));
90
91 return;
92 }
93
94 addInfo("ZIP compressing [" + file2zip + "] as [" + zippedFile + "]");
95 createMissingTargetDirsIfNecessary(zippedFile);
96
97 try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(nameOfFile2zip));
98 ZipOutputStream zos = new ZipOutputStream(new FileOutputStream(nameOfZippedFile))) {
99
100 ZipEntry zipEntry = computeZipEntry(innerEntryName);
101 zos.putNextEntry(zipEntry);
102
103 byte[] inbuf = new byte[BUFFER_SIZE];
104 int n;
105
106 while ((n = bis.read(inbuf)) != -1) {
107 zos.write(inbuf, 0, n);
108 }
109
110 addInfo("Done ZIP compressing [" + file2zip + "] as [" + zippedFile + "]");
111 } catch (Exception e) {
112 addStatus(new ErrorStatus(
113 "Error occurred while compressing [" + nameOfFile2zip + "] into [" + nameOfZippedFile + "].", this,
114 e));
115 }
116 if (!file2zip.delete()) {
117 addStatus(new WarnStatus("Could not delete [" + nameOfFile2zip + "].", this));
118 }
119 }
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136 ZipEntry computeZipEntry(File zippedFile) {
137 return computeZipEntry(zippedFile.getName());
138 }
139
140 ZipEntry computeZipEntry(String filename) {
141 String nameOfFileNestedWithinArchive = computeFileNameStrWithoutCompSuffix(filename, compressionMode);
142 return new ZipEntry(nameOfFileNestedWithinArchive);
143 }
144
145 private void gzCompress(String nameOfFile2gz, String nameOfgzedFile) {
146 File file2gz = new File(nameOfFile2gz);
147
148 if (!file2gz.exists()) {
149 addStatus(new WarnStatus("The file to compress named [" + nameOfFile2gz + "] does not exist.", this));
150
151 return;
152 }
153
154 if (!nameOfgzedFile.endsWith(".gz")) {
155 nameOfgzedFile = nameOfgzedFile + ".gz";
156 }
157
158 File gzedFile = new File(nameOfgzedFile);
159
160 if (gzedFile.exists()) {
161 addWarn("The target compressed file named [" + nameOfgzedFile
162 + "] exist already. Aborting file compression.");
163 return;
164 }
165
166 addInfo("GZ compressing [" + file2gz + "] as [" + gzedFile + "]");
167 createMissingTargetDirsIfNecessary(gzedFile);
168
169 try (BufferedInputStream bis = new BufferedInputStream(new FileInputStream(nameOfFile2gz));
170 GZIPOutputStream gzos = new GZIPOutputStream(new FileOutputStream(nameOfgzedFile))) {
171
172 byte[] inbuf = new byte[BUFFER_SIZE];
173 int n;
174
175 while ((n = bis.read(inbuf)) != -1) {
176 gzos.write(inbuf, 0, n);
177 }
178
179 addInfo("Done GZ compressing [" + file2gz + "] as [" + gzedFile + "]");
180 } catch (Exception e) {
181 addStatus(new ErrorStatus(
182 "Error occurred while compressing [" + nameOfFile2gz + "] into [" + nameOfgzedFile + "].", this,
183 e));
184 }
185
186 if (!file2gz.delete()) {
187 addStatus(new WarnStatus("Could not delete [" + nameOfFile2gz + "].", this));
188 }
189
190 }
191
192 static public String computeFileNameStrWithoutCompSuffix(String fileNamePatternStr,
193 CompressionMode compressionMode) {
194 int len = fileNamePatternStr.length();
195 switch (compressionMode) {
196 case GZ:
197 if (fileNamePatternStr.endsWith(".gz"))
198 return fileNamePatternStr.substring(0, len - 3);
199 else
200 return fileNamePatternStr;
201 case ZIP:
202 if (fileNamePatternStr.endsWith(".zip"))
203 return fileNamePatternStr.substring(0, len - 4);
204 else
205 return fileNamePatternStr;
206 case NONE:
207 return fileNamePatternStr;
208 }
209 throw new IllegalStateException("Execution should not reach this point");
210 }
211
212 void createMissingTargetDirsIfNecessary(File file) {
213 boolean result = FileUtil.createMissingParentDirectories(file);
214 if (!result) {
215 addError("Failed to create parent directories for [" + file.getAbsolutePath() + "]");
216 }
217 }
218
219 @Override
220 public String toString() {
221 return this.getClass().getName();
222 }
223
224 public Future<?> asyncCompress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName)
225 throws RolloverFailure {
226 CompressionRunnable runnable = new CompressionRunnable(nameOfFile2Compress, nameOfCompressedFile,
227 innerEntryName);
228 ExecutorService executorService = context.getExecutorService();
229 Future<?> future = executorService.submit(runnable);
230 return future;
231 }
232
233 class CompressionRunnable implements Runnable {
234 final String nameOfFile2Compress;
235 final String nameOfCompressedFile;
236 final String innerEntryName;
237
238 public CompressionRunnable(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) {
239 this.nameOfFile2Compress = nameOfFile2Compress;
240 this.nameOfCompressedFile = nameOfCompressedFile;
241 this.innerEntryName = innerEntryName;
242 }
243
244 public void run() {
245
246 Compressor.this.compress(nameOfFile2Compress, nameOfCompressedFile, innerEntryName);
247 }
248 }
249
250 }