001    /**
002     * Licensed to the Apache Software Foundation (ASF) under one or more
003     * contributor license agreements.  See the NOTICE file distributed with
004     * this work for additional information regarding copyright ownership.
005     * The ASF licenses this file to You under the Apache License, Version 2.0
006     * (the "License"); you may not use this file except in compliance with
007     * the License.  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    package org.apache.activemq.ra;
018    
019    import javax.jms.JMSException;
020    import javax.resource.ResourceException;
021    import javax.resource.spi.LocalTransaction;
022    import javax.transaction.xa.XAException;
023    import javax.transaction.xa.XAResource;
024    import javax.transaction.xa.Xid;
025    
026    import org.apache.activemq.TransactionContext;
027    
028    /**
029     * Used to provide a LocalTransaction and XAResource to a JMS session.
030     */
031    public class LocalAndXATransaction implements XAResource, LocalTransaction {
032    
033        private final TransactionContext transactionContext;
034        private boolean inManagedTx;
035    
036        public LocalAndXATransaction(TransactionContext transactionContext) {
037            this.transactionContext = transactionContext;
038        }
039    
040        public void setInManagedTx(boolean inManagedTx) throws JMSException {
041            this.inManagedTx = inManagedTx;
042            if (!inManagedTx) {
043                transactionContext.cleanup();
044            }
045        }
046    
047        public void begin() throws ResourceException {
048            try {
049                transactionContext.begin();
050                setInManagedTx(true);
051            } catch (JMSException e) {
052                throw new ResourceException("begin failed.", e);
053            }
054        }
055    
056        public void commit() throws ResourceException {
057            try {
058                transactionContext.commit();
059            } catch (JMSException e) {
060                throw new ResourceException("commit failed.", e);
061            } finally {
062                try {
063                    setInManagedTx(false);
064                } catch (JMSException e) {
065                    throw new ResourceException("commit failed.", e);
066                }
067            }
068        }
069    
070        public void rollback() throws ResourceException {
071            try {
072                transactionContext.rollback();
073            } catch (JMSException e) {
074                throw new ResourceException("rollback failed.", e);
075            } finally {
076                try {
077                    setInManagedTx(false);
078                } catch (JMSException e) {
079                    throw new ResourceException("rollback failed.", e);
080                }
081            }
082        }
083    
084        public void commit(Xid arg0, boolean arg1) throws XAException {
085            transactionContext.commit(arg0, arg1);
086        }
087    
088        public void end(Xid arg0, int arg1) throws XAException {
089            try {
090                transactionContext.end(arg0, arg1);
091            } finally {
092                try {
093                    setInManagedTx(false);
094                } catch (JMSException e) {
095                    throw (XAException)new XAException(XAException.XAER_PROTO).initCause(e);
096                }
097            }
098        }
099    
100        public void forget(Xid arg0) throws XAException {
101            transactionContext.forget(arg0);
102        }
103    
104        public int getTransactionTimeout() throws XAException {
105            return transactionContext.getTransactionTimeout();
106        }
107    
108        public boolean isSameRM(XAResource xaresource) throws XAException {
109            if (xaresource == null) {
110                return false;
111            }
112            // Do we have to unwrap?
113            if (xaresource instanceof LocalAndXATransaction) {
114                xaresource = ((LocalAndXATransaction)xaresource).transactionContext;
115            }
116            return transactionContext.isSameRM(xaresource);
117        }
118    
119        public int prepare(Xid arg0) throws XAException {
120            return transactionContext.prepare(arg0);
121        }
122    
123        public Xid[] recover(int arg0) throws XAException {
124            return transactionContext.recover(arg0);
125        }
126    
127        public void rollback(Xid arg0) throws XAException {
128            transactionContext.rollback(arg0);
129        }
130    
131        public boolean setTransactionTimeout(int arg0) throws XAException {
132            return transactionContext.setTransactionTimeout(arg0);
133        }
134    
135        public void start(Xid arg0, int arg1) throws XAException {
136            transactionContext.start(arg0, arg1);
137            try {
138                setInManagedTx(true);
139            } catch (JMSException e) {
140                throw (XAException)new XAException(XAException.XAER_PROTO).initCause(e);
141            }
142        }
143    
144        public boolean isInManagedTx() {
145            return inManagedTx;
146        }
147    
148        public void cleanup() {
149            transactionContext.cleanup();
150            inManagedTx = false;
151        }
152    }