/*
* JBoss, Home of Professional Open Source
* Copyright 2005, JBoss Inc., and individual contributors as indicated
* by the @authors tag. See the copyright.txt in the distribution for a
* full listing of individual contributors.
*
* This is free software; you can redistribute it and/or modify it
* under the terms of the GNU Lesser General Public License as
* published by the Free Software Foundation; either version 2.1 of
* the License, or (at your option) any later version.
*
* This software is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this software; if not, write to the Free
* Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
* 02110-1301 USA, or see the FSF site: http://www.fsf.org.
*/
package org.jbpm.env.session;
import java.text.DateFormat;
import java.text.SimpleDateFormat;
import java.util.Date;
import java.util.logging.Logger;
import org.jbpm.PvmException;
import org.jbpm.cal.BusinessCalendar;
import org.jbpm.cal.Duration;
import org.jbpm.env.Environment;
import org.jbpm.env.context.JobContext;
import org.jbpm.jobexecutor.JobSession;
import org.jbpm.pvm.Activity;
import org.jbpm.pvm.impl.ExecutionImpl;
import org.jbpm.pvm.impl.ObjectReference;
/**
* @author Tom Baeyens, Pascal Verdage
*/
public class Timer extends Job {
private static final long serialVersionUID = 1L;
private static final Logger log = Logger.getLogger(Timer.class.getName());
static BusinessCalendar businessCalendar = new BusinessCalendar();
protected String name;
protected String repeat;
protected ObjectReference<Activity> activityReference = null;
// protected String transitionName = null;
// protected ProcessElement processElement = null;
public static final String EVENT_TIMER = "timer";
public Timer() {
super();
eligibleDate = new Date(Long.MAX_VALUE);
}
public Timer(ExecutionImpl execution) {
super(execution);
eligibleDate = new Date(Long.MAX_VALUE);
}
public Timer(String name, ExecutionImpl execution) {
super(execution);
this.name = name;
if (name==null) {
throw new PvmException("timer name is null");
}
eligibleDate = new Date(Long.MAX_VALUE);
}
public Object execute(Environment environment) throws Exception {
log.info("executing timer " + this);
if (environment!=null) {
environment.addContext(new JobContext(this));
}
// // first fire the event if there is a graph element specified
// if (processElement!=null) {
// execution.fire(Timer.EVENT_TIMER, processElement);
// }
if (activityReference!=null) {
try {
activityReference.get().execute(execution);
} catch (Exception activityException) {
// NOTE that Errors are not caught because that might halt the JVM and mask the original Error.
log.warning("timer action threw exception");
// we put the exception in t
Exception t = activityException;
// try {
// // if there is a processElement connected to this timer...
// if (processElement != null) {
// // we give that processElement a chance to catch the exception
// processElement.raiseException(activityException, executionContext);
// log.warning("timer exception got handled by '"+processElement+"'");
// t = null;
// }
// } catch (Exception rethrowOrDelegationException) {
// // NOTE that Error's are not caught because that might halt the JVM and mask the original Error.
// // if the exception handler rethrows or the original exception results in a DelegationException...
// t = rethrowOrDelegationException;
// }
if (t!=null) {
// This is either the original exception wrapped as a delegation exception
// or an exception that was throws from an exception handler
throw t;
}
}
}
// // then take a transition if one is specified
// if ( (transitionName!=null)
// && (exception==null) // and if no unhandled exception occurred during the action
// ) {
// if (execution.getNode().hasLeavingTransition(transitionName)) {
// execution.takeTransition(transitionName);
// }
// }
boolean deleteThisJob = true;
// if repeat is specified, reschedule the job
if (repeat!=null) {
deleteThisJob = false;
log.finer("rescheduling the timer");
// suppose that it took the timer runner thread a
// very long time to execute the timers.
// then the repeat action eligibleDate could already have passed.
while (eligibleDate.getTime() <= System.currentTimeMillis()) {
eligibleDate =
businessCalendar.add(eligibleDate, new Duration(repeat));
}
// same for the dueDate which should be after the eligibleDate
while (dueDate.getTime() <= eligibleDate.getTime()) {
dueDate = businessCalendar.add(dueDate, new Duration(repeat));
}
log.finest("updated timer '"+this+"' for repetition in '"+
(eligibleDate.getTime()-System.currentTimeMillis())+"' millis" +
" with due date in " +
(dueDate.getTime()-System.currentTimeMillis())+"' millis");
// release the lock on the timer
setLockOwner(null);
setLockExpirationTime(null);
} else {
// else delete the job
log.finer("deleting the timer");
environment.get(JobSession.class).delete(this);
}
return deleteThisJob;
}
static DateFormat dateFormat = new SimpleDateFormat("HH:mm:ss,SSS");
@Override
public String toString() {
StringBuffer buffer = new StringBuffer();
buffer.append("timer");
if ( (name!=null)
|| (dueDate!=null)
) {
buffer.append("(");
if (name!=null) {
buffer.append(name);
if (dueDate!=null) {
buffer.append(",");
buffer.append(dateFormat.format(dueDate));
}
} else {
buffer.append(dateFormat.format(dueDate));
}
buffer.append(")");
}
return buffer.toString();
}
public String getRepeat() {
return repeat;
}
public void setRepeat(String repeat) {
this.repeat = repeat;
}
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
public ObjectReference<Activity> getActivityReference() {
return activityReference;
}
public void setActivityReference(ObjectReference<Activity> activityReference) {
this.activityReference = activityReference;
}
}