KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > geronimo > connector > outbound > TransactionCachingInterceptor


1 /**
2  * Licensed to the Apache Software Foundation (ASF) under one or more
3  * contributor license agreements. See the NOTICE file distributed with
4  * this work for additional information regarding copyright ownership.
5  * The ASF licenses this file to You under the Apache License, Version 2.0
6  * (the "License"); you may not use this file except in compliance with
7  * the License. You may obtain a copy of the License at
8  *
9  * http://www.apache.org/licenses/LICENSE-2.0
10  *
11  * Unless required by applicable law or agreed to in writing, software
12  * distributed under the License is distributed on an "AS IS" BASIS,
13  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14  * See the License for the specific language governing permissions and
15  * limitations under the License.
16  */

17
18 package org.apache.geronimo.connector.outbound;
19
20 import java.util.Collections JavaDoc;
21 import java.util.HashSet JavaDoc;
22 import java.util.Iterator JavaDoc;
23 import java.util.Set JavaDoc;
24 import javax.resource.ResourceException JavaDoc;
25 import javax.transaction.Transaction JavaDoc;
26 import javax.transaction.TransactionManager JavaDoc;
27 import javax.transaction.SystemException JavaDoc;
28
29 import org.apache.geronimo.connector.ConnectorTransactionContext;
30 import org.apache.geronimo.connector.ConnectionReleaser;
31 import org.apache.commons.logging.Log;
32 import org.apache.commons.logging.LogFactory;
33
34 /**
35  * TransactionCachingInterceptor.java
36  * TODO: This implementation does not take account of unshareable resources
37  * TODO: This implementation does not take account of application security
38  * where several connections with different security info are obtained.
39  * TODO: This implementation does not take account of container managed security where,
40  * within one transaction, a security domain boundary is crossed
41  * and connections are obtained with two (or more) different subjects.
42  * <p/>
43  * I suggest a state pattern, with the state set in a threadlocal upon entering a component,
44  * will be a usable implementation.
45  * <p/>
46  * The afterCompletion method will need to move to an interface, and that interface include the
47  * security info to distinguish connections.
48  * <p/>
49  * <p/>
50  * Created: Mon Sep 29 15:07:07 2003
51  *
52  * @version 1.0
53  */

54 public class TransactionCachingInterceptor implements ConnectionInterceptor, ConnectionReleaser {
55     protected static Log log = LogFactory.getLog(TransactionCachingInterceptor.class.getName());
56
57     private final ConnectionInterceptor next;
58     private final TransactionManager JavaDoc transactionManager;
59
60     public TransactionCachingInterceptor(ConnectionInterceptor next, TransactionManager JavaDoc transactionManager) {
61         this.next = next;
62         this.transactionManager = transactionManager;
63     }
64
65     public void getConnection(ConnectionInfo connectionInfo) throws ResourceException JavaDoc {
66         //There can be an inactive transaction context when a connection is requested in
67
//Synchronization.afterCompletion().
68

69         // get the current transation and status... if there is a problem just assume there is no transaction present
70
Transaction JavaDoc transaction = TxUtil.getTransactionIfActive(transactionManager);
71         if (transaction != null) {
72             ManagedConnectionInfos managedConnectionInfos = ConnectorTransactionContext.get(transaction, this);
73             if (connectionInfo.isUnshareable()) {
74                 if (!managedConnectionInfos.containsUnshared(connectionInfo.getManagedConnectionInfo())) {
75                     next.getConnection(connectionInfo);
76                     managedConnectionInfos.addUnshared(connectionInfo.getManagedConnectionInfo());
77                 }
78             } else {
79                 ManagedConnectionInfo managedConnectionInfo = managedConnectionInfos.getShared();
80                 if (managedConnectionInfo != null) {
81                     connectionInfo.setManagedConnectionInfo(managedConnectionInfo);
82                     //return;
83
if (log.isTraceEnabled()) {
84                         log.trace("supplying connection from tx cache " + connectionInfo.getConnectionHandle() + " for managed connection " + connectionInfo.getManagedConnectionInfo().getManagedConnection() + " to tx caching interceptor " + this);
85                     }
86                 } else {
87                     next.getConnection(connectionInfo);
88                     managedConnectionInfos.setShared(connectionInfo.getManagedConnectionInfo());
89                     if (log.isTraceEnabled()) {
90                         log.trace("supplying connection from pool " + connectionInfo.getConnectionHandle() + " for managed connection " + connectionInfo.getManagedConnectionInfo().getManagedConnection() + " to tx caching interceptor " + this);
91                     }
92                 }
93             }
94         } else {
95             next.getConnection(connectionInfo);
96         }
97     }
98
99     public void returnConnection(ConnectionInfo connectionInfo, ConnectionReturnAction connectionReturnAction) {
100
101         if (connectionReturnAction == ConnectionReturnAction.DESTROY) {
102             if (log.isTraceEnabled()) {
103                 log.trace("destroying connection" + connectionInfo.getConnectionHandle() + " for managed connection " + connectionInfo.getManagedConnectionInfo().getManagedConnection() + " to tx caching interceptor " + this);
104             }
105             next.returnConnection(connectionInfo, connectionReturnAction);
106             return;
107         }
108         Transaction JavaDoc transaction;
109         try {
110             transaction = transactionManager.getTransaction();
111             if (transaction != null) {
112                 if (TxUtil.isActive(transaction)) {
113                     if (log.isTraceEnabled()) {
114                         log.trace("tx active, not returning connection" + connectionInfo.getConnectionHandle() + " for managed connection " + connectionInfo.getManagedConnectionInfo().getManagedConnection() + " to tx caching interceptor " + this);
115                     }
116                     return;
117                 }
118                 //We are called from an afterCompletion synchronization. Remove the MCI from the ManagedConnectionInfos
119
//so we don't close it twice
120
ManagedConnectionInfos managedConnectionInfos = ConnectorTransactionContext.get(transaction, this);
121                 managedConnectionInfos.remove(connectionInfo.getManagedConnectionInfo());
122                 if (log.isTraceEnabled()) {
123                     log.trace("tx ended, but not removed");
124                 }
125             }
126         } catch (SystemException JavaDoc e) {
127             //ignore
128
}
129         if (log.isTraceEnabled()) {
130             log.trace("tx ended, returning connection" + connectionInfo.getConnectionHandle() + " for managed connection " + connectionInfo.getManagedConnectionInfo().getManagedConnection() + " to tx caching interceptor " + this);
131         }
132         internalReturn(connectionInfo, connectionReturnAction);
133     }
134
135     private void internalReturn(ConnectionInfo connectionInfo, ConnectionReturnAction connectionReturnAction) {
136         if (connectionInfo.getManagedConnectionInfo().hasConnectionHandles()) {
137             if (log.isTraceEnabled()) {
138                 log.trace("not returning connection from tx cache (has handles) " + connectionInfo.getConnectionHandle() + " for managed connection " + connectionInfo.getManagedConnectionInfo().getManagedConnection() + " to tx caching interceptor " + this);
139             }
140             return;
141         }
142         //No transaction, no handles, we return it.
143
next.returnConnection(connectionInfo, connectionReturnAction);
144         if (log.isTraceEnabled()) {
145             log.trace("completed return of connection through tx cache " + connectionInfo.getConnectionHandle() + " for MCI: " + connectionInfo.getManagedConnectionInfo() + " and MC " + connectionInfo.getManagedConnectionInfo().getManagedConnection() + " to tx caching interceptor " + this);
146         }
147     }
148
149     public void destroy() {
150         next.destroy();
151     }
152
153     public void afterCompletion(Object JavaDoc stuff) {
154         ManagedConnectionInfos managedConnectionInfos = (ManagedConnectionInfos) stuff;
155         ManagedConnectionInfo sharedMCI = managedConnectionInfos.getShared();
156         if (sharedMCI != null) {
157             if (log.isTraceEnabled()) {
158                 log.trace("Transaction completed, attempting to return shared connection MCI: " + sharedMCI + " for managed connection " + sharedMCI.getManagedConnection() + " to tx caching interceptor " + this);
159             }
160             returnHandle(sharedMCI);
161         }
162         for (Iterator JavaDoc iterator = managedConnectionInfos.getUnshared().iterator(); iterator.hasNext();) {
163             ManagedConnectionInfo managedConnectionInfo = (ManagedConnectionInfo) iterator.next();
164             if (log.isTraceEnabled()) {
165                 log.trace("Transaction completed, attempting to return unshared connection MCI: " + managedConnectionInfo + " for managed connection " + managedConnectionInfo.getManagedConnection() + " to tx caching interceptor " + this);
166             }
167             returnHandle(managedConnectionInfo);
168         }
169     }
170
171     private void returnHandle(ManagedConnectionInfo managedConnectionInfo) {
172         ConnectionInfo connectionInfo = new ConnectionInfo();
173         connectionInfo.setManagedConnectionInfo(managedConnectionInfo);
174         internalReturn(connectionInfo, ConnectionReturnAction.RETURN_HANDLE);
175     }
176
177     public static class ManagedConnectionInfos {
178         private ManagedConnectionInfo shared;
179         private Set JavaDoc unshared = Collections.EMPTY_SET;
180
181         public ManagedConnectionInfo getShared() {
182             return shared;
183         }
184
185         public void setShared(ManagedConnectionInfo shared) {
186             this.shared = shared;
187         }
188
189         public Set JavaDoc getUnshared() {
190             return unshared;
191         }
192
193         public void addUnshared(ManagedConnectionInfo unsharedMCI) {
194             if (this.unshared == Collections.EMPTY_SET) {
195                 this.unshared = new HashSet JavaDoc();
196             }
197             this.unshared.add(unsharedMCI);
198         }
199
200         public boolean containsUnshared(ManagedConnectionInfo unsharedMCI) {
201             return this.unshared.contains(unsharedMCI);
202         }
203
204         public void remove(ManagedConnectionInfo managedConnectionInfo) {
205             if (shared == managedConnectionInfo) {
206                 shared = null;
207             } else {
208                 unshared.remove(managedConnectionInfo);
209             }
210         }
211     }
212
213 }
214
Popular Tags