Skip to content

Commit f54ab16

Browse files
committed
If compression mode is XZ but the XZ library is missing, then fallback to GZ compression.
Signed-off-by: Ceki Gulcu <[email protected]>
1 parent fb45971 commit f54ab16

File tree

7 files changed

+64
-42
lines changed

7 files changed

+64
-42
lines changed

logback-core/src/main/java/ch/qos/logback/core/rolling/FixedWindowRollingPolicy.java

+2-1
Original file line numberDiff line numberDiff line change
@@ -55,8 +55,9 @@ public void start() {
5555
util.setContext(this.context);
5656

5757
if (fileNamePatternStr != null) {
58-
fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context);
5958
determineCompressionMode();
59+
adjustCompressionModeAndFileNamePatternStrIfNecessary();
60+
fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context);
6061
} else {
6162
addError(FNP_NOT_SET);
6263
addError(CoreConstants.SEE_FNP_NOT_SET);

logback-core/src/main/java/ch/qos/logback/core/rolling/RollingPolicyBase.java

+33-7
Original file line numberDiff line numberDiff line change
@@ -18,10 +18,12 @@
1818
import ch.qos.logback.core.rolling.helper.FileNamePattern;
1919
import ch.qos.logback.core.spi.ContextAwareBase;
2020

21+
import static ch.qos.logback.core.util.Loader.isClassLoadable;
22+
2123
/**
2224
* Implements methods common to most, it not all, rolling policies. Currently
2325
* such methods are limited to a compression mode getter/setter.
24-
*
26+
*
2527
* @author Ceki G&uuml;lc&uuml;
2628
*/
2729
public abstract class RollingPolicyBase extends ContextAwareBase implements RollingPolicy {
@@ -40,18 +42,18 @@ public abstract class RollingPolicyBase extends ContextAwareBase implements Roll
4042
/**
4143
* Given the FileNamePattern string, this method determines the compression mode
4244
* depending on last letters of the fileNamePatternStr. Patterns ending with .gz
43-
* imply GZIP compression, endings with '.zip' imply ZIP compression. Otherwise
44-
* and by default, there is no compression.
45-
*
45+
* imply GZIP compression, endings with '.zip' imply ZIP compression, endings with
46+
* .xz imply XZ compression. Otherwise and by default, there is no compression.
47+
*
4648
*/
4749
protected void determineCompressionMode() {
48-
if (fileNamePatternStr.endsWith(".gz")) {
50+
if (fileNamePatternStr.endsWith(CompressionMode.GZ_SUFFIX)) {
4951
addInfo("Will use gz compression");
5052
compressionMode = CompressionMode.GZ;
51-
} else if (fileNamePatternStr.endsWith(".zip")) {
53+
} else if (fileNamePatternStr.endsWith(CompressionMode.ZIP_SUFFIX)) {
5254
addInfo("Will use zip compression");
5355
compressionMode = CompressionMode.ZIP;
54-
} else if (fileNamePatternStr.endsWith(".xz")) {
56+
} else if (fileNamePatternStr.endsWith(CompressionMode.XZ_SUFFIX)) {
5557
addInfo("Will use xz compression");
5658
compressionMode = CompressionMode.XZ;
5759
} else {
@@ -60,6 +62,30 @@ protected void determineCompressionMode() {
6062
}
6163
}
6264

65+
/**
66+
* If compression mode is XZ but the XZ librarey is missing, then fallback to GZ compresison.
67+
*/
68+
protected void adjustCompressionModeAndFileNamePatternStrIfNecessary() {
69+
if (compressionMode == compressionMode.XZ) {
70+
boolean xzLibraryLoadable = isClassLoadable("org.tukaani.xz.XZOutputStream", getContext());
71+
if (!xzLibraryLoadable) {
72+
addWarn("XZ library missing, falling back to GZ compression");
73+
compressionMode = CompressionMode.GZ;
74+
fileNamePatternStr = replaceSuffix(fileNamePatternStr, CompressionMode.XZ_SUFFIX, CompressionMode.GZ_SUFFIX);
75+
}
76+
}
77+
}
78+
79+
private String replaceSuffix(String input, String existingSuffix, String newSuffix) {
80+
int existingSuffixLen = existingSuffix.length();
81+
if (input.endsWith(existingSuffix)) {
82+
return input.substring(0, input.length() - existingSuffixLen) + newSuffix;
83+
} else {
84+
// unreachable code
85+
throw new IllegalArgumentException("[" + input + "] should end with "+existingSuffix);
86+
}
87+
}
88+
6389
public void setFileNamePattern(String fnp) {
6490
fileNamePatternStr = fnp;
6591
}

logback-core/src/main/java/ch/qos/logback/core/rolling/TimeBasedRollingPolicy.java

+2-2
Original file line numberDiff line numberDiff line change
@@ -18,7 +18,6 @@
1818

1919
import java.io.File;
2020
import java.time.Instant;
21-
import java.util.Date;
2221
import java.util.concurrent.Future;
2322
import java.util.concurrent.TimeUnit;
2423
import java.util.concurrent.TimeoutException;
@@ -68,8 +67,9 @@ public void start() {
6867

6968
// find out period from the filename pattern
7069
if (fileNamePatternStr != null) {
71-
fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context);
7270
determineCompressionMode();
71+
adjustCompressionModeAndFileNamePatternStrIfNecessary();
72+
fileNamePattern = new FileNamePattern(fileNamePatternStr, this.context);
7373
} else {
7474
addWarn(FNP_NOT_SET);
7575
addWarn(CoreConstants.SEE_FNP_NOT_SET);

logback-core/src/main/java/ch/qos/logback/core/rolling/helper/CompressionMode.java

+7
Original file line numberDiff line numberDiff line change
@@ -15,4 +15,11 @@
1515

1616
public enum CompressionMode {
1717
NONE, GZ, ZIP, XZ;
18+
19+
static public String GZ_SUFFIX = ".gz";
20+
static public String XZ_SUFFIX = ".xz";
21+
static public String ZIP_SUFFIX = ".zip";
22+
23+
24+
1825
}

logback-core/src/main/java/ch/qos/logback/core/rolling/helper/Compressor.java

+1-1
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,7 @@
3232
public class Compressor extends ContextAwareBase {
3333

3434
public static final String COULD_NOT_OBTAIN_COMPRESSION_STRATEGY_MESSAGE = "Could not obtain compression strategy";
35-
static String XZ_COMPRESSION_STRATEGY_CLASS_NAME = "ch.qos.logback.core.rolling.helper.XZCompressionStrategy";
35+
public static final String XZ_COMPRESSION_STRATEGY_CLASS_NAME = "ch.qos.logback.core.rolling.helper.XZCompressionStrategy";
3636

3737
final CompressionMode compressionMode;
3838

logback-core/src/main/java/ch/qos/logback/core/rolling/helper/TimeBasedArchiveRemover.java

+6-5
Original file line numberDiff line numberDiff line change
@@ -68,7 +68,7 @@ public void clean(Instant now) {
6868
lastHeartBeat = nowInMillis;
6969
if (periodsElapsed > 1) {
7070
addInfo("Multiple periods, i.e. " + periodsElapsed
71-
+ " periods, seem to have elapsed. This is expected at application start.");
71+
+ " periods, seem to have elapsed. This can happen at application start.");
7272
}
7373
for (int i = 0; i < periodsElapsed; i++) {
7474
int offset = getPeriodOffsetForDeletionTarget() - i;
@@ -106,7 +106,7 @@ public void cleanPeriod(Instant instantOfPeriodToClean) {
106106
}
107107

108108
private boolean checkAndDeleteFile(File f) {
109-
addInfo("deleting " + f);
109+
addInfo("deleting historically stale " + f);
110110
if (f == null) {
111111
addWarn("Cannot delete empty file");
112112
return false;
@@ -136,9 +136,10 @@ void capTotalSize(Instant now) {
136136
long size = f.length();
137137
totalSize += size;
138138
if (totalSize > totalSizeCap) {
139-
addInfo("Deleting [" + f + "]" + " of size " + new FileSize(size));
139+
addInfo("Deleting [" + f + "]" + " of size " + new FileSize(size) + " on account of totalSizeCap " + totalSizeCap);
140140

141141
boolean success = checkAndDeleteFile(f);
142+
142143
if (success) {
143144
successfulDeletions++;
144145
totalRemoved += size;
@@ -149,9 +150,9 @@ void capTotalSize(Instant now) {
149150
}
150151
}
151152
if ((successfulDeletions + failedDeletions) == 0) {
152-
addInfo("No removal attempts were made.");
153+
addInfo("No removal attempts were made on account of totalSizeCap="+totalSizeCap);
153154
} else {
154-
addInfo("Removed " + new FileSize(totalRemoved) + " of files in " + successfulDeletions + " files.");
155+
addInfo("Removed " + new FileSize(totalRemoved) + " of files in " + successfulDeletions + " files on account of totalSizeCap=" + totalSizeCap);
155156
if (failedDeletions != 0) {
156157
addInfo("There were " + failedDeletions + " failed deletion attempts.");
157158
}

logback-core/src/main/java/ch/qos/logback/core/util/Loader.java

+13-26
Original file line numberDiff line numberDiff line change
@@ -33,27 +33,13 @@ public class Loader {
3333

3434
private static boolean ignoreTCL = false;
3535
public static final String IGNORE_TCL_PROPERTY_NAME = "logback.ignoreTCL";
36-
private static boolean HAS_GET_CLASS_LOADER_PERMISSION = false;
3736

3837
static {
3938
String ignoreTCLProp = OptionHelper.getSystemProperty(IGNORE_TCL_PROPERTY_NAME, null);
4039

4140
if (ignoreTCLProp != null) {
4241
ignoreTCL = OptionHelper.toBoolean(ignoreTCLProp, true);
4342
}
44-
45-
HAS_GET_CLASS_LOADER_PERMISSION = AccessController.doPrivileged(new PrivilegedAction<Boolean>() {
46-
public Boolean run() {
47-
try {
48-
AccessController.checkPermission(new RuntimePermission("getClassLoader"));
49-
return true;
50-
} catch (SecurityException e) {
51-
// Using SecurityException instead of AccessControlException.
52-
// See bug LOGBACK-760.
53-
return false;
54-
}
55-
}
56-
});
5743
}
5844

5945
/**
@@ -147,22 +133,23 @@ public static ClassLoader getClassLoaderOfObject(Object o) {
147133
}
148134

149135
/**
150-
* Returns the class loader of clazz in an access privileged section.
136+
* Check whether a given class is loadable by the class loader that loaded the context parameter.
151137
*
152-
* @param clazz
153-
* @return
138+
* @param className the class to check for availability
139+
* @param context the context object used to find the class loader
140+
* @return true if className is available, false otherwise
141+
* @since 1.5.18
154142
*/
155-
public static ClassLoader getClassLoaderAsPrivileged(final Class<?> clazz) {
156-
if (!HAS_GET_CLASS_LOADER_PERMISSION)
157-
return null;
158-
else
159-
return AccessController.doPrivileged(new PrivilegedAction<ClassLoader>() {
160-
public ClassLoader run() {
161-
return clazz.getClassLoader();
162-
}
163-
});
143+
public static boolean isClassLoadable(String className, Context context) {
144+
try {
145+
Class<?> aClass = Loader.loadClass(className, context);
146+
return true;
147+
} catch (ClassNotFoundException e) {
148+
return false;
149+
}
164150
}
165151

152+
166153
/**
167154
* Return the class loader which loaded the class passed as argument. Return the
168155
* system class loader if the class loader of 'clazz' argument is null.

0 commit comments

Comments
 (0)