/* * Copyright 2005-2010 the original author or authors. * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.wamblee.test.transactions; import javax.transaction.HeuristicMixedException; import javax.transaction.HeuristicRollbackException; import javax.transaction.NotSupportedException; import javax.transaction.RollbackException; import javax.transaction.Status; import javax.transaction.SystemException; import javax.transaction.UserTransaction; /** * Represents a user transaction spanning a number of resources. */ public class SimpleUserTransaction implements UserTransaction { private UserTransactionCallback callback; private TransactionResource[] resources; private Object[] txStates; private int status; /** * Construcst the transaction. * * @param aCallback * Callback to use. * @param aResources * Resources to use. */ public SimpleUserTransaction(UserTransactionCallback aCallback, TransactionResource... aResources) { callback = aCallback; resources = aResources; txStates = new Object[resources.length]; status = Status.STATUS_NO_TRANSACTION; } @Override public void begin() throws NotSupportedException, SystemException { if (status == Status.STATUS_ACTIVE) { throw new NotSupportedException( "Nested transactions not supported!"); } for (int i = 0; i < resources.length; i++) { txStates[i] = resources[i].begin(); } status = Status.STATUS_ACTIVE; } @Override public void rollback() throws IllegalStateException, SecurityException, SystemException { if ( status == Status.STATUS_NO_TRANSACTION) { throw new IllegalStateException("Rollback while not in a transaction"); } try { for (int i = 0; i < resources.length; i++) { resources[i].rollback(txStates[i]); } } finally { status = Status.STATUS_NO_TRANSACTION; callback.transactionFinished(); } } @Override public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException, SecurityException, IllegalStateException, SystemException { if (status == Status.STATUS_MARKED_ROLLBACK) { rollback(); throw new RollbackException(); } if (status != Status.STATUS_ACTIVE) { throw new IllegalStateException("Commit while not in a transaction"); } try { boolean committing = true; for (int i = 0; i < resources.length; i++) { try { if (committing) { resources[i].commit(txStates[i]); } else { resources[i].rollback(txStates[i]); } } catch (Exception e) { committing = false; } } if (!committing) { throw new HeuristicMixedException("Commit failed"); } } finally { status = Status.STATUS_NO_TRANSACTION; callback.transactionFinished(); } } @Override public int getStatus() throws SystemException { return status; } @Override public void setRollbackOnly() throws IllegalStateException, SystemException { if ( status == Status.STATUS_NO_TRANSACTION) { throw new IllegalStateException("setRollbackOnly() while not in a transaction"); } status = Status.STATUS_MARKED_ROLLBACK; } @Override public void setTransactionTimeout(int aSeconds) throws SystemException { // Ignored. } }