KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > tm > iiop > client > TransactionCurrent


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.tm.iiop.client;
23
24 import java.util.Collections JavaDoc;
25 import java.util.Set JavaDoc;
26 import java.util.HashSet JavaDoc;
27 import org.omg.CORBA.LocalObject JavaDoc;
28 import org.omg.CosNaming.NamingContextExt JavaDoc;
29 import org.omg.CosNaming.NamingContextPackage.CannotProceed JavaDoc;
30 import org.omg.CosNaming.NamingContextPackage.InvalidName JavaDoc;
31 import org.omg.CosNaming.NamingContextPackage.NotFound JavaDoc;
32 import org.omg.CosTransactions.Control;
33 import org.omg.CosTransactions.Coordinator;
34 import org.omg.CosTransactions.Current;
35 import org.omg.CosTransactions.HeuristicHazard;
36 import org.omg.CosTransactions.HeuristicMixed;
37 import org.omg.CosTransactions.Inactive;
38 import org.omg.CosTransactions.InvalidControl;
39 import org.omg.CosTransactions.NoTransaction;
40 import org.omg.CosTransactions.PropagationContext;
41 import org.omg.CosTransactions.Status;
42 import org.omg.CosTransactions.SubtransactionsUnavailable;
43 import org.omg.CosTransactions.Terminator;
44 import org.omg.CosTransactions.Unavailable;
45
46 import org.jboss.tm.iiop.TransactionDesc;
47 import org.jboss.tm.iiop.TransactionFactoryExt;
48 import org.jboss.tm.iiop.TransactionFactoryExtHelper;
49 import org.jboss.tm.iiop.TxClientInterceptor;
50
51 /**
52  * This class implements <code>org.omg.CosTransactions.Current</code>.
53  *
54  * @author Francisco Reverbel
55  */

56
57 public class TransactionCurrent
58       extends LocalObject JavaDoc
59       implements Current
60 {
61    // Static fields -------------------------------------------------
62

63    private static TransactionCurrent instance = null; // singleton instance
64
private static TransactionFactoryExt txFactory;
65    private static Set JavaDoc suspendedTransactions =
66                            Collections.synchronizedSet (new HashSet JavaDoc());
67    private static ThreadLocal JavaDoc threadLocalData = new ThreadLocal JavaDoc() {
68          protected synchronized Object JavaDoc initialValue()
69          {
70             return new TransactionInfo(); // see nested class below
71
}
72       };
73  
74    // Nested class -------------------------------------------------
75

76    /**
77     * The <code>TransactionInfo</code> class holds transaction information
78     * associated with the current thread. The <code>threadLocalData</code>
79     * field contains an instance of this class. The field timeout applies
80     * to new transactions started by the current thread; its value is not
81     * necessarily equal to the time out of the currrent transaction. The
82     * three remaining fields refer to the currrent transaction.
83     */

84    private static class TransactionInfo
85    {
86       int timeout = 0; // for new transactions started by the current thread
87
Control control; // null if no current transaction
88
Coordinator coord; // null if no current transaction
89
Terminator JavaDoc term; // null if no current transaction
90
}
91
92    // Static accessors to thread-local data -------------------------
93

94    private static void setThreadLocalTimeout(int timeout)
95    {
96       ((TransactionInfo)threadLocalData.get()).timeout = timeout;
97    }
98
99    private static int getThreadLocalTimeout()
100    {
101       return ((TransactionInfo)threadLocalData.get()).timeout;
102    }
103    
104    private static void setThreadLocalControl(Control control)
105    {
106       ((TransactionInfo)threadLocalData.get()).control = control;
107    }
108
109    private static Control getThreadLocalControl()
110    {
111       return ((TransactionInfo)threadLocalData.get()).control;
112    }
113    
114    private static void setThreadLocalCoordinator(Coordinator coord)
115    {
116       ((TransactionInfo)threadLocalData.get()).coord = coord;
117    }
118
119    private static Coordinator getThreadLocalCoordinator()
120    {
121       return ((TransactionInfo)threadLocalData.get()).coord;
122    }
123    
124    private static void setThreadLocalTerminator(Terminator JavaDoc term)
125    {
126       ((TransactionInfo)threadLocalData.get()).term = term;
127    }
128
129    private static Terminator JavaDoc getThreadLocalTerminator()
130       throws NoTransaction
131    {
132       Terminator JavaDoc term = ((TransactionInfo)threadLocalData.get()).term;
133
134       if (term == null)
135          throw new NoTransaction();
136
137       return term;
138    }
139    
140    // Management of the transaction-thread association --------------
141

142    /**
143     * Auxiliary method that sets the current transaction.
144     */

145    private static void setCurrentTransaction(Control control,
146                                              PropagationContext pc)
147    {
148       setThreadLocalControl(control);
149       setThreadLocalCoordinator(pc.current.coord);
150       setThreadLocalTerminator(pc.current.term);
151       TxClientInterceptor.setOutgoingPropagationContext(pc);
152    }
153
154    /**
155     * Auxiliary method that unsets the current transaction.
156     */

157    private static void unsetCurrentTransaction()
158    {
159       setThreadLocalControl(null);
160       setThreadLocalCoordinator(null);
161       setThreadLocalTerminator(null);
162       TxClientInterceptor.unsetOutgoingPropagationContext();
163    }
164
165    // Initialization of static fields -------------------------------
166

167    public static void init(NamingContextExt JavaDoc nc)
168    {
169       try
170       {
171          org.omg.CORBA.Object JavaDoc txFactoryObj =
172             nc.resolve_str("TransactionService");
173          txFactory = TransactionFactoryExtHelper.narrow(txFactoryObj);
174       }
175       catch (CannotProceed JavaDoc e)
176       {
177          throw new RuntimeException JavaDoc(
178                            "Exception initializing TransactionCurrent: " + e);
179       }
180       catch (NotFound JavaDoc e)
181       {
182          throw new RuntimeException JavaDoc(
183                            "Exception initializing TransactionCurrent: " + e);
184       }
185       catch (InvalidName JavaDoc e)
186       {
187          throw new RuntimeException JavaDoc(
188                            "Exception initializing TransactionCurrent: " + e);
189       }
190    }
191
192    // Singleton accessor --------------------------------------------
193

194    public static synchronized TransactionCurrent getInstance()
195    {
196       if (instance == null)
197          instance = new TransactionCurrent();
198       return instance;
199    }
200    
201    // org.omg.CosTransactions.Current operations --------------------
202

203    /**
204     * Begins a new transaction, which will become the current transaction
205     * associated with the calling thread.
206     *
207     * @see org.omg.CosTransactions.CurrentOperations#begin()
208     */

209    public void begin()
210       throws SubtransactionsUnavailable
211    {
212       if (getThreadLocalControl() != null)
213          throw new SubtransactionsUnavailable();
214       TransactionDesc td = txFactory.create_transaction(
215                                                       getThreadLocalTimeout());
216       setCurrentTransaction(td.control, td.propagationContext);
217    }
218    
219    /**
220     * Commits the current transaction.
221     *
222     * @see org.omg.CosTransactions.CurrentOperations#commit(boolean)
223     */

224    public void commit(boolean reportHeuristics)
225       throws NoTransaction,
226              HeuristicHazard,
227              HeuristicMixed
228    {
229       getThreadLocalTerminator().commit(reportHeuristics);
230       unsetCurrentTransaction();
231    }
232    
233    /**
234     * Rolls the current transaction back.
235     *
236     * @see org.omg.CosTransactions.CurrentOperations#rollback()
237     */

238    public void rollback()
239       throws NoTransaction
240    {
241       getThreadLocalTerminator().rollback();
242       unsetCurrentTransaction();
243    }
244    
245    /**
246     * Marks the current transaction as rollback only.
247     *
248     * @see org.omg.CosTransactions.CurrentOperations#rollback_only()
249     */

250    public void rollback_only()
251       throws NoTransaction
252    {
253       try
254       {
255          Coordinator coord = getThreadLocalCoordinator();
256
257          if (coord == null)
258             throw new NoTransaction();
259
260          coord.rollback_only();
261       }
262       catch (Inactive e)
263       {
264          throw new RuntimeException JavaDoc("Current transaction already prepared: "
265                                     + e);
266       }
267    }
268    
269    /**
270     * Gets the status of current transaction.
271     *
272     * @see org.omg.CosTransactions.CurrentOperations#get_status()
273     */

274    public Status get_status()
275    {
276       Coordinator coord = getThreadLocalCoordinator();
277       return (coord == null) ? Status.StatusNoTransaction : coord.get_status();
278    }
279    
280    /**
281     * Returns the name of the current transaction.
282     *
283     * @see org.omg.CosTransactions.CurrentOperations#get_transaction_name()
284     */

285    public String JavaDoc get_transaction_name()
286    {
287       Coordinator coord = getThreadLocalCoordinator();
288       return (coord == null) ? "" : coord.get_transaction_name();
289    }
290    
291    /**
292     * Sets the transaction time out that will be in effect for
293     * transactions created after this call.
294     *
295     * @see org.omg.CosTransactions.CurrentOperations#set_timeout(int)
296     */

297    public void set_timeout(int timeOut)
298    {
299       setThreadLocalTimeout(timeOut);
300    }
301    
302    /**
303     * Returns the Control associated with the current transaction.
304     *
305     * @see org.omg.CosTransactions.CurrentOperations#get_control()
306     */

307    public Control get_control()
308    {
309       return getThreadLocalControl();
310    }
311    
312    /**
313     * Suspends the current transaction.
314     *
315     * @see org.omg.CosTransactions.CurrentOperations#suspend()
316     */

317    public Control suspend()
318    {
319       Control control = getThreadLocalControl();
320       if (control != null)
321       {
322          unsetCurrentTransaction();
323          suspendedTransactions.add(control);
324       }
325       return control;
326    }
327    
328    /**
329     * Resumes the specified transaction.
330     *
331     * @see org.omg.CosTransactions.CurrentOperations#resume(org.omg.CosTransactions.Control)
332     */

333    public void resume(Control whichTransaction)
334       throws InvalidControl
335    {
336       try
337       {
338          if (whichTransaction == null)
339             throw new InvalidControl();
340          if (!suspendedTransactions.remove(whichTransaction))
341             throw new InvalidControl();
342          Coordinator coord = whichTransaction.get_coordinator();
343          if (coord == null)
344             throw new InvalidControl();
345          PropagationContext pc = coord.get_txcontext(); // throws Unavailable
346
setCurrentTransaction(whichTransaction, pc);
347       }
348       catch (Unavailable e)
349       {
350          throw new InvalidControl();
351       }
352    }
353    
354 }
355
Popular Tags