/**
 * 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$
 * --------------------------------------------------------------------------
 */

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

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.resource.internal.cm.jta.JResourceManagerEvent;
import org.ow2.jonas.resource.internal.cm.jta.LocalXAResource;
import org.ow2.jonas.resource.internal.cm.sql.cache.PreparedStatementCache;
import org.ow2.jonas.resource.internal.cm.sql.cache.PreparedStatementCacheStatistics;
import org.ow2.jonas.resource.internal.cm.sql.cache.PreparedStatementListCacheImpl;
import org.ow2.jonas.resource.internal.cm.sql.cache.PreparedStatementMapCacheImpl;

/**
 *  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;

    /**
     * Prepared statement cache for this
     * ManagedConnection.
     */
    public PreparedStatementCache pStmts = null;

    /**
     * Pstmt cache enabled ?
     */
    private boolean cacheEnabled = false;

    protected static Logger myLogger = null;

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

    /**
     * Constructor for the ManagedConnectionInfo object
     * @param mc ManagedConnection to associate with
     */
    public ManagedConnectionInfo(final ManagedConnection mc, final int maxCacheSize, final String pstmtCachePolicy, final PreparedStatementCacheStatistics pstmtStats, final Logger logger) {
        this.mc = mc;
        localTransaction = false;
        usedCs = new Vector();
        if (maxCacheSize >= 0) {
            cacheEnabled = true;
        }
        myLogger = logger;

        // select cache policy
        String cachePolicy = pstmtCachePolicy;

        if (cachePolicy == null || cachePolicy.equals("")) {
            cachePolicy = System.getProperty("org.ow2.jonas.resource.pstmt.cache.policy");
        }

        if (cachePolicy == null || cachePolicy.equals("")) {
            myLogger.log(BasicLevel.DEBUG, "Cache policy not set - take the default one : list");
            pStmts = new PreparedStatementListCacheImpl(maxCacheSize, pstmtStats, logger);
        } else if (cachePolicy.equalsIgnoreCase(PreparedStatementCache.CACHE_POLICY_LIST)) {
            myLogger.log(BasicLevel.DEBUG, "Cache policy set to list");
            pStmts = new PreparedStatementListCacheImpl(maxCacheSize, pstmtStats, logger);
        } else if (cachePolicy.equalsIgnoreCase(PreparedStatementCache.CACHE_POLICY_MAP)) {
            myLogger.log(BasicLevel.DEBUG, "Cache policy set to map");
            pStmts = new PreparedStatementMapCacheImpl(maxCacheSize, pstmtStats, logger);
        }
    }

    public void setGlobalTx(final 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(final 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";
        }
        res += pStmts.getState(prefix);
        return res;
    }

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

    /**
     * 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;
    }

    /**
     * @return true if Prepared statement cache is enabled
     */
    public boolean isCacheEnabled() {
        return cacheEnabled;
    }

}


