View Javadoc

1   /**
2    * Logback: the reliable, generic, fast and flexible logging framework.
3    * Copyright (C) 1999-2011, QOS.ch. All rights reserved.
4    *
5    * This program and the accompanying materials are dual-licensed under
6    * either the terms of the Eclipse Public License v1.0 as published by
7    * the Eclipse Foundation
8    *
9    *   or (per the licensee's choosing)
10   *
11   * under the terms of the GNU Lesser General Public License version 2.1
12   * as published by the Free Software Foundation.
13   */
14  package ch.qos.logback.core.rolling.helper;
15  
16  import java.io.File;
17  import java.io.FileInputStream;
18  import java.io.FileOutputStream;
19  import java.util.zip.GZIPOutputStream;
20  import java.util.zip.ZipEntry;
21  import java.util.zip.ZipOutputStream;
22  
23  import ch.qos.logback.core.spi.ContextAwareBase;
24  import ch.qos.logback.core.status.ErrorStatus;
25  import ch.qos.logback.core.status.WarnStatus;
26  
27  /**
28   * The <code>Compression</code> class implements ZIP and GZ file
29   * compression/decompression methods.
30   * 
31   * @author Ceki G&uuml;lc&uuml;
32   */
33  public class Compressor extends ContextAwareBase {
34  
35    final CompressionMode compressionMode;
36  
37    public Compressor(CompressionMode compressionMode) {
38      this.compressionMode = compressionMode;
39    }
40  
41      /**
42       *
43       * @param nameOfFile2Compress
44       * @param nameOfCompressedFile
45       * @param innerEntryName The name of the file within the zip file. Use for ZIP compression.
46       */
47    public void compress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) {
48      switch (compressionMode) {
49      case GZ:
50        addInfo("GZ compressing [" + nameOfFile2Compress + "].");
51        gzCompress(nameOfFile2Compress, nameOfCompressedFile);
52        break;
53      case ZIP:
54        addInfo("ZIP compressing [" + nameOfFile2Compress + "].");
55        zipCompress(nameOfFile2Compress, nameOfCompressedFile, innerEntryName);
56        break;
57      case NONE:
58        throw new UnsupportedOperationException(
59            "compress method called in NONE compression mode");
60      }
61    }
62  
63    private void zipCompress(String nameOfFile2zip, String nameOfZippedFile, String innerEntryName) {
64      File file2zip = new File(nameOfFile2zip);
65  
66      if (!file2zip.exists()) {
67        addStatus(new WarnStatus("The file to compress named [" + nameOfFile2zip
68            + "] does not exist.", this));
69  
70        return;
71      }
72  
73      if(innerEntryName == null) {
74        addStatus(new WarnStatus("The innerEntryName parameter cannot be null", this));
75        return;
76      }
77  
78      if (!nameOfZippedFile.endsWith(".zip")) {
79        nameOfZippedFile = nameOfZippedFile + ".zip";
80      }
81  
82      File zippedFile = new File(nameOfZippedFile);
83  
84      if (zippedFile.exists()) {
85        addStatus(new WarnStatus("The target compressed file named ["
86            + nameOfZippedFile + "] exist already.", this));
87  
88        return;
89      }
90  
91      try {
92        FileOutputStream fos = new FileOutputStream(nameOfZippedFile);
93        ZipOutputStream zos = new ZipOutputStream(fos);
94        FileInputStream fis = new FileInputStream(nameOfFile2zip);
95  
96        ZipEntry zipEntry = computeZipEntry(innerEntryName);
97        zos.putNextEntry(zipEntry);
98  
99        byte[] inbuf = new byte[8102];
100       int n;
101 
102       while ((n = fis.read(inbuf)) != -1) {
103         zos.write(inbuf, 0, n);
104       }
105 
106       fis.close();
107       zos.close();
108 
109       if (!file2zip.delete()) {
110         addStatus(new WarnStatus("Could not delete [" + nameOfFile2zip + "].",
111             this));
112       }
113     } catch (Exception e) {
114       addStatus(new ErrorStatus("Error occurred while compressing ["
115           + nameOfFile2zip + "] into [" + nameOfZippedFile + "].", this, e));
116     }
117   }
118 
119   // http://jira.qos.ch/browse/LBCORE-98
120   // The name of the compressed file as nested within the zip archive
121   //
122   // Case 1: RawFile = null, Patern = foo-%d.zip
123   // nestedFilename = foo-${current-date}
124   //
125   // Case 2: RawFile = hello.txt, Pattern = = foo-%d.zip
126   // nestedFilename = foo-${current-date}
127   //
128   // in both cases, the strategy consisting of removing the compression
129   // suffix of zip file works reasonably well. The alternative strategy
130   // whereby the nested file name was based on the value of the raw file name
131   // (applicable to case 2 only) has the disadvantage of the nested files
132   // all having the same name, which could make it harder for the user
133   // to unzip the file without collisions
134   ZipEntry computeZipEntry(File zippedFile) {
135     return computeZipEntry(zippedFile.getName());
136   }
137 
138   ZipEntry computeZipEntry(String filename) {
139     String nameOfFileNestedWithinArchive = computeFileNameStr_WCS(filename, compressionMode);
140     return new ZipEntry(nameOfFileNestedWithinArchive);
141   }
142 
143 
144   private void gzCompress(String nameOfFile2gz, String nameOfgzedFile) {
145     File file2gz = new File(nameOfFile2gz);
146 
147     if (!file2gz.exists()) {
148       addStatus(new WarnStatus("The file to compress named [" + nameOfFile2gz
149           + "] 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       addStatus(new WarnStatus("The target compressed file named ["
162           + nameOfgzedFile + "] exist already.", this));
163 
164       return;
165     }
166 
167     try {
168       FileOutputStream fos = new FileOutputStream(nameOfgzedFile);
169       GZIPOutputStream gzos = new GZIPOutputStream(fos);
170       FileInputStream fis = new FileInputStream(nameOfFile2gz);
171       byte[] inbuf = new byte[8102];
172       int n;
173 
174       while ((n = fis.read(inbuf)) != -1) {
175         gzos.write(inbuf, 0, n);
176       }
177 
178       fis.close();
179       gzos.close();
180 
181       if (!file2gz.delete()) {
182         addStatus(new WarnStatus("Could not delete [" + nameOfFile2gz + "].",
183             this));
184       }
185     } catch (Exception e) {
186       addStatus(new ErrorStatus("Error occurred while compressing ["
187           + nameOfFile2gz + "] into [" + nameOfgzedFile + "].", this, e));
188     }
189   }
190 
191   static public String computeFileNameStr_WCS(String fileNamePatternStr,
192                                               CompressionMode compressionMode) {
193     int len = fileNamePatternStr.length();
194     switch (compressionMode) {
195       case GZ:
196     	  if(fileNamePatternStr.endsWith(".gz")) 
197             return fileNamePatternStr.substring(0, len - 3);
198     	  else 
199     		 return fileNamePatternStr;
200       case ZIP:
201     	  if(fileNamePatternStr.endsWith(".zip")) 
202     	  return fileNamePatternStr.substring(0, len - 4);
203     	  else 
204     		return fileNamePatternStr;	  
205       case NONE:
206         return fileNamePatternStr;
207     }
208     throw new IllegalStateException("Execution should not reach this point");
209   }
210 
211   @Override
212   public String toString() {
213     return "c.q.l.core.rolling.helper.Compress";
214   }
215 
216 }