package tryXA;

import java.io.File;
import java.sql.Connection;
import java.sql.PreparedStatement;
import java.sql.ResultSet;
import java.sql.SQLException;

import javax.sql.XADataSource;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAException;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;


import org.apache.geronimo.transaction.manager.GeronimoTransactionManager;

import junit.framework.TestCase;

public class SimulateGeronimoTransaction extends TestCase {

	public void testGeronimoSameXAResourceJoinTwice_Oracle() throws Exception
	{
		TransactionManager tm = createGeronimoTransactionManager();
		XADataSource ds = createOracleXADataSource();
		javax.sql.XAConnection xaConn = ds.getXAConnection();
		for(int i = 0; i < 4; i++)
		{
		tm.begin();
		
		Transaction transaction = tm.getTransaction();
		
		doXADatabaseOperation(transaction, xaConn, 
				"a", "msgseq", XAResource.TMSUCCESS);
		tm.commit();
		}
	}
	private XADataSource createOracleXADataSource() throws SQLException {
		oracle.jdbc.xa.client.OracleXADataSource xaDs = new oracle.jdbc.xa.client.OracleXADataSource();
		//xaDs.setURL("jdbc:oracle:thin:@168.1.100.30:1521:ora9i30");
		xaDs.setUser("changjun");
		xaDs.setPassword("changjun");
		
		xaDs.setServerName("168.1.100.30");
		xaDs.setPortNumber(1521);
		xaDs.setDriverType("thin");
		xaDs.setDataSourceName("OracleXADataSource1");
		xaDs.setServiceName("ora9i30");
		return xaDs;
	}

	void doXADatabaseOperation(Transaction transaction, javax.sql.XAConnection xaConn, String appname, String table, int delistStatus) throws Exception
	{
		String sql = "select * from " + table + " where appname='"+appname+"'";
		
		XAResource res1 = new WrapperXAResource(xaConn.getXAResource());
		transaction.enlistResource(res1);

		Connection sqlConn = xaConn.getConnection();
		PreparedStatement statement = sqlConn.prepareStatement(sql);
		ResultSet set = statement.executeQuery();
		if(!set.next())
			sql = "insert into " + table + " values('" + appname+"', 'key', 0)";
		else
		{
			String value = set.getString("value");
			value = new Integer(Integer.parseInt(value) + 1).toString();
			sql = "update " + table + " set value=" + value + " where appname='" +  appname+ "'";
		}
		statement = sqlConn.prepareStatement(sql);
		statement.executeUpdate();
		//sqlConn.close();
		//transaction.delistResource(res1, delistStatus);
		
	}

	private static TransactionManager createGeronimoTransactionManager()
			throws Exception {
		org.apache.geronimo.transaction.manager.XidFactoryImpl xidFactory = new org.apache.geronimo.transaction.manager.XidFactoryImpl();
		org.apache.servicemix.transaction.HowlLogFactoryBean logFactory = new org.apache.servicemix.transaction.HowlLogFactoryBean();
		logFactory.setLogFileDir("./geronimo");
		logFactory.setXidFactory(xidFactory);
		GeronimoTransactionManager tm = new GeronimoTransactionManager(60000,
				xidFactory,
				/*
				 * (org.apache.geronimo.transaction.manager.TransactionLog)
				 * logFactory .getObject()
				 */null);

		return tm;
	}

	public static TransactionManager createJbossTransactionManager()
			throws Exception {
		com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple tm = new com.arjuna.ats.internal.jta.transaction.arjunacore.TransactionManagerImple();
		return tm;
	}

	public static TransactionManager createAtomicTransactionManager()
			throws Exception {
		new File("tmlog.lck").delete();
		new File("tm.out.lck").delete();
		System.setProperty("com.atomikos.icatch.file",
				"configs/atomikos.properties");
		com.atomikos.icatch.jta.UserTransactionManager tm = new com.atomikos.icatch.jta.UserTransactionManager();
		tm.init();
		tm.setForceShutdown(true);
		tm.setTransactionTimeout(60000);
		return tm;

	}
	static class WrapperXAResource implements XAResource
	{
		private XAResource real;

		WrapperXAResource(XAResource real)
		{
			this.real = real;
		}
		public void commit(Xid arg0, boolean arg1) throws XAException {
			real.commit(arg0, arg1);
			
		}

		public void end(Xid arg0, int arg1) throws XAException {
			real.end(arg0, arg1);
			
		}

		public void forget(Xid arg0) throws XAException {
			real.forget(arg0);
		}

		public int getTransactionTimeout() throws XAException {
			return real.getTransactionTimeout();
		}

		public boolean isSameRM(XAResource arg0) throws XAException {
			if(arg0 instanceof WrapperXAResource)
				return real.isSameRM(((WrapperXAResource)arg0).real);
			else
				return real.isSameRM(arg0);
		}

		public int prepare(Xid arg0) throws XAException {
			return real.prepare(arg0);
		}

		public Xid[] recover(int arg0) throws XAException {
			
			return real.recover(arg0);
		}

		public void rollback(Xid arg0) throws XAException {
			real.rollback(arg0);
			
		}

		public boolean setTransactionTimeout(int arg0) throws XAException {
			return real.setTransactionTimeout(arg0);
		}

		public void start(Xid arg0, int arg1) throws XAException {
			real.start(arg0, arg1);
		}
		
	}
}
