package org.jboss.seam.async;
import static org.jboss.seam.annotations.Install.BUILT_IN;
import java.io.Serializable;
import java.util.Date;
import java.util.concurrent.Callable;
import javax.annotation.PostConstruct;
import javax.annotation.Resource;
import javax.ejb.EJBException;
import javax.ejb.NoSuchObjectLocalException;
import javax.ejb.Stateless;
import javax.ejb.Timeout;
import javax.ejb.Timer;
import javax.ejb.TimerHandle;
import javax.ejb.TimerService;
import javax.interceptor.Interceptors;
import org.jboss.seam.Component;
import org.jboss.seam.annotations.Install;
import org.jboss.seam.annotations.Name;
import org.jboss.seam.ejb.SeamInterceptor;
import org.jboss.seam.intercept.InvocationContext;
/**
* Dispatcher implementation that uses the EJB
* TimerService.
*
* @author Gavin King
*
*/
@Stateless
@Name("org.jboss.seam.async.dispatcher")
@Interceptors(SeamInterceptor.class)
@Install(value=false, precedence=BUILT_IN)
public class TimerServiceDispatcher
extends AbstractDispatcher<Timer, TimerSchedule>
implements LocalTimerServiceDispatcher
{
@Resource TimerService timerService;
@PostConstruct
public void postConstruct() {} //workaround for a bug in EJB3
@Timeout
public void dispatch(Timer timer)
{
( (Asynchronous) timer.getInfo() ).execute(timer);
}
public Timer scheduleTimedEvent(String type, TimerSchedule schedule, Object... parameters)
{
return new TimerProxy( scheduleWithTimerService( schedule, new AsynchronousEvent(type, parameters) ) );
}
public Timer scheduleAsynchronousEvent(String type, Object... parameters)
{
return new TimerProxy( timerService.createTimer( 0l, new AsynchronousEvent(type, parameters) ) );
}
public Timer scheduleInvocation(InvocationContext invocation, Component component)
{
return new TimerProxy( scheduleWithTimerService( (TimerSchedule) createSchedule(invocation), new AsynchronousInvocation(invocation, component) ) );
}
private Timer scheduleWithTimerService(TimerSchedule schedule, Asynchronous asynchronous)
{
if ( schedule.getIntervalDuration()!=null )
{
if ( schedule.getExpiration()!=null )
{
return timerService.createTimer( schedule.getExpiration(), schedule.getIntervalDuration(), asynchronous );
}
else if ( schedule.getDuration()!=null )
{
return timerService.createTimer( schedule.getDuration(), schedule.getIntervalDuration(), asynchronous );
}
else
{
return timerService.createTimer( 0l, schedule.getIntervalDuration(), asynchronous );
}
}
else if ( schedule.getExpiration()!=null )
{
return timerService.createTimer( schedule.getExpiration(), asynchronous );
}
else if ( schedule.getDuration()!=null )
{
return timerService.createTimer( schedule.getDuration(), asynchronous );
}
else
{
return timerService.createTimer(0l, asynchronous);
}
}
static class TimerProxy
implements Timer
{
Timer timer;
public TimerProxy(Timer timer)
throws IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
this.timer = timer;
}
public void cancel()
throws
IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
instance().call(new Callable() {
public Object call()
{
timer.cancel();
return null;
}
});
}
public TimerHandle getHandle()
throws
IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
TimerHandle handle = (TimerHandle)
instance().call(new Callable() {
public Object call()
{
return timer.getHandle();
}
});
return new TimerHandleProxy(handle);
}
public Serializable getInfo()
throws
IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
return (Serializable)
instance().call(new Callable() {
public Object call()
{
return timer.getInfo();
}
});
}
public Date getNextTimeout()
throws
IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
return (Date)
instance().call(new Callable() {
public Object call()
{
return timer.getNextTimeout();
}
});
}
public long getTimeRemaining()
throws IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
return (Long)
instance().call(new Callable() {
public Object call()
{
return timer.getTimeRemaining();
}
});
}
}
static class TimerHandleProxy
implements TimerHandle,
Serializable
{
private static final long serialVersionUID = 6913362944260154627L;
TimerHandle handle;
public TimerHandleProxy(TimerHandle handle)
{
this.handle = handle;
}
public Timer getTimer()
throws IllegalStateException,
NoSuchObjectLocalException,
EJBException
{
Timer timer = (Timer) instance().call(new Callable() {
public Object call()
{
try
{
return handle.getTimer();
}
catch (NoSuchObjectLocalException nsoe)
{
return null;
}
}
});
if (timer==null)
{
throw new NoSuchObjectLocalException();
}
else
{
return new TimerProxy(timer);
}
}
}
public Object call(Callable task)
{
try
{
return task.call();
}
catch (RuntimeException e)
{
// just pass along runtime exceptions
throw e;
}
catch (Exception e)
{
throw new RuntimeException(e);
}
}
public static LocalTimerServiceDispatcher instance()
{
return ( (LocalTimerServiceDispatcher) AbstractDispatcher.instance() );
}
}