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; 027import org.slf4j.Logger; 028import org.slf4j.LoggerFactory; 029 030/** 031 * Used to provide a LocalTransaction and XAResource to a JMS session. 032 */ 033public class LocalAndXATransaction implements XAResource, LocalTransaction { 034 private static final Logger LOG = LoggerFactory.getLogger(LocalAndXATransaction.class); 035 036 private TransactionContext transactionContext; 037 private boolean inManagedTx; 038 039 public LocalAndXATransaction(TransactionContext transactionContext) { 040 this.transactionContext = transactionContext; 041 } 042 043 public void setTransactionContext(TransactionContext transactionContext) { 044 this.transactionContext = transactionContext; 045 } 046 047 public void setInManagedTx(boolean inManagedTx) throws JMSException { 048 this.inManagedTx = inManagedTx; 049 if (!inManagedTx) { 050 transactionContext.cleanup(); 051 } 052 } 053 054 public void begin() throws ResourceException { 055 try { 056 transactionContext.begin(); 057 setInManagedTx(true); 058 } catch (JMSException e) { 059 throw new ResourceException("begin failed.", e); 060 } 061 } 062 063 public void commit() throws ResourceException { 064 try { 065 transactionContext.commit(); 066 } catch (JMSException e) { 067 throw new ResourceException("commit failed.", e); 068 } finally { 069 try { 070 setInManagedTx(false); 071 } catch (JMSException e) { 072 throw new ResourceException("commit failed.", e); 073 } 074 } 075 } 076 077 public void rollback() throws ResourceException { 078 try { 079 transactionContext.rollback(); 080 } catch (JMSException e) { 081 throw new ResourceException("rollback failed.", e); 082 } finally { 083 try { 084 setInManagedTx(false); 085 } catch (JMSException e) { 086 throw new ResourceException("rollback failed.", e); 087 } 088 } 089 } 090 091 public void commit(Xid arg0, boolean arg1) throws XAException { 092 transactionContext.commit(arg0, arg1); 093 } 094 095 public void end(Xid arg0, int arg1) throws XAException { 096 LOG.debug("{} end {} with {}", new Object[]{this, arg0, arg1}); 097 try { 098 transactionContext.end(arg0, arg1); 099 } finally { 100 try { 101 setInManagedTx(false); 102 } catch (JMSException e) { 103 throw (XAException)new XAException(XAException.XAER_PROTO).initCause(e); 104 } 105 } 106 } 107 108 public void forget(Xid arg0) throws XAException { 109 transactionContext.forget(arg0); 110 } 111 112 public int getTransactionTimeout() throws XAException { 113 return transactionContext.getTransactionTimeout(); 114 } 115 116 public boolean isSameRM(XAResource xaresource) throws XAException { 117 boolean isSame = false; 118 if (xaresource != null) { 119 // Do we have to unwrap? 120 if (xaresource instanceof LocalAndXATransaction) { 121 xaresource = ((LocalAndXATransaction)xaresource).transactionContext; 122 } 123 isSame = transactionContext.isSameRM(xaresource); 124 } 125 LOG.trace("{} isSameRM({}) = {}", new Object[]{this, xaresource, isSame}); 126 return isSame; 127 } 128 129 public int prepare(Xid arg0) throws XAException { 130 return transactionContext.prepare(arg0); 131 } 132 133 public Xid[] recover(int arg0) throws XAException { 134 Xid[] answer = null; 135 LOG.trace("{} recover({})", new Object[]{this, arg0}); 136 answer = transactionContext.recover(arg0); 137 LOG.trace("{} recover({}) = {}", new Object[]{this, arg0, answer}); 138 return answer; 139 } 140 141 public void rollback(Xid arg0) throws XAException { 142 transactionContext.rollback(arg0); 143 } 144 145 public boolean setTransactionTimeout(int arg0) throws XAException { 146 return transactionContext.setTransactionTimeout(arg0); 147 } 148 149 public void start(Xid arg0, int arg1) throws XAException { 150 LOG.trace("{} start {} with {}", new Object[]{this, arg0, arg1}); 151 transactionContext.start(arg0, arg1); 152 try { 153 setInManagedTx(true); 154 } catch (JMSException e) { 155 throw (XAException)new XAException(XAException.XAER_PROTO).initCause(e); 156 } 157 } 158 159 public boolean isInManagedTx() { 160 return inManagedTx; 161 } 162 163 public void cleanup() { 164 transactionContext.cleanup(); 165 inManagedTx = false; 166 } 167 168 @Override 169 public String toString() { 170 return "[" + super.toString() + "," + transactionContext + "]"; 171 } 172}