blob: fd1a11d40c573fd4a90c3768695772826824ff65 [file] [log] [blame]
/*
* Copyright 1999,2004 The Apache Software Foundation.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
package org.apache.log4j.rolling.helper;
import org.apache.ugli.ULogger;
import java.text.SimpleDateFormat;
import java.util.Calendar;
import java.util.Date;
import java.util.GregorianCalendar;
import java.util.Locale;
import java.util.TimeZone;
/**
* RollingCalendar is a helper class to
* {@link org.apache.log4j.rolling.TimeBasedRollingPolicy TimeBasedRollingPolicy}
* or similar timed-based rolling policies. Given a periodicity type and the
* current time, it computes the start of the next interval.
*
* @author Ceki Gülcü
*
* */
public class RollingCalendar extends GregorianCalendar {
// The gmtTimeZone is used only in computeCheckPeriod() method.
static final TimeZone GMT_TIMEZONE = TimeZone.getTimeZone("GMT");
// The code assumes that the following constants are in a increasing
// sequence.
public static final int TOP_OF_TROUBLE = -1;
public static final int TOP_OF_SECOND = 0;
public static final int TOP_OF_MINUTE = 1;
public static final int TOP_OF_HOUR = 2;
public static final int HALF_DAY = 3;
public static final int TOP_OF_DAY = 4;
public static final int TOP_OF_WEEK = 5;
public static final int TOP_OF_MONTH = 6;
int type = TOP_OF_TROUBLE;
public RollingCalendar() {
super();
}
public RollingCalendar(TimeZone tz, Locale locale) {
super(tz, locale);
}
public void init(String datePattern) {
type = computeTriggeringPeriod(datePattern);
}
public void setType(int type) {
this.type = type;
}
public long getNextCheckMillis(Date now) {
return getNextCheckDate(now).getTime();
}
// This method computes the roll over period by looping over the
// periods, starting with the shortest, and stopping when the r0 is
// different from from r1, where r0 is the epoch formatted according
// the datePattern (supplied by the user) and r1 is the
// epoch+nextMillis(i) formatted according to datePattern. All date
// formatting is done in GMT and not local format because the test
// logic is based on comparisons relative to 1970-01-01 00:00:00
// GMT (the epoch).
public int computeTriggeringPeriod(String datePattern) {
RollingCalendar rollingCalendar =
new RollingCalendar(GMT_TIMEZONE, Locale.getDefault());
// set sate to 1970-01-01 00:00:00 GMT
Date epoch = new Date(0);
if (datePattern != null) {
for (int i = TOP_OF_SECOND; i <= TOP_OF_MONTH; i++) {
SimpleDateFormat simpleDateFormat = new SimpleDateFormat(datePattern);
simpleDateFormat.setTimeZone(GMT_TIMEZONE); // do all date formatting in GMT
String r0 = simpleDateFormat.format(epoch);
rollingCalendar.setType(i);
Date next = new Date(rollingCalendar.getNextCheckMillis(epoch));
String r1 = simpleDateFormat.format(next);
//System.out.println("Type = "+i+", r0 = "+r0+", r1 = "+r1);
if ((r0 != null) && (r1 != null) && !r0.equals(r1)) {
return i;
}
}
}
return TOP_OF_TROUBLE; // Deliberately head for trouble...
}
public void printPeriodicity(ULogger logger) {
switch (type) {
case TOP_OF_SECOND:
logger.debug("Rollover every second.");
break;
case TOP_OF_MINUTE:
logger.debug("Rollover every minute.");
break;
case TOP_OF_HOUR:
logger.debug("Rollover at the top of every hour.");
break;
case HALF_DAY:
logger.debug("Rollover at midday and midnight.");
break;
case TOP_OF_DAY:
logger.debug("Rollover at midnight.");
break;
case TOP_OF_WEEK:
logger.debug("Rollover at the start of week.");
break;
case TOP_OF_MONTH:
logger.debug("Rollover at start of every month.");
break;
default:
logger.warn("Unknown periodicity.");
}
}
public Date getNextCheckDate(Date now) {
this.setTime(now);
switch (type) {
case TOP_OF_SECOND:
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.SECOND, 1);
break;
case TOP_OF_MINUTE:
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MINUTE, 1);
break;
case TOP_OF_HOUR:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.HOUR_OF_DAY, 1);
break;
case HALF_DAY:
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
int hour = get(Calendar.HOUR_OF_DAY);
if (hour < 12) {
this.set(Calendar.HOUR_OF_DAY, 12);
} else {
this.set(Calendar.HOUR_OF_DAY, 0);
this.add(Calendar.DAY_OF_MONTH, 1);
}
break;
case TOP_OF_DAY:
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.MINUTE, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.DATE, 1);
break;
case TOP_OF_WEEK:
this.set(Calendar.DAY_OF_WEEK, getFirstDayOfWeek());
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.WEEK_OF_YEAR, 1);
break;
case TOP_OF_MONTH:
this.set(Calendar.DATE, 1);
this.set(Calendar.HOUR_OF_DAY, 0);
this.set(Calendar.SECOND, 0);
this.set(Calendar.MILLISECOND, 0);
this.add(Calendar.MONTH, 1);
break;
default:
throw new IllegalStateException("Unknown periodicity type.");
}
return getTime();
}
}