001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.rolling.helper; 015 016import java.util.concurrent.ExecutorService; 017import java.util.concurrent.Future; 018 019import ch.qos.logback.core.rolling.RolloverFailure; 020import ch.qos.logback.core.spi.ContextAwareBase; 021import ch.qos.logback.core.util.DynamicClassLoadingException; 022import ch.qos.logback.core.util.IncompatibleClassException; 023 024import static ch.qos.logback.core.util.OptionHelper.instantiateByClassName; 025 026/** 027 * The <code>Compression</code> class implements ZIP and GZ file 028 * compression/decompression methods. 029 * 030 * @author Ceki Gülcü 031 */ 032public class Compressor extends ContextAwareBase { 033 034 public static final String COULD_NOT_OBTAIN_COMPRESSION_STRATEGY_MESSAGE = "Could not obtain compression strategy"; 035 public static final String XZ_COMPRESSION_STRATEGY_CLASS_NAME = "ch.qos.logback.core.rolling.helper.XZCompressionStrategy"; 036 037 final CompressionMode compressionMode; 038 039 static final int BUFFER_SIZE = 8192; 040 041 public Compressor(CompressionMode compressionMode) { 042 this.compressionMode = compressionMode; 043 } 044 045 /** 046 * @param originalFileName 047 * @param compressedFileName 048 * @param innerEntryName The name of the file within the zip file. Use for 049 * ZIP compression. 050 */ 051 public void compress(String originalFileName, String compressedFileName, String innerEntryName) { 052 CompressionStrategy compressionStrategy = makeCompressionStrategy(compressionMode); 053 if (compressionStrategy == null) { 054 addWarn(COULD_NOT_OBTAIN_COMPRESSION_STRATEGY_MESSAGE); 055 return; 056 } 057 compressionStrategy.setContext(getContext()); 058 compressionStrategy.compress(originalFileName, compressedFileName, innerEntryName); 059 } 060 061 CompressionStrategy makeCompressionStrategy(CompressionMode compressionMode) { 062 switch (compressionMode) { 063 case GZ: 064 return new GZCompressionStrategy(); 065 case ZIP: 066 return new ZipCompressionStrategy(); 067 case XZ: 068 return dynamicInstantiation(XZ_COMPRESSION_STRATEGY_CLASS_NAME); 069 case NONE: 070 throw new UnsupportedOperationException("compress method called in NONE compression mode"); 071 default: 072 return null; 073 } 074 } 075 076 private CompressionStrategy dynamicInstantiation(String className) { 077 try { 078 return (CompressionStrategy) instantiateByClassName(className, CompressionStrategy.class, getContext()); 079 } catch (IncompatibleClassException | DynamicClassLoadingException e) { 080 addError("Could not instantiate " + className, e); 081 return null; 082 } 083 } 084 085 static public String computeFileNameStrWithoutCompSuffix(String fileNamePatternStr, CompressionMode compressionMode) { 086 int len = fileNamePatternStr.length(); 087 switch (compressionMode) { 088 case GZ: 089 if (fileNamePatternStr.endsWith(".gz")) 090 return fileNamePatternStr.substring(0, len - 3); 091 else 092 return fileNamePatternStr; 093 case ZIP: 094 if (fileNamePatternStr.endsWith(".zip")) 095 return fileNamePatternStr.substring(0, len - 4); 096 else 097 return fileNamePatternStr; 098 case XZ: 099 if (fileNamePatternStr.endsWith(".xz")) 100 return fileNamePatternStr.substring(0, len - 3); 101 else 102 return fileNamePatternStr; 103 case NONE: 104 return fileNamePatternStr; 105 } 106 throw new IllegalStateException("Execution should not reach this point"); 107 } 108 109 @Override 110 public String toString() { 111 return this.getClass().getName(); 112 } 113 114 public Future<?> asyncCompress(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) throws RolloverFailure { 115 CompressionRunnable runnable = new CompressionRunnable(nameOfFile2Compress, nameOfCompressedFile, innerEntryName); 116 ExecutorService executorService = context.getExecutorService(); 117 Future<?> future = executorService.submit(runnable); 118 return future; 119 } 120 121 class CompressionRunnable implements Runnable { 122 final String nameOfFile2Compress; 123 final String nameOfCompressedFile; 124 final String innerEntryName; 125 126 public CompressionRunnable(String nameOfFile2Compress, String nameOfCompressedFile, String innerEntryName) { 127 this.nameOfFile2Compress = nameOfFile2Compress; 128 this.nameOfCompressedFile = nameOfCompressedFile; 129 this.innerEntryName = innerEntryName; 130 } 131 132 public void run() { 133 134 Compressor.this.compress(nameOfFile2Compress, nameOfCompressedFile, innerEntryName); 135 } 136 } 137 138}