package co.codewizards.cloudstore.server;
import java.util.Date;
import java.util.Timer;
import java.util.TimerTask;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import co.codewizards.cloudstore.core.config.Config;
import co.codewizards.cloudstore.core.config.ConfigImpl;
import co.codewizards.cloudstore.core.updater.CloudStoreUpdaterCore;
public class CloudStoreUpdaterTimer {
/**
* Default value for {@link #CONFIG_KEY_TIMER_PERIOD} (15 minutes in milliseconds).
*/
public static final long DEFAULT_TIMER_PERIOD = 15 * 60 * 1000;
/**
* Configuration property key controlling how many milliseconds the timer waits between
* invocations of {@link CloudStoreUpdaterCore#createUpdaterDirIfUpdateNeeded()}.
* <p>
* Important: Setting this to 5 minutes does not necessarily mean that an update will be done
* 5 minutes after the new version was released. There's a local cache and a new release is only detected
* after this cache expired -- see {@link CloudStoreUpdaterCore#CONFIG_KEY_REMOTE_VERSION_CACHE_VALIDITY_PERIOD}.
* <p>
* The configuration can be overridden by a system property - see {@link Config#SYSTEM_PROPERTY_PREFIX}.
*
* @see #DEFAULT_TIMER_PERIOD
*/
public static final String CONFIG_KEY_TIMER_PERIOD = "updater.timer.period";
/**
* The timer-period for the very first check, done after {@link #start()} (30 seconds in milliseconds).
* <p>
* Important: This is also the time it takes until the "updater/"-directory from a previous
* update is deleted.
*/
private static final long ON_START_TIMER_PERIOD = 30 * 1000;
private static final Logger logger = LoggerFactory.getLogger(CloudStoreUpdaterTimer.class);
private Timer timer;
private TimerTask timerTask;
public CloudStoreUpdaterTimer() {
}
public synchronized void start() {
if (timer == null)
schedule(true);
}
public synchronized void stop() {
cancelTimerTask();
cancelTimer();
}
protected synchronized void schedule(final boolean onStart) {
cancelTimerTask();
final long timerPeriod = getTimerPeriod();
if (timerPeriod <= 0) {
logger.info("schedule: timerPeriod={}. Disabling this timer!", timerPeriod);
cancelTimer();
return;
}
if (timer == null)
timer = new Timer("CloudStoreUpdaterTimer");
if (timerTask != null) // due to cancelTimerTask() above, this should never happen!
throw new IllegalStateException("timerTask != null");
timerTask = new TimerTask() {
@Override
public void run() {
try {
CloudStoreUpdaterTimer.this.run();
schedule(false); // reschedule, because we always schedule without period (one time execution).
} catch (Exception x) {
logger.error("timerTask.run: " + x, x);
}
}
};
final Date nextRun;
if (onStart) {
nextRun = new Date(System.currentTimeMillis() + ON_START_TIMER_PERIOD);
logger.info("schedule: onStart=true nextRun={}", nextRun);
}
else {
nextRun = new Date(System.currentTimeMillis() + timerPeriod);
logger.info("schedule: timerPeriod={} nextRun={}", timerPeriod, nextRun);
}
timer.schedule(timerTask, nextRun);
}
protected synchronized void cancelTimerTask() {
if (timerTask != null) {
timerTask.cancel();
timerTask = null;
}
}
protected synchronized void cancelTimer() {
if (timer != null) {
timer.cancel();
timer = null;
}
}
protected long getTimerPeriod() {
final Config config = ConfigImpl.getInstance();
return config.getPropertyAsLong(CONFIG_KEY_TIMER_PERIOD, DEFAULT_TIMER_PERIOD);
}
protected void run() {
final boolean updateNeeded = new CloudStoreUpdaterCore().createUpdaterDirIfUpdateNeeded();
if (updateNeeded)
System.exit(0);
}
}