KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > resource > connectionmanager > TransactionSynchronizer


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.resource.connectionmanager;
23
24 import java.util.ArrayList JavaDoc;
25
26 import javax.transaction.RollbackException JavaDoc;
27 import javax.transaction.Synchronization JavaDoc;
28 import javax.transaction.SystemException JavaDoc;
29 import javax.transaction.Transaction JavaDoc;
30 import javax.transaction.TransactionManager JavaDoc;
31
32 import org.jboss.logging.Logger;
33 import org.jboss.tm.TransactionLocal;
34 import org.jboss.util.NestedRuntimeException;
35
36 /**
37  * Organizes transaction synchronization done by JCA.<p>
38  *
39  * This class exists to make sure all Tx synchronizations
40  * are invoked before the cached connection manager closes any
41  * closed connections.
42  *
43  * @author <a HREF="mailto:adrian@jboss.org">Adrian Brock</a>
44  * @version $Revision: 37459 $
45  */

46 public class TransactionSynchronizer implements Synchronization JavaDoc
47 {
48    /** The logger */
49    private static final Logger log = Logger.getLogger(TransactionSynchronizer.class);
50
51    /** The transaction synchronizations */
52    protected static TransactionLocal txSynchs;
53    
54    /** The transaction */
55    protected Transaction JavaDoc tx;
56    
57    /** The enlisting thread */
58    protected Thread JavaDoc enlistingThread;
59    
60    /** Unenlisted */
61    protected ArrayList JavaDoc unenlisted;
62    
63    /** Enlisted */
64    protected ArrayList JavaDoc enlisted;
65    
66    /** The cached connection manager synchronization */
67    protected Synchronization JavaDoc ccmSynch;
68
69    /** Initialization */
70    public static void setTransactionManager(TransactionManager JavaDoc tm)
71    {
72       txSynchs = new TransactionLocal(tm);
73    }
74    
75    /**
76     * Create a new transaction synchronizer
77     *
78     * @param tx the transaction to synchronize with
79     */

80    private TransactionSynchronizer(Transaction JavaDoc tx)
81    {
82       this.tx = tx;
83    }
84    
85    /**
86     * Add a new Tx synchronization that has not been enlisted
87     *
88     * @param synch the synchronization
89     */

90    synchronized void addUnenlisted(Synchronization JavaDoc synch)
91    {
92       if (unenlisted == null)
93          unenlisted = new ArrayList JavaDoc();
94       unenlisted.add(synch);
95    }
96    
97    /**
98     * Get the unenlisted synchronizations
99     * and say we are enlisting if some are returned.
100     *
101     * @return the unenlisted synchronizations
102     */

103    synchronized ArrayList JavaDoc getUnenlisted()
104    {
105       Thread JavaDoc currentThread = Thread.currentThread();
106       while (enlistingThread != null && enlistingThread != currentThread)
107       {
108          boolean interrupted = false;
109          try
110          {
111             wait();
112          }
113          catch (InterruptedException JavaDoc e)
114          {
115             interrupted = true;
116          }
117          if (interrupted)
118             currentThread.interrupt();
119       }
120       ArrayList JavaDoc result = unenlisted;
121       unenlisted = null;
122       if (result != null)
123          enlistingThread = currentThread;
124       return result;
125    }
126    
127    /**
128     * The synchronization is now enlisted
129     *
130     * @param synch the synchronization
131     */

132    synchronized void addEnlisted(Synchronization JavaDoc synch)
133    {
134       if (enlisted == null)
135          enlisted = new ArrayList JavaDoc();
136       enlisted.add(synch);
137    }
138    
139    /**
140     * Remove an enlisted synchronization
141     *
142     * @param synch the synchronization
143     * @return true when the synchronization was enlisted
144     */

145    synchronized boolean removeEnlisted(Synchronization JavaDoc synch)
146    {
147       return enlisted.remove(synch);
148    }
149    
150    /**
151     * This thread has finished enlisting
152     */

153    synchronized void enlisted()
154    {
155       Thread JavaDoc currentThread = Thread.currentThread();
156       if (enlistingThread == null || enlistingThread != currentThread)
157       {
158          log.warn("Thread " + currentThread + " not the enlisting thread " + enlistingThread, new Exception JavaDoc("STACKTRACE"));
159          return;
160       }
161       enlistingThread = null;
162       notifyAll();
163    }
164    
165    /**
166     * Get a registered transaction synchronizer.
167     *
168     * @param tx the transaction
169     * @return the registered transaction synchronizer for this transaction
170     * @throws RolledbackException if the transaction is already rolled back
171     * @throws SystemException for an error in the tranaction manager
172     */

173    static TransactionSynchronizer getRegisteredSynchronizer(Transaction JavaDoc tx) throws RollbackException JavaDoc, SystemException JavaDoc
174    {
175       TransactionSynchronizer result = (TransactionSynchronizer) txSynchs.get(tx);
176       if (result == null)
177       {
178          result = new TransactionSynchronizer(tx);
179          tx.registerSynchronization(result);
180          txSynchs.set(tx, result);
181       }
182       return result;
183    }
184    
185    /**
186     * Check whether we have a CCM synchronization
187     *
188     * @param tx the transaction
189     */

190    static Synchronization JavaDoc getCCMSynchronization(Transaction JavaDoc tx)
191    {
192       TransactionSynchronizer ts = (TransactionSynchronizer) txSynchs.get(tx);
193       if (ts != null)
194          return ts.ccmSynch;
195       else
196          return null;
197    }
198    
199    /**
200     * Register a new CCM synchronization
201     *
202     * @param tx the transaction
203     * @param synch the synchronization
204     * @throws RolledbackException if the transaction is already rolled back
205     * @throws SystemException for an error in the tranaction manager
206     */

207    static void registerCCMSynchronization(Transaction JavaDoc tx, Synchronization JavaDoc synch) throws RollbackException JavaDoc, SystemException JavaDoc
208    {
209       TransactionSynchronizer ts = getRegisteredSynchronizer(tx);
210       ts.ccmSynch = synch;
211    }
212    
213    /**
214     * Lock for the given transaction
215     *
216     * @param tx the transaction
217     */

218    static void lock(Transaction JavaDoc tx)
219    {
220       try
221       {
222          txSynchs.lock(tx);
223       }
224       catch (InterruptedException JavaDoc e)
225       {
226          throw new NestedRuntimeException("Unable to get synchronization", e);
227       }
228    }
229    
230    /**
231     * Unlock for the given transaction
232     *
233     * @param tx the transaction
234     */

235    static void unlock(Transaction JavaDoc tx)
236    {
237       txSynchs.unlock(tx);
238    }
239
240    public void beforeCompletion()
241    {
242       if (enlisted != null)
243       {
244          int i = 0;
245          while (i < enlisted.size())
246          {
247             Synchronization JavaDoc synch = (Synchronization JavaDoc) enlisted.get(i);
248             invokeBefore(synch);
249             ++i;
250          }
251       }
252       
253       if (ccmSynch != null)
254          invokeBefore(ccmSynch);
255    }
256
257    public void afterCompletion(int status)
258    {
259       if (enlisted != null)
260       {
261          int i = 0;
262          while (i < enlisted.size())
263          {
264             Synchronization JavaDoc synch = (Synchronization JavaDoc) enlisted.get(i);
265             invokeAfter(synch, status);
266             ++i;
267          }
268       }
269       
270       if (ccmSynch != null)
271          invokeAfter(ccmSynch, status);
272    }
273
274    /**
275     * Invoke a beforeCompletion
276     *
277     * @param synch the synchronization
278     */

279    protected void invokeBefore(Synchronization JavaDoc synch)
280    {
281       try
282       {
283          synch.beforeCompletion();
284       }
285       catch (Throwable JavaDoc t)
286       {
287          log.warn("Transaction " + tx + " error in before completion " + synch, t);
288       }
289    }
290
291    /**
292     * Invoke an afterCompletion
293     *
294     * @param synch the synchronization
295     * @param status the status of the transaction
296     */

297    protected void invokeAfter(Synchronization JavaDoc synch, int status)
298    {
299       try
300       {
301          synch.afterCompletion(status);
302       }
303       catch (Throwable JavaDoc t)
304       {
305          log.warn("Transaction " + tx + " error in after completion " + synch, t);
306       }
307    }
308 }
309
Popular Tags