/*
* JBoss, Home of Professional Open Source
* Copyright 2006, Red Hat Middleware LLC, and individual contributors
* as indicated by the @author tags.
* See the copyright.txt in the distribution for a
* full listing of individual contributors.
* This copyrighted material is made available to anyone wishing to use,
* modify, copy, or redistribute it subject to the terms and conditions
* of the GNU Lesser General Public License, v. 2.1.
* This program is distributed in the hope that it will be useful, but WITHOUT A
* WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A
* PARTICULAR PURPOSE. See the GNU Lesser General Public License for more details.
* You should have received a copy of the GNU Lesser General Public License,
* v.2.1 along with this distribution; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston,
* MA 02110-1301, USA.
*
* (C) 2005-2006,
* @author JBoss Inc.
*/
/*
* Copyright (C) 2004,
*
* Arjuna Technologies Ltd.,
* Newcastle upon Tyne,
* Tyne and Wear,
* UK.
*
* $Id: ExampleXAResource.java 2342 2006-03-30 13:06:17Z $
*/
package com.hp.mwtests.ts.jta.common;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
public abstract class ExampleXAResource implements XAResource
{
public ExampleXAResource ()
{
/*
* Add this instance to a reaper, such that if it is still active when
* the timeout goes off, the reaper will roll back the work.
*/
}
public void start (Xid xid, int flags) throws XAException
{
if (!validXid(xid))
throw new XAException(XAException.XAER_NOTA);
switch (flags)
{
case XAResource.TMNOFLAGS:
associateNewUniqueTransaction(xid);
break;
case XAResource.TMJOIN:
joinExistingTransaction(xid);
break;
case XAResource.TMRESUME:
resumeOldTransaction(xid);
break;
default:
throw new XAException(XAException.XAER_PROTO);
}
}
public void end (Xid xid, int flags) throws XAException
{
if (!validXid(xid))
throw new XAException(XAException.XAER_NOTA);
switch (flags)
{
case XAResource.TMSUSPEND:
temporarilySuspendBranch(xid);
break;
case XAResource.TMFAIL:
endAssociationAndRollback(xid);
break;
case XAResource.TMSUCCESS:
endAssociation(xid);
break;
default:
throw new XAException(XAException.XAER_PROTO);
}
}
public int prepare (Xid xid) throws XAException
{
if (!validXid(xid))
throw new XAException(XAException.XAER_NOTA);
if (!validResourceManager(xid))
throw new XAException(XAException.XAER_RMFAIL);
return resourceManagerPrepare(xid);
}
public void commit (Xid xid, boolean onePhase) throws XAException
{
if (!validXid(xid))
throw new XAException(XAException.XAER_NOTA);
if (!validResourceManager(xid))
throw new XAException(XAException.XAER_RMFAIL);
if (!onePhase && !resourceManagerPrepared(xid))
throw new XAException(XAException.XAER_PROTO);
resourceManagerCommit(xid, onePhase);
}
public void rollback (Xid xid) throws XAException
{
if (!validXid(xid))
throw new XAException(XAException.XAER_NOTA);
if (!validResourceManager(xid))
throw new XAException(XAException.XAER_RMFAIL);
resourceManagerRollback(xid);
}
public void forget (Xid xid) throws XAException
{
if (!validXid(xid))
throw new XAException(XAException.XAER_NOTA);
if (!validResourceManager(xid))
throw new XAException(XAException.XAER_RMFAIL);
if (!resourceManagerPrepared(xid))
throw new XAException(XAException.XAER_PROTO);
resourceManagerForget(xid);
}
public Xid[] recover (int flag) throws XAException
{
switch (flag)
{
case XAResource.TMNOFLAGS:
{
if (recoveryScanStarted())
{
return indoubtTransactions();
}
else
throw new XAException(XAException.XAER_PROTO);
}
case XAResource.TMSTARTRSCAN:
{
if (recoveryScanStarted())
throw new XAException(XAException.XAER_PROTO);
else
startRecoveryScan();
}
break;
case XAResource.TMENDRSCAN:
{
if (recoveryScanStarted())
endRecoveryScan();
else
throw new XAException(XAException.XAER_PROTO);
}
break;
default:
{
if ((flag & XAResource.TMSTARTRSCAN & XAResource.TMENDRSCAN) != 0)
{
if (recoveryScanStarted())
throw new XAException(XAException.XAER_PROTO);
else
{
startRecoveryScan();
Xid[] indoubts = indoubtTransactions();
endRecoveryScan();
return indoubts;
}
}
else
throw new XAException(XAException.XAER_PROTO);
}
}
return null;
}
public int getTransactionTimeout () throws XAException
{
return timeout;
}
public boolean setTransactionTimeout (int seconds) throws XAException
{
if (seconds >= 0)
{
timeout = seconds;
return true;
}
else
return false;
}
public boolean isSameRM (XAResource xares) throws XAException
{
return (xares == this);
}
/*
* Determine whether or not this is an Xid instance we can deal with.
*/
protected abstract boolean validXid (Xid xid);
/*
* Ensure that this Xid is unique within the context of this RM. If it is
* then associate the RM (and thread) with the transaction identified by the
* Xid, such that all work performed on the RM is transactional.
*/
protected abstract void associateNewUniqueTransaction (Xid xid)
throws XAException;
/*
* Ensure that this Xid is one we have seen before and is still active. If
* it is, then associate the RM as before. If the thread is already
* associated with a transaction, then throw an appropriate XAException.
*/
protected abstract void joinExistingTransaction (Xid xid)
throws XAException;
/*
* Ensure that this Xid is one we have seen before and have previously
* suspended. If it isn't then throw an XAException. If it is, then resume
* the association.
*/
protected abstract void resumeOldTransaction (Xid xid) throws XAException;
/*
* Ensure that this Xid is one we know about. If it isn't then throw an
* XAException. If it is, then suspend the association of the RM (and
* thread) with the transaction. Suspend is different to ending, because the
* association can be (should be) resumed later or ended.
*/
protected abstract void temporarilySuspendBranch (Xid xid)
throws XAException;
/*
* Ensure that this Xid is one we know about. If it isn't then it's a
* protocol error and we should throw an appropriate XAException. If it is,
* then end the association with the RM.
*/
protected abstract void endAssociation (Xid xid) throws XAException;
/*
* Ensure that this Xid is one we know about. If it isn't then it's a
* protocol error and we should throw an appropriate XAException. If it is,
* then end the association with the RM and roll back the work performed by
* the RM in the scope of that transaction.
*/
protected abstract void endAssociationAndRollback (Xid xid)
throws XAException;
/*
* Is there a valid RM associated with this transaction?
*/
protected abstract boolean validResourceManager (Xid xid);
/*
* Find the RM associated with this transaction and ask it to prepare the
* work done in the scope of the transaction. Returns either OK or READ
* ONLY.
*/
protected abstract int resourceManagerPrepare (Xid xid) throws XAException;
/*
* Find the RM associated with this transaction and ask it to commit the
* work done in the scope of the transaction.
*/
protected abstract void resourceManagerCommit (Xid xid, boolean onePhase)
throws XAException;
/*
* Find the RM associated with this transaction and ask it to roll back the
* work done in the scope of the transaction.
*/
protected abstract void resourceManagerRollback (Xid xid)
throws XAException;
/*
* Find the RM associated with this transaction and ask it to forget any
* heuristic information on behalf of the transaction.
*/
protected abstract void resourceManagerForget (Xid xid) throws XAException;
/*
* Find the RM associated with this transaction and determine if it has been
* prepared.
*/
protected abstract boolean resourceManagerPrepared (Xid xid)
throws XAException;
/*
* Has the recovery scan begun?
*/
protected abstract boolean recoveryScanStarted () throws XAException;
/*
* Return the list of indoubt (and heuristic) transactions.
*/
protected abstract Xid[] indoubtTransactions () throws XAException;
/*
* Start the recovery scan.
*/
protected abstract void startRecoveryScan () throws XAException;
/*
* End the recovery scan.
*/
protected abstract void endRecoveryScan () throws XAException;
private int timeout = 0;
}