001: /*
002: * Copyright 2004 Clinton Begin
003: *
004: * Licensed under the Apache License, Version 2.0 (the "License");
005: * you may not use this file except in compliance with the License.
006: * You may obtain a copy of the License at
007: *
008: * http://www.apache.org/licenses/LICENSE-2.0
009: *
010: * Unless required by applicable law or agreed to in writing, software
011: * distributed under the License is distributed on an "AS IS" BASIS,
012: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
013: * See the License for the specific language governing permissions and
014: * limitations under the License.
015: */
016: package com.ibatis.sqlmap.engine.transaction;
017:
018: import com.ibatis.common.util.Throttle;
019: import com.ibatis.sqlmap.engine.scope.SessionScope;
020:
021: import javax.sql.DataSource;
022: import java.sql.SQLException;
023:
024: public class TransactionManager {
025:
026: private TransactionConfig transactionConfig;
027:
028: private boolean forceCommit;
029:
030: private Throttle txThrottle;
031:
032: public TransactionManager(TransactionConfig transactionConfig) {
033: this .transactionConfig = transactionConfig;
034: this .txThrottle = new Throttle(transactionConfig
035: .getMaximumConcurrentTransactions());
036: }
037:
038: public void begin(SessionScope session) throws SQLException,
039: TransactionException {
040: begin(session, IsolationLevel.UNSET_ISOLATION_LEVEL);
041: }
042:
043: public void begin(SessionScope session, int transactionIsolation)
044: throws SQLException, TransactionException {
045: Transaction trans = session.getTransaction();
046: TransactionState state = session.getTransactionState();
047: if (state == TransactionState.STATE_STARTED) {
048: throw new TransactionException(
049: "TransactionManager could not start a new transaction. "
050: + "A transaction is already started.");
051: } else if (state == TransactionState.STATE_USER_PROVIDED) {
052: throw new TransactionException(
053: "TransactionManager could not start a new transaction. "
054: + "A user provided connection is currently being used by this session. "
055: + "The calling .setUserConnection (null) will clear the user provided transaction.");
056: }
057:
058: txThrottle.increment();
059:
060: try {
061: trans = transactionConfig
062: .newTransaction(transactionIsolation);
063: session.setCommitRequired(false);
064: } catch (SQLException e) {
065: txThrottle.decrement();
066: throw e;
067: } catch (TransactionException e) {
068: txThrottle.decrement();
069: throw e;
070: }
071:
072: session.setTransaction(trans);
073: session.setTransactionState(TransactionState.STATE_STARTED);
074: }
075:
076: public void commit(SessionScope session) throws SQLException,
077: TransactionException {
078: Transaction trans = session.getTransaction();
079: TransactionState state = session.getTransactionState();
080: if (state == TransactionState.STATE_USER_PROVIDED) {
081: throw new TransactionException(
082: "TransactionManager could not commit. "
083: + "A user provided connection is currently being used by this session. "
084: + "You must call the commit() method of the Connection directly. "
085: + "The calling .setUserConnection (null) will clear the user provided transaction.");
086: } else if (state != TransactionState.STATE_STARTED
087: && state != TransactionState.STATE_COMMITTED) {
088: throw new TransactionException(
089: "TransactionManager could not commit. No transaction is started.");
090: }
091: if (session.isCommitRequired() || forceCommit) {
092: trans.commit();
093: session.setCommitRequired(false);
094: }
095: session.setTransactionState(TransactionState.STATE_COMMITTED);
096: }
097:
098: public void end(SessionScope session) throws SQLException,
099: TransactionException {
100: Transaction trans = session.getTransaction();
101: TransactionState state = session.getTransactionState();
102:
103: if (state == TransactionState.STATE_USER_PROVIDED) {
104: throw new TransactionException(
105: "TransactionManager could not end this transaction. "
106: + "A user provided connection is currently being used by this session. "
107: + "You must call the rollback() method of the Connection directly. "
108: + "The calling .setUserConnection (null) will clear the user provided transaction.");
109: }
110:
111: try {
112: if (trans != null) {
113: try {
114: if (state != TransactionState.STATE_COMMITTED) {
115: if (session.isCommitRequired() || forceCommit) {
116: trans.rollback();
117: session.setCommitRequired(false);
118: }
119: }
120: } finally {
121: session.closePreparedStatements();
122: trans.close();
123: }
124: }
125: } finally {
126:
127: if (state != TransactionState.STATE_ENDED) {
128: txThrottle.decrement();
129: }
130:
131: session.setTransaction(null);
132: session.setTransactionState(TransactionState.STATE_ENDED);
133: }
134: }
135:
136: public DataSource getDataSource() {
137: return transactionConfig.getDataSource();
138: }
139:
140: public void setDataSource(DataSource ds) {
141: transactionConfig.setDataSource(ds);
142: }
143:
144: public boolean isForceCommit() {
145: return forceCommit;
146: }
147:
148: public void setForceCommit(boolean forceCommit) {
149: this.forceCommit = forceCommit;
150: }
151:
152: }
|