1
2
3
4
5
6
7
8
9
10
11
12 package ch.qos.logback.core.rolling;
13
14 import static ch.qos.logback.core.CoreConstants.CODES_URL;
15 import static ch.qos.logback.core.CoreConstants.MORE_INFO_PREFIX;
16
17 import java.io.File;
18 import java.io.IOException;
19 import java.util.Map;
20 import java.util.Map.Entry;
21 import java.util.concurrent.locks.Lock;
22 import java.util.concurrent.locks.ReentrantLock;
23
24 import ch.qos.logback.core.CoreConstants;
25 import ch.qos.logback.core.FileAppender;
26 import ch.qos.logback.core.rolling.helper.CompressionMode;
27 import ch.qos.logback.core.rolling.helper.FileNamePattern;
28 import ch.qos.logback.core.util.ContextUtil;
29
30
31
32
33
34
35
36
37
38
39
40
41 public class RollingFileAppender<E> extends FileAppender<E> {
42 File currentlyActiveFile;
43 TriggeringPolicy<E> triggeringPolicy;
44 RollingPolicy rollingPolicy;
45
46 Lock triggeringPolicyLock = new ReentrantLock();
47
48 static private String RFA_NO_TP_URL = CODES_URL + "#rfa_no_tp";
49 static private String RFA_NO_RP_URL = CODES_URL + "#rfa_no_rp";
50 static private String COLLISION_URL = CODES_URL + "#rfa_collision";
51 static private String RFA_LATE_FILE_URL = CODES_URL + "#rfa_file_after";
52 static private String RFA_RESET_RP_OR_TP = CODES_URL + "#rfa_reset_rp_or_tp";
53
54 public void start() {
55 if (triggeringPolicy == null) {
56 addWarn("No TriggeringPolicy was set for the RollingFileAppender named " + getName());
57 addWarn(MORE_INFO_PREFIX + RFA_NO_TP_URL);
58 return;
59 }
60 if (!triggeringPolicy.isStarted()) {
61 addWarn("TriggeringPolicy has not started. RollingFileAppender will not start");
62 return;
63 }
64
65
66
67
68
69
70
71
72 if (!append) {
73 addWarn("Append mode is mandatory for RollingFileAppender. Defaulting to append=true.");
74 append = true;
75 }
76
77 if (rollingPolicy == null) {
78 addError("No RollingPolicy was set for the RollingFileAppender named " + getName());
79 addError(MORE_INFO_PREFIX + RFA_NO_RP_URL);
80 return;
81 }
82
83
84 if (checkForFileAndPatternCollisions()) {
85 addError("File property collides with fileNamePattern. Aborting.");
86 addError(MORE_INFO_PREFIX + COLLISION_URL);
87 return;
88 }
89
90 if (isPrudent()) {
91 if (rawFileProperty() != null) {
92 addWarn("Setting \"File\" property to null on account of prudent mode");
93 setFile(null);
94 }
95 if (rollingPolicy.getCompressionMode() != CompressionMode.NONE) {
96 addError("Compression is not supported in prudent mode. Aborting");
97 return;
98 }
99 }
100
101 addInfo("Active log file name: " + getFile());
102 currentlyActiveFile = new File(getFile());
103 initializeLengthCounter();
104 super.start();
105 }
106
107
108
109 private boolean checkForFileAndPatternCollisions() {
110 if (triggeringPolicy instanceof RollingPolicyBase) {
111 final RollingPolicyBase base = (RollingPolicyBase) triggeringPolicy;
112 final FileNamePattern fileNamePattern = base.fileNamePattern;
113
114 if (fileNamePattern != null && fileName != null) {
115 String regex = fileNamePattern.toRegex();
116 return fileName.matches(regex);
117 }
118 }
119 return false;
120 }
121
122 private void initializeLengthCounter() {
123 if(getLengthCounter() != null && currentlyActiveFile.exists()) {
124 long currentFileLength = currentlyActiveFile.length();
125 addInfo("Setting currentFileLength to "+currentFileLength+ " for "+currentlyActiveFile);
126 incrementByteCount(currentFileLength);
127 }
128 }
129
130 @Override
131 public void stop() {
132 if (!isStarted()) {
133 return;
134 }
135 super.stop();
136
137 if (rollingPolicy != null)
138 rollingPolicy.stop();
139 if (triggeringPolicy != null)
140 triggeringPolicy.stop();
141 }
142
143 @Override
144 public void setFile(String file) {
145
146
147 if (file != null && ((triggeringPolicy != null) || (rollingPolicy != null))) {
148 addError("File property must be set before any triggeringPolicy or rollingPolicy properties");
149 addError(MORE_INFO_PREFIX + RFA_LATE_FILE_URL);
150 }
151 super.setFile(file);
152 }
153
154 @Override
155 public String getFile() {
156 return rollingPolicy.getActiveFileName();
157 }
158
159
160
161
162 public void rollover() {
163 streamWriteLock.lock();
164 try {
165
166
167
168
169
170 this.closeOutputStream();
171 attemptRollover();
172 attemptOpenFile();
173 } finally {
174 streamWriteLock.unlock();
175 }
176 }
177
178 private void attemptOpenFile() {
179 try {
180
181 currentlyActiveFile = new File(rollingPolicy.getActiveFileName());
182
183
184
185 this.openFile(rollingPolicy.getActiveFileName());
186 } catch (IOException e) {
187 addError("setFile(" + fileName + ", false) call failed.", e);
188 }
189 }
190
191 private void attemptRollover() {
192 try {
193 rollingPolicy.rollover();
194 } catch (RolloverFailure rf) {
195 addWarn("RolloverFailure occurred. Deferring roll-over.");
196
197 this.append = true;
198 }
199 }
200
201
202
203
204 @Override
205 protected void subAppend(E event) {
206
207
208
209
210
211
212
213
214 triggeringPolicyLock.lock();
215 try {
216 if (triggeringPolicy.isTriggeringEvent(currentlyActiveFile, event)) {
217 rollover();
218 }
219 } finally {
220 triggeringPolicyLock.unlock();
221 }
222
223 super.subAppend(event);
224 }
225
226 public RollingPolicy getRollingPolicy() {
227 return rollingPolicy;
228 }
229
230 public TriggeringPolicy<E> getTriggeringPolicy() {
231 return triggeringPolicy;
232 }
233
234
235
236
237
238
239
240
241 @SuppressWarnings("unchecked")
242 public void setRollingPolicy(RollingPolicy policy) {
243 if (this.rollingPolicy instanceof TriggeringPolicy) {
244 String className = rollingPolicy.getClass().getSimpleName();
245 addWarn("A rolling policy of type " + className + " was already set.");
246 addWarn("Note that " + className + " doubles as a TriggeringPolicy");
247 addWarn("See also " + RFA_RESET_RP_OR_TP);
248 }
249 this.rollingPolicy = policy;
250 if (this.rollingPolicy instanceof TriggeringPolicy) {
251 this.triggeringPolicy = (TriggeringPolicy<E>) policy;
252 }
253
254 }
255
256 public void setTriggeringPolicy(TriggeringPolicy<E> policy) {
257 if (triggeringPolicy instanceof RollingPolicy) {
258 String className = triggeringPolicy.getClass().getSimpleName();
259 addWarn("A triggering policy of type " + className + " was already set.");
260 addWarn("Note that " + className + " doubles as a RollingPolicy");
261 addWarn("See also " + RFA_RESET_RP_OR_TP);
262 }
263 triggeringPolicy = policy;
264 if (policy instanceof RollingPolicy) {
265 rollingPolicy = (RollingPolicy) policy;
266 }
267 }
268
269 @Override
270 protected void updateByteCount(byte[] byteArray) {
271 if(byteArray == null)
272 return;
273 incrementByteCount(byteArray.length);
274 }
275
276 void incrementByteCount(long increment) {
277 LengthCounter lengthCounter = getLengthCounter();
278 if (lengthCounter == null)
279 return;
280
281 if (increment > 0) {
282 lengthCounter.add(increment);
283 }
284 }
285
286 private LengthCounter getLengthCounter() {
287 return triggeringPolicy.getLengthCounter();
288 }
289
290 }