// TransactedCASLR.java
// Stateful Session bean

package org.objectweb.jonas.jtests.beans.jca15;

import java.rmi.RemoteException;
import javax.ejb.CreateException;
import javax.ejb.EJBException;
import javax.ejb.RemoveException;
import javax.ejb.EJBObject;
import javax.ejb.SessionBean;
import javax.ejb.SessionContext;
import javax.naming.Context;
import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.DataSource;
import ersatz.resourceadapter.*;
import javax.resource.cci.Connection;
import javax.resource.cci.LocalTransaction;
import javax.resource.spi.ManagedConnection;
import javax.resource.spi.ConnectionEvent;
import javax.resource.spi.ConnectionManager;
import javax.transaction.xa.XAResource;
import javax.transaction.xa.Xid;
import javax.transaction.SystemException;
import javax.transaction.NotSupportedException;
import javax.transaction.RollbackException;
import javax.transaction.HeuristicRollbackException;
import javax.transaction.HeuristicMixedException;


/**
 *
 */
public class TransactedCASLR implements SessionBean {

    private SessionContext ejbContext;
    private ManagedConnectionImpl mcf = null;   //Managed Connection Factory
    private ConnectionSpecImpl csp = null;      //ConnectionSpec
    private ConnectionFactoryImpl cccf = null;  //Common Client Connection Factory
    private ConnectionImpl conn = null;
    private InitialContext ic=null;
    private String cName = "TransactedCASLR";
    public boolean NoTransaction = false;
    public boolean LoTransaction = false;
    public boolean XATransaction = false;
    final public int CLOSE_HANDLE = 0;
    final public int CLOSE_PHYSICAL = 1;
    String xidTest;

    // ------------------------------------------------------------------
    // SessionBean implementation
    // ------------------------------------------------------------------


    public void setSessionContext(SessionContext ctx) {
        Utility.log(cName+".setSessionContext");
        ejbContext = ctx;
    }
        

    public void ejbRemove() {
        Utility.log("");
    }
        

    public void ejbCreate() throws CreateException {
        Utility.log("");
    }

    public void ejbPassivate() {
        Utility.log("");
    }

    public void ejbActivate() {
        Utility.log("");
    }
    /**
     * closeUp
     */
    public void closeUp(int closeType) {
        Utility.log(cName+
                             ".closeUp (enter) closeType="+closeType);
        try {
            if (closeType==CLOSE_PHYSICAL) {
                // The CONNECTION_ERROR_OCCURRED indicates that the associated 
                // ManagedConnectionImpl instance is now invalid and unusable.
                conn.close(ConnectionEvent.CONNECTION_ERROR_OCCURRED);
                Utility.log(cName+
                    ".closeUp (exit) : closed physical connection closeType="+closeType+
                    " ConnectionEvent.CONNECTION_ERROR_OCCURRED="+
                      ConnectionEvent.CONNECTION_ERROR_OCCURRED);
            } else {
                // The CONNECTION_CLOSED indicates that connection handle
                // is closed, but physical connection still exists
                conn.close();
                Utility.log(cName+
                             ".closeUp (exit) : closed connection closeType="+closeType);
            }
        } catch (Exception e) {
            Utility.log(cName+".closeUp (exit) error: close "+
                        "handle/physical connection failed closeType="+closeType);
        }
    }
    
    // ------------------------------------------------------------------
    // transacted implementation
    // ------------------------------------------------------------------

    /**
     * method1
     */
    public void method1(String rar_jndi_name, String testName) 
            throws Exception
    {
        Utility.log("============================ "+testName);

        if ("eis/ErsatzXATransaction".equals(rar_jndi_name)) 
            XATransaction = true;
        else if ("eis/ErsatzLoTransaction".equals(rar_jndi_name)) 
            LoTransaction = true;
        else 
            NoTransaction = true;

        try {
            ic = new InitialContext();
        } catch (Exception e1) {
            Utility.log(cName+".method1 error: InitialContext failed");
            throw e1;
        }
        try {
            cccf = (ConnectionFactoryImpl)ic.lookup(rar_jndi_name);
            Utility.log(cName+".method1 : found "+rar_jndi_name);
        } catch (Exception e2) {
            Utility.log(cName+".method1 error: lookup failed for "+rar_jndi_name);
            throw e2;
        }
        
        try {
            csp = new ConnectionSpecImpl(); // get a new ConnectionSpecImpl

        } catch (Exception e3) {
            Utility.log(cName+".method1 : new connection spec failed");
            throw e3;
        }
        try {
            conn = (ConnectionImpl)cccf.getConnection();
            Utility.log(cName+".method1 : getConnection conn="+conn);
            if (conn==null) {
                Utility.log(cName+".method1 error: getConnection returned null connection.");
                throw new Exception("");
            }
        } catch (Exception e4) {
            Utility.log(cName+".method1 error: getConnection failed "
                    +e4.toString());
            throw e4;
        }
        if (testName.equals("testIsXaresource")) {
            try {
                xidTest = doXid();
            } catch (Exception e) { throw e; }
        }
        if (testName.equals("testIsXAend2")) {
            try {
                closeUp(CLOSE_PHYSICAL);
                xidTest = doXid();
            } catch (Exception e) { throw e; }
        }
    }
    public String getXid() 
    {
        return xidTest;   // xidTest == OK | FAIL
    }
    
    public String doXid() 
                throws Exception
    {
        String ret;
        Utility.log(cName+".doXid [enter]");
        if (conn==null) {
            Utility.log(cName+".doXid [exit] error: Connection=null");
            return "FAIL";
        }
        ConnectionImpl conni = (ConnectionImpl)conn;
        try {
            ManagedConnectionImpl mc = (ManagedConnectionImpl)conni.getMC(); //get ManagedConnectionImpl
            if (mc==null) {
                Utility.log(cName+".doXid mc==null Should be null in testIsXAend2");
                ret = "FAIL";
            } else {
                XAResourceImpl xar = mc.getCurrentXar();
                if (xar==null) {
                    Utility.log(cName+".doXid error: failed xar==null");
                    ret = "FAIL";
                } else {
                    Xid xid = xar.getCurrentXid();
                    if (xid==null) {
                       Utility.log(cName+".doXid error: xid="+xid);
                       ret = "FAIL";
                    } else {
                       ret = "OK";
                    }
                }
            }
            Utility.log(cName+".doXid [exit] with "+ret);
            return ret;
        } catch (IllegalStateException ise) {
            String s=cName+".doXid error: failed IllegalStateException="+ise;
            Utility.log(s);
            throw new Exception(s);
        } catch (Exception e) {
            String s=cName+".doXid error: failed "+e;
            Utility.log(s);
            throw new Exception(s);
        }
    }
    /**
     * After the newly created ManagedConnectionFactory instance has been configured with
     * its property set, the application server creates a new ConnectionManager instance.
     * true returned if ConnectionManager is valid
     */
    public boolean getCMInstance()
            throws Exception
    {
        ConnectionManager cm;
        cm=cccf.getCM();
        if (cm==null) {                              // ConnectionManager not null
            Utility.log(cName+".getCMInstance error: ConnectionManager is null");
            return false;
        }
        else {
            Utility.log(cName+".getCMInstance ConnectionManager is o.k.");
            return true;
        }
    }
    LocalTransactionImpl lt=null;
    public void beginLoTransaction() {
        Utility.log(cName+".beginLoTransaction (enter)");
        try {
            LocalTransaction l = conn.getLocalTransaction();
            lt = (LocalTransactionImpl) l;
            lt.begin();
            int s=lt.getTxState();
            Utility.log(cName+".beginLoTransaction (exit) State="+s);
        } catch (Exception e) {
            Utility.log(cName+".beginLoTransaction (exit) error:"
                  +" "+e.toString());
                    
        }
    }
    public void commitLoTransaction() throws Exception
    {
        Utility.log(cName+".commitLoTransaction (enter)");
        try {
            if (lt==null) {
                Exception e = new Exception("Undefined LocalTransaction");
                throw e;
            }
            lt.commit();
            int s=lt.getTxState();
            Utility.log(cName+".commitLoTransaction (exit) ="+s);
        } catch (Exception e) {
            Utility.log(cName+".commitLoTransaction (exit) error: State error."
                  +" "+e.getMessage());
            throw e;        
        }
        lt=null;
    }
    public void rollbackLoTransaction() {
        Utility.log(cName+".rollbackLoTransaction (enter)");
        try {
            if (lt==null) {
                Exception e = new Exception("Undefined LocalTransaction");
                throw e;
            }
            lt.rollback();
            int s=lt.getTxState();
            Utility.log(cName+".rollbackLoTransaction (exit) State="+s);
        } catch (Exception e) {
            Utility.log(cName+".rollbackLoTransaction (exit) error: State error"
                  +" "+e.getMessage());
                    
        }
        lt=null;
    }
}

