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