Logback: the reliable, generic, fast and flexible logging framework. Copyright (C) 1999-2015, QOS.ch. All rights reserved. This program and the accompanying materials are dual-licensed under either the terms of the Eclipse Public License v1.0 as published by the Eclipse Foundation or (per the licensee's choosing) under the terms of the GNU Lesser General Public License version 2.1 as published by the Free Software Foundation.
/** * Logback: the reliable, generic, fast and flexible logging framework. * Copyright (C) 1999-2015, QOS.ch. All rights reserved. * * This program and the accompanying materials are dual-licensed under * either the terms of the Eclipse Public License v1.0 as published by * the Eclipse Foundation * * or (per the licensee's choosing) * * under the terms of the GNU Lesser General Public License version 2.1 * as published by the Free Software Foundation. */
package ch.qos.logback.core.rolling.helper; import java.io.BufferedInputStream; import java.io.File; import java.io.FileInputStream; import java.io.FileOutputStream; import java.io.IOException; import java.util.concurrent.ExecutorService; import java.util.concurrent.Future; import java.util.zip.GZIPOutputStream; import java.util.zip.ZipEntry; import java.util.zip.ZipOutputStream; import ch.qos.logback.core.rolling.RolloverFailure; import ch.qos.logback.core.spi.ContextAwareBase; import ch.qos.logback.core.status.ErrorStatus; import ch.qos.logback.core.status.WarnStatus; import ch.qos.logback.core.util.FileUtil;
The Compression class implements ZIP and GZ file compression/decompression methods.
Author:Ceki Gülcü
/** * The <code>Compression</code> class implements ZIP and GZ file * compression/decompression methods. * * @author Ceki G&uuml;lc&uuml; */
public class Compressor extends ContextAwareBase { final CompressionMode compressionMode; static final int BUFFER_SIZE = 8192; public Compressor(CompressionMode compressionMode) { this.compressionMode = compressionMode; }
Params:
  • nameOfFile2Compress –
  • nameOfCompressedFile –
  • innerEntryName – The name of the file within the zip file. Use for ZIP compression.
/** * @param nameOfFile2Compress * @param nameOfCompressedFile * @param innerEntryName * The name of the file within the zip file. Use for ZIP compression. */
public void compress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) { switch (compressionMode) { case GZ: gzCompress(nameOfFile2Compress, nameOfCompressedFile); break; case ZIP: zipCompress(nameOfFile2Compress, nameOfCompressedFile, innerEntryName); break; case NONE: throw new UnsupportedOperationException("compress method called in NONE compression mode"); } } private void zipCompress(String nameOfFile2zip, String nameOfZippedFile, String innerEntryName) { File file2zip = new File(nameOfFile2zip); if (!file2zip.exists()) { addStatus(new WarnStatus("The file to compress named [" + nameOfFile2zip + "] does not exist.", this)); return; } if (innerEntryName == null) { addStatus(new WarnStatus("The innerEntryName parameter cannot be null", this)); return; } if (!nameOfZippedFile.endsWith(".zip")) { nameOfZippedFile = nameOfZippedFile + ".zip"; } File zippedFile = new File(nameOfZippedFile); if (zippedFile.exists()) { addStatus(new WarnStatus("The target compressed file named [" + nameOfZippedFile + "] exist already.", this)); return; } addInfo("ZIP compressing [" + file2zip + "] as [" + zippedFile + "]"); createMissingTargetDirsIfNecessary(zippedFile); BufferedInputStream bis = null; ZipOutputStream zos = null; try { bis = new BufferedInputStream(new FileInputStream(nameOfFile2zip)); zos = new ZipOutputStream(new FileOutputStream(nameOfZippedFile)); ZipEntry zipEntry = computeZipEntry(innerEntryName); zos.putNextEntry(zipEntry); byte[] inbuf = new byte[BUFFER_SIZE]; int n; while ((n = bis.read(inbuf)) != -1) { zos.write(inbuf, 0, n); } bis.close(); bis = null; zos.close(); zos = null; if (!file2zip.delete()) { addStatus(new WarnStatus("Could not delete [" + nameOfFile2zip + "].", this)); } } catch (Exception e) { addStatus(new ErrorStatus("Error occurred while compressing [" + nameOfFile2zip + "] into [" + nameOfZippedFile + "].", this, e)); } finally { if (bis != null) { try { bis.close(); } catch (IOException e) { // ignore } } if (zos != null) { try { zos.close(); } catch (IOException e) { // ignore } } } } // http://jira.qos.ch/browse/LBCORE-98 // The name of the compressed file as nested within the zip archive // // Case 1: RawFile = null, Patern = foo-%d.zip // nestedFilename = foo-${current-date} // // Case 2: RawFile = hello.txt, Pattern = = foo-%d.zip // nestedFilename = foo-${current-date} // // in both cases, the strategy consisting of removing the compression // suffix of zip file works reasonably well. The alternative strategy // whereby the nested file name was based on the value of the raw file name // (applicable to case 2 only) has the disadvantage of the nested files // all having the same name, which could make it harder for the user // to unzip the file without collisions ZipEntry computeZipEntry(File zippedFile) { return computeZipEntry(zippedFile.getName()); } ZipEntry computeZipEntry(String filename) { String nameOfFileNestedWithinArchive = computeFileNameStrWithoutCompSuffix(filename, compressionMode); return new ZipEntry(nameOfFileNestedWithinArchive); } private void gzCompress(String nameOfFile2gz, String nameOfgzedFile) { File file2gz = new File(nameOfFile2gz); if (!file2gz.exists()) { addStatus(new WarnStatus("The file to compress named [" + nameOfFile2gz + "] does not exist.", this)); return; } if (!nameOfgzedFile.endsWith(".gz")) { nameOfgzedFile = nameOfgzedFile + ".gz"; } File gzedFile = new File(nameOfgzedFile); if (gzedFile.exists()) { addWarn("The target compressed file named [" + nameOfgzedFile + "] exist already. Aborting file compression."); return; } addInfo("GZ compressing [" + file2gz + "] as [" + gzedFile + "]"); createMissingTargetDirsIfNecessary(gzedFile); BufferedInputStream bis = null; GZIPOutputStream gzos = null; try { bis = new BufferedInputStream(new FileInputStream(nameOfFile2gz)); gzos = new GZIPOutputStream(new FileOutputStream(nameOfgzedFile)); byte[] inbuf = new byte[BUFFER_SIZE]; int n; while ((n = bis.read(inbuf)) != -1) { gzos.write(inbuf, 0, n); } bis.close(); bis = null; gzos.close(); gzos = null; if (!file2gz.delete()) { addStatus(new WarnStatus("Could not delete [" + nameOfFile2gz + "].", this)); } } catch (Exception e) { addStatus(new ErrorStatus("Error occurred while compressing [" + nameOfFile2gz + "] into [" + nameOfgzedFile + "].", this, e)); } finally { if (bis != null) { try { bis.close(); } catch (IOException e) { // ignore } } if (gzos != null) { try { gzos.close(); } catch (IOException e) { // ignore } } } } static public String computeFileNameStrWithoutCompSuffix(String fileNamePatternStr, CompressionMode compressionMode) { int len = fileNamePatternStr.length(); switch (compressionMode) { case GZ: if (fileNamePatternStr.endsWith(".gz")) return fileNamePatternStr.substring(0, len - 3); else return fileNamePatternStr; case ZIP: if (fileNamePatternStr.endsWith(".zip")) return fileNamePatternStr.substring(0, len - 4); else return fileNamePatternStr; case NONE: return fileNamePatternStr; } throw new IllegalStateException("Execution should not reach this point"); } void createMissingTargetDirsIfNecessary(File file) { boolean result = FileUtil.createMissingParentDirectories(file); if (!result) { addError("Failed to create parent directories for [" + file.getAbsolutePath() + "]"); } } @Override public String toString() { return this.getClass().getName(); } public Future<?> asyncCompress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) throws RolloverFailure { CompressionRunnable runnable = new CompressionRunnable(nameOfFile2Compress, nameOfCompressedFile, innerEntryName); ExecutorService executorService = context.getScheduledExecutorService(); Future<?> future = executorService.submit(runnable); return future; } class CompressionRunnable implements Runnable { final String nameOfFile2Compress; final String nameOfCompressedFile; final String innerEntryName; public CompressionRunnable(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) { this.nameOfFile2Compress = nameOfFile2Compress; this.nameOfCompressedFile = nameOfCompressedFile; this.innerEntryName = innerEntryName; } public void run() { Compressor.this.compress(nameOfFile2Compress, nameOfCompressedFile, innerEntryName); } } }