/* JFox, the OpenSource J2EE Application Server
 *
 * Distributable under GNU LGPL license by gun.org
 * more details please visit http://www.huihoo.org/jfox
 */

package org.jfox.ejb;

import java.lang.reflect.Proxy;
import javax.ejb.EJBException;
import javax.ejb.EJBLocalObject;
import javax.ejb.EJBObject;
import javax.ejb.SessionContext;
import javax.transaction.Status;
import javax.transaction.SystemException;
import javax.transaction.UserTransaction;

import org.jfox.ejb.connector.ContainerRemote;
import org.jfox.ejb.connector.local.LOCALContainerInvoker;
import org.jfox.ejb.connector.local.LOCALContainerService;
import org.jfox.ejb.meta.SessionBeanDescriptor;
import org.jfox.framework.Registry;
import org.jfox.tm.ServerUserTransaction;

/**
 * @author <a href="mailto:young_yy@hotmail.com">Young Yang</a>
 */

public class SessionContextImpl extends EJBContextSupport implements SessionContext {
    private UserTransaction ut = null;

    public SessionContextImpl(EJBObjectId objectId, BucketMetaData bucketMeta) {
        super(objectId, bucketMeta);
    }

    public EJBLocalObject getEJBLocalObject() throws IllegalStateException {
        throw new IllegalStateException("do not need EJBLocalObject as to jfox!");
    }

    // use LocalInvocationHanlder & LOCALContainerService
    public EJBObject getEJBObject() throws IllegalStateException {
        ClassLoader ctxLoader = Thread.currentThread().getContextClassLoader();
        // get the EJBObject class name
        String remoteInterfaceName = objectId.getRemoteInterfaceName();
        try {
            Class remoteInterface = ctxLoader.loadClass(remoteInterfaceName);
            return (EJBObject) Proxy.newProxyInstance(Thread.currentThread().getContextClassLoader(),
                    new Class[]{remoteInterface},
//              new LOCALContainerInvoker(objectId, LOCALContainerService.getInstance()));
                    new LOCALContainerInvoker(objectId, (ContainerRemote) (Registry.getInstance().getFirstComponentMetabyImplemetation(LOCALContainerService.class).getComponentInstance())));
        }
        catch(Exception e) {
            throw new EJBException(e);
        }
    }

    public UserTransaction getUserTransaction() throws IllegalStateException {
        if(ut == null) {
            if(!((SessionBeanDescriptor) bucketMeta.getEJBDescriptor()).isBeanManagedTransaction()) {
                throw new IllegalStateException("EJBContext.getUserTransaction() not allowed for CMT beans");
            }
            else {
                ut = ServerUserTransaction.getInstance();
            }
        }
        return ut;
    }


    public void setRollbackOnly() throws IllegalStateException {
        if(((SessionBeanDescriptor) bucketMeta.getEJBDescriptor()).isBeanManagedTransaction()) {
            throw new IllegalStateException("EJBContext.setRollbackOnly() not allowed for BMT beans.");
        }

        try {
            ContainerImpl.getInstance().getTransactionManager().setRollbackOnly();
        }
        catch(IllegalStateException e) {
            logger.warn(e.getMessage(), e);
        }
        catch(SystemException e) {
            logger.warn("failed to set rollback only", e);
        }
    }

    public boolean getRollbackOnly() throws IllegalStateException {
        if(((SessionBeanDescriptor) bucketMeta.getEJBDescriptor()).isBeanManagedTransaction()) {
            throw new IllegalStateException("EJBContext.setRollbackOnly() not allowed for BMT beans.");
        }
        try {
            return ContainerImpl.getInstance().getTransactionManager().getStatus() == Status.STATUS_MARKED_ROLLBACK;
        }
        catch(SystemException e) {
            logger.warn("failed to set get tx manager status", e);
            return true;
        }
    }

    public javax.xml.rpc.handler.MessageContext getMessageContext() throws IllegalStateException {
        throw new EJBException("not implement yet!");
    }

}
