package org.jblooming.scheduler;
import org.jblooming.PlatformRuntimeException;
import org.jblooming.waf.ActionUtilities;
import org.jblooming.persistence.hibernate.PersistenceContext;
import org.jblooming.persistence.hibernate.HibernateFactory;
import org.jblooming.persistence.exceptions.PersistenceException;
import org.jblooming.persistence.PersistenceHome;
import org.jblooming.ontology.IdentifiableSupport;
import org.jblooming.utilities.ReflectionUtilities;
import org.jblooming.agenda.ScheduleSupport;
import java.util.*;
import java.lang.reflect.Field;
/**
* @author Pietro Polsinelli ppolsinelli@open-lab.com
* @author Roberto Bicchierai rbicchierai@open-lab.com
*/
public class Job extends IdentifiableSupport implements Runnable {
protected ScheduleSupport schedule;
protected String executable;
protected Map<String, String> parameters = new HashMap();
protected String name;
protected String description;
protected int estimatedDuration;
protected boolean onErrorRetryNow = true;
protected boolean onErrorSuspendScheduling = false;
protected boolean enabled = true;
protected long timeoutTime = 0;
private long lastExecutionTime = 0;
//not persistent
private long startedOn;
private long secondLastExecutionTime;
//read only collections
//private Set<JobLog> jobLogs = new TreeSet();
public Job() {
}
public Job(String executable, ScheduleSupport schedule) {
try {
if (! (Class.forName(executable).newInstance() instanceof Executable))
throw new PlatformRuntimeException("Executable required");
this.executable = executable;
} catch (InstantiationException e) {
throw new PlatformRuntimeException(e);
} catch (IllegalAccessException e) {
throw new PlatformRuntimeException(e);
} catch (ClassNotFoundException e) {
throw new PlatformRuntimeException(e);
}
this.schedule = schedule;
}
public Map<String, String> getParameters() {
return parameters;
}
public void setParameters(Map<String, String> parameters) {
this.parameters = parameters;
}
public ScheduleSupport getSchedule() {
return schedule;
}
public void setSchedule(ScheduleSupport schedule) {
this.schedule = schedule;
}
public int getEstimatedDuration() {
return estimatedDuration;
}
public void setEstimatedDuration(int estimatedDuration) {
this.estimatedDuration = estimatedDuration;
}
public String getExecutable() {
return executable;
}
public void setExecutable(String executable) {
this.executable = executable;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public String getDescription() {
return description;
}
public void setDescription(String description) {
this.description = description;
}
public boolean isEnabled() {
return enabled;
}
public void setEnabled(boolean enabled) {
this.enabled = enabled;
}
public void run() {
boolean exception = true;
Exception exc = null;
this.startedOn = System.currentTimeMillis();
Executable executable = null;
try {
executable = (Executable) Class.forName(this.getExecutable()).newInstance();
} catch (InstantiationException e) {
throw new PlatformRuntimeException(e);
} catch (IllegalAccessException e) {
throw new PlatformRuntimeException(e);
} catch (ClassNotFoundException e) {
throw new PlatformRuntimeException(e);
}
//refresh persistent job
PersistenceContext pc=null;
try {
pc = PersistenceContext.getDefaultPersistenceContext();
Job persJob = (Job) PersistenceHome.findByPrimaryKey(Job.class, getId());
Map<String, String> parameters = persJob.getParameters();
for (String fieldName : parameters.keySet()) {
String value = parameters.get(fieldName);
Field field = ReflectionUtilities.getField(fieldName, executable.getClass());
field.setAccessible(true);
try {
// todo get the right type
field.set(executable, value);
} catch (IllegalAccessException e) {
exc = e;
}
}
pc.commitAndClose();
} catch (PersistenceException e) {
if (pc!=null)
pc.rollbackAndClose();
throw new PlatformRuntimeException(e);
}
JobLogData jobLogData = null;
try {
jobLogData = executable.runAndLog(this);
if (exc == null)
exception = false;
} catch (Exception e) {
exc = e;
} finally {
if (exception) {
if (jobLogData == null) {
jobLogData = new JobLogData();
jobLogData.id = this.id;
jobLogData.date = new Date();
}
if (exc != null)
jobLogData.notes = jobLogData.notes + exc.getMessage();
else
jobLogData.notes = jobLogData.notes + "Run failed with Runtime, so no message available; see the container logs.";
jobLogData.successfull = false;
}
}
Scheduler.getInstance().addJobLogData(jobLogData);
}
public boolean isOnErrorRetryNow() {
return onErrorRetryNow;
}
public void setOnErrorRetryNow(boolean onErrorRetryNow) {
this.onErrorRetryNow = onErrorRetryNow;
}
public boolean isOnErrorSuspendScheduling() {
return onErrorSuspendScheduling;
}
public void setOnErrorSuspendScheduling(boolean onErrorSuspendScheduling) {
this.onErrorSuspendScheduling = onErrorSuspendScheduling;
}
public long getTimeoutTime() {
return timeoutTime;
}
public void setTimeoutTime(long timeoutTime) {
this.timeoutTime = timeoutTime;
}
/*public synchronized void addJobLog(JobLog jobLog) {
jobLogs.add(jobLog);
}
public JobLog getLastLog() {
TreeSet<JobLog> jl = new TreeSet(jobLogs);
return jl.last();
}*/
public long getStartedOn() {
return startedOn;
}
private void setStartedOn(long startedOn) {
this.startedOn = startedOn;
}
/* private Set<JobLog> getJobLogs() {
return jobLogs;
}
private void setJobLogs(Set<JobLog> jobLogs) {
this.jobLogs = jobLogs;
}*/
public long getLastExecutionTime() {
return lastExecutionTime;
}
private void setLastExecutionTime(long lastExecutionTime) {
this.lastExecutionTime = lastExecutionTime;
}
public void resetLastExecutionTime(){
secondLastExecutionTime=getLastExecutionTime();
setLastExecutionTime(System.currentTimeMillis());
}
public long getSecondLastExecutionTime() {
return secondLastExecutionTime;
}
}