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 }