1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.logging.log4j.core.appender.rolling;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.nio.file.DirectoryStream;
22 import java.nio.file.Files;
23 import java.nio.file.Path;
24 import java.util.ArrayList;
25 import java.util.List;
26 import java.util.SortedMap;
27 import java.util.TreeMap;
28 import java.util.regex.Matcher;
29 import java.util.regex.Pattern;
30
31 import org.apache.logging.log4j.Logger;
32 import org.apache.logging.log4j.LoggingException;
33 import org.apache.logging.log4j.core.appender.rolling.action.Action;
34 import org.apache.logging.log4j.core.appender.rolling.action.CompositeAction;
35 import org.apache.logging.log4j.core.lookup.StrSubstitutor;
36 import org.apache.logging.log4j.core.pattern.NotANumber;
37 import org.apache.logging.log4j.status.StatusLogger;
38
39
40
41
42 public abstract class AbstractRolloverStrategy implements RolloverStrategy {
43
44
45
46
47 protected static final Logger LOGGER = StatusLogger.getLogger();
48
49 public static final Pattern PATTERN_COUNTER= Pattern.compile(".*%((?<ZEROPAD>0)?(?<PADDING>\\d+))?i.*");
50
51 protected final StrSubstitutor strSubstitutor;
52
53 protected AbstractRolloverStrategy(final StrSubstitutor strSubstitutor) {
54 this.strSubstitutor = strSubstitutor;
55 }
56
57
58 public StrSubstitutor getStrSubstitutor() {
59 return strSubstitutor;
60 }
61
62 protected Action merge(final Action compressAction, final List<Action> custom, final boolean stopOnError) {
63 if (custom.isEmpty()) {
64 return compressAction;
65 }
66 if (compressAction == null) {
67 return new CompositeAction(custom, stopOnError);
68 }
69 final List<Action> all = new ArrayList<>();
70 all.add(compressAction);
71 all.addAll(custom);
72 return new CompositeAction(all, stopOnError);
73 }
74
75 protected int suffixLength(final String lowFilename) {
76 for (final FileExtension extension : FileExtension.values()) {
77 if (extension.isExtensionFor(lowFilename)) {
78 return extension.length();
79 }
80 }
81 return 0;
82 }
83
84
85 protected SortedMap<Integer, Path> getEligibleFiles(final RollingFileManager manager) {
86 return getEligibleFiles(manager, true);
87 }
88
89 protected SortedMap<Integer, Path> getEligibleFiles(final RollingFileManager manager,
90 final boolean isAscending) {
91 final StringBuilder buf = new StringBuilder();
92 final String pattern = manager.getPatternProcessor().getPattern();
93 manager.getPatternProcessor().formatFileName(strSubstitutor, buf, NotANumber.NAN);
94 return getEligibleFiles(buf.toString(), pattern, isAscending);
95 }
96
97 protected SortedMap<Integer, Path> getEligibleFiles(final String path, final String pattern) {
98 return getEligibleFiles(path, pattern, true);
99 }
100
101 protected SortedMap<Integer, Path> getEligibleFiles(final String path, final String logfilePattern, final boolean isAscending) {
102 final TreeMap<Integer, Path> eligibleFiles = new TreeMap<>();
103 final File file = new File(path);
104 File parent = file.getParentFile();
105 if (parent == null) {
106 parent = new File(".");
107 } else {
108 parent.mkdirs();
109 }
110 if (!PATTERN_COUNTER.matcher(logfilePattern).matches()) {
111 return eligibleFiles;
112 }
113 final Path dir = parent.toPath();
114 String fileName = file.getName();
115 final int suffixLength = suffixLength(fileName);
116 if (suffixLength > 0) {
117 fileName = fileName.substring(0, fileName.length() - suffixLength) + ".*";
118 }
119 final String filePattern = fileName.replace(NotANumber.VALUE, "(\\d+)");
120 final Pattern pattern = Pattern.compile(filePattern);
121
122 try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
123 for (final Path entry: stream) {
124 final Matcher matcher = pattern.matcher(entry.toFile().getName());
125 if (matcher.matches()) {
126 final Integer index = Integer.parseInt(matcher.group(1));
127 eligibleFiles.put(index, entry);
128 }
129 }
130 } catch (final IOException ioe) {
131 throw new LoggingException("Error reading folder " + dir + " " + ioe.getMessage(), ioe);
132 }
133 return isAscending? eligibleFiles : eligibleFiles.descendingMap();
134 }
135 }