Compressor.java
/*
* Logback: the reliable, generic, fast and flexible logging framework.
* Copyright (C) 1999-2026, QOS.ch. All rights reserved.
*
* This program and the accompanying materials are dual-licensed under
* either the terms of the Eclipse Public License v2.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.util.concurrent.ExecutorService;
import java.util.concurrent.Future;
import ch.qos.logback.core.rolling.RolloverFailure;
import ch.qos.logback.core.spi.ContextAwareBase;
import ch.qos.logback.core.util.DynamicClassLoadingException;
import ch.qos.logback.core.util.IncompatibleClassException;
import static ch.qos.logback.core.util.OptionHelper.instantiateByClassName;
/**
* The <code>Compression</code> class implements ZIP and GZ file
* compression/decompression methods.
*
* @author Ceki Gülcü
*/
public class Compressor extends ContextAwareBase {
public static final String COULD_NOT_OBTAIN_COMPRESSION_STRATEGY_MESSAGE = "Could not obtain compression strategy";
public static final String XZ_COMPRESSION_STRATEGY_CLASS_NAME = "ch.qos.logback.core.rolling.helper.XZCompressionStrategy";
final CompressionMode compressionMode;
static final int BUFFER_SIZE = 8192;
public Compressor(CompressionMode compressionMode) {
this.compressionMode = compressionMode;
}
/**
* @param originalFileName
* @param compressedFileName
* @param innerEntryName The name of the file within the zip file. Use for
* ZIP compression.
*/
public void compress(String originalFileName, String compressedFileName, String innerEntryName) {
CompressionStrategy compressionStrategy = makeCompressionStrategy(compressionMode);
if (compressionStrategy == null) {
addWarn(COULD_NOT_OBTAIN_COMPRESSION_STRATEGY_MESSAGE);
return;
}
compressionStrategy.setContext(getContext());
compressionStrategy.compress(originalFileName, compressedFileName, innerEntryName);
}
CompressionStrategy makeCompressionStrategy(CompressionMode compressionMode) {
switch (compressionMode) {
case GZ:
return new GZCompressionStrategy();
case ZIP:
return new ZipCompressionStrategy();
case XZ:
return dynamicInstantiation(XZ_COMPRESSION_STRATEGY_CLASS_NAME);
case NONE:
throw new UnsupportedOperationException("compress method called in NONE compression mode");
default:
return null;
}
}
private CompressionStrategy dynamicInstantiation(String className) {
try {
return (CompressionStrategy) instantiateByClassName(className, CompressionStrategy.class, getContext());
} catch (IncompatibleClassException | DynamicClassLoadingException e) {
addError("Could not instantiate " + className, e);
return null;
}
}
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 XZ:
if (fileNamePatternStr.endsWith(".xz"))
return fileNamePatternStr.substring(0, len - 3);
else
return fileNamePatternStr;
case NONE:
return fileNamePatternStr;
}
throw new IllegalStateException("Execution should not reach this point");
}
@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.getExecutorService();
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);
}
}
}