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 */
017package org.apache.activemq.ra;
018
019import javax.jms.JMSException;
020import javax.resource.ResourceException;
021import javax.resource.spi.LocalTransaction;
022import javax.transaction.xa.XAException;
023import javax.transaction.xa.XAResource;
024import javax.transaction.xa.Xid;
025
026import org.apache.activemq.TransactionContext;
027
028/**
029 * Used to provide a LocalTransaction and XAResource to a JMS session.
030 */
031public 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}