package eu.dnetlib.enabling.tools; import java.text.ParseException; import javax.annotation.PostConstruct; import javax.annotation.Resource; import org.quartz.*; import org.quartz.Trigger.TriggerState; import org.quartz.impl.JobDetailImpl; import org.quartz.impl.triggers.CronTriggerImpl; import org.springframework.beans.factory.BeanNameAware; import org.springframework.beans.factory.annotation.Required; /** * Common implementation for schedulable beans. * * @author claudio * */ public abstract class AbstractSchedulable implements Schedulable, Job, BeanNameAware { private static final String THIS = "this"; private final static String GROUP = "schedulableJobs"; private boolean enabled; private CronExpression cronExpression; private String beanName; @Resource(name = "dnetJobScheduler") private Scheduler jobScheduler; @PostConstruct protected void init() { try { JobDataMap jobDataMap = new JobDataMap(); jobDataMap.put(THIS, this); JobDetailImpl jd = new JobDetailImpl(); jd.setName(getBeanName()); jd.setGroup(GROUP); jd.setJobDataMap(jobDataMap); jd.setJobClass(this.getClass()); jobScheduler.scheduleJob(jd, createTrigger()); } catch (SchedulerException e) { throw new RuntimeException(e); } } private Trigger createTrigger() { try { CronTriggerImpl trigger = new CronTriggerImpl(getBeanName(), GROUP, getCronExpression()); trigger.setMisfireInstruction(Trigger.MISFIRE_INSTRUCTION_IGNORE_MISFIRE_POLICY); trigger.setJobGroup(GROUP); trigger.setJobName(getBeanName()); return trigger; } catch (ParseException e) { throw new IllegalArgumentException("invalid cron expression: " + cronExpression, e); } } protected abstract void doExecute(); @Override public void execute() { // bean represents the quartz instance of this object if (isEnabled()) { doExecute(); } } @Override public void execute(JobExecutionContext context) throws JobExecutionException { AbstractSchedulable bean = (AbstractSchedulable) context.getJobDetail().getJobDataMap().get(THIS); // bean represents the quartz instance of this object if (bean.isEnabled()) { bean.doExecute(); } } @Override public boolean isEnabled() { return enabled; } @Override public void setEnabled(boolean enabled) { this.enabled = enabled; } @Override public String getCronExpression() { return cronExpression.getCronExpression(); } @Required public void setCronExpression(String cronExpression) { try { this.cronExpression = new CronExpression(cronExpression); } catch (ParseException e) { throw new IllegalArgumentException("invalid cron expression: " + cronExpression, e); } } @Override public void updateCronExpression(String cronExpression) { if (!cronExpression.equals(getCronExpression())) { setCronExpression(cronExpression); try { final TriggerKey tk = new TriggerKey(getBeanName()); jobScheduler.rescheduleJob(tk, createTrigger()); } catch (SchedulerException e) { throw new RuntimeException("unable to reschedule trigger", e); } } } @Override public String getNextFireTime() { try { if (isPaused()) { return ""; } if (!isEnabled()) { return ""; } final TriggerKey tk = new TriggerKey(getBeanName()); final Trigger t = jobScheduler.getTrigger(tk); return t != null ? t.getNextFireTime().toString() : ""; } catch (SchedulerException e) { throw new RuntimeException("unable to get trigger", e); } } @Override public boolean isPaused() { try { final TriggerKey tk = new TriggerKey(getBeanName()); final TriggerState state = jobScheduler.getTriggerState(tk); switch (state) { case PAUSED: case NONE: case ERROR: return true; default: return false; } } catch (SchedulerException e) { throw new RuntimeException("unable to get trigger", e); } } @Override public void pause() { try { final TriggerKey tk = new TriggerKey(getBeanName()); jobScheduler.pauseTrigger(tk); } catch (SchedulerException e) { throw new RuntimeException("unable to pause trigger", e); } } @Override public void resume() { try { final TriggerKey tk = new TriggerKey(getBeanName()); jobScheduler.resumeTrigger(tk); } catch (SchedulerException e) { throw new RuntimeException("unable to resume trigger", e); } } public String getBeanName() { return beanName; } @Override @Required public void setBeanName(String beanName) { this.beanName = beanName; } }