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 protected final StrSubstitutor strSubstitutor;
50
51 protected AbstractRolloverStrategy(final StrSubstitutor strSubstitutor) {
52 this.strSubstitutor = strSubstitutor;
53 }
54
55
56 public StrSubstitutor getStrSubstitutor() {
57 return strSubstitutor;
58 }
59
60 protected Action merge(final Action compressAction, final List<Action> custom, final boolean stopOnError) {
61 if (custom.isEmpty()) {
62 return compressAction;
63 }
64 if (compressAction == null) {
65 return new CompositeAction(custom, stopOnError);
66 }
67 final List<Action> all = new ArrayList<>();
68 all.add(compressAction);
69 all.addAll(custom);
70 return new CompositeAction(all, stopOnError);
71 }
72
73 protected int suffixLength(final String lowFilename) {
74 for (final FileExtension extension : FileExtension.values()) {
75 if (extension.isExtensionFor(lowFilename)) {
76 return extension.length();
77 }
78 }
79 return 0;
80 }
81
82
83 protected SortedMap<Integer, Path> getEligibleFiles(final RollingFileManager manager) {
84 return getEligibleFiles(manager, true);
85 }
86
87 protected SortedMap<Integer, Path> getEligibleFiles(final RollingFileManager manager,
88 final boolean isAscending) {
89 final StringBuilder buf = new StringBuilder();
90 final String pattern = manager.getPatternProcessor().getPattern();
91 manager.getPatternProcessor().formatFileName(strSubstitutor, buf, NotANumber.NAN);
92 return getEligibleFiles(buf.toString(), pattern, isAscending);
93 }
94
95 protected SortedMap<Integer, Path> getEligibleFiles(final String path, final String pattern) {
96 return getEligibleFiles(path, pattern, true);
97 }
98
99 protected SortedMap<Integer, Path> getEligibleFiles(final String path, final String logfilePattern, final boolean isAscending) {
100 final TreeMap<Integer, Path> eligibleFiles = new TreeMap<>();
101 final File file = new File(path);
102 File parent = file.getParentFile();
103 if (parent == null) {
104 parent = new File(".");
105 } else {
106 parent.mkdirs();
107 }
108 if (!logfilePattern.contains("%i")) {
109 return eligibleFiles;
110 }
111 final Path dir = parent.toPath();
112 String fileName = file.getName();
113 final int suffixLength = suffixLength(fileName);
114 if (suffixLength > 0) {
115 fileName = fileName.substring(0, fileName.length() - suffixLength) + ".*";
116 }
117 final String filePattern = fileName.replace(NotANumber.VALUE, "(\\d+)");
118 final Pattern pattern = Pattern.compile(filePattern);
119
120 try (DirectoryStream<Path> stream = Files.newDirectoryStream(dir)) {
121 for (final Path entry: stream) {
122 final Matcher matcher = pattern.matcher(entry.toFile().getName());
123 if (matcher.matches()) {
124 final Integer index = Integer.parseInt(matcher.group(1));
125 eligibleFiles.put(index, entry);
126 }
127 }
128 } catch (final IOException ioe) {
129 throw new LoggingException("Error reading folder " + dir + " " + ioe.getMessage(), ioe);
130 }
131 return isAscending? eligibleFiles : eligibleFiles.descendingMap();
132 }
133 }