/** * Copyright 2010 JBoss Inc * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.drools.process.instance.timer; import java.util.Collection; import java.util.Date; import java.util.HashMap; import java.util.Map; import org.drools.common.InternalKnowledgeRuntime; import org.drools.process.instance.InternalProcessRuntime; import org.drools.process.instance.ProcessInstance; import org.drools.time.Job; import org.drools.time.JobContext; import org.drools.time.JobHandle; import org.drools.time.TimerService; import org.drools.time.impl.IntervalTrigger; /** * * @author <a href="mailto:kris_verlaenen@hotmail.com">Kris Verlaenen</a> */ public class TimerManager { private long timerId = 0; private InternalKnowledgeRuntime kruntime; private TimerService timerService; private Map<Long, TimerInstance> timers = new HashMap<Long, TimerInstance>(); private Job processJob = new ProcessJob(); public TimerManager(InternalKnowledgeRuntime kruntime, TimerService timerService) { this.kruntime = kruntime; this.timerService = timerService; } public void registerTimer(final TimerInstance timer, ProcessInstance processInstance) { timer.setId( ++timerId ); timer.setProcessInstanceId( processInstance.getId() ); timer.setActivated( new Date() ); ProcessJobContext ctx = new ProcessJobContext( timer, processInstance.getId(), this.kruntime ); JobHandle jobHandle = this.timerService.scheduleJob( processJob, ctx, new IntervalTrigger( timerService.getCurrentTime(), null, null, -1, timer.getDelay(), timer.getPeriod(), null, null ) ); timer.setJobHandle( jobHandle ); timers.put( timer.getId(), timer ); } public void internalAddTimer(final TimerInstance timer) { ProcessJobContext ctx = new ProcessJobContext( timer, timer.getProcessInstanceId(), this.kruntime ); long delay; Date lastTriggered = timer.getLastTriggered(); if ( lastTriggered == null ) { Date activated = timer.getActivated(); Date now = new Date(); long timespan = now.getTime() - activated.getTime(); delay = timer.getDelay() - timespan; if ( delay < 0 ) { delay = 0; } } else { Date now = new Date(); long timespan = now.getTime() - lastTriggered.getTime(); delay = timespan - timer.getPeriod(); if ( delay < 0 ) { delay = 0; } } JobHandle jobHandle = this.timerService.scheduleJob( processJob, ctx, new IntervalTrigger( timerService.getCurrentTime(), null, null, -1, delay, timer.getPeriod(), null, null ) ); timer.setJobHandle( jobHandle ); timers.put( timer.getId(), timer ); } public void cancelTimer(long timerId) { TimerInstance timer = timers.remove( timerId ); if ( timer != null ) { timerService.removeJob( timer.getJobHandle() ); } } public void dispose() { for ( TimerInstance timer : timers.values() ) { timerService.removeJob( timer.getJobHandle() ); } timerService.shutdown(); } public TimerService getTimerService() { return this.timerService; } public Collection<TimerInstance> getTimers() { return timers.values(); } public long internalGetTimerId() { return timerId; } public void internalSetTimerId(long timerId) { this.timerId = timerId; } public void setTimerService(TimerService timerService) { this.timerService = timerService; } public class ProcessJob implements Job { public void execute(JobContext c) { ProcessJobContext ctx = (ProcessJobContext) c; Long processInstanceId = ctx.getProcessInstanceId(); InternalKnowledgeRuntime kruntime = ctx.getKnowledgeRuntime(); if ( processInstanceId == null ) { throw new IllegalArgumentException( "Could not find process instance for timer " ); } ctx.getTimer().setLastTriggered( new Date() ); ((InternalProcessRuntime) kruntime.getProcessRuntime()) .getSignalManager().signalEvent( processInstanceId, "timerTriggered", ctx.getTimer() ); if ( ctx.getTimer().getPeriod() == 0 ) { TimerManager.this.timers.remove( ctx.getTimer().getId() ); } } } public static class ProcessJobContext implements JobContext { private Long processInstanceId; private InternalKnowledgeRuntime kruntime; private TimerInstance timer; private JobHandle jobHandle; public ProcessJobContext(final TimerInstance timer, final Long processInstanceId, final InternalKnowledgeRuntime kruntime) { this.timer = timer; this.processInstanceId = processInstanceId; this.kruntime = kruntime; } public Long getProcessInstanceId() { return processInstanceId; } public InternalKnowledgeRuntime getKnowledgeRuntime() { return kruntime; } public JobHandle getJobHandle() { return this.jobHandle; } public void setJobHandle(JobHandle jobHandle) { this.jobHandle = jobHandle; } public TimerInstance getTimer() { return timer; } } }