001    /** 
002     * 
003     * Copyright 2004 Hiram Chirino
004     * 
005     * Licensed under the Apache License, Version 2.0 (the "License"); 
006     * you may not use this file except in compliance with the License. 
007     * You may obtain a copy of the License at 
008     * 
009     * http://www.apache.org/licenses/LICENSE-2.0
010     * 
011     * Unless required by applicable law or agreed to in writing, software
012     * distributed under the License is distributed on an "AS IS" BASIS, 
013     * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 
014     * See the License for the specific language governing permissions and 
015     * limitations under the License. 
016     * 
017     **/
018    package org.activemq.service.impl;
019    
020    import java.util.ArrayList;
021    import java.util.Iterator;
022    
023    import javax.transaction.xa.XAException;
024    
025    import org.activemq.service.Transaction;
026    import org.activemq.service.TransactionTask;
027    
028    /**
029     * Keeps track of all the actions the need to be done when
030     * a transaction does a commit or rollback.
031     *
032     * @version $Revision: 1.1.1.1 $
033     */
034    public abstract class AbstractTransaction implements Transaction {
035    
036        static final public byte START_STATE = 0;      // can go to: 1,2,3
037        static final public byte IN_USE_STATE = 1;     // can go to: 2,3
038        static final public byte PREPARED_STATE = 2;   // can go to: 3
039        static final public byte FINISHED_STATE = 3;
040    
041    
042        private ArrayList prePrepareTasks = new ArrayList();
043        private ArrayList postCommitTasks = new ArrayList();
044        private ArrayList postRollbackTasks = new ArrayList();
045        private byte state = START_STATE;
046    
047        public byte getState() {
048            return state;
049        }
050    
051        public void setState(byte state) {
052            this.state = state;
053        }
054    
055        public void addPostCommitTask(TransactionTask r) {
056            postCommitTasks.add(r);
057            if (state == START_STATE) {
058                state = IN_USE_STATE;
059            }
060        }
061    
062        public void addPostRollbackTask(TransactionTask r) {
063            postRollbackTasks.add(r);
064            if (state == START_STATE) {
065                state = IN_USE_STATE;
066            }
067        }
068    
069        public void addPrePrepareTask(TransactionTask r) {
070            prePrepareTasks.add(r);
071            if (state == START_STATE) {
072                state = IN_USE_STATE;
073            }
074        }
075    
076        public void prePrepare() throws Throwable {
077    
078            // Is it ok to call prepare now given the state of the
079            // transaction?
080            switch (state) {
081                case START_STATE:
082                case IN_USE_STATE:
083                    break;
084                default:
085                    XAException xae = new XAException("Prepare cannot be called now.");
086                    xae.errorCode = XAException.XAER_PROTO;
087                    throw xae;
088            }
089    
090            // Run the prePrepareTasks
091            for (Iterator iter = prePrepareTasks.iterator(); iter.hasNext();) {
092                TransactionTask r = (TransactionTask) iter.next();
093                r.execute();
094            }
095        }
096    
097        protected void postCommit() throws Throwable {
098            // Run the postCommitTasks
099            for (Iterator iter = postCommitTasks.iterator(); iter.hasNext();) {
100                TransactionTask r = (TransactionTask) iter.next();
101                r.execute();
102            }
103        }
104    
105        public void postRollback() throws Throwable {
106            // Run the postRollbackTasks
107            for (Iterator iter = postRollbackTasks.iterator(); iter.hasNext();) {
108                TransactionTask r = (TransactionTask) iter.next();
109                r.execute();
110            }
111        }
112    
113        public String toString() {
114            return super.toString() + "[prePrepares=" + prePrepareTasks + "; postCommits=" + postCommitTasks
115                    + "; postRollbacks=" + postRollbackTasks + "]";
116        }
117    
118    }