package com.hp.mwtests.ts.jta.jts.tools;
import com.arjuna.ats.arjuna.common.ObjectStoreEnvironmentBean;
import com.arjuna.ats.arjuna.common.Uid;
import com.arjuna.ats.arjuna.common.arjPropertyManager;
import com.arjuna.ats.arjuna.tools.osb.mbean.LogRecordWrapper;
import com.arjuna.ats.arjuna.tools.osb.mbean.OSEntryBean;
import com.arjuna.ats.arjuna.tools.osb.mbean.OSEntryBeanMBean;
import com.arjuna.ats.arjuna.tools.osb.mbean.ObjStoreBrowser;
import com.arjuna.ats.arjuna.tools.osb.mbean.UidWrapper;
import com.arjuna.ats.arjuna.tools.osb.util.JMXServer;
import com.arjuna.ats.internal.arjuna.thread.ThreadActionData;
import com.arjuna.ats.internal.jta.tools.osb.mbean.jta.CommitMarkableResourceRecordBean;
import com.arjuna.ats.internal.jta.tools.osb.mbean.jta.JTAActionBean;
import com.arjuna.ats.internal.jta.tools.osb.mbean.jts.XAResourceRecordBeanMBean;
import com.arjuna.ats.internal.jta.transaction.jts.TransactionImple;
import com.arjuna.common.internal.util.propertyservice.BeanPopulator;
import com.hp.mwtests.ts.jta.common.DummyXA;
import com.hp.mwtests.ts.jta.tools.FailureXAResource;
import org.junit.After;
import org.junit.Before;
import org.junit.Test;
import javax.management.InstanceNotFoundException;
import javax.management.JMX;
import javax.management.MBeanException;
import javax.management.MBeanServer;
import javax.management.MalformedObjectNameException;
import javax.management.ObjectName;
import javax.transaction.HeuristicMixedException;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import java.io.File;
import java.util.Collection;
import java.util.HashSet;
import java.util.Set;
import static org.junit.Assert.assertEquals;
import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertTrue;
import static org.junit.Assert.fail;
import com.arjuna.ats.internal.jts.ORBManager;
import com.arjuna.orbportability.OA;
import com.arjuna.orbportability.ORB;
import com.arjuna.orbportability.RootOA;
/**
* @deprecated as of 5.0.5.Final In a subsequent release we will change packages names in order to
* provide a better separation between public and internal classes.
*/
@Deprecated // in order to provide a better separation between public and internal classes.
class ExtendedFailureXAResource extends FailureXAResource {
private boolean forgotten;
@Override
public void commit(Xid id, boolean onePhase) throws XAException {
if (!forgotten)
super.commit(id, onePhase);
}
@Override
public void forget(Xid xid) throws XAException {
super.forget(xid);
forgotten = true;
}
}
public class ObjStoreBrowserTest {
private ORB myORB = null;
private RootOA myOA = null;
private ObjStoreBrowser osb;
private ObjStoreBrowser createObjStoreBrowser() {
ObjStoreBrowser osb = new ObjStoreBrowser();
osb.setType("com.arjuna.ats.arjuna.AtomicAction", "com.arjuna.ats.internal.jta.tools.osb.mbean.jta.JTAActionBean");
return osb;
}
@Before
public void beforeTest() throws Exception {
emptyObjectStore();
setUpJTS();
FailureXAResource.resetForgetCounts();
osb = createObjStoreBrowser();
osb.start();
}
@After
public void afterTest() throws Exception {
osb.stop();
tearDownJTS();
}
private void setUpJTS () throws Exception {
myORB = ORB.getInstance("test");
myOA = OA.getRootOA(myORB);
myORB.initORB(new String[] {}, null);
myOA.initOA();
ORBManager.setORB(myORB);
ORBManager.setPOA(myOA);
}
private void tearDownJTS () throws Exception {
myOA.destroy();
myORB.shutdown();
}
/* @Test
public void testXAResourceRecordBean() throws Exception {
com.arjuna.common.tests.simple.EnvironmentBeanTest.testBeanByReflection(new XAResourceRecordBean(new UidWrapper(Uid.nullUid())));
}*/
@Test
public void testCommitMarkableResourceRecordBean() throws Exception {
com.arjuna.common.tests.simple.EnvironmentBeanTest.testBeanByReflection(new CommitMarkableResourceRecordBean(new UidWrapper(Uid.nullUid())));
}
/**
* Test that resources that generate heuristics are instrumented correctly
* @throws Exception
*/
@Test
public void testMBeanHeuristic () throws Exception
{
FailureXAResource failureXAResource = new FailureXAResource(FailureXAResource.FailLocation.commit); // generates a heuristic on commit
getHeuristicMBean(osb, new TransactionImple(), failureXAResource);
}
/**
* Test removing a heuristic participant (each test asserts forget was called (see tryRemove)
* - if forget succeeds check that the log is removed
*/
@Test
public void testParticipantForgetAndRemove () throws Exception
{
// generate a heuristic
HeuristicTestData hd = getHeuristic();
// try removing the resource (forget calls succeed)
tryRemove(false, false, hd);
// since the remove op ignores forget failures it should succeed (meaning that there will be no corresponding MBean)
assertEquals(0, hd.getHeuristicParticipants().size());
}
/**
* Test removing a heuristic participant (each test asserts forget was called (see tryRemove)
* - if forget fails and the property to ignore forget failures is set check that the log is removed
*/
@Test
public void testParticipantRemovePasses () throws Exception
{
// generate a heuristic
HeuristicTestData hd = getHeuristic();
// try removing the resource (forget fails and remove ignores forget failures)
tryRemove(true, true, hd);
// since the remove op ignores forget failures it should succeed (meaning that there will be no corresponding MBean)
assertEquals(0, hd.getHeuristicParticipants().size());
}
/**
* Test removing a heuristic participant (each test asserts forget was called (see tryRemove)
* - if forget fails and the property to ignore forget failures is not set check that the log is not removed
*/
@Test
public void testParticipantRemoveFails () throws Exception
{
// generate a heuristic
HeuristicTestData hd = getHeuristic();
// try removing the resource (forget fails and remove does not ignore forget failures)
tryRemove(true, false, hd);
// since the remove op does not ignores forget failures it should fail (meaning that the corresponding MBean still exists)
assertEquals(1, hd.getHeuristicParticipants().size());
}
/**
* Test removing a transaction with heuristic participants succeeds if the ignores heuristics property is true
*/
@Test
public void testTxnRemovePasses () throws Exception
{
// generate a heuristic
HeuristicTestData hd = getHeuristic();
// ignore forget failures during MBean remove opertaions
arjPropertyManager.getObjectStoreEnvironmentBean().setIgnoreMBeanHeuristics(true);
// tell the heuristic resource to fail forget calls
hd.setRefuseForget(true);
// invoke the MBean remove operation on the transaction
hd.txnMBean.remove();
osb.probe();
// verify that the txn is no longer instrumented
assertEquals(0, hd.getTransactionObjectNames().size());
}
/**
* Test removing a transaction with heuristic participants fails if the ignores heuristics property is false
*/
@Test
public void testTxnRemoveFails () throws Exception
{
// generate a heuristic
HeuristicTestData hd = getHeuristic();
// ignore forget failures during MBean remove opertaions
arjPropertyManager.getObjectStoreEnvironmentBean().setIgnoreMBeanHeuristics(false);
// tell the heuristic resource to fail forget calls
hd.setRefuseForget(true);
// invoke the MBean remove operation on the transaction
hd.txnMBean.remove();
osb.probe();
// verify that the txn is still instrumented
assertEquals(1, hd.getTransactionObjectNames().size());
}
private static final class HeuristicTestData {
FailureXAResource failureXAResource;
TransactionImple tx;
XAResourceRecordBeanMBean resourceBean;
JTAActionBean txnMBean;
ObjectName participantBeanName;
String resourceBeanName;
String txnBeanName;
HeuristicTestData(TransactionImple tx, FailureXAResource failureXAResource, JTAActionBean txnMBean,
XAResourceRecordBeanMBean resourceBean, ObjectName participantBeanName,
String txnBeanName, String resourceBeanName) {
this.failureXAResource = failureXAResource;
this.tx = tx;
this.resourceBean = resourceBean;
this.txnBeanName = txnBeanName;
this.txnMBean = txnMBean;
this.participantBeanName = participantBeanName;
this.resourceBeanName = resourceBeanName;
}
Set<ObjectName> getTransactionObjectNames() throws MalformedObjectNameException {
Set<ObjectName> names = JMXServer.getAgent().queryNames(txnBeanName, null);
return names != null ? names : new HashSet<>();
}
Set<ObjectName> getHeuristicParticipants() throws MalformedObjectNameException {
Set<ObjectName> names = JMXServer.getAgent().queryNames(resourceBeanName, null);
return names != null ? names : new HashSet<>();
}
OSEntryBeanMBean getParticipantMBean() throws InstanceNotFoundException {
MBeanServer server = JMXServer.getAgent().getServer();
return JMX.newMBeanProxy(server, participantBeanName, OSEntryBeanMBean.class);
}
void setRefuseForget(boolean refuse) {
failureXAResource.setRefuseForget(failureXAResource.getXid(), refuse);
}
}
private HeuristicTestData getHeuristic() throws Exception
{
FailureXAResource failureXAResource = new FailureXAResource(FailureXAResource.FailLocation.commit); // generates a heuristic on commit
TransactionImple tx = new TransactionImple();
XAResourceRecordBeanMBean resourceBean = getHeuristicMBean(osb, tx, failureXAResource);
JTAActionBean txnMBean = getTransactionBean(osb, tx, true);
Set<ObjectName> participants;
String resourceBeanName;
String txnBeanName;
assertNotNull(txnMBean);
assertNotNull(resourceBean);
txnBeanName = String.format("jboss.jta:type=ObjectStore,itype=%s,uid=%s",
txnMBean.type(), txnMBean.getId().replace(':', '_'));
resourceBeanName = String.format("%s,puid=%s",
txnBeanName, resourceBean.getId().replace(':', '_'));
participants = JMXServer.getAgent().queryNames(resourceBeanName, null);
assertEquals(1, participants.size());
return new HeuristicTestData(tx, failureXAResource, txnMBean, resourceBean, participants.iterator().next(),
txnBeanName, resourceBeanName);
}
private HeuristicTestData tryRemove(boolean failForget, boolean ignoreMBeanHeuristics, HeuristicTestData hd)
throws MBeanException, MalformedObjectNameException, InstanceNotFoundException {
ObjectStoreEnvironmentBean osEnv = arjPropertyManager.getObjectStoreEnvironmentBean();
osEnv.setIgnoreMBeanHeuristics(ignoreMBeanHeuristics);
hd.failureXAResource.setRefuseForget(hd.failureXAResource.getXid(), failForget);
// remove the bean via a JMX proxy
hd.getParticipantMBean().remove();
// an equivalent alternative would have been to call remove directly on the bean
//hd.resourceBean.remove();
// assert that forget was called on the resource
assertEquals(1, hd.failureXAResource.getForgetCount(hd.failureXAResource.getXid()));
osb.probe();
return hd;
}
private TransactionImple generateHeuristic(TransactionImple tx, FailureXAResource failureXAResource) throws Exception {
ThreadActionData.purgeActions();
XAResource[] resources = {
new DummyXA(false),
failureXAResource
};
// enlist the XA resources into the transaction
for (XAResource resource : resources)
tx.enlistResource(resource);
try {
tx.commit();
fail("Expected a mixed heuristic");
} catch (final HeuristicMixedException expected) {
}
return tx;
}
private JTAActionBean getTransactionBean(ObjStoreBrowser osb, TransactionImple tx, boolean present) {
// there should be one MBean corresponding to the Transaction tx
UidWrapper w = osb.findUid(tx.get_uid());
if (!present) {
assertNull(w);
return null;
}
assertNotNull(w);
OSEntryBean ai = w.getMBean();
assertNotNull(ai);
// the MBean should wrap a JTAActionBean
assertTrue(ai instanceof JTAActionBean);
return (JTAActionBean) ai;
}
private XAResourceRecordBeanMBean getHeuristicMBean(ObjStoreBrowser osb, TransactionImple tx, FailureXAResource failureXAResource) throws Exception {
generateHeuristic(tx, failureXAResource);
osb.probe();
// there should be one MBean corresponding to the Transaction
JTAActionBean actionBean = getTransactionBean(osb, tx, true);
assertNotNull(actionBean);
// and the transaction should contain only one participant (namely the FailureXAResource that generated the heuristic):
Collection<LogRecordWrapper> participants = actionBean.getParticipants();
assertEquals(1, participants.size());
assertNotNull(failureXAResource.getXid());
LogRecordWrapper participant = participants.iterator().next();
assertTrue(participant.isHeuristic());
assertTrue(participant instanceof XAResourceRecordBeanMBean);
return (XAResourceRecordBeanMBean) participant;
}
public void emptyObjectStore()
{
String objectStoreDirName = BeanPopulator.getDefaultInstance(ObjectStoreEnvironmentBean.class).getObjectStoreDir();
System.out.println("Emptying " + objectStoreDirName);
File objectStoreDir = new File(objectStoreDirName);
removeContents(objectStoreDir);
}
public boolean removeContents(File directory)
{
boolean deleteParent = true;
if ((directory != null) &&
directory.isDirectory() &&
(!directory.getName().equals("")) &&
(!directory.getName().equals("/")) &&
(!directory.getName().equals("\\")) &&
(!directory.getName().equals(".")) &&
(!directory.getName().equals("..")))
{
File[] contents = directory.listFiles();
if (contents != null) {
boolean canDelete = true;
for (File content : contents) {
if (content.isDirectory()) {
if (!content.getName().equals("RecoveryCoordinator")) {
canDelete = removeContents(content) && canDelete;
if (!canDelete) {
deleteParent = false;
} else {
content.delete();
}
} else {
deleteParent = false;
}
} else {
content.delete();
}
}
}
}
return deleteParent;
}
}