package org.jboss.seam.async; import java.lang.annotation.Annotation; import java.util.Date; import org.jboss.seam.Component; import org.jboss.seam.annotations.async.Duration; import org.jboss.seam.annotations.async.Expiration; import org.jboss.seam.annotations.async.FinalExpiration; import org.jboss.seam.annotations.async.IntervalCron; import org.jboss.seam.annotations.async.IntervalDuration; import org.jboss.seam.contexts.Contexts; import org.jboss.seam.intercept.InvocationContext; import org.jboss.seam.transaction.Transaction; /** * Abstract Dispatcher implementation * * @author Gavin King * */ public abstract class AbstractDispatcher<T, S extends Schedule> implements Dispatcher<T, S> { public class DispatcherParameters { private Date expiration; private Date finalExpiration; private Long duration; private Long intervalDuration; private String intervalCron; public String getIntervalCron() { return intervalCron; } public Long getDuration() { return duration; } public Date getExpiration() { return expiration; } public Date getFinalExpiration() { return finalExpiration; } public Long getIntervalDuration() { return intervalDuration; } public void setIntervalCron(String cron) { this.intervalCron = cron; } public void setDuration(Long duration) { this.duration = duration; } public void setExpiration(Date expiration) { this.expiration = expiration; } public void setFinalExpiration(Date finalExpiration) { this.finalExpiration = finalExpiration; } public void setIntervalDuration(Long intervalDuration) { this.intervalDuration = intervalDuration; } } public static final String EXECUTING_ASYNCHRONOUS_CALL = "org.jboss.seam.core.executingAsynchronousCall"; public static Dispatcher instance() { if ( !Contexts.isApplicationContextActive() ) { throw new IllegalStateException("no application context active"); } return (Dispatcher) Component.getInstance("org.jboss.seam.async.dispatcher"); } public void scheduleTransactionSuccessEvent(String type, Object... parameters) { Transaction.instance().registerSynchronization( new TransactionSuccessEvent(type, parameters) ); } public void scheduleTransactionCompletionEvent(String type, Object... parameters) { Transaction.instance().registerSynchronization( new TransactionCompletionEvent(type, parameters) ); } protected Schedule createSchedule(InvocationContext invocation) { DispatcherParameters dispatcherParameters = extractAndValidateParameters(invocation); if (dispatcherParameters.getIntervalCron() == null) { return new TimerSchedule(dispatcherParameters.getDuration(), dispatcherParameters.getExpiration(), dispatcherParameters.getIntervalDuration(), dispatcherParameters.getFinalExpiration()); } else { return new CronSchedule(dispatcherParameters.getDuration(), dispatcherParameters.getExpiration(), dispatcherParameters.getIntervalCron(), dispatcherParameters.getFinalExpiration()); } } protected TimerSchedule createTimerSchedule(InvocationContext invocation) { DispatcherParameters dispatcherParameters = extractAndValidateParameters(invocation); return createTimerSchedule(dispatcherParameters); } private TimerSchedule createTimerSchedule(DispatcherParameters dispatcherParameters) { return new TimerSchedule(dispatcherParameters.getDuration(), dispatcherParameters.getExpiration(), dispatcherParameters.getIntervalDuration(), dispatcherParameters.getFinalExpiration()); } protected DispatcherParameters extractAndValidateParameters(InvocationContext invocation) { DispatcherParameters dispatcherParameters = new DispatcherParameters(); for ( int i=0; i < invocation.getMethod().getParameterAnnotations().length; i++ ) { Annotation[] annotations = invocation.getMethod().getParameterAnnotations()[i]; for (Annotation annotation: annotations) { if ( annotation.annotationType().equals(Duration.class) ) { if (invocation.getParameters()[i] instanceof Long) { dispatcherParameters.setDuration((Long) invocation.getParameters()[i]); } else if (invocation.getParameters()[i] != null) { throw new IllegalArgumentException("@Duration on " + invocation.getTarget().getClass() + ":" + invocation.getMethod().getName() + " must be a Long"); } } else if ( annotation.annotationType().equals(Expiration.class) ) { if (invocation.getParameters()[i] instanceof Date) { dispatcherParameters.setExpiration((Date) invocation.getParameters()[i]); } else if (invocation.getParameters()[i] != null) { throw new IllegalArgumentException("@Expiration on " + invocation.getTarget().getClass() + ":" + invocation.getMethod().getName() + " must be a java.util.Date"); } } else if ( annotation.annotationType().equals(FinalExpiration.class) ) { if (!( this instanceof QuartzDispatcher )) { throw new IllegalArgumentException("Can only use @FinalExpiration with the QuartzDispatcher"); } else if (invocation.getParameters()[i] instanceof Date) { dispatcherParameters.setFinalExpiration((Date) invocation.getParameters()[i]); } else if (invocation.getParameters()[i] != null) { throw new IllegalArgumentException("@FinalExpiration on " + invocation.getTarget().getClass() + ":" + invocation.getMethod().getName() + " must be a java.util.Date"); } } else if ( annotation.annotationType().equals(IntervalCron.class) ) { if (!( this instanceof QuartzDispatcher )) { throw new IllegalArgumentException("Can only use @IntervalCron with the QuartzDispatcher"); } else if (invocation.getParameters()[i] instanceof String) { dispatcherParameters.setIntervalCron((String) invocation.getParameters()[i]); } else if (invocation.getParameters()[i] != null) { throw new IllegalArgumentException("@IntervalCron on " + invocation.getTarget().getClass() + ":" + invocation.getMethod().getName() + " must be a String"); } } else if ( annotation.annotationType().equals(IntervalDuration.class) ) { if (invocation.getParameters()[i] instanceof Long) { dispatcherParameters.setIntervalDuration((Long) invocation.getParameters()[i]); } else if (invocation.getParameters()[i] != null) { throw new IllegalArgumentException("@IntervalDuration on " + invocation.getTarget().getClass() + ":" + invocation.getMethod().getName() + " must be a Long"); } } } } if ( dispatcherParameters.getIntervalCron() != null && dispatcherParameters.getIntervalDuration() != null ) { throw new IllegalArgumentException("Can only use one of @IntervalCron and @IntervalDuration"); } return dispatcherParameters; } }