blob: 0722bc80dd7f0814cc0a98fed3d8c28ee0495b26 [file] [log] [blame]
/*
* Copyright (c) 2017, 2018 Oracle and/or its affiliates. All rights reserved.
*
* This program and the accompanying materials are made available under the
* terms of the Eclipse Public License v. 2.0, which is available at
* http://www.eclipse.org/legal/epl-2.0.
*
* This Source Code may also be made available under the following Secondary
* Licenses when the conditions for such availability set forth in the
* Eclipse Public License v. 2.0 are satisfied: GNU General Public License,
* version 2 with the GNU Classpath Exception, which is available at
* https://www.gnu.org/software/classpath/license.html.
*
* SPDX-License-Identifier: EPL-2.0 OR GPL-2.0 WITH Classpath-exception-2.0
*/
package com.sun.s1asdev.ejb32.ejblite.timer;
import java.lang.reflect.*;
import javax.naming.*;
import java.rmi.RemoteException;
import java.io.Serializable;
import java.util.Date;
import java.util.Collection;
import java.util.Iterator;
import jakarta.ejb.*;
public class TimerStuffImpl implements TimerStuff {
private EJBContext context_;
protected boolean isBMT = false;
protected boolean cancelAutomaticTimer = false;
public TimerStuffImpl() {}
protected void setContext(EJBContext context) {
context_ = context;
}
// XXX - TODO
protected boolean isTxUnspecified() { return false; }
public Timer createTimer(long duration, String info) throws Exception {
TimerService ts = context_.getTimerService();
Timer t = ts.createSingleActionTimer(duration, new TimerConfig(info, false));
return t;
}
public Timer createTimer(long duration) throws Exception {
return createTimer(duration, "createTimer<long>" + duration);
}
public Timer createTimer(long initialDuration, long interval)
throws Exception {
return createTimer(initialDuration, interval,
"createTimer<long, long>" + initialDuration +
"," + interval);
}
public Timer createTimer(long initialDuration, long interval,
String info)
throws Exception {
if( isBMT ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createIntervalTimer(initialDuration, interval,
new TimerConfig(new AppInfo(info), false));
if( isBMT ) {
context_.getUserTransaction().commit();
}
return t;
}
public Timer createTimer(Date expirationTime)
throws Exception {
TimerService ts = context_.getTimerService();
if( isBMT ) {
context_.getUserTransaction().begin();
}
// NOTE : in tx_unspecified case, technically there is a race
// condition if the timer expires before method is returned.
// This should happen very rarely since container puts the brakes
// on a bit by adding a few seconds if, upon creation, the expiration
// time has already passed.
Timer t = ts.createSingleActionTimer(expirationTime,
new TimerConfig("createTimer<Date>" + expirationTime, false));
if( isBMT ) {
context_.getUserTransaction().commit();
}
return t;
}
public Timer createTimer(Date expirationTime, long interval)
throws Exception {
if( isBMT ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createIntervalTimer(expirationTime, interval,
new TimerConfig("createTimer<Date, long>" + expirationTime +
"," + interval, false));
if( isBMT ) {
context_.getUserTransaction().commit();
}
return t;
}
public void createTimerAndRollback(long duration) throws Exception {
if( isTxUnspecified() ) {
return;
} else if( isBMT ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createSingleActionTimer(duration,
new TimerConfig("createTimerAndRollback" + duration, false));
if( isBMT ) {
context_.getUserTransaction().rollback();
} else {
context_.setRollbackOnly();
}
}
public void createTimerAndCancel(long duration) throws Exception {
if( isBMT ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createSingleActionTimer(duration,
new TimerConfig("createTimerAndCancel" + duration, false));
t.cancel();
if( isBMT ) {
context_.getUserTransaction().commit();
}
}
public void createTimerAndCancelAndCancel(long duration) throws Exception {
if( isTxUnspecified() ) {
return;
} else if( isBMT ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createSingleActionTimer(duration,
new TimerConfig("createTimerAndCancelAndCancel"+ duration, false));
t.cancel();
t.cancel();
if( isBMT ) {
context_.getUserTransaction().commit();
}
}
public void createTimerAndCancelAndRollback(long duration)
throws Exception {
if( isTxUnspecified() ) {
return;
} else if( isBMT ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createSingleActionTimer(duration,
new TimerConfig("createTimerAndCancelAndRollback" + duration, false));
t.cancel();
if( isBMT ) {
context_.getUserTransaction().rollback();
} else {
context_.setRollbackOnly();
}
}
public void cancelTimerNoError(Timer timer) throws Exception {
cancelTimer(timer, false);
}
public void cancelTimer(Timer timer) throws Exception {
cancelTimer(timer, true);
}
private void cancelTimer(Timer timer, boolean throwError) throws Exception {
if( isBMT ) {
context_.getUserTransaction().begin();
}
try {
if (timer == null) {
cancelAutomaticTimer = true;
// and let it expire and cancel itself
} else {
timer.cancel();
}
} catch(Exception e) {
if( throwError ) {
throw new RemoteException("", e);
}
} finally {
if( isBMT ) {
context_.getUserTransaction().commit();
}
}
}
public void cancelTimerAndCancel(Timer timer) throws Exception {
if( isBMT ) {
context_.getUserTransaction().begin();
}
timer.cancel();
timer.cancel();
if( isBMT ) {
context_.getUserTransaction().commit();
}
}
public void cancelTimerAndRollback(Timer timer)
throws Exception {
if( isTxUnspecified() ) {
return;
} else if( isBMT ) {
context_.getUserTransaction().begin();
}
timer.cancel();
if( isBMT ) {
context_.getUserTransaction().rollback();
} else {
context_.setRollbackOnly();
}
}
public void cancelTimerAndCancelAndRollback(Timer timer)
throws Exception {
if( isTxUnspecified() ) {
return;
} else if( isBMT ) {
context_.getUserTransaction().begin();
}
timer.cancel();
timer.cancel();
if( isBMT ) {
context_.getUserTransaction().rollback();
} else {
context_.setRollbackOnly();
}
}
private void printTimers(Collection timers) {
System.out.println("printTimers:" + timers.size());
int i = 0;
for(Iterator iter = timers.iterator(); iter.hasNext();) {
Timer t = (Timer) iter.next();
System.out.println("timer element " + i);
System.out.println("info = " + t.getInfo());
System.out.println("next timeout = " + t.getNextTimeout());
System.out.println("time remaining = " + t.getTimeRemaining());
i++;
}
}
public void getTimersTest() throws Exception {
if( isBMT ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Collection timers1= ts.getTimers();
printTimers(timers1);
Timer t = ts.createSingleActionTimer(1000000, new TimerConfig("getTimersTest", false));
Collection timers2 = ts.getTimers();
printTimers(timers2);
t.cancel();
Collection timers3 = ts.getTimers();
printTimers(timers3);
if( isBMT ) {
context_.getUserTransaction().commit();
}
if( (timers1.size() == timers3.size()) &&
(timers2.size() == (timers1.size() + 1)) ) {
// success
} else {
throw new RemoteException("getTimers failure");
}
}
public Timer getTimeRemainingTest1(int numIterations) throws Exception {
if( isBMT ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createIntervalTimer(1, 1,
new TimerConfig("getTimeRemainingTest1", false));
System.out.println("Remaining times for " + t.getInfo());
for(int i = 0; i < numIterations; i++) {
long timeRemaining = t.getTimeRemaining();
System.out.println("Time remaining = " + timeRemaining);
try { Thread.sleep(100); } catch(Exception e) {};
}
if( isBMT ) {
context_.getUserTransaction().commit();
}
return t;
}
public void getTimeRemainingTest2(int numIterations, Timer t) throws Exception {
System.out.println("Remaining times for " + t.getInfo());
for(int i = 0; i < numIterations; i++) {
long timeRemaining = t.getTimeRemaining();
System.out.println("Time remaining = " + timeRemaining);
try { Thread.sleep(100); } catch(Exception e) {};
}
}
public Timer getNextTimeoutTest1(int numIterations) throws Exception {
if( isBMT ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createIntervalTimer(1, 1,
new TimerConfig("getNextTimeoutTest1", false));
System.out.println("Remaining times for " + t.getInfo());
for(int i = 0; i < numIterations; i++) {
Date nextTimeout = t.getNextTimeout();
System.out.println("Next timeout = " + nextTimeout);
try { Thread.sleep(100); } catch(Exception e) {};
}
if( isBMT ) {
context_.getUserTransaction().commit();
}
return t;
}
public void getNextTimeoutTest2(int numIterations, Timer t) throws Exception {
System.out.println("Remaining times for " + t.getInfo());
for(int i = 0; i < numIterations; i++) {
Date nextTimeout = t.getNextTimeout();
System.out.println("Next timeout = " + nextTimeout);
try { Thread.sleep(100); } catch(Exception e) {};
}
}
// Make sure there are no active timers.
public void assertNoTimers() throws Exception {
TimerService ts = context_.getTimerService();
Collection timers= ts.getTimers();
if(!timers.isEmpty()) {
throw new RemoteException(timers.size() + " timers still exist");
}
}
public void assertTimerNotActive(Timer timer)
throws RemoteException {
try {
timer.getTimeRemaining();
throw
new Exception("assertTimerNotActive called with active timer");
} catch(NoSuchObjectLocalException nsole) {
// caught expected exception
} catch(Throwable t) {
throw new RemoteException("caught wrong exception", t);
}
}
public Serializable getInfoNoError(Timer timer)
throws Exception {
return getInfo(timer, false);
}
public Serializable getInfo(Timer timer) throws Exception {
return getInfo(timer, true);
}
private void timerAfterCancelTest(Timer t) {
try {
t.cancel();
throw new EJBException("timer " + t + " should have thrown " +
" an exception since it was accessed after having been " +
"cancelled");
} catch(NoSuchObjectLocalException fe) {
System.out.println("Successfully got exception after accessing " +
"cancelled timer " + t);
}
try {
t.getInfo();
throw new EJBException("timer " + t + " should have thrown " +
" an exception since it was accessed after having been " +
"cancelled");
} catch(NoSuchObjectLocalException fe) {
System.out.println("Successfully got exception after accessing " +
"cancelled timer " + t);
}
try {
t.getNextTimeout();
throw new EJBException("timer " + t + " should have thrown " +
" an exception since it was accessed after having been " +
"cancelled");
} catch(NoSuchObjectLocalException fe) {
System.out.println("Successfully got exception after accessing " +
"cancelled timer " + t);
}
try {
t.getTimeRemaining();
throw new EJBException("timer " + t + " should have thrown " +
" an exception since it was accessed after having been " +
"cancelled");
} catch(NoSuchObjectLocalException fe) {
System.out.println("Successfully got exception after accessing " +
"cancelled timer " + t);
}
}
private Serializable getInfo(Timer timer, boolean throwError) throws Exception {
try {
return timer.getInfo();
} catch(Exception e) {
if( throwError ) {
throw e;
}
}
return null;
}
protected void getTimerService(String method, boolean allowed) {
try {
TimerService ts = context_.getTimerService();
if( !allowed ) {
throw new EJBException("Error : getTimerService should have " +
"failed in " + method);
}
} catch(IllegalStateException e) {
if( allowed ) {
throw new EJBException("Error : getTimerService should have " +
"succeeded in " + method);
}
}
}
protected void doTimerStuff(String method, boolean allowed) {
boolean txStarted = false;
try {
if( isTxUnspecified() ) {
return;
}
TimerService ts = context_.getTimerService();
if( isBMT ) {
context_.getUserTransaction().begin();
txStarted = true;
}
Timer t = ts.createIntervalTimer(1, 1,
new TimerConfig("doTimerStuff_" + method, false));
t.cancel();
if( !allowed ) {
throw new EJBException("Error : doTimerStuff should have " +
"failed in " + method);
}
} catch(IllegalStateException ise) {
if( allowed ) {
throw new EJBException("Error : doTimerStuff should have " +
"succeeded in " + method);
}
} catch(EJBException ejbe) {
throw ejbe;
} catch(Exception e) {
e.printStackTrace();
throw new EJBException("Caught unexpected exception in " +
" doTimerStuff " + method);
} finally {
if( txStarted ) {
try {
context_.getUserTransaction().commit();
} catch(Exception e) {
e.printStackTrace();
}
}
}
}
protected void handleTimeout(Timer t) throws Exception {
Serializable info = t.getInfo();
if (t.isPersistent()) {
throw new EJBException("Error : Timer: " + info + " is persistent");
}
String infoString = info.toString();
if( infoString.startsWith("cancelTimer") ) {
try {
Method m = this.getClass().getMethod
(infoString, new Class[] {Timer.class});
System.out.println("Invoking " + infoString + " in handleTimeout");
m.invoke(this, new Object[] { t });
} catch(InvocationTargetException ite) {
throw new Exception(ite.getCause());
} catch(Exception e) {
throw e;
}
} else if( infoString.startsWith("Automatic") ) {
System.out.println("Got automatic timeout for " + infoString);
if (cancelAutomaticTimer) {
cancelTimerNoError(t);
System.out.println("... Canceled " + infoString);
}
} else if( infoString.startsWith("RuntimeException") ) {
System.out.println("Causing runtime exception from Timeout");
throw new RuntimeException("force ejbtimeout delivery");
} else if( infoString.startsWith("setRollbackOnly") ) {
if( !isBMT ) {
System.out.println("setRollbackOnly from Timeout");
context_.setRollbackOnly();
}
} else {
try {
t.getHandle();
throw new EJBException("Error : Timer.getHandle should have " +
"failed for non-persistent timer: " + info);
} catch(IllegalStateException e) { }
getTimerService("Timeout", true);
doTimerStuff("Timeout", true);
}
}
}