blob: 484a5d6c0973ff9e07033900cc03dbeac033c177 [file] [log] [blame]
/*
* Copyright (c) 2017, 2020 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.ejb.timer.timertests;
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 javax.ejb.*;
import jakarta.jms.JMSException;
import jakarta.jms.QueueConnectionFactory;
import jakarta.jms.QueueConnection;
import jakarta.jms.Queue;
import jakarta.jms.QueueSession;
import jakarta.jms.QueueSender;
import jakarta.jms.QueueReceiver;
import jakarta.jms.TextMessage;
public class TimerStuffImpl implements TimerStuff {
private static final int TX_CMT = 0;
private static final int TX_BMT = 1;
private static final int TX_UNSPECIFIED = 2;
private EJBContext context_;
private int txMode = TX_CMT;
private Queue queue;
private QueueSession session;
private QueueConnection connection;
private QueueConnectionFactory qcFactory;
public TimerStuffImpl() {}
protected void setContext(EJBContext context) {
context_ = context;
try {
InitialContext ic = new InitialContext();
String txModeStr = (String) ic.lookup("java:comp/env/txmode");
if( txModeStr.equals("CMT") ) {
txMode = TX_CMT;
} else if( txModeStr.equals("BMT") ) {
txMode = TX_BMT;
} else {
txMode = TX_UNSPECIFIED;
}
/** TODO
queue = (Queue) ic.lookup("java:comp/env/jms/MyQueue");
qcFactory = (QueueConnectionFactory)
ic.lookup("java:comp/env/jms/MyQueueConnectionFactory");
**/
} catch(Exception e) {
e.printStackTrace();
}
}
protected boolean isCMT() { return txMode == TX_CMT; }
protected boolean isBMT() { return txMode == TX_BMT; }
protected boolean isTxUnspecified() { return txMode == TX_UNSPECIFIED; }
public TimerHandle createTimer(long duration, String info) throws RemoteException, Exception {
TimerService ts = context_.getTimerService();
Timer t = ts.createTimer(duration, info);
return t.getHandle();
}
public TimerHandle createTimer(long duration) throws RemoteException, Exception {
return createTimer(duration, "createTimer<long>" + duration);
}
public TimerHandle createTimer(long initialDuration, long interval)
throws RemoteException, Exception {
return createTimer(initialDuration, interval,
"createTimer<long, long>" + initialDuration +
"," + interval);
}
public TimerHandle createTimer(long initialDuration, long interval,
String info)
throws RemoteException, Exception {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createTimer(initialDuration, interval,
new AppInfo(info));
if( isBMT() ) {
context_.getUserTransaction().commit();
}
return t.getHandle();
}
public TimerHandle createTimer(Date expirationTime)
throws RemoteException, 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 getHandle is called.
// 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.createTimer(expirationTime,
"createTimer<Date>" + expirationTime);
if( isBMT() ) {
context_.getUserTransaction().commit();
}
return t.getHandle();
}
public TimerHandle createTimer(Date expirationTime, long interval)
throws RemoteException, Exception {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createTimer(expirationTime, interval,
"createTimer<Date, long>" + expirationTime +
"," + interval);
if( isBMT() ) {
context_.getUserTransaction().commit();
}
return t.getHandle();
}
public void createTimerAndRollback(long duration) throws RemoteException, Exception {
if( isTxUnspecified() ) {
return;
} else if( isBMT() ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createTimer(duration, "createTimerAndRollback" + duration);
if( isBMT() ) {
context_.getUserTransaction().rollback();
} else {
context_.setRollbackOnly();
}
}
public void createTimerAndCancel(long duration) throws RemoteException, Exception {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createTimer(duration, "createTimerAndCancel" + duration);
t.cancel();
if( isBMT() ) {
context_.getUserTransaction().commit();
}
}
public void createTimerAndCancelAndCancel(long duration) throws RemoteException, Exception {
if( isTxUnspecified() ) {
return;
} else if( isBMT() ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createTimer(duration, "createTimerAndCancelAndCancel"
+ duration);
t.cancel();
t.cancel();
if( isBMT() ) {
context_.getUserTransaction().commit();
}
}
public void createTimerAndCancelAndRollback(long duration)
throws RemoteException, Exception {
if( isTxUnspecified() ) {
return;
} else if( isBMT() ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createTimer(duration, "createTimerAndCancelAndRollback"
+ duration);
t.cancel();
if( isBMT() ) {
context_.getUserTransaction().rollback();
} else {
context_.setRollbackOnly();
}
}
public void cancelTimerNoError(TimerHandle timerHandle) throws RemoteException, Exception {
cancelTimer(timerHandle, false);
}
public void cancelTimer(TimerHandle timerHandle) throws RemoteException, Exception {
cancelTimer(timerHandle, true);
}
private void cancelTimer(TimerHandle timerHandle, boolean throwError) throws RemoteException, Exception {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
try {
Timer t = timerHandle.getTimer();
t.cancel();
} catch(Exception e) {
if( throwError ) {
throw new RemoteException("", e);
}
} finally {
if( isBMT() ) {
context_.getUserTransaction().commit();
}
}
}
public void cancelTimerAndCancel(TimerHandle timerHandle) throws RemoteException, Exception {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
Timer t = timerHandle.getTimer();
t.cancel();
t.cancel();
if( isBMT() ) {
context_.getUserTransaction().commit();
}
}
public void cancelTimerAndRollback(TimerHandle timerHandle)
throws RemoteException, Exception {
if( isTxUnspecified() ) {
return;
} else if( isBMT() ) {
context_.getUserTransaction().begin();
}
Timer t = timerHandle.getTimer();
t.cancel();
if( isBMT() ) {
context_.getUserTransaction().rollback();
} else {
context_.setRollbackOnly();
}
}
public void cancelTimerAndCancelAndRollback(TimerHandle timerHandle)
throws RemoteException, Exception {
if( isTxUnspecified() ) {
return;
} else if( isBMT() ) {
context_.getUserTransaction().begin();
}
Timer t = timerHandle.getTimer();
t.cancel();
t.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 RemoteException, Exception {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Collection timers1= ts.getTimers();
printTimers(timers1);
Timer t = ts.createTimer(1000000, "getTimersTest");
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 TimerHandle getTimeRemainingTest1(int numIterations) throws RemoteException, Exception {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createTimer(1, 1, "getTimeRemainingTest1");
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.getHandle();
}
public void getTimeRemainingTest2(int numIterations, TimerHandle th) throws RemoteException, Exception {
Timer t = th.getTimer();
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 TimerHandle getNextTimeoutTest1(int numIterations) throws RemoteException, Exception {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
TimerService ts = context_.getTimerService();
Timer t = ts.createTimer(1, 1, "getNextTimeoutTest1");
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.getHandle();
}
public void getNextTimeoutTest2(int numIterations, TimerHandle th) throws RemoteException, Exception {
Timer t = th.getTimer();
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 RemoteException, Exception {
checkCallerSecurityAccess("assertNoTimers", true);
TimerService ts = context_.getTimerService();
Collection timers= ts.getTimers();
if(!timers.isEmpty()) {
throw new RemoteException(timers.size() + " timers still exist");
}
}
public void assertTimerNotActive(TimerHandle timerHandle)
throws RemoteException {
try {
Timer t = timerHandle.getTimer();
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(TimerHandle timerHandle)
throws Exception {
return getInfo(timerHandle, false);
}
public Serializable getInfo(TimerHandle timerHandle) throws Exception {
return getInfo(timerHandle, true);
}
public void sendMessageAndCreateTimer() throws RemoteException, Exception {
if( isTxUnspecified() ) {
return;
}
try {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
sendMessageAndCreateTimer("sendMessageAndCreateTimer");
} catch(Exception e) {
e.printStackTrace();
throw new RemoteException(e.getMessage(), e);
} finally {
if( isBMT() ) {
context_.getUserTransaction().commit();
}
}
return;
}
public void sendMessageAndCreateTimerAndRollback() throws RemoteException, Exception {
if( isTxUnspecified() ) {
return;
}
try {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
sendMessageAndCreateTimer("sendMessageAndCreateTimerAndRollback");
} catch(Exception e) {
e.printStackTrace();
throw new RemoteException(e.getMessage(), e);
} finally {
if( isBMT() ) {
context_.getUserTransaction().rollback();
} else {
context_.setRollbackOnly();
}
}
return;
}
public void recvMessageAndCreateTimer(boolean expectMessage)
throws RemoteException, Exception {
if( isTxUnspecified() ) {
return;
}
try {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
recvMessageAndCreateTimer("recvMessageAndCreateTimer",
expectMessage);
} catch(Exception e) {
e.printStackTrace();
throw new RemoteException(e.getMessage(), e);
} finally {
if( isBMT() ) {
context_.getUserTransaction().commit();
}
}
return;
}
public void recvMessageAndCreateTimerAndRollback(boolean expectMessage)
throws RemoteException, Exception {
if( isTxUnspecified() ) {
return;
}
try {
if( isBMT() ) {
context_.getUserTransaction().begin();
}
recvMessageAndCreateTimer("recvMessageAndCreateTimerAndRollback",
expectMessage);
} catch(Exception e) {
e.printStackTrace();
throw new RemoteException(e.getMessage(), e);
} finally {
if( isBMT() ) {
context_.getUserTransaction().rollback();
} else {
context_.setRollbackOnly();
}
}
return;
}
private void sendMessageAndCreateTimer(String timerName)
throws Exception {
try {
QueueSender sender = session.createSender(queue);
// Send a message.
TextMessage message = session.createTextMessage();
message.setText(timerName);
sender.send(message);
TimerService ts = context_.getTimerService();
Timer t = ts.createTimer(1, timerName);
TimerHandle th = t.getHandle();
} catch(Exception e) {
throw e;
}
return;
}
private void recvMessageAndCreateTimer(String timerName,
boolean expectMessage)
throws Exception {
try {
QueueReceiver receiver = session.createReceiver(queue);
// Send a message.
TextMessage message = (TextMessage) receiver.receiveNoWait();
if( message == null ) {
if( expectMessage ) {
throw new RemoteException("Expecting message in " +
"recvMessageAndCreateTimerAndRollback");
}
} else {
if( !expectMessage ) {
throw new RemoteException("shouldn't have gotten msg " +
message.getText());
}
}
TimerService ts = context_.getTimerService();
Timer t = ts.createTimer(1, timerName);
TimerHandle th = t.getHandle();
} catch(Exception e) {
throw e;
}
return;
}
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.getHandle();
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(TimerHandle timerHandle, boolean throwError) throws Exception {
try {
Timer t = timerHandle.getTimer();
return t.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.createTimer(1, 1, "doTimerStuff_" + method);
TimerHandle th = t.getHandle();
t = th.getTimer();
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 handleEjbTimeout(Timer t) throws RemoteException, Exception {
Serializable info = t.getInfo();
String infoString = info.toString();
TimerHandle th = t.getHandle();
if( infoString.startsWith("cancelTimer") ) {
try {
Method m = this.getClass().getMethod
(infoString, new Class[] {TimerHandle.class});
System.out.println("Invoking " + infoString + " in handleEjbTimeout");
m.invoke(this, new Object[] { th });
} catch(InvocationTargetException ite) {
throw new Exception(ite.getCause());
} catch(Exception e) {
throw e;
}
} else if( infoString.startsWith("RuntimeException") ) {
System.out.println("Causing runtime exception from ejbTimeout");
throw new RuntimeException("force ejbtimeout delivery");
} else if( infoString.startsWith("setRollbackOnly") ) {
if( isCMT() ) {
System.out.println("setRollbackOnly from ejbTimeout");
context_.setRollbackOnly();
}
} else {
getTimerService("ejbTimeout", true);
doTimerStuff("ejbTimeout", true);
}
}
protected void checkCallerSecurityAccess(String method, boolean allowed) {
try {
context_.getCallerPrincipal();
if( !allowed ) {
throw new IllegalStateException(method + " should NOT have " +
"access to getCallerPrincipal");
}
} catch(IllegalStateException ise) {
if( allowed ) {
ise.printStackTrace();
throw new IllegalStateException(method + " should have access" +
"to getCallerPrincipal");
}
}
}
protected void checkGetSetRollbackOnly(String method, boolean allowed) {
allowed = allowed && isBMT();
try {
context_.getRollbackOnly();
if( !allowed ) {
throw new IllegalStateException(method + " should NOT have " +
"access to getRollbackOnly");
}
} catch(IllegalStateException ise) {
if( allowed ) {
ise.printStackTrace();
throw new IllegalStateException(method + " should have access" +
"to getRollbackOnly");
}
}
}
protected void setupJmsConnection() {
/** TODO
try {
InitialContext ic = new InitialContext();
connection = qcFactory.createQueueConnection();
session = connection.createQueueSession(true, 0);
connection.start();
} catch(Exception e) { e.printStackTrace(); }
*/
}
protected void cleanup() {
/** TODO
if( connection != null ) {
try {
connection.close();
connection = null;
} catch(JMSException jmse) {
jmse.printStackTrace();
}
}
**/
}
}