⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 xaconnectionfactory.java

📁 国外的一套开源CRM
💻 JAVA
📖 第 1 页 / 共 2 页
字号:
/*
 * Licensed under the X license (see http://www.x.org/terms.htm)
 */
package org.ofbiz.minerva.pool.jdbc.xa;

import java.sql.Connection;
import java.sql.SQLException;
import java.util.Collections;
import java.util.HashMap;
import java.util.Map;

import javax.naming.InitialContext;
import javax.naming.NamingException;
import javax.sql.ConnectionEvent;
import javax.sql.ConnectionEventListener;
import javax.sql.XAConnection;
import javax.sql.XADataSource;
import javax.transaction.Status;
import javax.transaction.Transaction;
import javax.transaction.TransactionManager;
import javax.transaction.xa.XAResource;

import org.apache.log4j.Logger;
import org.ofbiz.minerva.pool.ObjectPool;
import org.ofbiz.minerva.pool.PoolObjectFactory;
import org.ofbiz.minerva.pool.jdbc.xa.wrapper.TransactionListener;
import org.ofbiz.minerva.pool.jdbc.xa.wrapper.XAConnectionImpl;
import org.ofbiz.minerva.pool.jdbc.xa.wrapper.XADataSourceImpl;
import org.ofbiz.minerva.pool.jdbc.xa.wrapper.XAResourceImpl;

/**
 * Object factory for JDBC 2.0 standard extension XAConnections.  You pool the
 * XAConnections instead of the java.sql.Connections since with vendor
 * conformant drivers, you don't have direct access to the java.sql.Connection,
 * and any work done isn't associated with the java.sql.Connection anyway.
 * <P><B>Note:</B> This implementation requires that the TransactionManager
 * be bound to a JNDI name.</P>
 * <P><B>Note:</B> This implementation has special handling for Minerva JDBC
 * 1/2 XA Wrappers.  Namely, when a request comes in, if it is for a wrapper
 * connection and it has the same current transaction as a previous active
 * connection, the same previous connection will be returned.  Otherwise,
 * you won't be able to share changes across connections like you can with
 * the native JDBC 2 Standard Extension implementations.</P>
 *
 * @author Aaron Mulder (ammulder@alumni.princeton.edu)
 * @author <a href="mailto:bill@burkecentral.com">Bill Burke</a>
 *
 * REVISIONS:
 * 20010703 bill added code for transaction isolation
 @version $Revision: 1.2 $
 */
public class XAConnectionFactory extends PoolObjectFactory {

    public static final int DEFAULT_ISOLATION = -1;

    private InitialContext ctx;
    private XADataSource source;
    private String userName;
    private String password;
    private int psCacheSize = 10;
    private boolean releaseOnCommit = false;
    private boolean saveStackTrace = false;
    private int transactionIsolation = DEFAULT_ISOLATION;
    private ConnectionEventListener listener, errorListener;
    private TransactionListener transListener;
    private ObjectPool pool;
    private final Map wrapperTx = Collections.synchronizedMap(new HashMap());
    private final Map rms = Collections.synchronizedMap(new HashMap());
    private TransactionManager tm;

    private static Logger log = Logger.getLogger(XAConnectionFactory.class);

    /**
     * Creates a new factory.  You must set the XADataSource and
     * TransactionManager JNDI name before the factory can be used.
     */
    public XAConnectionFactory() throws NamingException {
        ctx = new InitialContext();
        //wrapperTx = new HashMap();
        //rms = new HashMap();
        errorListener = new ConnectionEventListener() {
            public void connectionErrorOccurred(ConnectionEvent evt) {
                if (pool.isInvalidateOnError()) {
                    pool.markObjectAsInvalid(evt.getSource());
                }
            }

            public void connectionClosed(ConnectionEvent evt) {
            }
        };

        listener = new ConnectionEventListener() {

            public void connectionErrorOccurred(ConnectionEvent evt) {
                if (pool.isInvalidateOnError()) {
                    pool.markObjectAsInvalid(evt.getSource());
                }
//                closeConnection(evt, XAResource.TMFAIL);
            }

            public void connectionClosed(ConnectionEvent evt) {
                closeConnection(evt, XAResource.TMSUCCESS);
            }

            private void closeConnection(ConnectionEvent evt, int status) {
                XAConnection con = (XAConnection) evt.getSource();
                try {
                    con.removeConnectionEventListener(listener);
                } catch (IllegalArgumentException e) {
                    return; // Removed twice somehow?
                }
                Transaction trans = null;
                try {
                    if (tm.getStatus() != Status.STATUS_NO_TRANSACTION) {
                        trans = tm.getTransaction();
                        XAResource res = (XAResource) rms.remove(con);
                        if (res != null) {
                            trans.delistResource(res, status);
                        } // end of if ()
                        else {
                            log.warn("no xares in rms for con " + con);
                        } // end of else
                    }
                } catch (Exception e) {
                    log.error("Unable to deregister with TransactionManager", e);
                    throw new RuntimeException("Unable to deregister with TransactionManager: " + e);
                }

                if (!(con instanceof XAConnectionImpl)) {
                    // Real XAConnection -> not associated w/ transaction
                    pool.releaseObject(con);
                } else {
                    XAConnectionImpl xaCon = (XAConnectionImpl) con;
                    if (!((XAResourceImpl) xaCon.getXAResource()).isTransaction()) {
                        // Wrapper - we can only release it if there's no current transaction
                        // Can't just check TM because con may have been committed but left open
                        //   so if there's a current transaction it may not apply to the con.
                        log.warn("XAConnectionImpl: " + xaCon + " has no current tx!");
                        try {
                            xaCon.rollback();
                        } catch (SQLException e) {
                            pool.markObjectAsInvalid(con);
                        }
                        pool.releaseObject(con);
                    } else {
                        // Still track errors, but don't try to close again.
                        con.addConnectionEventListener(errorListener);
                    }
                }
            }
        };
        transListener = new TransactionListener() {
            public void transactionFinished(XAConnectionImpl con) {
                con.clearTransactionListener();
                Object tx = wrapperTx.remove(con);
                //System.out.println("removing con: " + con + "from wrapperTx, tx: " + tx);
                if (tx != null)
                    wrapperTx.remove(tx);
                try {
                    con.removeConnectionEventListener(errorListener);
                } catch (IllegalArgumentException e) {
                    // connection was not closed, but transaction ended
                    if (!releaseOnCommit) {
                        return;
                    } else {
                        rms.remove(con);
                        pool.markObjectAsInvalid(con);
                        con.forceClientConnectionsClose();
                    }
                }

                pool.releaseObject(con);
            }

            public void transactionFailed(XAConnectionImpl con) {
                con.clearTransactionListener();
                Object tx = wrapperTx.remove(con);
                if (tx != null)
                    wrapperTx.remove(tx);
                //System.out.println("removing con: " + con + "from wrapperTx, tx: " + tx);
                pool.markObjectAsInvalid(con);
                try {
                    con.removeConnectionEventListener(errorListener);
                } catch (IllegalArgumentException e) {
                    if (!releaseOnCommit) {
                        return;
                    } else {
                        rms.remove(con);
                        con.forceClientConnectionsClose();
                    }
                }
                pool.releaseObject(con);
            }
        };
    }

    /**
     * Sets the user name used to generate XAConnections.  This is optional,
     * and will only be used if present.
     */
    public void setUser(String userName) {
        this.userName = userName;
    }

    /**
     * Gets the user name used to generate XAConnections.
     */
    public String getUser() {
        return userName;
    }

    /**
     * Sets the password used to generate XAConnections.  This is optional,
     * and will only be used if present.
     */
    public void setPassword(String password) {
        this.password = password;
    }

    /**
     * Gets the password used to generate XAConnections.
     */
    public String getPassword() {
        return password;
    }

    public boolean getReleaseOnCommit() {
        return releaseOnCommit;
    }

    public void setReleaseOnCommit(boolean rel) {
        releaseOnCommit = rel;
    }

    /**
     * Sets the number of PreparedStatements to be cached for each
     * Connection.  Your DB product may impose a limit on the number
     * of open PreparedStatements.  The default value is 10.
     */

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -