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 org.apache.logging.log4j.core.pattern.ArrayPatternConverter;
20 import org.apache.logging.log4j.core.pattern.DatePatternConverter;
21 import org.apache.logging.log4j.core.pattern.FormattingInfo;
22 import org.apache.logging.log4j.core.pattern.PatternConverter;
23 import org.apache.logging.log4j.core.pattern.PatternParser;
24
25 import java.util.ArrayList;
26 import java.util.Calendar;
27 import java.util.Date;
28 import java.util.List;
29
30
31
32
33 public class PatternProcessor {
34
35 private static final String KEY = "FileConverter";
36
37 private static final char YEAR_CHAR = 'y';
38 private static final char MONTH_CHAR = 'M';
39 private static final char[] WEEK_CHARS = {'w', 'W'};
40 private static final char[] DAY_CHARS = {'D', 'd', 'F', 'E'};
41 private static final char[] HOUR_CHARS = {'H', 'K', 'h', 'k'};
42 private static final char MINUTE_CHAR = 'm';
43 private static final char SECOND_CHAR = 's';
44 private static final char MILLIS_CHAR = 'S';
45
46 private final ArrayPatternConverter[] patternConverters;
47 private final FormattingInfo[] patternFields;
48
49 private RolloverFrequency frequency = null;
50
51
52
53
54
55 public PatternProcessor(String pattern) {
56 PatternParser parser = createPatternParser();
57 List<PatternConverter> converters = new ArrayList<PatternConverter>();
58 List<FormattingInfo> fields = new ArrayList<FormattingInfo>();
59 parser.parse(pattern, converters, fields);
60 FormattingInfo[] infoArray = new FormattingInfo[fields.size()];
61 patternFields = fields.toArray(infoArray);
62 ArrayPatternConverter[] converterArray = new ArrayPatternConverter[converters.size()];
63 patternConverters = converters.toArray(converterArray);
64
65 for (ArrayPatternConverter converter : patternConverters) {
66 if (converter instanceof DatePatternConverter) {
67 DatePatternConverter dateConverter = (DatePatternConverter) converter;
68 frequency = calculateFrequency(dateConverter.getPattern());
69 }
70 }
71 }
72
73
74
75
76
77
78
79 public long getNextTime(long current, int increment, boolean modulus) {
80 if (frequency == null) {
81 throw new IllegalStateException("Pattern does not contain a date");
82 }
83 Calendar currentCal = Calendar.getInstance();
84 currentCal.setTimeInMillis(current);
85 Calendar cal = Calendar.getInstance();
86 cal.set(currentCal.get(Calendar.YEAR), 0, 1, 0, 0, 0);
87 cal.set(Calendar.MILLISECOND, 0);
88 if (frequency == RolloverFrequency.ANNUALLY) {
89 increment(cal, Calendar.YEAR, increment, modulus);
90 return cal.getTimeInMillis();
91 }
92 if (frequency == RolloverFrequency.MONTHLY) {
93 increment(cal, Calendar.MONTH, increment, modulus);
94 return cal.getTimeInMillis();
95 }
96 if (frequency == RolloverFrequency.WEEKLY) {
97 increment(cal, Calendar.WEEK_OF_YEAR, increment, modulus);
98 return cal.getTimeInMillis();
99 }
100 cal.set(Calendar.DAY_OF_YEAR, currentCal.get(Calendar.DAY_OF_YEAR));
101 if (frequency == RolloverFrequency.DAILY) {
102 increment(cal, Calendar.DAY_OF_YEAR, increment, modulus);
103 return cal.getTimeInMillis();
104 }
105 cal.set(Calendar.HOUR, currentCal.get(Calendar.HOUR));
106 if (frequency == RolloverFrequency.HOURLY) {
107 increment(cal, Calendar.HOUR, increment, modulus);
108 return cal.getTimeInMillis();
109 }
110 cal.set(Calendar.MINUTE, currentCal.get(Calendar.MINUTE));
111 if (frequency == RolloverFrequency.EVERY_MINUTE) {
112 increment(cal, Calendar.MINUTE, increment, modulus);
113 return cal.getTimeInMillis();
114 }
115 cal.set(Calendar.SECOND, currentCal.get(Calendar.SECOND));
116 if (frequency == RolloverFrequency.EVERY_SECOND) {
117 increment(cal, Calendar.SECOND, increment, modulus);
118 return cal.getTimeInMillis();
119 }
120 increment(cal, Calendar.MILLISECOND, increment, modulus);
121 return cal.getTimeInMillis();
122 }
123
124 private void increment(Calendar cal, int type, int increment, boolean modulate) {
125 int interval = modulate ? increment - (cal.get(type) % increment) : increment;
126 cal.add(type, interval);
127 }
128
129
130
131
132
133
134 protected final void formatFileName(final StringBuilder buf, final Object obj) {
135 formatFileName(buf, new Date(System.currentTimeMillis()), obj);
136 }
137
138
139
140
141
142
143 protected final void formatFileName(final StringBuilder buf, final Object... objects) {
144 for (int i = 0; i < patternConverters.length; i++) {
145 int fieldStart = buf.length();
146 patternConverters[i].format(buf, objects);
147
148 if (patternFields[i] != null) {
149 patternFields[i].format(fieldStart, buf);
150 }
151 }
152 }
153
154 private RolloverFrequency calculateFrequency(String pattern) {
155 if (patternContains(pattern, MILLIS_CHAR)) {
156 return RolloverFrequency.EVERY_MILLISECOND;
157 }
158 if (patternContains(pattern, SECOND_CHAR)) {
159 return RolloverFrequency.EVERY_SECOND;
160 }
161 if (patternContains(pattern, MINUTE_CHAR)) {
162 return RolloverFrequency.EVERY_MINUTE;
163 }
164 if (patternContains(pattern, HOUR_CHARS)) {
165 return RolloverFrequency.HOURLY;
166 }
167 if (patternContains(pattern, DAY_CHARS)) {
168 return RolloverFrequency.DAILY;
169 }
170 if (patternContains(pattern, WEEK_CHARS)) {
171 return RolloverFrequency.WEEKLY;
172 }
173 if (patternContains(pattern, MONTH_CHAR)) {
174 return RolloverFrequency.MONTHLY;
175 }
176 if (patternContains(pattern, YEAR_CHAR)) {
177 return RolloverFrequency.ANNUALLY;
178 }
179 return null;
180 }
181
182 private PatternParser createPatternParser() {
183
184 return new PatternParser(null, KEY, null);
185 }
186
187 private boolean patternContains(String pattern, char... chars) {
188 for (char character : chars) {
189 if (patternContains(pattern, character)) {
190 return true;
191 }
192 }
193 return false;
194 }
195
196 private boolean patternContains(String pattern, char character) {
197 return pattern.indexOf(character) >= 0;
198 }
199 }