// Copyright (c) 2001 Dustin Sallings <dustin@spy.net>
package net.spy.cron;
import java.util.Date;
import net.spy.SpyObject;
/**
* All Jobs should implement this interface.
*/
public abstract class Job extends SpyObject implements Runnable {
// The next time the job is due to start.
private Date nextStart=null;
// How to increment the time value in the case of recurring jobs.
private TimeIncrement increment=null;
// Whether the job is currently running or not
private volatile boolean isrunning=false;
// The name of ths thing
private String name=null;
/**
* Get a new Job with the given name and start date.
*/
public Job(String nm, Date startDate) {
this(nm, startDate, null);
}
/**
* Get a new recurring Job with the given name and start date that will
* run on an interval defined by the TimeIncrement.
*/
public Job(String nm, Date startDate, TimeIncrement ti) {
super();
nextStart=startDate;
this.increment=ti;
setName(nm);
}
/**
* Get a string representation of this Job.
*/
@Override
public String toString() {
return("Job:" + getName());
}
/**
* Set the name of this thing.
*/
public void setName(String to) {
name=to;
}
/**
* Get the name of this thing.
*/
public String getName() {
return(name);
}
/**
* Get the time this job was requested to start.
*/
public synchronized Date getStartTime() {
return(nextStart);
}
/**
* Set the next time the job is due to start.
*/
public void setStartTime(Date to) {
nextStart=to;
}
/**
* Is this Job ready to go?
*/
public boolean isReady() {
boolean rv=false;
// Short circuit a null nextStart Date.
if(nextStart==null) {
return(false);
}
long now=System.currentTimeMillis();
// If the time is current or has passed, and the job is not
// currently running, then it's ready to run.
if((nextStart.getTime() <= now) && (!isAlive())) {
rv=true;
}
return(rv);
}
/**
* Mark started, call runJob, then mark finished.
*/
public final void run() {
markStarted();
runJob();
markFinished();
}
/**
* Subclasses of Job should extend this method to implement their
* running.
*/
protected abstract void runJob();
/**
* Is this Job ready to be thrown away?
*/
public boolean isTrash() {
// When nextStart is null, we won't be starting again.
return(nextStart==null);
}
/**
* Get the current TimeIncrement object incrementing the time on this job.
*
* @return the TimeIncrement
*/
protected TimeIncrement getTimeIncrement() {
return(increment);
}
/**
* Mark this job as having been started.
*/
protected void markStarted() {
isrunning=true;
}
/**
* Find the next time this Job should be run and adjust the start date
* accordingly.
*
* This method will be called by JobQueue when looking for tasks to
* run.
*/
public final synchronized void findNextRun() {
if(increment == null) {
nextStart = null;
getLogger().debug("I have no time increment, not rescheduling");
} else {
Date now=new Date();
while(nextStart.before(now)) {
nextStart=increment.nextDate(nextStart);
}
getLogger().debug("Rescheduled %s for %s", this, nextStart);
}
}
/**
* Stop this job from running.
*/
protected void stopRunning() {
nextStart=null;
increment=null;
}
/**
* Is this job alive (is it running)?
*/
public boolean isAlive() {
return(isrunning);
}
/**
* Mark this job as having stopped running.
*/
protected void markFinished() {
isrunning=false;
}
}