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