1
2
3
4
5
6
7
8
9
10
11
12
13
14 package ch.qos.logback.core.rolling;
15
16 import static ch.qos.logback.core.CoreConstants.CODES_URL;
17 import static ch.qos.logback.core.CoreConstants.MORE_INFO_PREFIX;
18
19 import java.io.File;
20 import java.io.IOException;
21 import java.util.Map;
22 import java.util.Map.Entry;
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 static private String RFA_NO_TP_URL = CODES_URL + "#rfa_no_tp";
47 static private String RFA_NO_RP_URL = CODES_URL + "#rfa_no_rp";
48 static private String COLLISION_URL = CODES_URL + "#rfa_collision";
49 static private String RFA_LATE_FILE_URL = CODES_URL + "#rfa_file_after";
50
51 public void start() {
52 if (triggeringPolicy == null) {
53 addWarn("No TriggeringPolicy was set for the RollingFileAppender named " + getName());
54 addWarn(MORE_INFO_PREFIX + RFA_NO_TP_URL);
55 return;
56 }
57 if (!triggeringPolicy.isStarted()) {
58 addWarn("TriggeringPolicy has not started. RollingFileAppender will not start");
59 return;
60 }
61
62 if (checkForCollisionsInPreviousRollingFileAppenders()) {
63 addError("Collisions detected with FileAppender/RollingAppender instances defined earlier. Aborting.");
64 addError(MORE_INFO_PREFIX + COLLISION_WITH_EARLIER_APPENDER_URL);
65 return;
66 }
67
68
69 if (!append) {
70 addWarn("Append mode is mandatory for RollingFileAppender. Defaulting to append=true.");
71 append = true;
72 }
73
74 if (rollingPolicy == null) {
75 addError("No RollingPolicy was set for the RollingFileAppender named " + getName());
76 addError(MORE_INFO_PREFIX + RFA_NO_RP_URL);
77 return;
78 }
79
80
81 if (checkForFileAndPatternCollisions()) {
82 addError("File property collides with fileNamePattern. Aborting.");
83 addError(MORE_INFO_PREFIX + COLLISION_URL);
84 return;
85 }
86
87 if (isPrudent()) {
88 if (rawFileProperty() != null) {
89 addWarn("Setting \"File\" property to null on account of prudent mode");
90 setFile(null);
91 }
92 if (rollingPolicy.getCompressionMode() != CompressionMode.NONE) {
93 addError("Compression is not supported in prudent mode. Aborting");
94 return;
95 }
96 }
97
98 currentlyActiveFile = new File(getFile());
99 addInfo("Active log file name: " + getFile());
100 super.start();
101 }
102
103 private boolean checkForFileAndPatternCollisions() {
104 if (triggeringPolicy instanceof RollingPolicyBase) {
105 final RollingPolicyBase base = (RollingPolicyBase) triggeringPolicy;
106 final FileNamePattern fileNamePattern = base.fileNamePattern;
107
108 if (fileNamePattern != null && fileName != null) {
109 String regex = fileNamePattern.toRegex();
110 return fileName.matches(regex);
111 }
112 }
113 return false;
114 }
115
116 private boolean checkForCollisionsInPreviousRollingFileAppenders() {
117 boolean collisionResult = false;
118 if (triggeringPolicy instanceof RollingPolicyBase) {
119 final RollingPolicyBase base = (RollingPolicyBase) triggeringPolicy;
120 final FileNamePattern fileNamePattern = base.fileNamePattern;
121 boolean collisionsDetected = innerCheckForFileNamePatternCollisionInPreviousRFA(fileNamePattern);
122 if (collisionsDetected)
123 collisionResult = true;
124 }
125 return collisionResult;
126 }
127
128 private boolean innerCheckForFileNamePatternCollisionInPreviousRFA(FileNamePattern fileNamePattern) {
129 boolean collisionsDetected = false;
130 @SuppressWarnings("unchecked")
131 Map<String, FileNamePattern> map = (Map<String, FileNamePattern>) context
132 .getObject(CoreConstants.RFA_FILENAME_PATTERN_COLLISION_MAP);
133 if (map == null) {
134 return collisionsDetected;
135 }
136 for (Entry<String, FileNamePattern> entry : map.entrySet()) {
137 if (fileNamePattern.equals(entry.getValue())) {
138 addErrorForCollision("FileNamePattern", entry.getValue().toString(), entry.getKey());
139 collisionsDetected = true;
140 }
141 }
142 if (name != null) {
143 map.put(getName(), fileNamePattern);
144 }
145 return collisionsDetected;
146 }
147
148 @Override
149 public void stop() {
150 if(!isStarted()) {
151 return;
152 }
153 super.stop();
154
155 if (rollingPolicy != null)
156 rollingPolicy.stop();
157 if (triggeringPolicy != null)
158 triggeringPolicy.stop();
159
160 Map<String, FileNamePattern> map = ContextUtil.getFilenamePatternCollisionMap(context);
161 if (map != null && getName() != null)
162 map.remove(getName());
163
164 }
165
166 @Override
167 public void setFile(String file) {
168
169
170 if (file != null && ((triggeringPolicy != null) || (rollingPolicy != null))) {
171 addError("File property must be set before any triggeringPolicy or rollingPolicy properties");
172 addError(MORE_INFO_PREFIX + RFA_LATE_FILE_URL);
173 }
174 super.setFile(file);
175 }
176
177 @Override
178 public String getFile() {
179 return rollingPolicy.getActiveFileName();
180 }
181
182
183
184
185 public void rollover() {
186 lock.lock();
187 try {
188
189
190
191
192
193 this.closeOutputStream();
194 attemptRollover();
195 attemptOpenFile();
196 } finally {
197 lock.unlock();
198 }
199 }
200
201 private void attemptOpenFile() {
202 try {
203
204 currentlyActiveFile = new File(rollingPolicy.getActiveFileName());
205
206
207
208 this.openFile(rollingPolicy.getActiveFileName());
209 } catch (IOException e) {
210 addError("setFile(" + fileName + ", false) call failed.", e);
211 }
212 }
213
214 private void attemptRollover() {
215 try {
216 rollingPolicy.rollover();
217 } catch (RolloverFailure rf) {
218 addWarn("RolloverFailure occurred. Deferring roll-over.");
219
220 this.append = true;
221 }
222 }
223
224
225
226
227 @Override
228 protected void subAppend(E event) {
229
230
231
232
233
234 synchronized (triggeringPolicy) {
235 if (triggeringPolicy.isTriggeringEvent(currentlyActiveFile, event)) {
236 rollover();
237 }
238 }
239
240 super.subAppend(event);
241 }
242
243 public RollingPolicy getRollingPolicy() {
244 return rollingPolicy;
245 }
246
247 public TriggeringPolicy<E> getTriggeringPolicy() {
248 return triggeringPolicy;
249 }
250
251
252
253
254
255
256
257
258 @SuppressWarnings("unchecked")
259 public void setRollingPolicy(RollingPolicy policy) {
260 rollingPolicy = policy;
261 if (rollingPolicy instanceof TriggeringPolicy) {
262 triggeringPolicy = (TriggeringPolicy<E>) policy;
263 }
264
265 }
266
267 public void setTriggeringPolicy(TriggeringPolicy<E> policy) {
268 triggeringPolicy = policy;
269 if (policy instanceof RollingPolicy) {
270 rollingPolicy = (RollingPolicy) policy;
271 }
272 }
273 }