1
2
3
4
5
6
7
8
9
10
11
12
13 package org.abstracthorizon.danube.support.logging.util;
14
15 import java.io.BufferedOutputStream;
16 import java.io.File;
17 import java.io.FileOutputStream;
18 import java.io.IOException;
19 import java.io.OutputStream;
20 import java.util.ArrayList;
21 import java.util.Calendar;
22 import java.util.GregorianCalendar;
23
24 import org.slf4j.Logger;
25 import org.slf4j.LoggerFactory;
26
27
28
29
30
31
32
33
34
35
36
37
38
39 public class LogFileRotatorImpl implements LogFileRotator {
40
41
42 protected final Logger logger = LoggerFactory.getLogger(getClass());
43
44
45 protected OutputStream cachedOutputStream;
46
47
48 protected File logFile;
49
50
51 protected File logPath;
52
53
54 private int numberOfGenerations = -1;
55
56
57 private long maxSize = -1;
58
59
60 private long maxAge = -1;
61
62
63 private Calendar timeOfDay = null;
64
65
66
67
68
69 private int checkDelayMillis = 100;
70
71
72 protected long lastAccessed;
73
74
75 protected long nextRotate;
76
77
78 protected long logFileCreated;
79
80
81 private int bufferLen = -1;
82
83
84
85
86 public LogFileRotatorImpl() {
87 }
88
89
90
91
92
93
94 public LogFileRotatorImpl(File logFile) {
95 this.setLogFile(logFile);
96 }
97
98
99
100
101
102
103
104
105
106 public synchronized OutputStream logFile() throws IOException {
107 if ((System.currentTimeMillis() - lastAccessed) > checkDelayMillis) {
108 lastAccessed = System.currentTimeMillis();
109 check();
110 }
111 return cachedOutputStream;
112 }
113
114
115
116
117
118 public File getLogFile() {
119 return logFile;
120 }
121
122
123
124
125
126 public void setLogFile(File logFile) {
127 this.logFile = logFile;
128 this.logPath = logFile.getParentFile();
129 }
130
131
132
133
134
135
136
137 public File getLogDirectory() {
138 return logPath;
139 }
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155 public void setLogDirectory(File logPath) {
156 this.logPath = logPath;
157 this.logFile = new File(logPath, "access.log");
158 }
159
160
161
162
163
164 public String getLogFileName() {
165 return logFile.getName();
166 }
167
168
169
170
171
172 public void setLogFileName(String name) {
173 this.logFile = new File(logPath, name);
174 }
175
176
177
178
179
180
181
182 public long getMaxAge() {
183 return maxAge;
184 }
185
186
187
188
189
190
191
192 public void setMaxAge(long maxAge) {
193 this.maxAge = maxAge;
194 }
195
196
197
198
199
200
201
202
203 public long getMaxSize() {
204 return maxSize;
205 }
206
207
208
209
210
211
212
213 public void setMaxSize(long maxSize) {
214 this.maxSize = maxSize;
215 }
216
217
218
219
220
221
222
223 public int getNumberOfGenerations() {
224 return numberOfGenerations;
225 }
226
227
228
229
230
231
232
233 public void setNumberOfGenerations(int numberOfGeneration) {
234 this.numberOfGenerations = numberOfGeneration;
235 }
236
237
238
239
240
241
242
243 public Calendar getTimeOfDay() {
244 return timeOfDay;
245 }
246
247
248
249
250
251
252
253 public void setTimeOfDay(Calendar timeOfDay) {
254 this.timeOfDay = timeOfDay;
255 if (timeOfDay == null) {
256 nextRotate = 0;
257 } else {
258 GregorianCalendar cal = new GregorianCalendar();
259 cal.set(Calendar.HOUR, timeOfDay.get(Calendar.HOUR));
260 cal.set(Calendar.MINUTE, timeOfDay.get(Calendar.MINUTE));
261 cal.set(Calendar.SECOND, timeOfDay.get(Calendar.SECOND));
262 cal.set(Calendar.MILLISECOND, timeOfDay.get(Calendar.MILLISECOND));
263 cal.add(Calendar.DAY_OF_YEAR, 1);
264 nextRotate = cal.getTimeInMillis();
265 }
266 }
267
268
269
270
271
272
273
274 public int getCheckDelayMillis() {
275 return checkDelayMillis;
276 }
277
278
279
280
281
282
283
284 public void setCheckDelayMillis(int checkDelayMillis) {
285 this.checkDelayMillis = checkDelayMillis;
286 }
287
288
289
290
291
292
293
294 public int getBufferLen() {
295 return bufferLen;
296 }
297
298
299
300
301
302
303
304 public void setBufferLen(int bufferLen) {
305 this.bufferLen = bufferLen;
306 }
307
308
309
310
311
312
313 protected void check() throws IOException {
314 boolean doRotate = false;
315 if (cachedOutputStream == null) {
316 doRotate = true;
317 }
318 if (!doRotate) {
319 long maxAge = getMaxAge();
320 if ((maxAge > 0) && ((lastAccessed - logFileCreated) > maxAge)) {
321 doRotate = true;
322 }
323 }
324 if (!doRotate) {
325 long maxSize = getMaxSize();
326 if ((maxSize > 0) && (getLogFile().length()) > maxSize) {
327 doRotate = true;
328 }
329 }
330 if (!doRotate) {
331 if ((nextRotate > 0) && (lastAccessed > nextRotate)) {
332 doRotate = true;
333 GregorianCalendar cal = new GregorianCalendar();
334 cal.setTimeInMillis(nextRotate);
335 cal.add(Calendar.DAY_OF_YEAR, 1);
336 nextRotate = cal.getTimeInMillis();
337 }
338 }
339 if (doRotate) {
340 rotate();
341 }
342 }
343
344
345
346
347
348
349 public void rotate() throws IOException {
350 if (cachedOutputStream != null) {
351 try {
352 cachedOutputStream.close();
353 } catch (IOException e) {
354 logger.error("Failed to close previous file", e);
355 }
356 }
357 ArrayList<File> files = new ArrayList<File>();
358 int i = 1;
359 File f = createFileName(i);
360 while (f.exists()) {
361 if ((numberOfGenerations >= 0) && (i >= numberOfGenerations)) {
362 f.delete();
363 }
364 if ((numberOfGenerations < 0) || (i <= numberOfGenerations)) {
365 files.add(f);
366 }
367 i++;
368 f = createFileName(i);
369 }
370 if ((numberOfGenerations < 0) || (i <= numberOfGenerations)) {
371 files.add(createFileName(i));
372 i++;
373 }
374 i = i - 1;
375 if (i > 1) {
376 for (int j = i-1; j >= 1; j--) {
377 File last = files.get(j);
378 File second = files.get(j-1);
379 second.renameTo(last);
380 }
381 }
382 if (numberOfGenerations != 0) {
383 getLogFile().renameTo(createFileName(1));
384 } else {
385 getLogFile().delete();
386 }
387 createLogFile();
388 }
389
390
391
392
393
394
395
396
397 protected File createFileName(int g) {
398 if (g == 0) {
399 return getLogFile();
400 } else {
401 File p = getLogFile().getParentFile();
402 if (p == null) {
403 p = new File(".");
404 }
405 String name = getLogFile().getName();
406 int i = name.lastIndexOf('.');
407 if (i >= 0) {
408 name = name.substring(0, i) + "." + g + name.substring(i);
409 } else {
410 name = name + "." + g;
411 }
412 return new File(p, name);
413 }
414 }
415
416
417
418
419
420
421 protected void createLogFile() throws IOException {
422 File file = getLogFile();
423 FileOutputStream fos = new FileOutputStream(file);
424 if (getBufferLen() > 0) {
425 BufferedOutputStream out = new BufferedOutputStream(fos, getBufferLen());
426 cachedOutputStream = out;
427 } else {
428 cachedOutputStream = fos;
429 }
430 logFileCreated = file.lastModified();
431 }
432 }