1 16 17 18 19 package org.apache.log4j; 20 21 import java.io.IOException ; 22 import java.io.File ; 23 import java.text.SimpleDateFormat ; 24 import java.util.Date ; 25 import java.util.GregorianCalendar ; 26 import java.util.Calendar ; 27 import java.util.TimeZone ; 28 import java.util.Locale ; 29 30 import org.apache.log4j.helpers.LogLog; 31 import org.apache.log4j.spi.LoggingEvent; 32 33 134 public class DailyRollingFileAppender extends FileAppender { 135 136 137 static final int TOP_OF_TROUBLE=-1; 140 static final int TOP_OF_MINUTE = 0; 141 static final int TOP_OF_HOUR = 1; 142 static final int HALF_DAY = 2; 143 static final int TOP_OF_DAY = 3; 144 static final int TOP_OF_WEEK = 4; 145 static final int TOP_OF_MONTH = 5; 146 147 148 152 private String datePattern = "'.'yyyy-MM-dd"; 153 154 164 private String scheduledFilename; 165 166 168 private long nextCheck = System.currentTimeMillis () - 1; 169 170 Date now = new Date (); 171 172 SimpleDateFormat sdf; 173 174 RollingCalendar rc = new RollingCalendar(); 175 176 int checkPeriod = TOP_OF_TROUBLE; 177 178 static final TimeZone gmtTimeZone = TimeZone.getTimeZone("GMT"); 180 181 182 184 public DailyRollingFileAppender() { 185 } 186 187 193 public DailyRollingFileAppender (Layout layout, String filename, 194 String datePattern) throws IOException { 195 super(layout, filename, true); 196 this.datePattern = datePattern; 197 activateOptions(); 198 } 199 200 205 public void setDatePattern(String pattern) { 206 datePattern = pattern; 207 } 208 209 210 public String getDatePattern() { 211 return datePattern; 212 } 213 214 public void activateOptions() { 215 super.activateOptions(); 216 if(datePattern != null && fileName != null) { 217 now.setTime(System.currentTimeMillis()); 218 sdf = new SimpleDateFormat (datePattern); 219 int type = computeCheckPeriod(); 220 printPeriodicity(type); 221 rc.setType(type); 222 File file = new File (fileName); 223 scheduledFilename = fileName+sdf.format(new Date (file.lastModified())); 224 225 } else { 226 LogLog.error("Either File or DatePattern options are not set for appender [" 227 +name+"]."); 228 } 229 } 230 231 void printPeriodicity(int type) { 232 switch(type) { 233 case TOP_OF_MINUTE: 234 LogLog.debug("Appender ["+name+"] to be rolled every minute."); 235 break; 236 case TOP_OF_HOUR: 237 LogLog.debug("Appender ["+name 238 +"] to be rolled on top of every hour."); 239 break; 240 case HALF_DAY: 241 LogLog.debug("Appender ["+name 242 +"] to be rolled at midday and midnight."); 243 break; 244 case TOP_OF_DAY: 245 LogLog.debug("Appender ["+name 246 +"] to be rolled at midnight."); 247 break; 248 case TOP_OF_WEEK: 249 LogLog.debug("Appender ["+name 250 +"] to be rolled at start of week."); 251 break; 252 case TOP_OF_MONTH: 253 LogLog.debug("Appender ["+name 254 +"] to be rolled at start of every month."); 255 break; 256 default: 257 LogLog.warn("Unknown periodicity for appender ["+name+"]."); 258 } 259 } 260 261 262 271 int computeCheckPeriod() { 272 RollingCalendar rollingCalendar = new RollingCalendar(gmtTimeZone, Locale.ENGLISH); 273 Date epoch = new Date (0); 275 if(datePattern != null) { 276 for(int i = TOP_OF_MINUTE; i <= TOP_OF_MONTH; i++) { 277 SimpleDateFormat simpleDateFormat = new SimpleDateFormat (datePattern); 278 simpleDateFormat.setTimeZone(gmtTimeZone); String r0 = simpleDateFormat.format(epoch); 280 rollingCalendar.setType(i); 281 Date next = new Date (rollingCalendar.getNextCheckMillis(epoch)); 282 String r1 = simpleDateFormat.format(next); 283 if(r0 != null && r1 != null && !r0.equals(r1)) { 285 return i; 286 } 287 } 288 } 289 return TOP_OF_TROUBLE; } 291 292 295 void rollOver() throws IOException { 296 297 298 if (datePattern == null) { 299 errorHandler.error("Missing DatePattern option in rollOver()."); 300 return; 301 } 302 303 String datedFilename = fileName+sdf.format(now); 304 if (scheduledFilename.equals(datedFilename)) { 308 return; 309 } 310 311 this.closeFile(); 313 314 File target = new File (scheduledFilename); 315 if (target.exists()) { 316 target.delete(); 317 } 318 319 File file = new File (fileName); 320 boolean result = file.renameTo(target); 321 if(result) { 322 LogLog.debug(fileName +" -> "+ scheduledFilename); 323 } else { 324 LogLog.error("Failed to rename ["+fileName+"] to ["+scheduledFilename+"]."); 325 } 326 327 try { 328 this.setFile(fileName, false, this.bufferedIO, this.bufferSize); 331 } 332 catch(IOException e) { 333 errorHandler.error("setFile("+fileName+", false) call failed."); 334 } 335 scheduledFilename = datedFilename; 336 } 337 338 346 protected void subAppend(LoggingEvent event) { 347 long n = System.currentTimeMillis(); 348 if (n >= nextCheck) { 349 now.setTime(n); 350 nextCheck = rc.getNextCheckMillis(now); 351 try { 352 rollOver(); 353 } 354 catch(IOException ioe) { 355 LogLog.error("rollOver() failed.", ioe); 356 } 357 } 358 super.subAppend(event); 359 } 360 } 361 362 367 class RollingCalendar extends GregorianCalendar { 368 369 int type = DailyRollingFileAppender.TOP_OF_TROUBLE; 370 371 RollingCalendar() { 372 super(); 373 } 374 375 RollingCalendar(TimeZone tz, Locale locale) { 376 super(tz, locale); 377 } 378 379 void setType(int type) { 380 this.type = type; 381 } 382 383 public long getNextCheckMillis(Date now) { 384 return getNextCheckDate(now).getTime(); 385 } 386 387 public Date getNextCheckDate(Date now) { 388 this.setTime(now); 389 390 switch(type) { 391 case DailyRollingFileAppender.TOP_OF_MINUTE: 392 this.set(Calendar.SECOND, 0); 393 this.set(Calendar.MILLISECOND, 0); 394 this.add(Calendar.MINUTE, 1); 395 break; 396 case DailyRollingFileAppender.TOP_OF_HOUR: 397 this.set(Calendar.MINUTE, 0); 398 this.set(Calendar.SECOND, 0); 399 this.set(Calendar.MILLISECOND, 0); 400 this.add(Calendar.HOUR_OF_DAY, 1); 401 break; 402 case DailyRollingFileAppender.HALF_DAY: 403 this.set(Calendar.MINUTE, 0); 404 this.set(Calendar.SECOND, 0); 405 this.set(Calendar.MILLISECOND, 0); 406 int hour = get(Calendar.HOUR_OF_DAY); 407 if(hour < 12) { 408 this.set(Calendar.HOUR_OF_DAY, 12); 409 } else { 410 this.set(Calendar.HOUR_OF_DAY, 0); 411 this.add(Calendar.DAY_OF_MONTH, 1); 412 } 413 break; 414 case DailyRollingFileAppender.TOP_OF_DAY: 415 this.set(Calendar.HOUR_OF_DAY, 0); 416 this.set(Calendar.MINUTE, 0); 417 this.set(Calendar.SECOND, 0); 418 this.set(Calendar.MILLISECOND, 0); 419 this.add(Calendar.DATE, 1); 420 break; 421 case DailyRollingFileAppender.TOP_OF_WEEK: 422 this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek()); 423 this.set(Calendar.HOUR_OF_DAY, 0); 424 this.set(Calendar.SECOND, 0); 425 this.set(Calendar.MILLISECOND, 0); 426 this.add(Calendar.WEEK_OF_YEAR, 1); 427 break; 428 case DailyRollingFileAppender.TOP_OF_MONTH: 429 this.set(Calendar.DATE, 1); 430 this.set(Calendar.HOUR_OF_DAY, 0); 431 this.set(Calendar.SECOND, 0); 432 this.set(Calendar.MILLISECOND, 0); 433 this.add(Calendar.MONTH, 1); 434 break; 435 default: 436 throw new IllegalStateException ("Unknown periodicity type."); 437 } 438 return getTime(); 439 } 440 } 441 | Popular Tags |