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.transaction.RollbackException;
022    import javax.transaction.SystemException;
023    import javax.transaction.Transaction;
024    import javax.transaction.TransactionManager;
025    import javax.transaction.xa.XAResource;
026    
027    /**
028     * TransactionEnlistingInterceptor.java
029     * <p/>
030     * <p/>
031     * Created: Fri Sep 26 14:52:24 2003
032     *
033     * @version 1.0
034     */
035    public class TransactionEnlistingInterceptor implements ConnectionInterceptor {
036    
037        private final ConnectionInterceptor next;
038        private final TransactionManager transactionManager;
039    
040        public TransactionEnlistingInterceptor(ConnectionInterceptor next, TransactionManager transactionManager) {
041            this.next = next;
042            this.transactionManager = transactionManager;
043        }
044    
045        public void getConnection(ConnectionInfo connectionInfo) throws ResourceException {
046            next.getConnection(connectionInfo);
047            try {
048                ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo();
049    
050                // get the current transation and status... if there is a problem just assume there is no transaction present
051                Transaction transaction = TxUtil.getTransactionIfActive(transactionManager);
052                if (transaction != null) {
053                    XAResource xares = mci.getXAResource();
054                    transaction.enlistResource(xares);
055                }
056            } catch (SystemException e) {
057                returnConnection(connectionInfo, ConnectionReturnAction.DESTROY);
058                throw new ResourceException("Could not get transaction", e);
059            } catch (RollbackException e) {
060                //transaction is marked rolled back, so the xaresource could not have been enlisted
061                next.returnConnection(connectionInfo, ConnectionReturnAction.RETURN_HANDLE);
062                throw new ResourceException("Could not enlist resource in rolled back transaction", e);
063            } catch (Throwable t) {
064                returnConnection(connectionInfo, ConnectionReturnAction.DESTROY);
065                throw new ResourceException("Unknown throwable when trying to enlist connection in tx", t);
066            }
067        }
068    
069        /**
070         * The <code>returnConnection</code> method
071         * <p/>
072         * todo Probably the logic needs improvement if a connection
073         * error occurred and we are destroying the handle.
074         *
075         * @param connectionInfo         a <code>ConnectionInfo</code> value
076         * @param connectionReturnAction a <code>ConnectionReturnAction</code> value
077         */
078        public void returnConnection(ConnectionInfo connectionInfo,
079                                     ConnectionReturnAction connectionReturnAction) {
080            try {
081                ManagedConnectionInfo mci = connectionInfo.getManagedConnectionInfo();
082                Transaction transaction = TxUtil.getTransactionIfActive(transactionManager);
083                if (transaction != null) {
084                    XAResource xares = mci.getXAResource();
085                    transaction.delistResource(xares, XAResource.TMSUSPEND);
086                }
087    
088            } catch (SystemException e) {
089                //maybe we should warn???
090                connectionReturnAction = ConnectionReturnAction.DESTROY;
091            } catch (IllegalStateException e) {
092                connectionReturnAction = ConnectionReturnAction.DESTROY;
093            }
094    
095            next.returnConnection(connectionInfo, connectionReturnAction);
096        }
097    
098        public void destroy() {
099            next.destroy();
100        }
101    
102    }