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    
018    package org.apache.geronimo.connector.outbound;
019    
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.geronimo.transaction.manager.NamedXAResource;
027    
028    /**
029     * LocalXAResource adapts a local transaction to be controlled by a
030     * JTA transaction manager.  Of course, it cannot provide xa
031     * semantics.
032     *
033     *
034     * @version $Rev: 547737 $ $Date: 2007-06-15 18:47:19 +0200 (Fri, 15 Jun 2007) $
035     */
036    public class LocalXAResource implements NamedXAResource {
037    
038        //accessible in package for testing
039        final LocalTransaction localTransaction;
040        private final String name;
041        private Xid xid;
042        private int transactionTimeout;
043    
044        public LocalXAResource(LocalTransaction localTransaction, String name) {
045            this.localTransaction = localTransaction;
046            this.name = name;
047        }
048    
049        // Implementation of javax.transaction.xa.XAResource
050    
051        public void commit(Xid xid, boolean flag) throws XAException {
052            if (this.xid == null || !this.xid.equals(xid)) {
053                throw new XAException("Invalid Xid");
054            }
055            try {
056                localTransaction.commit();
057            } catch (ResourceException e) {
058                throw (XAException)new XAException().initCause(e);
059             } finally {
060                this.xid = null;
061            }
062    
063        }
064    
065        public void forget(Xid xid) throws XAException {
066            this.xid = null;
067        }
068    
069        public int getTransactionTimeout() throws XAException {
070            return transactionTimeout;
071        }
072    
073        public boolean isSameRM(XAResource xares) throws XAException {
074            return this == xares;
075        }
076    
077        public Xid[] recover(int n) throws XAException {
078            return new Xid[0];
079        }
080    
081        public void rollback(Xid xid) throws XAException {
082            if (this.xid == null || !this.xid.equals(xid)) {
083                throw new XAException("Invalid Xid");
084            }
085            try {
086                localTransaction.rollback();
087            } catch (ResourceException e) {
088                throw (XAException)new XAException().initCause(e);
089            } finally {
090                this.xid = null;
091            }
092        }
093    
094        public boolean setTransactionTimeout(int txTimeout) throws XAException {
095            this.transactionTimeout = txTimeout;
096            return true;
097        }
098    
099        public void start(Xid xid, int flag) throws XAException {
100            if (flag == XAResource.TMNOFLAGS) {
101                // first time in this transaction
102                if (this.xid != null) {
103                    throw new XAException("already enlisted");
104                }
105                this.xid = xid;
106                try {
107                    localTransaction.begin();
108                } catch (ResourceException e) {
109                    throw (XAException) new XAException("could not start local tx").initCause(e);
110                }
111            } else if (flag == XAResource.TMRESUME) {
112                if (xid != this.xid) {
113                    throw new XAException("attempting to resume in different transaction");
114                }
115            } else {
116                throw new XAException("unknown state");
117            }
118        }
119    
120        public void end(Xid xid, int flag) throws XAException {
121            if (xid != this.xid) {
122                throw new XAException("Invalid Xid");
123            }
124            //we could keep track of if the flag is TMSUCCESS...
125        }
126    
127        public int prepare(Xid xid) throws XAException {
128            //log warning that semantics are incorrect...
129            return XAResource.XA_OK;
130        }
131    
132        public String getName() {
133            return name;
134        }
135    }