/**
 * JOnAS: Java(TM) Open Application Server
 * Copyright (C) 1999-2007 Bull S.A.S.
 * Contact: jonas-team@ow2.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: ManagedConnectionInfo.java 19145 2010-01-05 13:32:07Z durieuxp $
 * --------------------------------------------------------------------------
 */

package org.ow2.jonas.resource.internal.cm;

import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
import java.util.Vector;

import javax.resource.ResourceException;
import javax.resource.spi.ManagedConnection;
import javax.transaction.Synchronization;
import javax.transaction.xa.XAResource;

import org.objectweb.util.monolog.api.BasicLevel;
import org.objectweb.util.monolog.api.Logger;
import org.ow2.jonas.lib.util.Log;

import org.ow2.jonas.resource.internal.cm.jta.JResourceManagerEvent;
import org.ow2.jonas.resource.internal.cm.jta.LocalXAResource;
import org.ow2.jonas.resource.internal.cm.sql.PreparedStatementWrapper;


/**
 *  A ManagedConnection and its Information
 *
 * @author     sebastien.chassande@inrialpes.fr
 * @author     Eric.Hardesty@bull.com
 */
public class ManagedConnectionInfo {
    /**
     *  The managedConnection
     */
    public ManagedConnection mc;

    /**
     *  The list of used Connections
     */
    public Vector usedCs = null;

    /**
     *  The event used for the later enlisting into transaction
     */
    public JResourceManagerEvent rme = null;

    /**
     *  Has the ResourceManagerEvent Listener been called
     */
    public boolean rmeCalled = false;

    /**
     *  Is the the managedConnection is inside a local transaction
     */
    public boolean localTransaction = false;

    /**
     *  If local transaction is used, then here is the LocalXAWrapper to use
     *  instead of an XA object
     */
    public LocalXAResource lw = null;

    /**
     *  The Global Transaction linked to the managedConnection instance
     * There are three state possible
     * global transaction : globaltx= the reference to the transaction instance
     * local transaction:   globaltx=null / localTransaction = true
     * no transaction:      globaltx = null;
     */
    private Object globaltx;

    /**
     * The current Synchronisation object  used for the later enlisting into
     * the global transaction
     */
    public Synchronization synchro = null;

    /**
     * This vector will hold any necessary preparedStatements for this
     * ManagedConnection.
     */
    public List pStmts = null;

    protected static Logger logger = null;

    /**
     *  Has the ConnectionEventListener been set
     */
    public boolean connectionEventListener = false;

    /**
     * Constructor for the ManagedConnectionInfo object
     * @param mc ManagedConnection to associate with
     */
    public ManagedConnectionInfo(ManagedConnection mc) {
        this.mc = mc;
        localTransaction = false;
        usedCs = new Vector();
        pStmts = new ArrayList();
        logger = Log.getLogger(Log.JONAS_JCA_PREFIX);
    }

    public void setGlobalTx(Object tx) {
        //logger.log(BasicLevel.DEBUG, "tx=" + tx);
        globaltx = tx;
    }

    public Object getGlobalTx() {
        return globaltx;
    }

    /**
     *  Gets the State attribute of the ManagedConnectionInfo object
     *
     * @param prefix String to print out
     * @return         The State value
     */
    public String getState(String prefix) {
        String res = prefix + "* mc=" + mc + "\n";
        res += prefix + "Context=" + globaltx + "\n";
        res += prefix + "size of usedCs:" + usedCs.size() + "\n";
        for (int i = 0; i < usedCs.size(); i++) {
            res += prefix + "\t" + usedCs.elementAt(i).toString() + "\n";
        }
        synchronized(pStmts) {
            res += prefix + "size of pStmts:" + pStmts.size() + "\n";
            for (Iterator it = pStmts.iterator(); it.hasNext();) {
                res += prefix + "\t" + it.next() + "\n";
            }
        }
        return res;
    }


    /**
     * Gets the State attribute of the ManagedConnectionInfo object
     * @return String current state
     */
    public String getState() {
        return getState("");
    }

    /**
     * Determine if there is a pStmt to remove
     * The method calling this code should use synchronized block
     * @return int offset of the first free entry
     */
    public int findFreeStmt() {
        int offset = -1;
        int size = pStmts.size();
        PreparedStatementWrapper psw = null;
        if (pStmts != null) {
            for (int i = 0; i < size; i++) {
                psw = (PreparedStatementWrapper) pStmts.get(i);
                if (psw.isClosed()) {
                    offset = i;
                    break;
                }
            }
        }
        return offset;
    }

    /**
     * Fowards the detroy call on the ManagedConnection
     * @throws Exception if an Exception occurs
     */
    public void destroy() throws Exception {
        mc.destroy();
    }

    /**
     * Gets the associated XAResource
     * @return XAResource associated with this object
     * @throws ResourceException if an Exception occurs
     */
    public XAResource getXAResource() throws ResourceException {
        if (lw != null) {
            return lw;
        } else {
            return mc.getXAResource();
        }
    }


    /**
     * @return the rme
     */
    public JResourceManagerEvent getResourceManagementEvent() {
        return rme;
    }
}


