usertransactionimpl.java
来自「RESIN 3.2 最新源码」· Java 代码 · 共 554 行
JAVA
554 行
/* * Copyright (c) 1998-2008 Caucho Technology -- all rights reserved * * This file is part of Resin(R) Open Source * * Each copy or derived work must preserve the copyright notice and this * notice unmodified. * * Resin Open Source is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation; either version 2 of the License, or * (at your option) any later version. * * Resin Open Source 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, or any warranty * of NON-INFRINGEMENT. See the GNU General Public License for more * details. * * You should have received a copy of the GNU General Public License * along with Resin Open Source; if not, write to the * * Free Software Foundation, Inc. * 59 Temple Place, Suite 330 * Boston, MA 02111-1307 USA * * @author Scott Ferguson */package com.caucho.jca;import com.caucho.log.Log;import com.caucho.transaction.TransactionImpl;import com.caucho.transaction.TransactionManagerImpl;import com.caucho.util.L10N;import com.caucho.webbeans.component.*;import javax.resource.spi.ConnectionRequestInfo;import javax.resource.spi.ManagedConnectionFactory;import javax.security.auth.Subject;import javax.transaction.*;import javax.transaction.xa.Xid;import java.util.ArrayList;import java.util.logging.Level;import java.util.logging.Logger;/** * Implementation of the UserTransactionImpl for a thread instance. */public class UserTransactionImpl implements UserTransaction{ private static final Logger log = Logger.getLogger(UserTransactionImpl.class.getName()); private static final L10N L = new L10N(UserTransactionImpl.class); private TransactionManagerImpl _transactionManager; private ArrayList<UserPoolItem> _resources = new ArrayList<UserPoolItem>(); private ArrayList<PoolItem> _poolItems = new ArrayList<PoolItem>(); private ArrayList<BeginResource> _beginResources = new ArrayList<BeginResource>(); private ArrayList<CloseResource> _closeResources = new ArrayList<CloseResource>(); private boolean _isInContext; private int _xaDepth; /** * Creates the proxy. */ public UserTransactionImpl(TransactionManagerImpl tm) { _transactionManager = tm; } /** * Sets the transaction's timeout. */ public void setTransactionTimeout(int seconds) throws SystemException { _transactionManager.setTransactionTimeout(seconds); } /** * Gets the transaction's status */ public int getStatus() throws SystemException { return _transactionManager.getStatus(); } /** * inContext is valid within a managed UserTransactionImpl context, e.g * in a webApp, but not in a cron job. */ public boolean isInContext() { return _isInContext; } /** * inContext is valid within a managed UserTransactionImpl context, e.g * in a webApp, but not in a cron job. */ public void setInContext(boolean isInContext) { _isInContext = isInContext; } /** * Enlist a resource. */ void enlistResource(UserPoolItem resource) throws SystemException, RollbackException { if (_resources.contains(resource)) return; Transaction xa = _transactionManager.getTransaction(); if (xa != null) { PoolItem poolItem = resource.getXAPoolItem(); enlistPoolItem(xa, poolItem); } _resources.add(resource); } private void enlistPoolItem(Transaction xa, PoolItem poolItem) throws SystemException, RollbackException { if (poolItem == null) return; else if (! poolItem.supportsTransaction()) { // server/164j return; } // XXX: new if (_poolItems.contains(poolItem)) return; poolItem.setTransaction(this); if (xa instanceof TransactionImpl) { TransactionImpl xaImpl = (TransactionImpl) xa; // server/164l if (xaImpl.allowLocalTransactionOptimization()) poolItem.enableLocalTransactionOptimization(true); } if (poolItem.getXid() == null) xa.enlistResource(poolItem); _poolItems.add(poolItem); } /** * Delist a pool item */ void delistPoolItem(PoolItem poolItem, int flags) throws SystemException, RollbackException { Transaction xa = _transactionManager.getTransaction(); try { if (xa != null) xa.delistResource(poolItem, flags); } finally { _poolItems.remove(poolItem); } } /** * Delist a resource. */ void delistResource(UserPoolItem resource) { _resources.remove(resource); } /** * Enlist a resource automatically called when a transaction begins */ public void enlistBeginResource(BeginResource resource) { _beginResources.add(resource); try { Transaction xa = _transactionManager.getTransaction(); if (xa != null) resource.begin(xa); } catch (Exception e) { throw new RuntimeException(e); } } /** * Enlist a resource automatically closed when the context ends. */ public void enlistCloseResource(CloseResource resource) { _closeResources.add(resource); } /** * Allocates a resource matching the parameters. If none matches, * return null. */ UserPoolItem allocate(ManagedConnectionFactory mcf, Subject subject, ConnectionRequestInfo info) { if (_xaDepth == 0) return null; ArrayList<PoolItem> poolItems = _poolItems; int length = poolItems.size(); for (int i = 0; i < length; i++) { PoolItem poolItem = poolItems.get(i); UserPoolItem item = poolItem.allocateXA(mcf, subject, info); if (item != null) return item; } return null; } /** * Finds the pool item joined to this one. * return null. */ PoolItem findJoin(PoolItem item) { if (_xaDepth == 0) return null; ArrayList<PoolItem> poolItems = _poolItems; int length = poolItems.size(); for (int i = 0; i < length; i++) { PoolItem poolItem = poolItems.get(i); if (poolItem.isJoin(item)) return poolItem; } return null; } /** * Returns the XID. */ public Xid getXid() throws SystemException, RollbackException { TransactionImpl xa = (TransactionImpl) _transactionManager.getTransaction(); if (xa != null) return xa.getXid(); else return null; } /** * Returns the XID. */ public int getEnlistedResourceCount() throws SystemException, RollbackException { TransactionImpl xa = (TransactionImpl) _transactionManager.getTransaction(); if (xa != null) return xa.getEnlistedResourceCount(); else return 0; } /** * Start the transaction. */ public void begin() throws NotSupportedException, SystemException { _transactionManager.begin(); _xaDepth++; boolean isOkay = false; try { TransactionImpl xa = (TransactionImpl) _transactionManager.getTransaction(); xa.setUserTransaction(this); _poolItems.clear(); // enlist "cached" connections int length = _resources.size(); for (int i = 0; i < length; i++) { UserPoolItem userPoolItem = _resources.get(i); for (int j = _poolItems.size() - 1; j >= 0; j--) { PoolItem poolItem = _poolItems.get(j); if (poolItem.share(userPoolItem)) { break; } } PoolItem xaPoolItem = userPoolItem.getXAPoolItem(); if (! _poolItems.contains(xaPoolItem)) _poolItems.add(xaPoolItem); } for (int i = 0; i < _poolItems.size(); i++) { PoolItem poolItem = _poolItems.get(i); poolItem.enableLocalTransactionOptimization(_poolItems.size() == 1); try { xa.enlistResource(poolItem); } catch (Exception e) { throw new SystemException(e); } } // enlist begin resources for (int i = 0; i < _beginResources.size(); i++) { try { BeginResource resource = _beginResources.get(i); resource.begin(xa); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } } isOkay = true; } finally { if (! isOkay) { log.warning("Rolling back transaction from failed begin()"); // something has gone very wrong _xaDepth--; ArrayList<PoolItem> recoveryList = new ArrayList<PoolItem>(_poolItems); _poolItems.clear(); _resources.clear(); for (int i = 0; i < recoveryList.size(); i++) { try { PoolItem item = recoveryList.get(i); item.abortConnection(); item.destroy(); } catch (Throwable e) { log.log(Level.FINE, e.toString(), e); } } _transactionManager.rollback(); } } } /** * Suspends the transaction. */ public UserTransactionSuspendState userSuspend() { if (_xaDepth == 0) throw new IllegalStateException(L.l("suspend may only be called in a transaction.")); _xaDepth--; UserTransactionSuspendState state; state = new UserTransactionSuspendState(_poolItems); _poolItems.clear(); return state; } /** * Resumes the transaction. */ public void userResume(UserTransactionSuspendState state) { /* if (_inTransaction) throw new IllegalStateException(L.l("resume may only be called outside of a transaction.")); */ _xaDepth++; _poolItems.addAll(state.getPoolItems()); } /** * Marks the transaction as rollback only. */ public void setRollbackOnly() throws IllegalStateException, SystemException { _transactionManager.setRollbackOnly(); } /** * Marks the transaction as rollback only. */ public void setRollbackOnly(Exception e) throws IllegalStateException { _transactionManager.setRollbackOnly(e); } /** * Commits the transaction */ public void commit() throws IllegalStateException, RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, SystemException { try { /* XXX: interaction with hessian XA if (_xaDepth == 0) throw new IllegalStateException("Can't commit outside of a transaction. Either the UserTransaction.begin() is missing or the transaction has already been committed or rolled back."); */ _transactionManager.commit(); } finally { _poolItems.clear(); if (_xaDepth > 0) _xaDepth--; } } /** * Rolls the transaction back */ public void rollback() throws IllegalStateException, SecurityException, SystemException { try { _transactionManager.rollback(); } finally { _poolItems.clear(); if (_xaDepth > 0) _xaDepth--; } } /** * Aborts the transaction. */ public void abortTransaction() throws IllegalStateException { IllegalStateException exn = null; _isInContext = false; boolean inTransaction = _xaDepth > 0; _xaDepth = 0; if (! inTransaction && _poolItems.size() > 0) { Exception e = new IllegalStateException("user transaction pool broken"); log.log(Level.WARNING, e.toString(), e); } _poolItems.clear(); if (inTransaction) { try { TransactionImpl xa = (TransactionImpl) _transactionManager.getTransaction(); exn = new IllegalStateException(L.l("Transactions must have a commit() or rollback() in a finally block.")); log.warning("Rolling back dangling transaction. All transactions must have a commit() or rollback() in a finally block."); _transactionManager.rollback(); } catch (Throwable e) { log.log(Level.WARNING, e.toString()); } } _beginResources.clear(); while (_closeResources.size() > 0) { try { CloseResource resource; resource = _closeResources.remove(_closeResources.size() - 1); resource.close(); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } } boolean hasWarning = false; while (_resources.size() > 0) { UserPoolItem userPoolItem = _resources.remove(_resources.size() - 1); if (! userPoolItem.isCloseDanglingConnections()) continue; if (! hasWarning) { hasWarning = true; log.warning("Closing dangling connections. All connections must have a close() in a finally block."); } try { IllegalStateException stackTrace = userPoolItem.getAllocationStackTrace(); if (stackTrace != null) log.log(Level.WARNING, stackTrace.getMessage(), stackTrace); else { // start saving the allocation stack trace. userPoolItem.setSaveAllocationStackTrace(true); } if (exn == null) exn = new IllegalStateException(L.l("Connection {0} was not closed. Connections must have a close() in a finally block.", userPoolItem.getUserConnection())); userPoolItem.abortConnection(); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } } _poolItems.clear(); try { _transactionManager.setTransactionTimeout(0); } catch (Throwable e) { log.log(Level.WARNING, e.toString(), e); } if (exn != null) throw exn; }}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?