/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2004 Bull S.A.
 * Contact: jonas-team@objectweb.org
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY 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 along with this library; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307
 * USA
 *
 * --------------------------------------------------------------------------
 * $Id$
 * --------------------------------------------------------------------------
 */

package org.objectweb.jonas.jtests.clients.exception;

import java.rmi.RemoteException;

import javax.transaction.Status;
import javax.transaction.TransactionRolledbackException;

import org.objectweb.jonas.jtests.beans.beanexc.AccountS;
import org.objectweb.jonas.jtests.beans.beanexc.AppException;
import org.objectweb.jonas.jtests.util.JTestCase;

/**
 * Exception test cases common for all type of beans (Entity/Session)
 * @author Ph.Coq
 */
public abstract class A_Catcher extends JTestCase {

    public A_Catcher(String name) {
        super(name);
    }

    protected void setUp() {
        super.setUp();
        useBeans("beanexc", true);
    }

    /**
     * This method depends on the home used to get it. AccountS is the base
     * interface of Account (common to Session/Entity)
     */
    public abstract AccountS getAccountS(int i);

    // -----------------------------------------------------
    // ApplicationException
    // -----------------------------------------------------

    /**
     * Test business method throwing an Application exception. It must be caught
     * by the client. The business method has NotSupported attribute. Spec 2.0
     * page 376 (table15)
     */
    public void testApplicationNoTx() throws Exception {
        AccountS acs = getAccountS(83);
        try {
            acs.doAppException_3();
            fail("No AppException");
        } catch (AppException e) {
        }
    }

    /**
     * Test business method throwing an Application exception. It must be caught
     * by the client. The business method has NotSupported attribute. Test that
     * the transaction has not been marked rollback. Spec 2.0 page 376 (table15)
     */
    public void testApplicationNotTx() throws Exception {
        AccountS acs = getAccountS(83);
        utx.begin();
        try {
            acs.doAppException_3();
            fail("No AppException");
        } catch (AppException e) {
            assertTrue(utx.getStatus() == Status.STATUS_ACTIVE);
        } finally {
            utx.rollback();
        }
    }

    /**
     * Test business method throwing an Application exception. It must be caught
     * by the client. A transaction is started in the container. (RequiresNew)
     * Bean does NOT call setRollbackOnly Test that the AppException has been
     * caught. Spec 2.0 page 376 (table15)
     */
    public void testApplicationContTx1() throws Exception {
        AccountS acs = getAccountS(82);
        try {
            // the instance doesn't call setRollbackOnly
            acs.doAppException_2(false);
            fail("No AppException");
        } catch (AppException e) {

        }
    }

    /**
     * Test business method throwing an Application exception. It must be caught
     * by the client. A transaction is started in the container. (RequiresNew)
     * Bean calls setRollbackOnly Test that the AppException has been caught.
     * Spec 2.0 page 376 (table15)
     */
    public void testApplicationContTxRb1() throws Exception {
        AccountS acs = getAccountS(82);
        try {
            // the instance calls setRollbackOnly
            acs.doAppException_2(true);
            fail("No AppException");
        } catch (AppException e) {
        }
    }

    /**
     * Test business method throwing an Application exception. It must be caught
     * by the client. Methods runs in the context of the caller's transaction
     * The business method has Mandatory attribute. Test that the transaction
     * has not been marked rollback. Spec 2.0 page 375 (table15)
     */
    public void testApplicationCallerTx1() throws Exception {
        AccountS acs = getAccountS(81);
        utx.begin();
        try {
            acs.doAppException_1();
            fail("No AppException");
        } catch (AppException e) {
            assertTrue(utx.getStatus() == Status.STATUS_ACTIVE);
        } finally {
            utx.rollback();
        }
    }

    // -----------------------------------------------------
    // UncheckedException
    // -----------------------------------------------------

    /**
     * Test business method throwing an unchecked exception. Methods runs in the
     * context of the caller's transaction TransactionRolledbackException must
     * be caught by the client. The business method has Mandatory attribute. See
     * EJB2.0 specs page 375 (table 15)
     */
    public void testUncheckedCallerTx() throws Exception {
        AccountS acs = getAccountS(85);
        utx.begin();
        try {
            acs.doUncheckedException_1();
            fail("No RemoteException");
        } catch (RemoteException e) {
            assertTrue((e.detail instanceof TransactionRolledbackException)
                    || (e instanceof TransactionRolledbackException));
        } finally {
            utx.rollback();
        }
    }

    /**
     * Test business method throwing an unchecked exception. Called inside a
     * containertransaction. The client must receive RemoteException See EJB2.0
     * specs page 376 (table 15)
     */
    public void testUncheckedContTx() throws Exception {
        AccountS acs = getAccountS(84);
        try {
            acs.doUncheckedException_2(); // RequiresNew
            fail("No RemoteException");
        } catch (RemoteException e) {
        }

    }

    /**
     * Test business method throwing an unchecked exception. Method runs with an
     * unspecified transaction context (NotSupported) The client must receive
     * RemoteException See EJB2.0 specs page 376 (table 15)
     */
    public void testUncheckedNoTx() throws Exception {
        AccountS acs = getAccountS(84);
        try {
            acs.doUncheckedException_3(); // NotSupported
            fail("No RemoteException");
        } catch (RemoteException e) {
        }
    }

    // -----------------------------------------------------
    // EJBException
    // -----------------------------------------------------

    /**
     * Test business method throwing an EJBException Called inside a
     * containertransaction (RequiresNew). The client must receive
     * RemoteException See EJB2.0 specs page 376 (table 15)
     */
    public void testEJBContTx() throws Exception {
        AccountS acs = getAccountS(84);
        try {
            acs.doEJBException_1(); // RequiresNew
            fail("No RemoteException");
        } catch (RemoteException e) {
        }
    }

    // -----------------------------------------------------
    // RemoteException
    // -----------------------------------------------------

    /**
     * Test business method throwing a RemoteException. Methods runs in the
     * context of the caller's transaction The bean method is TxMandatory The
     * client must receive TransactionRolledbackException See EJB2.0 specs page
     * 375 (table 15)
     */
    public void testRemoteCallerTx() throws Exception {
        AccountS acs = getAccountS(86);
        utx.begin();
        acs.ping(); // avoid another bug with RMI
        try {
            acs.doRemoteException_1(); // TxMandatory
            fail("No RemoteException");
        } catch (RemoteException e) {
            assertTrue((e.detail instanceof TransactionRolledbackException)
                    || (e instanceof TransactionRolledbackException));
        } finally {
            utx.rollback();
        }
    }

}