/**
* Copyright (c) 2014-2017 by the respective copyright holders.
* All rights reserved. This program and the accompanying materials
* are made available under the terms of the Eclipse Public License v1.0
* which accompanies this distribution, and is available at
* http://www.eclipse.org/legal/epl-v10.html
*/
package org.eclipse.smarthome.model.script.internal.actions;
import static org.quartz.TriggerBuilder.newTrigger;
import org.eclipse.smarthome.model.script.actions.Timer;
import org.joda.time.DateTime;
import org.joda.time.base.AbstractInstant;
import org.quartz.JobExecutionContext;
import org.quartz.JobKey;
import org.quartz.Scheduler;
import org.quartz.SchedulerException;
import org.quartz.Trigger;
import org.quartz.TriggerKey;
import org.quartz.impl.StdSchedulerFactory;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
/**
* This is an implementation of the {@link Timer} interface using the Quartz
* library for scheduling.
*
* @author Kai Kreuzer - Initial contribution and API
*
*/
public class TimerImpl implements Timer {
private final Logger logger = LoggerFactory.getLogger(TimerImpl.class);
// the scheduler used for timer events
public static Scheduler scheduler;
static {
try {
scheduler = StdSchedulerFactory.getDefaultScheduler();
} catch (SchedulerException e) {
LoggerFactory.getLogger(TimerImpl.class).error("initializing scheduler throws exception", e);
}
}
private JobKey jobKey;
private TriggerKey triggerKey;
private AbstractInstant startTime;
private boolean cancelled = false;
private boolean terminated = false;
public TimerImpl(JobKey jobKey, TriggerKey triggerKey, AbstractInstant startTime) {
this.jobKey = jobKey;
this.triggerKey = triggerKey;
this.startTime = startTime;
}
@Override
public boolean cancel() {
try {
boolean result = scheduler.deleteJob(jobKey);
if (result) {
cancelled = true;
}
} catch (SchedulerException e) {
logger.warn("An error occurred while cancelling the job '{}': {}", jobKey.toString(), e.getMessage());
}
return cancelled;
}
@Override
public boolean reschedule(AbstractInstant newTime) {
try {
Trigger trigger = newTrigger().startAt(newTime.toDate()).build();
scheduler.rescheduleJob(triggerKey, trigger);
this.triggerKey = trigger.getKey();
this.cancelled = false;
this.terminated = false;
return true;
} catch (SchedulerException e) {
logger.warn("An error occurred while rescheduling the job '{}': {}", jobKey.toString(), e.getMessage());
return false;
}
}
@Override
public boolean isRunning() {
try {
for (JobExecutionContext context : scheduler.getCurrentlyExecutingJobs()) {
if (context.getJobDetail().getKey().equals(jobKey)) {
return true;
}
}
return false;
} catch (SchedulerException e) {
// fallback implementation
logger.debug("An error occurred getting currently running jobs: {}", e.getMessage());
return DateTime.now().isAfter(startTime) && !terminated;
}
}
@Override
public boolean hasTerminated() {
return terminated;
}
public void setTerminated(boolean terminated) {
this.terminated = terminated;
}
}