KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > sun > jts > jta > TransactionManagerImpl


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the License). You may not use this file except in
5  * compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * https://glassfish.dev.java.net/public/CDDLv1.0.html or
9  * glassfish/bootstrap/legal/CDDLv1.0.txt.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * Header Notice in each file and include the License file
15  * at glassfish/bootstrap/legal/CDDLv1.0.txt.
16  * If applicable, add the following below the CDDL Header,
17  * with the fields enclosed by brackets [] replaced by
18  * you own identifying information:
19  * "Portions Copyrighted [year] [name of copyright owner]"
20  *
21  * Copyright 2006 Sun Microsystems, Inc. All rights reserved.
22  */

23
24 /*
25  * Copyright 2004-2005 Sun Microsystems, Inc. All rights reserved.
26  * Use is subject to license terms.
27  */

28
29 package com.sun.jts.jta;
30
31 import java.util.*;
32 import javax.transaction.*;
33 import org.omg.CosTransactions.*;
34 import org.omg.CORBA.*;
35 import org.omg.CORBA.ORBPackage.InvalidName JavaDoc;
36
37 import com.sun.jts.CosTransactions.*;
38 import com.sun.jts.otsidl.*;
39
40 import javax.transaction.SystemException JavaDoc;
41 import javax.transaction.Synchronization JavaDoc;
42 import org.omg.CosTransactions.Status;
43 import org.omg.CosTransactions.Current;
44 import org.omg.CosTransactions.NoTransaction;
45 import org.omg.CosTransactions.HeuristicMixed;
46 import org.omg.CosTransactions.HeuristicHazard;
47 import com.sun.jts.CosTransactions.GlobalTID;
48
49 import javax.transaction.xa.Xid JavaDoc;
50 import javax.resource.spi.work.WorkException JavaDoc;
51 import javax.resource.spi.work.WorkCompletedException JavaDoc;
52
53 import javax.transaction.xa.XAException JavaDoc;
54
55 import java.util.logging.Logger JavaDoc;
56 import java.util.logging.Level JavaDoc;
57 import com.sun.logging.LogDomains;
58 import com.sun.jts.utils.LogFormatter;
59 /**
60  * An implementation of javax.transaction.TransactionManager using JTA.
61  *
62  * This is a singleton object
63  *
64  * @author Tony Ng
65  */

66 public class TransactionManagerImpl implements TransactionManager {
67
68     /**
69      * the singleton object
70      */

71     static private TransactionManagerImpl tm = null;
72
73     /**
74      * store the current psuedo object
75      */

76     private Current current;
77
78     /**
79      * a mapping of GlobalTID -> TransactionState
80      */

81     // private Hashtable transactionStates;
82

83     /**
84      * mapping between CosTransaction status -> JTA status
85      */

86     static private HashMap statusMap;
87     static private int[] directLookup;
88     static final int maxStatus;
89
90     /*
91         Logger to log transaction messages
92     */

93     static Logger JavaDoc _logger = LogDomains.getLogger(LogDomains.TRANSACTION_LOGGER);
94     
95     //START IASRI 4706150
96

97     /**
98     * store XAResource Timeout
99     */

100     static private int xaTimeOut = 0;
101     //END IASRI 4706150
102

103     static private Status CosTransactionStatus[] =
104     {
105         org.omg.CosTransactions.Status.StatusActive,
106         org.omg.CosTransactions.Status.StatusMarkedRollback,
107         org.omg.CosTransactions.Status.StatusPrepared,
108         org.omg.CosTransactions.Status.StatusCommitted,
109         org.omg.CosTransactions.Status.StatusRolledBack,
110         org.omg.CosTransactions.Status.StatusUnknown,
111         org.omg.CosTransactions.Status.StatusNoTransaction,
112         org.omg.CosTransactions.Status.StatusPreparing,
113         org.omg.CosTransactions.Status.StatusCommitting,
114         org.omg.CosTransactions.Status.StatusRollingBack
115     };
116
117     static private int JTAStatus[] =
118     {
119         javax.transaction.Status.STATUS_ACTIVE,
120         javax.transaction.Status.STATUS_MARKED_ROLLBACK,
121         javax.transaction.Status.STATUS_PREPARED,
122         javax.transaction.Status.STATUS_COMMITTED,
123         javax.transaction.Status.STATUS_ROLLEDBACK,
124         javax.transaction.Status.STATUS_UNKNOWN,
125         javax.transaction.Status.STATUS_NO_TRANSACTION,
126         javax.transaction.Status.STATUS_PREPARING,
127         javax.transaction.Status.STATUS_COMMITTING,
128         javax.transaction.Status.STATUS_ROLLING_BACK
129     };
130
131     // static block to initialize statusMap
132
static {
133         statusMap = new HashMap();
134         int calcMaxStatus = 0;
135         for (int i=0; i<CosTransactionStatus.length; i++) {
136             statusMap.put(CosTransactionStatus[i],
137                           new Integer JavaDoc(JTAStatus[i]));
138             calcMaxStatus = Math.max(calcMaxStatus, CosTransactionStatus[i].value());
139         }
140         maxStatus = calcMaxStatus;
141         directLookup = new int[maxStatus + 1];
142         for (int i=0; i < directLookup.length; i++) {
143             // initialize so that any unused slots point to 'unkown'.
144
directLookup[i] = javax.transaction.Status.STATUS_UNKNOWN;
145         }
146         for (int i=0; i < CosTransactionStatus.length; i++) {
147             int statusVal = CosTransactionStatus[i].value();
148             if (statusVal < 0) {
149                 _logger.log(Level.SEVERE, "A negative CosTransaction Status value was detected.");
150             } else {
151                 directLookup[statusVal] = JTAStatus[i];
152             }
153         }
154
155     }
156
157     /**
158      * get the singleton TransactionManagerImpl
159      */

160     static synchronized
161     public TransactionManagerImpl getTransactionManagerImpl() {
162         if (tm == null) {
163             tm = new TransactionManagerImpl();
164         }
165         return tm;
166     }
167
168     /**
169      * Create a transaction manager instance
170      */

171     private TransactionManagerImpl() {
172         try {
173             ORB orb = Configuration.getORB();
174             current = org.omg.CosTransactions.CurrentHelper.
175                 narrow(orb.resolve_initial_references("TransactionCurrent"/*#Frozen*/));
176             // transactionStates = new Hashtable();
177
} catch (InvalidName JavaDoc inex) {
178             _logger.log(Level.SEVERE,
179                     "jts.unexpected_error_in_create_transaction_manager",inex);
180         } catch (Exception JavaDoc ex) {
181             _logger.log(Level.SEVERE,
182                     "jts.unexpected_error_in_create_transaction_manager",ex);
183         }
184     }
185
186     /**
187      * extends props with the JTS-related properties
188      * based on the specified parameters.
189      * The properties will be used as part of ORB.init() call.
190      *
191      * @param prop the properties that will be extended
192      * @param logDir directory for the log, current directory if null
193      * @param trace enable JTS tracing
194      * @param traceDir directory for tracing, current directory if null
195      *
196      */

197     static public void initJTSProperties(Properties props, String JavaDoc logDir,
198                                          boolean trace, String JavaDoc traceDir) {
199         if (traceDir == null) traceDir = "."/*#Frozen*/;
200         if (logDir == null) logDir = "."/*#Frozen*/;
201
202         props.put("com.sun.corba.se.CosTransactions.ORBJTSClass"/*#Frozen*/,
203                   "com.sun.jts.CosTransactions.DefaultTransactionService"/*#Frozen*/);
204         props.put("com.sun.jts.traceDirectory"/*#Frozen*/, traceDir);
205         props.put("com.sun.jts.logDirectory"/*#Frozen*/, logDir);
206         if (trace) {
207             props.put("com.sun.jts.trace"/*#Frozen*/, "true"/*#Frozen*/);
208         }
209     }
210
211     /**
212      * given a CosTransactions Status, return
213      * the equivalent JTA Status
214      */

215     static public int mapStatus(Status status) {
216         int statusVal = status.value();
217         if (statusVal < 0 || statusVal > maxStatus) {
218             return javax.transaction.Status.STATUS_UNKNOWN;
219         } else {
220             return directLookup[statusVal];
221         }
222     }
223
224     /**
225      * Create a new transaction and associate it with the current thread.
226      *
227      * @exception NotSupportedException Thrown if the thread is already
228      * associated with a transaction.
229      */

230     public void begin()
231         throws NotSupportedException, SystemException JavaDoc {
232
233         try {
234             // does not support nested transaction
235
if (current.get_control() != null) {
236                 throw new NotSupportedException();
237             }
238             current.begin();
239         } catch (TRANSACTION_ROLLEDBACK ex) {
240             throw new NotSupportedException();
241         } catch (SubtransactionsUnavailable ex) {
242             throw new SystemException JavaDoc();
243         }
244     }
245
246     //START IASRI PERFIMPROVEMNT
247
/**
248      * Create a new transaction with the given timeout and associate it
249      * with the current thread.
250      *
251      * @exception NotSupportedException Thrown if the thread is already
252      * associated with a transaction.
253      */

254     public void begin(int timeout)
255         throws NotSupportedException, SystemException JavaDoc {
256         try {
257             // does not support nested transaction
258
if (current.get_control() != null) {
259                 throw new NotSupportedException();
260             }
261             ((com.sun.jts.CosTransactions.CurrentImpl)current).begin(timeout);
262         } catch (TRANSACTION_ROLLEDBACK ex) {
263             throw new NotSupportedException();
264         } catch (SubtransactionsUnavailable ex) {
265             throw new SystemException JavaDoc();
266         }
267     }
268     //END IASRI PERFIMPROVEMNT
269

270     /**
271      * Complete the transaction associated with the current thread. When this
272      * method completes, the thread becomes associated with no transaction.
273      *
274      * @exception RollbackException Thrown to indicate that
275      * the transaction has been rolled back rather than committed.
276      *
277      * @exception HeuristicMixedException Thrown to indicate that a heuristic
278      * decision was made and that some relevant updates have been committed
279      * while others have been rolled back.
280      *
281      * @exception HeuristicRollbackException Thrown to indicate that a
282      * heuristic decision was made and that all relevant updates have been
283      * rolled back.
284      *
285      * @exception SecurityException Thrown to indicate that the thread is
286      * not allowed to commit the transaction.
287      *
288      * @exception IllegalStateException Thrown if the current thread is
289      * not associated with a transaction.
290      */

291     public void commit() throws RollbackException,
292     HeuristicMixedException, HeuristicRollbackException, SecurityException JavaDoc,
293     IllegalStateException JavaDoc, SystemException JavaDoc {
294
295         try {
296             current.commit(true);
297         } catch (TRANSACTION_ROLLEDBACK ex) {
298             throw new RollbackException();
299         } catch (NoTransaction ex) {
300             throw new IllegalStateException JavaDoc();
301         } catch (NO_PERMISSION ex) {
302             throw new SecurityException JavaDoc();
303         } catch (HeuristicMixed ex) {
304             throw new HeuristicMixedException();
305         } catch (HeuristicHazard ex) {
306             throw new HeuristicRollbackException();
307         } catch (Exception JavaDoc ex) {
308             throw new SystemException JavaDoc(ex.toString());
309         }
310         /***
311         Transaction tran = getTransaction();
312         if (tran == null) throw new IllegalStateException();
313         tran.commit();
314         ***/

315     }
316
317     /**
318      * Roll back the transaction associated with the current thread. When this
319      * method completes, the thread becomes associated with no transaction.
320      *
321      * @exception SecurityException Thrown to indicate that the thread is
322      * not allowed to roll back the transaction.
323      *
324      * @exception IllegalStateException Thrown if the current thread is
325      * not associated with a transaction.
326      */

327     public void rollback()
328         throws IllegalStateException JavaDoc, SecurityException JavaDoc, SystemException JavaDoc {
329
330         try {
331             current.rollback();
332         } catch (NoTransaction ex) {
333             throw new IllegalStateException JavaDoc();
334         } catch (NO_PERMISSION ex) {
335             throw new SecurityException JavaDoc();
336         } catch (Exception JavaDoc ex) {
337             throw new SystemException JavaDoc(ex.toString());
338         }
339
340         /***
341         Transaction tran = getTransaction();
342         if (tran == null) throw new IllegalStateException();
343         tran.rollback();
344         ***/

345     }
346
347     /**
348      * Modify the transaction associated with the current thread such that
349      * the only possible outcome of the transaction is to roll back the
350      * transaction.
351      *
352      * @exception IllegalStateException Thrown if the current thread is
353      * not associated with a transaction.
354      */

355     public void setRollbackOnly()
356         throws IllegalStateException JavaDoc, SystemException JavaDoc {
357
358         try {
359             current.rollback_only();
360         } catch (NoTransaction ex) {
361             throw new IllegalStateException JavaDoc();
362         } catch (Exception JavaDoc ex) {
363             throw new SystemException JavaDoc(ex.toString());
364         }
365     }
366
367     /**
368      * Obtain the status of the transaction associated with the current thread.
369      *
370      * @return The transaction status. If no transaction is associated with
371      * the current thread, this method returns the Status.NoTransaction
372      * value.
373      */

374     public int getStatus() throws SystemException JavaDoc {
375         try {
376             Status status = current.get_status();
377             return mapStatus(status);
378         } catch (Exception JavaDoc ex) {
379             throw new SystemException JavaDoc(ex.toString());
380         }
381     }
382
383     /**
384      * Modify the timeout value that is associated with transactions started
385      * by subsequent invocations of the begin method.
386      *
387      * <p> If an application has not called this method, the transaction
388      * service uses some default value for the transaction timeout.
389      *
390      * @param seconds The value of the timeout in seconds. If the value is zero,
391      * the transaction service restores the default value. If the value
392      * is negative a SystemException is thrown.
393      *
394      * @exception SystemException Thrown if the transaction manager
395      * encounters an unexpected error condition.
396      *
397      */

398     public synchronized void setTransactionTimeout(int seconds)
399         throws SystemException JavaDoc {
400
401         try {
402             if (seconds < 0) {
403                 String JavaDoc msg = LogFormatter.getLocalizedMessage(_logger,
404                              "jts.invalid_timeout");
405                 throw new SystemException JavaDoc(msg);
406             }
407             current.set_timeout(seconds);
408         } catch (Exception JavaDoc ex) {
409             throw new SystemException JavaDoc(ex.toString());
410         }
411     }
412
413     /**
414      * Get the transaction object that represents the transaction
415      * context of the calling thread
416      */

417     public Transaction getTransaction()
418         throws SystemException JavaDoc {
419
420         try {
421             Control control = current.get_control();
422             if (control == null) {
423                 return null;
424             } else {
425                 return createTransactionImpl(control);
426             }
427         } catch (Unavailable uex) {
428             throw new SystemException JavaDoc(uex.toString());
429         } catch (Exception JavaDoc ex) {
430             throw new SystemException JavaDoc(ex.toString());
431         }
432     }
433
434     /**
435      * Resume the transaction context association of the calling thread
436      * with the transaction represented by the supplied Transaction object.
437      * When this method returns, the calling thread is associated with the
438      * transaction context specified.
439      */

440     public void resume(Transaction suspended) throws
441         InvalidTransactionException, IllegalStateException JavaDoc, SystemException JavaDoc {
442         // thread is already associated with a transaction?
443
if (getTransaction() != null) throw new IllegalStateException JavaDoc();
444         // check for invalid Transaction object
445
if (suspended == null) throw new InvalidTransactionException();
446         if ((suspended instanceof TransactionImpl) == false) {
447             throw new InvalidTransactionException();
448         }
449         Control control = ((TransactionImpl) suspended).getControl();
450         try {
451             current.resume(control);
452         } catch (InvalidControl ex) {
453             //_logger.log(Level.FINE,"Invalid Control Exception in resume",ex);
454
throw new InvalidTransactionException();
455         } catch (Exception JavaDoc ex) {
456             throw new SystemException JavaDoc(ex.toString());
457         }
458     }
459
460
461     /**
462      * Suspend the transaction currently associated with the calling
463      * thread and return a Transaction object that represents the
464      * transaction context being suspended. If the calling thread is
465      * not associated with a transaction, the method returns a null
466      * object reference. When this method returns, the calling thread
467      * is associated with no transaction.
468      */

469     public Transaction suspend() throws SystemException JavaDoc {
470         try {
471             Control control = current.suspend();
472             if (control == null) return null;
473             return createTransactionImpl(control);
474         } catch (Unavailable uex) {
475             throw new SystemException JavaDoc(uex.toString());
476         } catch (Exception JavaDoc ex) {
477             throw new SystemException JavaDoc(ex.toString());
478         }
479     }
480
481     /**
482     TransactionState getOrCreateTransactionState(GlobalTID gtid,
483                                                  Transaction tran)
484         throws SystemException {
485
486         synchronized (transactionStates) {
487             TransactionState result =
488                 (TransactionState) transactionStates.get(gtid);
489             if (result == null) {
490                 result = new TransactionState(gtid);
491                 transactionStates.put(gtid, result);
492                 try {
493                     // remove Transaction State on transaction completion
494                     Synchronization sync =
495                         new SynchronizationListener(gtid, result);
496                     tran.registerSynchronization(sync);
497                 } catch (Exception ex) {
498                     _logger.log(Level.WARNING,
499                             "jts.unexpected_error_in_get_or_create_transaction_state",ex);
500                     throw new SystemException();
501                 }
502             }
503             return result;
504         }
505     }
506
507     TransactionState getTransactionState(GlobalTID gtid,
508                                          Transaction tran)
509         throws SystemException {
510
511         synchronized (transactionStates) {
512             return (TransactionState) transactionStates.get(gtid);
513         }
514     }
515
516    **/

517
518     private Transaction createTransactionImpl(Control control)
519         throws Unavailable, SystemException JavaDoc
520     {
521         GlobalTID gtid = null;
522         if (Configuration.isLocalFactory()) {
523             gtid = ((ControlImpl) control).getGlobalTID();
524         } else {
525             ControlImpl cntrlImpl = ControlImpl.servant(JControlHelper.narrow(control));
526             gtid = cntrlImpl.getGlobalTID();
527         }
528
529         // return new TransactionImpl(this, control, gtid);
530
return new TransactionImpl(control, gtid);
531     }
532
533     /**
534      * The application server passes in the list of XAResource objects
535      * to be recovered.
536      *
537      * @param xaResourceList list of XAResource objects.
538      */

539     public static void recover(Enumeration xaResourceList) {
540         RecoveryManager.recoverXAResources(xaResourceList);
541     }
542
543     /**
544      * Recreate a transaction based on the Xid. This call causes the calling
545      * thread to be associated with the specified transaction.
546      *
547      * @param xid the Xid object representing a transaction.
548      * @param timeout positive, non-zero value for transaction timeout.
549      */

550     public static void recreate(Xid JavaDoc xid, long timeout) throws WorkException JavaDoc {
551                 
552         // check if xid is valid
553
if (xid == null || xid.getFormatId() == 0 ||
554                 xid.getBranchQualifier() == null ||
555                 xid.getGlobalTransactionId() == null) {
556             WorkException JavaDoc workExc = new WorkCompletedException JavaDoc("Invalid Xid");
557             workExc.setErrorCode(WorkException.TX_RECREATE_FAILED);
558             throw workExc;
559         }
560
561         // has TransactionService been initialized?
562
if (!DefaultTransactionService.isActive()) {
563             WorkException JavaDoc workExc =
564                 new WorkCompletedException JavaDoc("Transaction Manager unavailable");
565             workExc.setErrorCode(WorkException.TX_RECREATE_FAILED);
566             throw workExc;
567         }
568         
569         // recreate the transaction
570
GlobalTID tid = new GlobalTID(xid);
571         try {
572             CurrentTransaction.recreate(
573         tid, (int) ((timeout <= 0) ? 0 : timeout));
574         } catch (Throwable JavaDoc exc) {
575             String JavaDoc errorCode = WorkException.TX_RECREATE_FAILED;
576             if (exc instanceof INVALID_TRANSACTION &&
577                     (((INVALID_TRANSACTION) exc).minor ==
578                         MinorCode.TX_CONCURRENT_WORK_DISALLOWED)) {
579                 errorCode = WorkException.TX_CONCURRENT_WORK_DISALLOWED;
580             }
581             WorkException JavaDoc workExc = new WorkCompletedException JavaDoc(exc);
582             workExc.setErrorCode(errorCode);
583             throw workExc;
584         }
585     }
586
587     /**
588      * Release a transaction. This call causes the calling thread to be
589      * dissociated from the specified transaction.
590      *
591      * @param xid the Xid object representing a transaction.
592      */

593     public static void release(Xid JavaDoc xid) throws WorkException JavaDoc {
594                 
595         GlobalTID tid = new GlobalTID(xid);
596         try {
597             CurrentTransaction.release(tid);
598         } catch (Throwable JavaDoc exc) {
599             String JavaDoc errorCode = WorkException.UNDEFINED;
600             if (exc instanceof INTERNAL) {
601                 errorCode = WorkException.INTERNAL;
602             }
603             WorkException JavaDoc workExc = new WorkCompletedException JavaDoc(exc);
604             workExc.setErrorCode(errorCode);
605             throw workExc;
606         }
607     }
608
609     /**
610      * Provides a handle to a <code>XATerminator</code> instance. The
611      * <code>XATerminator</code> instance could be used by a resource adapter
612      * to flow-in transaction completion and crash recovery calls from an EIS.
613      *
614      * @return a <code>XATerminator</code> instance.
615      */

616     public static javax.resource.spi.XATerminator JavaDoc getXATerminator() {
617         return new XATerminatorImpl();
618     }
619
620     /**
621      * a simple assertion mechanism that print stack trace
622      * if assertion fails
623      */

624     static private void assert_prejdk14(boolean value) {
625         if (!value) {
626             Exception JavaDoc e = new Exception JavaDoc();
627             _logger.log(Level.WARNING,"jts.assert",e);
628         }
629     }
630
631     
632     //START IASRI 4706150
633
/**
634     * used to set XAResource timeout
635     */

636     public static void setXAResourceTimeOut(int value){
637         xaTimeOut = value;
638     }
639
640     public static int getXAResourceTimeOut(){
641         return xaTimeOut;
642     }
643     //END IASRI 4706150
644
/**
645     class SynchronizationListener implements Synchronization {
646
647         private GlobalTID gtid;
648         private TransactionState tranState;
649
650         SynchronizationListener(GlobalTID gtid, TransactionState tranState) {
651             this.gtid = gtid;
652             this.tranState = tranState;
653         }
654
655         public void afterCompletion(int status) {
656             tranState.cleanupTransactionStateMapping();
657         }
658
659         public void beforeCompletion() {
660             try {
661           tranState.beforeCompletion();
662         }catch(XAException xaex){
663           _logger.log(Level.WARNING,"jts.unexpected_xa_error_in_beforecompletion", new java.lang.Object[] {new Integer(xaex.errorCode), xaex.getMessage()});
664           _logger.log(Level.WARNING,"",xaex);
665             } catch (Exception ex) {
666                 _logger.log(Level.WARNING,"jts.unexpected_error_in_beforecompletion",ex);
667             }
668         }
669     }
670   **/

671
672     /**
673     void cleanupTransactionState(GlobalTID gtid) {
674         transactionStates.remove(gtid);
675     }
676     **/

677 }
678
679
Popular Tags