/*-----------------------------------------------------------------------------
 *
 * Enhydra JdbcS
 * The Initial Developer of the Original Code is Lutris Technologies Inc.
 * Portions created by Lutris are Copyright 1997-2000 Lutris Technologies Inc.
 * All Rights Reserved.
 *
 * The contents of this file are subject to the Enhydra Public License
 * Version 1.1 (the "License"); you may not use this file except in compliance
 * with the License. You may obtain a copy of the License at
 * www.enhydra.org/license/epl.html
 *
 * Software distributed under the License is distributed on an "ASIS" basis,
 * WITHOUT WARRANTY OF ANY KIND, either express or implied. See the License for
 * the specific language governing rights and limitations under the License.
 *
 * -----------------------------------------------------------------------------
 * $Id$
 * -----------------------------------------------------------------------------
 */
package org.enhydra.jdbc.standard;

import java.sql.SQLException;
import java.sql.Connection;
import javax.sql.ConnectionEvent;
import javax.transaction.Transaction;
import javax.transaction.SystemException;
import javax.transaction.RollbackException;

public class StandardXAPreparedStatement extends StandardPreparedStatement {
    
    private StandardXAConnectionHandle	con;	// the StandardXAConnectionHandle that created this object
    public String sql;
    public int resultSetType;
    public int resultSetConcurrency;

    StandardXAPreparedStatement (StandardXAConnectionHandle con_, String sql_, int resultSetType_,int resultSetConcurrency_) throws SQLException {
	this.con = con_;
	this.sql = sql_;
	this.key = sql_+resultSetType_+resultSetConcurrency_;
	this.resultSetType = resultSetType_;
	this.resultSetConcurrency = resultSetConcurrency_;
 	//ps = con.checkPreparedCache(sql, resultSetType, resultSetConcurrency,key);
    } // constructor

    /**
     * Close this statement.
     */
    public synchronized void close() throws SQLException {
	// Note no check for already closed - some servers make mistakes
	closed = true;
	if (con.preparedStmtCacheSize == 0) {
	    if (ps != null) {
		ps.close(); // no cache, so we can close
	    }
	} else {
	    con.returnToCache (key);		// return the underlying statement to the cache
	}
    } // method close

    /** 
     * Pre-invokation of the delegation, in case of the Statement is
     * closed, we throw an exception
     */
    public synchronized void preInvoke() throws SQLException {
	if (closed)
	    throw new SQLException ("Prepare Statement is closed");

	Transaction ntx = null;
	Connection oldCon = con.con;
	if (con.tx == null) {
	    try {
		try {
		    ntx = (con.transactionManager!=null)?con.transactionManager.getTransaction():null;
		    if (ntx != null) {
			con.tx = ntx;
			con.setAutoCommit(false);
			try {
			    con.tx.enlistResource(con.xacon.getXAResource());// enlist the xaResource in the transaction
			    if (ps != null) {
				con.returnToCache(key, oldCon);
				ps = null;
			    }
			} catch (RollbackException n) {
			    n.printStackTrace();
			    throw new SQLException("StandardXAPreparedStatement:preInvoke enlistResource exception");
			}
		    }
		    //else con.setAutoCommit(true);
		} catch (SystemException n) {
		    n.printStackTrace();
		    throw new SQLException("StandardXAPreparedStatement:preInvoke getTransaction exception: "+n.toString());
		}
	    } catch (NullPointerException n) {
		// current is null: we are not in EJBServer.
		n.printStackTrace();
		throw new SQLException("StandardXAPreparedStatement:preInvoke should not be used outside an EJBServer");
	    }
	}

	if (ps == null) {
	    key = sql+resultSetType+resultSetConcurrency+((con.tx!=null)?true:false);
	    ps = con.checkPreparedCache(sql, resultSetType, resultSetConcurrency,key);
	}

    } // method preInvoke

    /**
     * Exception management : catch or throw the exception
     */
    public void catchInvoke(SQLException sqlException) throws SQLException {
	//ConnectionEvent event = new ConnectionEvent (con.pooledCon);
	//con.pooledCon.connectionErrorOccurred(event);
	throw(sqlException);
    } // method catchInvoke

} // class StandardXAPreparedStatement
