001/** 002 * Logback: the reliable, generic, fast and flexible logging framework. 003 * Copyright (C) 1999-2015, QOS.ch. All rights reserved. 004 * 005 * This program and the accompanying materials are dual-licensed under 006 * either the terms of the Eclipse Public License v1.0 as published by 007 * the Eclipse Foundation 008 * 009 * or (per the licensee's choosing) 010 * 011 * under the terms of the GNU Lesser General Public License version 2.1 012 * as published by the Free Software Foundation. 013 */ 014package ch.qos.logback.core.rolling; 015 016import static ch.qos.logback.core.CoreConstants.CODES_URL; 017 018import java.io.File; 019import java.time.Instant; 020import java.util.Date; 021import java.util.Locale; 022import java.util.TimeZone; 023import java.util.concurrent.atomic.AtomicLong; 024 025import ch.qos.logback.core.CoreConstants; 026import ch.qos.logback.core.rolling.helper.ArchiveRemover; 027import ch.qos.logback.core.rolling.helper.DateTokenConverter; 028import ch.qos.logback.core.rolling.helper.RollingCalendar; 029import ch.qos.logback.core.spi.ContextAwareBase; 030 031/** 032 * Base implementation of {@link TimeBasedFileNamingAndTriggeringPolicy}. 033 * 034 * <p>See also derived classes {@link DefaultTimeBasedFileNamingAndTriggeringPolicy} and 035 * {@link SizeAndTimeBasedFNATP}. 036 * 037 * </p> 038 * 039 * @param <E> 040 */ 041abstract public class TimeBasedFileNamingAndTriggeringPolicyBase<E> extends ContextAwareBase 042 implements TimeBasedFileNamingAndTriggeringPolicy<E> { 043 044 static private String COLLIDING_DATE_FORMAT_URL = CODES_URL + "#rfa_collision_in_dateFormat"; 045 046 protected TimeBasedRollingPolicy<E> tbrp; 047 048 protected ArchiveRemover archiveRemover = null; 049 protected String elapsedPeriodsFileName; 050 protected RollingCalendar rc; 051 052 protected long artificialCurrentTime = -1; 053 054 protected AtomicLong atomicNextCheck = new AtomicLong(0); 055 protected Instant dateInCurrentPeriod = null; 056 057 protected boolean started = false; 058 protected boolean errorFree = true; 059 060 public boolean isStarted() { 061 return started; 062 } 063 064 public void start() { 065 DateTokenConverter<Object> dtc = tbrp.fileNamePattern.getPrimaryDateTokenConverter(); 066 if (dtc == null) { 067 throw new IllegalStateException( 068 "FileNamePattern [" + tbrp.fileNamePattern.getPattern() + "] does not contain a valid DateToken"); 069 } 070 071 if (dtc.getZoneId() != null) { 072 TimeZone tz = TimeZone.getTimeZone(dtc.getZoneId()); 073 rc = new RollingCalendar(dtc.getDatePattern(), tz, Locale.getDefault()); 074 } else { 075 rc = new RollingCalendar(dtc.getDatePattern()); 076 } 077 addInfo("The date pattern is '" + dtc.getDatePattern() + "' from file name pattern '" 078 + tbrp.fileNamePattern.getPattern() + "'."); 079 rc.printPeriodicity(this); 080 081 if (!rc.isCollisionFree()) { 082 addError( 083 "The date format in FileNamePattern will result in collisions in the names of archived log files."); 084 addError(CoreConstants.MORE_INFO_PREFIX + COLLIDING_DATE_FORMAT_URL); 085 withErrors(); 086 return; 087 } 088 089 long timestamp = getCurrentTime(); 090 setDateInCurrentPeriod(timestamp); 091 092 if (tbrp.getParentsRawFileProperty() != null) { 093 File currentFile = new File(tbrp.getParentsRawFileProperty()); 094 if (currentFile.exists() && currentFile.canRead()) { 095 timestamp = currentFile.lastModified(); 096 setDateInCurrentPeriod(timestamp); 097 } 098 } 099 addInfo("Setting initial period to " + dateInCurrentPeriod); 100 long nextCheck = computeNextCheck(timestamp); 101 atomicNextCheck.set(nextCheck); 102 } 103 104 public void stop() { 105 started = false; 106 } 107 108 protected long computeNextCheck(long timestamp) { 109 return rc.getNextTriggeringDate(Instant.ofEpochMilli(timestamp)).toEpochMilli(); 110 } 111 112 public String getElapsedPeriodsFileName() { 113 return elapsedPeriodsFileName; 114 } 115 116 public String getCurrentPeriodsFileNameWithoutCompressionSuffix() { 117 return tbrp.fileNamePatternWithoutCompSuffix.convert(dateInCurrentPeriod); 118 } 119 120 protected void setDateInCurrentPeriod(long timestamp) { 121 dateInCurrentPeriod = Instant.ofEpochMilli(timestamp); 122 } 123 124 public void setCurrentTime(long timeInMillis) { 125 artificialCurrentTime = timeInMillis; 126 } 127 128 public long getCurrentTime() { 129 // if time is forced return the time set by user 130 if (artificialCurrentTime >= 0) { 131 return artificialCurrentTime; 132 } else { 133 return System.currentTimeMillis(); 134 } 135 } 136 137 public void setTimeBasedRollingPolicy(TimeBasedRollingPolicy<E> _tbrp) { 138 this.tbrp = _tbrp; 139 140 } 141 142 public ArchiveRemover getArchiveRemover() { 143 return archiveRemover; 144 } 145 146 protected void withErrors() { 147 errorFree = false; 148 } 149 150 protected boolean isErrorFree() { 151 return errorFree; 152 } 153 154}