djencks 2004/07/18 18:24:01
Added: modules/core/src/java/org/openejb/timer
EJBTimeoutInvocationFactory.java
StatelessEJBInvocationFactoryImpl.java
TimerHandleImpl.java TimerImpl.java
TimerServiceImpl.java
Log:
timer implementation
Revision Changes Path
1.1
openejb/modules/core/src/java/org/openejb/timer/EJBTimeoutInvocationFactory.java
Index: EJBTimeoutInvocationFactory.java
===================================================================
package org.openejb.timer;
import org.openejb.EJBInvocation;
/**
*
*
* @version $Revision: 1.1 $ $Date: 2004/07/18 22:24:00 $
*
* */
public interface EJBTimeoutInvocationFactory {
EJBInvocation getEJBTimeoutInvocation(TimerImpl timer);
}
1.1
openejb/modules/core/src/java/org/openejb/timer/StatelessEJBInvocationFactoryImpl.java
Index: StatelessEJBInvocationFactoryImpl.java
===================================================================
/* ====================================================================
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided
* that the following conditions are met:
*
* 1. Redistributions of source code must retain copyright
* statements and notices. Redistributions must also contain a
* copy of this document.
*
* 2. Redistributions in binary form must reproduce this list of
* conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name "OpenEJB" must not be used to endorse or promote
* products derived from this Software without prior written
* permission of The OpenEJB Group. For written permission,
* please contact [EMAIL PROTECTED]
*
* 4. Products derived from this Software may not be called "OpenEJB"
* nor may "OpenEJB" appear in their names without prior written
* permission of The OpenEJB Group. OpenEJB is a registered
* trademark of The OpenEJB Group.
*
* 5. Due credit should be given to the OpenEJB Project
* (http://openejb.org/).
*
* THIS SOFTWARE IS PROVIDED BY THE OPENEJB GROUP AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE OPENEJB GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the OpenEJB Project. For more information
* please see <http://openejb.org/>.
*
* ====================================================================
*/
package org.openejb.timer;
import org.openejb.EJBInvocation;
import org.openejb.EJBInvocationImpl;
import org.openejb.EJBInterfaceType;
/**
*
*
* @version $Revision: 1.1 $ $Date: 2004/07/18 22:24:00 $
*
* */
public class StatelessEJBInvocationFactoryImpl implements
EJBTimeoutInvocationFactory {
public EJBInvocation getEJBTimeoutInvocation(TimerImpl timer) {
EJBInvocation invocation = new EJBInvocationImpl(EJBInterfaceType.TIMEOUT,
1, new Object[] {timer});
return invocation;
}
}
1.1
openejb/modules/core/src/java/org/openejb/timer/TimerHandleImpl.java
Index: TimerHandleImpl.java
===================================================================
/* ====================================================================
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided
* that the following conditions are met:
*
* 1. Redistributions of source code must retain copyright
* statements and notices. Redistributions must also contain a
* copy of this document.
*
* 2. Redistributions in binary form must reproduce this list of
* conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name "OpenEJB" must not be used to endorse or promote
* products derived from this Software without prior written
* permission of The OpenEJB Group. For written permission,
* please contact [EMAIL PROTECTED]
*
* 4. Products derived from this Software may not be called "OpenEJB"
* nor may "OpenEJB" appear in their names without prior written
* permission of The OpenEJB Group. OpenEJB is a registered
* trademark of The OpenEJB Group.
*
* 5. Due credit should be given to the OpenEJB Project
* (http://openejb.org/).
*
* THIS SOFTWARE IS PROVIDED BY THE OPENEJB GROUP AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE OPENEJB GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the OpenEJB Project. For more information
* please see <http://openejb.org/>.
*
* ====================================================================
*/
package org.openejb.timer;
import java.io.Serializable;
import javax.ejb.EJBException;
import javax.ejb.NoSuchObjectLocalException;
import javax.ejb.Timer;
import javax.ejb.TimerHandle;
import javax.management.ObjectName;
import org.apache.geronimo.kernel.Kernel;
/**
*
*
* @version $Revision: 1.1 $ $Date: 2004/07/18 22:24:00 $
*
* */
public class TimerHandleImpl implements TimerHandle, Serializable {
private final long id;
private final String kernelName;
private final ObjectName timerSourceName;
public TimerHandleImpl(long id, String kernelName, ObjectName timerSourceName) {
this.id = id;
this.kernelName = kernelName;
this.timerSourceName = timerSourceName;
}
public Timer getTimer() throws EJBException, IllegalStateException,
NoSuchObjectLocalException {
Kernel kernel = Kernel.getKernel(kernelName);
try {
return (Timer) kernel.invoke(timerSourceName, "getWorkInfoById", new
Object[] {new Long(id)}, new String[] {Long.class.getName()});
} catch (Exception e) {
throw new EJBException(e);
}
}
}
1.1 openejb/modules/core/src/java/org/openejb/timer/TimerImpl.java
Index: TimerImpl.java
===================================================================
/* ====================================================================
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided
* that the following conditions are met:
*
* 1. Redistributions of source code must retain copyright
* statements and notices. Redistributions must also contain a
* copy of this document.
*
* 2. Redistributions in binary form must reproduce this list of
* conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name "OpenEJB" must not be used to endorse or promote
* products derived from this Software without prior written
* permission of The OpenEJB Group. For written permission,
* please contact [EMAIL PROTECTED]
*
* 4. Products derived from this Software may not be called "OpenEJB"
* nor may "OpenEJB" appear in their names without prior written
* permission of The OpenEJB Group. OpenEJB is a registered
* trademark of The OpenEJB Group.
*
* 5. Due credit should be given to the OpenEJB Project
* (http://openejb.org/).
*
* THIS SOFTWARE IS PROVIDED BY THE OPENEJB GROUP AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE OPENEJB GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the OpenEJB Project. For more information
* please see <http://openejb.org/>.
*
* ====================================================================
*/
package org.openejb.timer;
import java.util.Date;
import java.io.Serializable;
import javax.ejb.Timer;
import javax.ejb.EJBException;
import javax.ejb.NoSuchObjectLocalException;
import javax.ejb.TimerHandle;
import javax.management.ObjectName;
import javax.transaction.Synchronization;
import javax.transaction.Status;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;
import org.apache.geronimo.timer.WorkInfo;
/**
* TODO keep track of state so after single-shot firing nothing works.
*
* @version $Revision: 1.1 $ $Date: 2004/07/18 22:24:00 $
*
* */
public class TimerImpl implements Timer {
private final WorkInfo workInfo;
private final TimerServiceImpl timerService;
private final String kernelName;
private final ObjectName timerSourceName;
private boolean cancelled = false;
public TimerImpl(WorkInfo workInfo, TimerServiceImpl timerService, String
kernelName, ObjectName timerSourceName) {
this.workInfo = workInfo;
this.timerService = timerService;
this.kernelName = kernelName;
this.timerSourceName = timerSourceName;
}
public void cancel() throws EJBException, IllegalStateException,
NoSuchObjectLocalException {
checkState();
workInfo.getExecutorFeedingTimerTask().cancel();
cancelled = true;
try {
timerService.registerCancelSynchronization(new CancelSynchronization());
} catch (RollbackException e) {
throw (IllegalStateException)new IllegalStateException("Transaction is
already rolled back").initCause(e);
} catch (SystemException e) {
throw new EJBException(e);
}
}
public long getTimeRemaining() throws EJBException, IllegalStateException,
NoSuchObjectLocalException {
checkState();
long now = System.currentTimeMillis();
long then = workInfo.getTime().getTime();
return then - now;
}
public Date getNextTimeout() throws EJBException, IllegalStateException,
NoSuchObjectLocalException {
checkState();
return workInfo.getTime();
}
public Serializable getInfo() throws EJBException, IllegalStateException,
NoSuchObjectLocalException {
checkState();
return (Serializable)workInfo.getUserInfo();
}
public TimerHandle getHandle() throws EJBException, IllegalStateException,
NoSuchObjectLocalException {
checkState();
return new TimerHandleImpl(workInfo.getId(), kernelName, timerSourceName);
}
private void checkState() throws NoSuchObjectLocalException {
if (cancelled) {
throw new NoSuchObjectLocalException("Timer is cancelled");
}
}
private class CancelSynchronization implements Synchronization {
public void beforeCompletion() {
}
public void afterCompletion(int status) {
if (status == Status.STATUS_COMMITTED) {
} else if (status == Status.STATUS_ROLLEDBACK) {
cancelled = false;
} //else???
}
}
}
1.1
openejb/modules/core/src/java/org/openejb/timer/TimerServiceImpl.java
Index: TimerServiceImpl.java
===================================================================
/* ====================================================================
* Redistribution and use of this software and associated documentation
* ("Software"), with or without modification, are permitted provided
* that the following conditions are met:
*
* 1. Redistributions of source code must retain copyright
* statements and notices. Redistributions must also contain a
* copy of this document.
*
* 2. Redistributions in binary form must reproduce this list of
* conditions and the following disclaimer in the documentation
* and/or other materials provided with the distribution.
*
* 3. The name "OpenEJB" must not be used to endorse or promote
* products derived from this Software without prior written
* permission of The OpenEJB Group. For written permission,
* please contact [EMAIL PROTECTED]
*
* 4. Products derived from this Software may not be called "OpenEJB"
* nor may "OpenEJB" appear in their names without prior written
* permission of The OpenEJB Group. OpenEJB is a registered
* trademark of The OpenEJB Group.
*
* 5. Due credit should be given to the OpenEJB Project
* (http://openejb.org/).
*
* THIS SOFTWARE IS PROVIDED BY THE OPENEJB GROUP AND CONTRIBUTORS
* ``AS IS'' AND ANY EXPRESSED OR IMPLIED WARRANTIES, INCLUDING, BUT
* NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND
* FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL
* THE OPENEJB GROUP OR ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT,
* INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
* (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
* SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
* HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
* STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED
* OF THE POSSIBILITY OF SUCH DAMAGE.
*
* ====================================================================
*
* This software consists of voluntary contributions made by many
* individuals on behalf of the OpenEJB Project. For more information
* please see <http://openejb.org/>.
*
* ====================================================================
*/
package org.openejb.timer;
import java.io.Serializable;
import java.util.ArrayList;
import java.util.Collection;
import java.util.Date;
import java.util.Iterator;
import javax.ejb.EJBException;
import javax.ejb.Timer;
import javax.ejb.TimerService;
import javax.management.ObjectName;
import javax.transaction.RollbackException;
import javax.transaction.Status;
import javax.transaction.Synchronization;
import javax.transaction.SystemException;
import org.apache.commons.logging.Log;
import org.apache.commons.logging.LogFactory;
import org.apache.geronimo.core.service.Interceptor;
import org.apache.geronimo.transaction.context.TransactionContext;
import org.apache.geronimo.transaction.context.TransactionContextManager;
import org.apache.geronimo.timer.PersistenceException;
import org.apache.geronimo.timer.ThreadPooledTimer;
import org.apache.geronimo.timer.UserTaskFactory;
import org.apache.geronimo.timer.WorkInfo;
import org.apache.geronimo.timer.PersistentTimer;
import org.openejb.EJBInvocation;
/**
*
*
* @version $Revision: 1.1 $ $Date: 2004/07/18 22:24:00 $
*
* */
public class TimerServiceImpl implements TimerService {
private static final Log log = LogFactory.getLog(EJBInvokeTask.class);
private final EJBTimeoutInvocationFactory invocationFactory;
private final Interceptor stack;
private final PersistentTimer persistentTimer;
private final String key;
private final UserTaskFactory userTaskFactory;
private final String kernelName;
private final ObjectName timerSourceName;
private final TransactionContextManager transactionContextManager;
public TimerServiceImpl(EJBTimeoutInvocationFactory invocationFactory,
Interceptor stack, ThreadPooledTimer timer, String key, String kernelName, ObjectName
timerSourceName, TransactionContextManager transactionContextManager) throws
PersistenceException {
this.invocationFactory = invocationFactory;
this.stack = stack;
this.persistentTimer = timer;
this.key = key;
this.kernelName = kernelName;
this.timerSourceName = timerSourceName;
this.transactionContextManager = transactionContextManager;
userTaskFactory = new EJBInvokeTaskFactory(this);
}
public void doStart() throws PersistenceException {
//reconstruct saved timers.
Collection workInfos = persistentTimer.playback(key, userTaskFactory);
for (Iterator iterator = workInfos.iterator(); iterator.hasNext();) {
WorkInfo workInfo = (WorkInfo) iterator.next();
newTimer(workInfo);
}
}
public void doStop() {
//TODO remove the ejb timers from the Timer but not the persistence service.
}
public Timer createTimer(Date initialExpiration, long intervalDuration,
Serializable info) throws IllegalArgumentException, IllegalStateException,
EJBException {
try {
WorkInfo workInfo = persistentTimer.scheduleAtFixedRate(key,
userTaskFactory, info, initialExpiration, intervalDuration);
return newTimer(workInfo);
} catch (PersistenceException e) {
throw new EJBException(e);
} catch (RollbackException e) {
throw new EJBException(e);
} catch (SystemException e) {
throw new EJBException(e);
}
}
public Timer createTimer(Date expiration, Serializable info) throws
IllegalArgumentException, IllegalStateException, EJBException {
try {
WorkInfo workInfo = persistentTimer.schedule(key, userTaskFactory, info,
expiration);
return newTimer(workInfo);
} catch (PersistenceException e) {
throw new EJBException(e);
} catch (RollbackException e) {
throw new EJBException(e);
} catch (SystemException e) {
throw new EJBException(e);
}
}
public Timer createTimer(long initialDuration, long intervalDuration,
Serializable info) throws IllegalArgumentException, IllegalStateException,
EJBException {
try {
WorkInfo workInfo = persistentTimer.scheduleAtFixedRate(key,
userTaskFactory, info, initialDuration, intervalDuration);
return newTimer(workInfo);
} catch (PersistenceException e) {
throw new EJBException(e);
} catch (RollbackException e) {
throw new EJBException(e);
} catch (SystemException e) {
throw new EJBException(e);
}
}
public Timer createTimer(long duration, Serializable info) throws
IllegalArgumentException, IllegalStateException, EJBException {
try {
WorkInfo workInfo = persistentTimer.schedule(userTaskFactory, key, info,
duration);
return newTimer(workInfo);
} catch (PersistenceException e) {
throw new EJBException(e);
} catch (RollbackException e) {
throw new EJBException(e);
} catch (SystemException e) {
throw new EJBException(e);
}
}
public Collection getTimers() throws IllegalStateException, EJBException {
Collection ids = null;
try {
ids = persistentTimer.getIdsByKey(key);
} catch (PersistenceException e) {
throw new EJBException(e);
}
Collection timers = new ArrayList();
for (Iterator iterator = ids.iterator(); iterator.hasNext();) {
Long id = (Long) iterator.next();
TimerImpl timer = getTimerById(id);
timers.add(timer);
}
return timers;
}
private TimerImpl getTimerById(Long id) {
WorkInfo workInfo = persistentTimer.getWorkInfo(id);
TimerImpl timer = (TimerImpl) workInfo.getClientHandle();
return timer;
}
void registerCancelSynchronization(Synchronization cancelSynchronization) throws
RollbackException, SystemException {
TransactionContext transactionContext =
transactionContextManager.getContext();
if (transactionContext != null && transactionContext.isActive()) {
transactionContext.getTransaction().registerSynchronization(cancelSynchronization);
} else {
cancelSynchronization.afterCompletion(Status.STATUS_COMMITTED);
}
}
private Timer newTimer(WorkInfo workInfo) {
Timer timer = new TimerImpl(workInfo, this, kernelName, timerSourceName);
workInfo.setClientHandle(timer);
return timer;
}
private Interceptor getStack() {
return stack;
}
private static class EJBInvokeTask implements Runnable {
private final TimerServiceImpl timerService;
private final long id;
private EJBInvocation invocation;
public EJBInvokeTask(TimerServiceImpl timerService, long id) {
this.timerService = timerService;
this.id = id;
}
public void run() {
if (invocation == null) {
TimerImpl timerImpl = timerService.getTimerById(new Long(id));
invocation =
timerService.invocationFactory.getEJBTimeoutInvocation(timerImpl);
}
try {
timerService.getStack().invoke(invocation);
} catch (Throwable throwable) {
log.info(throwable);
}
}
}
private static class EJBInvokeTaskFactory implements UserTaskFactory {
private final TimerServiceImpl timerService;
public EJBInvokeTaskFactory(TimerServiceImpl timerService) {
this.timerService = timerService;
}
public Runnable newTask(long id) {
return new EJBInvokeTask(timerService, id);
}
}
}