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