Source Code Cross Referenced for TransactionImpl.java in  » Database-JDBC-Connection-Pool » jotm-2.0.10 » org » objectweb » jotm » Java Source Code / Java DocumentationJava Source Code and Java Documentation

Java Source Code / Java Documentation
1. 6.0 JDK Core
2. 6.0 JDK Modules
3. 6.0 JDK Modules com.sun
4. 6.0 JDK Modules com.sun.java
5. 6.0 JDK Modules sun
6. 6.0 JDK Platform
7. Ajax
8. Apache Harmony Java SE
9. Aspect oriented
10. Authentication Authorization
11. Blogger System
12. Build
13. Byte Code
14. Cache
15. Chart
16. Chat
17. Code Analyzer
18. Collaboration
19. Content Management System
20. Database Client
21. Database DBMS
22. Database JDBC Connection Pool
23. Database ORM
24. Development
25. EJB Server geronimo
26. EJB Server GlassFish
27. EJB Server JBoss 4.2.1
28. EJB Server resin 3.1.5
29. ERP CRM Financial
30. ESB
31. Forum
32. GIS
33. Graphic Library
34. Groupware
35. HTML Parser
36. IDE
37. IDE Eclipse
38. IDE Netbeans
39. Installer
40. Internationalization Localization
41. Inversion of Control
42. Issue Tracking
43. J2EE
44. JBoss
45. JMS
46. JMX
47. Library
48. Mail Clients
49. Net
50. Parser
51. PDF
52. Portal
53. Profiler
54. Project Management
55. Report
56. RSS RDF
57. Rule Engine
58. Science
59. Scripting
60. Search Engine
61. Security
62. Sevlet Container
63. Source Control
64. Swing Library
65. Template Engine
66. Test Coverage
67. Testing
68. UML
69. Web Crawler
70. Web Framework
71. Web Mail
72. Web Server
73. Web Services
74. Web Services apache cxf 2.0.1
75. Web Services AXIS2
76. Wiki Engine
77. Workflow Engines
78. XML
79. XML UI
Java
Java Tutorial
Java Open Source
Jar File Download
Java Articles
Java Products
Java by API
Photoshop Tutorials
Maya Tutorials
Flash Tutorials
3ds-Max Tutorials
Illustrator Tutorials
GIMP Tutorials
C# / C Sharp
C# / CSharp Tutorial
C# / CSharp Open Source
ASP.Net
ASP.NET Tutorial
JavaScript DHTML
JavaScript Tutorial
JavaScript Reference
HTML / CSS
HTML CSS Reference
C / ANSI-C
C Tutorial
C++
C++ Tutorial
Ruby
PHP
Python
Python Tutorial
Python Open Source
SQL Server / T-SQL
SQL Server / T-SQL Tutorial
Oracle PL / SQL
Oracle PL/SQL Tutorial
PostgreSQL
SQL / MySQL
MySQL Tutorial
VB.Net
VB.Net Tutorial
Flash / Flex / ActionScript
VBA / Excel / Access / Word
XML
XML Tutorial
Microsoft Office PowerPoint 2007 Tutorial
Microsoft Office Excel 2007 Tutorial
Microsoft Office Word 2007 Tutorial
Java Source Code / Java Documentation » Database JDBC Connection Pool » jotm 2.0.10 » org.objectweb.jotm 
Source Cross Referenced  Class Diagram Java Document (Java Doc) 


0001:        /*
0002:         * @(#) TransactionImpl.java 
0003:         *
0004:         * JOTM: Java Open Transaction Manager 
0005:         *
0006:         *
0007:         * This module was originally developed by 
0008:         *
0009:         *  - Bull S.A. as part of the JOnAS application server code released in 
0010:         *    July 1999 (www.bull.com)
0011:         * 
0012:         * --------------------------------------------------------------------------
0013:         *  The original code and portions created by Bull SA are 
0014:         *  Copyright (c) 1999 BULL SA  
0015:         *  All rights reserved.
0016:         *  
0017:         * Redistribution and use in source and binary forms, with or without 
0018:         * modification, are permitted provided that the following conditions are met:
0019:         *
0020:         * -Redistributions of source code must retain the above copyright notice, this
0021:         * list of conditions and the following disclaimer. 
0022:         *
0023:         * -Redistributions in binary form must reproduce the above copyright notice, 
0024:         * this list of conditions and the following disclaimer in the documentation 
0025:         * and/or other materials provided with the distribution. 
0026:         *
0027:         * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 
0028:         * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 
0029:         * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 
0030:         * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 
0031:         * LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 
0032:         * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 
0033:         * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 
0034:         * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 
0035:         * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 
0036:         * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 
0037:         * POSSIBILITY OF SUCH DAMAGE.
0038:         * 
0039:         * --------------------------------------------------------------------------
0040:         * Contributor(s):
0041:         * 01/11/06 Christophe Ney cney@batisseurs.com 
0042:         *          Added ResourceManagerListener mechanism to remove ThreadData
0043:         *          dependency.
0044:         * 
0045:         * 02/01/15 Dean Jennings - List  instead of Vector for enlistedXARes delistedXARes
0046:         *
0047:         * 02/06/18 Marek Prochazka - in timeoutExpired() removed code
0048:         *          preventing deadlock by rolling back transaction
0049:         * --------------------------------------------------------------------------
0050:         * $Id: TransactionImpl.java,v 1.45 2005/05/10 22:52:35 tonyortiz Exp $
0051:         * --------------------------------------------------------------------------
0052:         */
0053:        package org.objectweb.jotm;
0054:
0055:        import java.rmi.RemoteException;
0056:        import java.util.ArrayList;
0057:        import java.util.Collections;
0058:        import java.util.List;
0059:        import javax.transaction.*;
0060:        import javax.transaction.xa.XAException;
0061:        import javax.transaction.xa.XAResource;
0062:
0063:        /**
0064:         * TransactionImpl is the implementation of the Transaction interface,
0065:         * defined in JTA specifications. This object is intended to be used
0066:         * by the EJBServer for transaction management. It is used indirectly
0067:         * by the UserTransaction implementation too, i.e. the Current object.
0068:         * The goal is to use the JTA interface to hide the JTM interface to
0069:         * the caller (EJBServer, Bean or Client).
0070:         */
0071:
0072:        public class TransactionImpl implements  Transaction, TimerEventListener {
0073:
0074:            // ------------------------------------------------------------------
0075:            // Private data
0076:            // ------------------------------------------------------------------
0077:            private SubCoordinator subcoord = null;
0078:            private TransactionContext myCtx = null;
0079:            private Xid myXid = null;
0080:            private boolean genXidhashcode = false;
0081:            private boolean genXidtostring = false;
0082:            private int myXidhashcode = 0;
0083:            private String myXidtostring = null;
0084:            private String txDate = null;
0085:            private boolean interpose = false;
0086:            private int ucount = 0; // count of users (0 => can be freed)
0087:            private TimerEvent timer = null; // keep this to unvalidate timer
0088:            private RecoveryCoordinator recoveryCoord = null;
0089:            /// store enlisted resources
0090:            private List enlistedXARes = Collections
0091:                    .synchronizedList(new ArrayList());
0092:            /// store suspended resources
0093:            private List delistedXARes = null;
0094:            //  propagate context
0095:            private boolean propagateCtx = true;
0096:            private List enlistedJavaxXid = Collections
0097:                    .synchronizedList(new ArrayList());
0098:
0099:            // ------------------------------------------------------------------
0100:            // Constructors
0101:            // ------------------------------------------------------------------
0102:
0103:            /**
0104:             * New transaction (begin).
0105:             *
0106:             * @param timeout The value of the timeout in seconds.
0107:             *
0108:             */
0109:
0110:            public TransactionImpl(Xid xid, int timeout) throws SystemException {
0111:                if (TraceTm.jta.isDebugEnabled()) {
0112:                    TraceTm.jta.debug("xid= " + xid);
0113:                    TraceTm.jta.debug("timeout= " + timeout);
0114:                }
0115:
0116:                // Build a propagation context local (no ref to JTM yet)
0117:                myXid = xid;
0118:                // myXidhashcode = myXid.hashCode();
0119:                // myXidtostring = myXid.toString();
0120:                myCtx = new InternalTransactionContext(timeout, null,
0121:                        (javax.transaction.xa.Xid) xid);
0122:            }
0123:
0124:            /**
0125:             * New Transaction for this thread (setPropagationContext)
0126:             *
0127:             * @param pctx propagation context
0128:             *
0129:             */
0130:
0131:            public TransactionImpl(TransactionContext pctx) {
0132:
0133:                if (pctx == null) {
0134:                    TraceTm.jotm
0135:                            .error("TransactionImpl: null PropagationContext");
0136:                }
0137:                myCtx = pctx;
0138:                myXid = pctx.getXid();
0139:                // myXidhashcode = myXid.hashCode();
0140:                // myXidtostring = myXid.toString();
0141:                // interposition will be done later, only if necessary.
0142:                interpose = true;
0143:            }
0144:
0145:            // ------------------------------------------------------------------
0146:            // Transaction implementation
0147:            // ------------------------------------------------------------------
0148:
0149:            /**
0150:             * Complete the transaction represented by this Transaction object
0151:             * The calling thread is not required to have the same transaction
0152:             * associated with the thread. (JTA 3.3.3)
0153:             *
0154:             * @exception RollbackException Thrown to indicate that
0155:             *    the transaction has been rolled back rather than committed.
0156:             *
0157:             * @exception HeuristicMixedException Thrown to indicate that a heuristic 
0158:             *    decision was made and that some relevant updates have been committed
0159:             *    while others have been rolled back.
0160:             *
0161:             * @exception HeuristicRollbackException Thrown to indicate that a 
0162:             *    heuristic decision was made and that some relevant updates have been
0163:             *    rolled back.
0164:             *
0165:             * @exception SecurityException Thrown to indicate that the thread is
0166:             *    not allowed to commit the transaction.
0167:             *
0168:             * @exception IllegalStateException Thrown if the current thread is
0169:             *    not associated with a transaction.
0170:             *
0171:             * @exception SystemException Thrown if the transaction manager 
0172:             *    encounters an unexpected error condition
0173:             */
0174:
0175:            public void commit() throws RollbackException,
0176:                    HeuristicMixedException, HeuristicRollbackException,
0177:                    SecurityException, SystemException {
0178:
0179:                if (TraceTm.jta.isDebugEnabled()) {
0180:                    TraceTm.jta.debug("TransactionImpl.commit (tx= " + this 
0181:                            + ")");
0182:                }
0183:
0184:                // *** Distributed transaction.
0185:                Terminator term = myCtx.getTerminator();
0186:
0187:                if (term != null) {
0188:                    // Commits the Transaction, with heuristic report
0189:                    try {
0190:                        propagateCtx = false;
0191:                        term.commit(true);
0192:                        propagateCtx = true;
0193:                    } catch (TransactionRolledbackException e) {
0194:                        Current.getCurrent().forgetTx(getXid());
0195:                        if (TraceTm.jta.isDebugEnabled()) {
0196:                            TraceTm.jta
0197:                                    .debug("Commit distributed transaction -> rolled back!");
0198:                        }
0199:                        throw new RollbackException();
0200:                    } catch (RemoteException e) {
0201:
0202:                        if (TraceTm.jta.isWarnEnabled()) {
0203:                            TraceTm.jta.warn("got a RemoteException", e);
0204:                        }
0205:
0206:                        if (e.detail instanceof  TransactionRolledbackException) {
0207:                            Current.getCurrent().forgetTx(getXid());
0208:                            if (TraceTm.jta.isDebugEnabled()) {
0209:                                TraceTm.jta
0210:                                        .debug("Commit distributed transaction -> rolled back!");
0211:                            }
0212:                            throw new RollbackException();
0213:                        }
0214:
0215:                        if (e.detail instanceof  HeuristicMixed) {
0216:                            TraceTm.jotm
0217:                                    .info("Commit distributed transaction -> Heuristic mixed!");
0218:                            throw new HeuristicMixedException();
0219:                        } else {
0220:                            throw new SystemException(
0221:                                    "Unexpected RemoteException on commit:"
0222:                                            + e.detail.getMessage());
0223:                        }
0224:                    } catch (Exception e) {
0225:                        TraceTm.jotm
0226:                                .error("Unexpected Exception on commit:", e);
0227:                        throw new SystemException(
0228:                                "Unexpected Exception on commit");
0229:                    }
0230:
0231:                    if (subcoord == null) {
0232:                        // if no coordinator, timer will not be unset by JTM.
0233:                        unsetTimer();
0234:                    }
0235:
0236:                    Current.getCurrent().forgetTx(getXid());
0237:                    return;
0238:                }
0239:
0240:                // *** Local transaction
0241:                // commit_one_phase may raise remote exceptions. We must rethrow local exceptions.
0242:
0243:                if (subcoord != null) {
0244:                    try {
0245:                        subcoord.commit_one_phase();
0246:                    } catch (TransactionRolledbackException e) {
0247:                        if (TraceTm.jta.isDebugEnabled()) {
0248:                            TraceTm.jta
0249:                                    .debug("Commit local transaction -> rolled back!");
0250:                        }
0251:                        Current.getCurrent().forgetTx(getXid());
0252:                        throw new RollbackException();
0253:                    } catch (RemoteException e) {
0254:                        TraceTm.jotm.error(
0255:                                "Unexpected Exception on commit_one_phase:", e);
0256:                        Current.getCurrent().forgetTx(getXid());
0257:                        throw new SystemException(
0258:                                "Unexpected Exception on commit_one_phase");
0259:                    }
0260:                } else {
0261:                    // if no coordinator, just unset the timer and release this object.
0262:                    unsetTimer();
0263:                    Current.getCurrent().forgetTx(getXid());
0264:                }
0265:            }
0266:
0267:            /**
0268:             * Delist the resource specified from the current transaction 
0269:             * associated with the calling thread.
0270:             *
0271:             * @param xares The XAResource object representing the resource to delist
0272:             *
0273:             * @param flag One of the values of TMSUCCESS, TMSUSPEND, or TMFAIL.
0274:             *
0275:             * @exception IllegalStateException Thrown if the transaction in the 
0276:             *    target object is inactive.
0277:             *
0278:             * @exception SystemException Thrown if the transaction manager 
0279:             *    encounters an unexpected error condition
0280:             *
0281:             * @return true if the dissociation of the Resource is successful;
0282:             *         false otherwise.
0283:             */
0284:
0285:            public boolean delistResource(XAResource xares, int flag)
0286:                    throws IllegalStateException, SystemException {
0287:
0288:                if (TraceTm.jta.isDebugEnabled()) {
0289:                    TraceTm.jta.debug("TransactionImpl.delistResource");
0290:                    TraceTm.jta.debug("xares= " + xares + ", flag= " + flag);
0291:                }
0292:
0293:                if (enlistedXARes == null) {
0294:                    if (TraceTm.jta.isDebugEnabled()) {
0295:                        TraceTm.jta.error("No XA resources enlisted by JOTM");
0296:                    }
0297:                    return false;
0298:                }
0299:
0300:                // Verify that the XAResource to be delisted was enlisted earlier.
0301:
0302:                if (!enlistedXARes.contains(xares)) {
0303:                    if (TraceTm.jta.isDebugEnabled()) {
0304:                        TraceTm.jta.error("XAResouce " + xares
0305:                                + " not enlisted by JOTM");
0306:                    }
0307:                    return false;
0308:                }
0309:
0310:                Xid resXid = new XidImpl(getXid(), subcoord
0311:                        .getXaresIndex(xares));
0312:
0313:                javax.transaction.xa.Xid javaxxid = subcoord
0314:                        .getJavaxXid(subcoord.getXaresIndex(xares));
0315:
0316:                if (!enlistedJavaxXid.contains(javaxxid)) {
0317:                    if (TraceTm.jta.isDebugEnabled()) {
0318:                        TraceTm.jta.error("XAResouce " + xares
0319:                                + " not enlisted by JOTM");
0320:                    }
0321:                    return false;
0322:                }
0323:
0324:                int javaxxidindex = enlistedJavaxXid.indexOf(javaxxid);
0325:                javax.transaction.xa.Xid myjavaxxid = (javax.transaction.xa.Xid) enlistedJavaxXid
0326:                        .get(javaxxidindex);
0327:
0328:                if (TraceTm.jta.isDebugEnabled()) {
0329:                    TraceTm.jta.debug("resXid= " + resXid);
0330:                    TraceTm.jta.debug("delisted with resource= " + xares);
0331:                    TraceTm.jta.debug("end myjavaxxid= " + myjavaxxid);
0332:                }
0333:
0334:                // Send the XA end to the XAResource
0335:                try {
0336:                    xares.end(myjavaxxid, flag);
0337:                    // xares.end( (javax.transaction.xa.Xid) resXid, flag );
0338:                } catch (XAException e) {
0339:                    String error = "Cannot send XA end:" + e
0340:                            + " (error code = " + e.errorCode + ") --"
0341:                            + e.getMessage();
0342:                    TraceTm.jotm.error(error);
0343:                    if (TraceTm.jta.isDebugEnabled()) {
0344:                        TraceTm.jotm.debug("xares.end= " + xares);
0345:                    }
0346:                    throw new SystemException(error);
0347:                }
0348:
0349:                if (TraceTm.jta.isDebugEnabled()) {
0350:                    TraceTm.jta.debug("enlistedXAres.remove xares= " + xares);
0351:                }
0352:
0353:                /// remove from enlisted list
0354:                enlistedXARes.remove(xares);
0355:                enlistedJavaxXid.remove(javaxxid);
0356:                return true;
0357:            }
0358:
0359:            /**
0360:             * Enlist the resource specified with the current transaction 
0361:             * context of the calling thread
0362:             *
0363:             * @param xares The XAResource object representing the resource to enlist
0364:             *
0365:             * @return <i>true</i> if the resource was enlisted successfully; otherwise 
0366:             *    false.
0367:             *
0368:             * @exception RollbackException Thrown to indicate that
0369:             *    the transaction has been marked for rollback only.
0370:             *
0371:             * @exception IllegalStateException Thrown if the transaction in the 
0372:             *    target object is in prepared state or the transaction is inactive.
0373:             *
0374:             * @exception SystemException Thrown if the transaction manager 
0375:             *    encounters an unexpected error condition
0376:             *
0377:             */
0378:
0379:            public boolean enlistResource(XAResource xares)
0380:                    throws RollbackException, IllegalStateException,
0381:                    SystemException {
0382:
0383:                if (TraceTm.jta.isDebugEnabled()) {
0384:                    TraceTm.jta.debug("TransactionImpl.enlistResource");
0385:                    TraceTm.jta.debug("xares= " + xares);
0386:                }
0387:
0388:                // Check trivial cases
0389:                if (xares == null) {
0390:                    TraceTm.jotm.error("enlistResource: null argument");
0391:                    throw new SystemException("enlistResource: null argument");
0392:                }
0393:
0394:                if (myCtx == null) {
0395:                    throw new SystemException(
0396:                            "enlistResource: no Transactional Context");
0397:                }
0398:
0399:                // make a subCoordinator object if not existing yet
0400:                if (subcoord == null) {
0401:                    makeSubCoord();
0402:                    if (subcoord == null) {
0403:                        TraceTm.jotm
0404:                                .error("enlistResource: could not create subcoordinator");
0405:                        throw new SystemException(
0406:                                "enlistResource: could not create subcoordinator");
0407:                    }
0408:                }
0409:
0410:                boolean found = false;
0411:
0412:                try {
0413:                    found = subcoord.addResource(xares);
0414:                } catch (IllegalStateException e) {
0415:                    throw new IllegalStateException(
0416:                            "enlistResource: could not addResource " + xares);
0417:                }
0418:
0419:                boolean rollbackOnly = false;
0420:
0421:                // Send the XA start to the XAResource
0422:                // A new Xid branch should be generated in case of new RM (if !found)
0423:                //    See JTA Specifications, page 12/13.
0424:                int flag = found ? XAResource.TMJOIN : XAResource.TMNOFLAGS;
0425:
0426:                if ((delistedXARes != null) && delistedXARes.contains(xares)) {
0427:                    flag = XAResource.TMRESUME;
0428:                }
0429:
0430:                Xid resXid = new XidImpl(getXid(), subcoord
0431:                        .getXaresIndex(xares));
0432:                javax.transaction.xa.Xid javaxxid = new JavaXidImpl(resXid);
0433:
0434:                if (TraceTm.jta.isDebugEnabled()) {
0435:                    TraceTm.jta.debug("resXid= " + resXid);
0436:                    TraceTm.jta.debug("enlisted with resource= " + xares);
0437:                    TraceTm.jta.debug("start javaxxid= " + javaxxid);
0438:                }
0439:
0440:                if (!found) {
0441:                    subcoord.addJavaxXid(javaxxid);
0442:                }
0443:
0444:                try {
0445:                    xares.start(javaxxid, flag);
0446:                    // xares.start( (javax.transaction.xa.Xid) resXid, flag );
0447:                } catch (XAException e) {
0448:                    String error = "Cannot send XA(" + xares + ") start:" + e
0449:                            + " (error code = " + e.errorCode + ") --"
0450:                            + e.getMessage();
0451:                    TraceTm.jotm.error(error);
0452:                    throw new SystemException(error);
0453:                }
0454:
0455:                if (rollbackOnly) {
0456:                    throw new RollbackException();
0457:                }
0458:
0459:                if (!enlistedXARes.contains(xares)) {
0460:                    /// add to enlisted list
0461:                    enlistedXARes.add(xares);
0462:                    enlistedJavaxXid.add(javaxxid);
0463:                }
0464:
0465:                int status = this .getStatus();
0466:
0467:                switch (status) {
0468:                case Status.STATUS_ACTIVE:
0469:                case Status.STATUS_PREPARING:
0470:                    break;
0471:                case Status.STATUS_PREPARED:
0472:                    throw new IllegalStateException(
0473:                            "Transaction already prepared.");
0474:                case Status.STATUS_COMMITTING:
0475:                    // throw new IllegalStateException("Transaction already started committing.");
0476:                    break;
0477:                case Status.STATUS_COMMITTED:
0478:                    throw new IllegalStateException(
0479:                            "Transaction already committed.");
0480:                case Status.STATUS_MARKED_ROLLBACK:
0481:                    throw new RollbackException(
0482:                            "Transaction already marked for rollback");
0483:                case Status.STATUS_ROLLING_BACK:
0484:                    throw new RollbackException(
0485:                            "Transaction already started rolling back.");
0486:                case Status.STATUS_ROLLEDBACK:
0487:                    throw new RollbackException(
0488:                            "Transaction already rolled back.");
0489:                case Status.STATUS_NO_TRANSACTION:
0490:                    throw new IllegalStateException("No current transaction.");
0491:                case Status.STATUS_UNKNOWN:
0492:                    throw new IllegalStateException(
0493:                            "Unknown transaction status");
0494:                default:
0495:                    throw new IllegalStateException(
0496:                            "Illegal transaction status: " + status);
0497:                }
0498:
0499:                return true;
0500:            }
0501:
0502:            /// delist  all enlisted resources and move to suspended
0503:
0504:            public void doDetach(int flag) throws SystemException {
0505:                if (TraceTm.jta.isDebugEnabled()) {
0506:                    TraceTm.jta.debug("TransactionImpl.doDetach flag= "
0507:                            + XAResourceHelper.getFlagName(flag));
0508:                    TraceTm.jta.debug("number of enlisted= "
0509:                            + enlistedXARes.size());
0510:                }
0511:
0512:                // always copy enlisted to suspended resource list
0513:                // since jonas may resume the transaction in beforecompletion
0514:
0515:                delistedXARes = new ArrayList(enlistedXARes);
0516:
0517:                for (int i = 0; i < delistedXARes.size(); i++) {
0518:                    delistResource((XAResource) delistedXARes.get(i), flag);
0519:                }
0520:            }
0521:
0522:            /// enlist/clear all suspended resource
0523:
0524:            public void doAttach(int flag) throws SystemException,
0525:                    RollbackException {
0526:                if (TraceTm.jta.isDebugEnabled()) {
0527:                    TraceTm.jta.debug("TransactionImpl.doAttach flag= "
0528:                            + XAResourceHelper.getFlagName(flag));
0529:                    TraceTm.jta.debug("number of enlisted= "
0530:                            + enlistedXARes.size());
0531:                }
0532:
0533:                // we attach suspended transactions
0534:
0535:                if (flag == XAResource.TMRESUME) {
0536:                    // we may be calling resume from beforecompletion on transaction that are not suspended!
0537:
0538:                    for (int i = 0; (delistedXARes != null)
0539:                            && (i < delistedXARes.size()); i++) {
0540:
0541:                        enlistResource((XAResource) delistedXARes.get(i));
0542:                    }
0543:                }
0544:
0545:                delistedXARes = null;
0546:            }
0547:
0548:            /// get a copy of the list of currently enlisted resource
0549:
0550:            public List getEnlistedXAResource() {
0551:                if (TraceTm.jta.isDebugEnabled()) {
0552:                    TraceTm.jta.debug("getEnlistedXAResource size= "
0553:                            + enlistedXARes.size());
0554:                }
0555:                return new ArrayList(enlistedXARes);
0556:            }
0557:
0558:            /**
0559:             * Obtain the status of the transaction associated with the current thread.
0560:             * 
0561:             * @return The transaction status. If no transaction is associated with 
0562:             *    the current thread, this method returns the Status.NoTransaction 
0563:             *    value.
0564:             *
0565:             * @exception SystemException Thrown if the transaction manager 
0566:             *    encounters an unexpected error condition
0567:             *
0568:             */
0569:
0570:            public int getStatus() throws SystemException {
0571:                if (TraceTm.jta.isDebugEnabled()) {
0572:                    TraceTm.jta.debug("TransactionImpl.getStatus()");
0573:                }
0574:
0575:                // *** Distributed transaction
0576:                Coordinator coord = myCtx.getCoordinator();
0577:
0578:                if (coord != null) {
0579:                    // Ask the transaction status to JTM 
0580:                    int ret;
0581:                    try {
0582:                        ret = coord.get_status();
0583:                    } catch (Exception e) {
0584:                        TraceTm.jotm.error("cannot reach JTM:", e);
0585:                        return Status.STATUS_NO_TRANSACTION;
0586:                    }
0587:                    return ret;
0588:                }
0589:
0590:                // *** Local transaction
0591:                // The status is kept in the subcoordinator
0592:
0593:                if (subcoord == null) {
0594:                    // The transaction has just been started
0595:                    // No resource or synchro are registered yet.
0596:                    return Status.STATUS_ACTIVE;
0597:                }
0598:
0599:                return subcoord.getStatus();
0600:            }
0601:
0602:            /** 
0603:             * Register a synchronization object for the transaction currently
0604:             * associated with the calling thread. The transction manager invokes
0605:             * the beforeCompletion method prior to starting the transaction 
0606:             * commit process. After the transaction is completed, the transaction
0607:             * manager invokes the afterCompletion method.
0608:             *
0609:             * @param sync The javax.transaction.Synchronization object for the 
0610:             *    transaction associated with the target object
0611:             *
0612:             * @exception RollbackException Thrown to indicate that
0613:             *    the transaction has been marked for rollback only.
0614:             *
0615:             * @exception IllegalStateException Thrown if the transaction in the 
0616:             *    target object is in prepared state or the transaction is inactive.
0617:             *
0618:             * @exception SystemException Thrown if the transaction manager 
0619:             *    encounters an unexpected error condition
0620:             */
0621:
0622:            public void registerSynchronization(Synchronization sync)
0623:                    throws RollbackException, IllegalStateException,
0624:                    SystemException {
0625:                if (TraceTm.jta.isDebugEnabled()) {
0626:                    TraceTm.jta
0627:                            .debug("TransactionImpl.registerSynchronization(Synchronization sync)");
0628:                }
0629:
0630:                // It's time to make the subcoordinator, if not existing yet.
0631:                if (subcoord == null) {
0632:                    makeSubCoord();
0633:                }
0634:
0635:                // Add Synchronization to the list.
0636:                // may raise exceptions
0637:                subcoord.addSynchronization(sync);
0638:            }
0639:
0640:            /**
0641:             * Rollback the transaction represented by this Transaction object.
0642:             *
0643:             * @exception IllegalStateException Thrown if the transaction in the 
0644:             *    target object is in prepared state or the transaction is inactive.
0645:             *
0646:             * @exception SystemException Thrown if the transaction manager 
0647:             *    encounters an unexpected error condition
0648:             *
0649:             */
0650:
0651:            public void rollback() throws IllegalStateException,
0652:                    SystemException {
0653:                if (TraceTm.jta.isDebugEnabled()) {
0654:                    TraceTm.jta.debug("TransactionImpl.rollback(tx= " + this 
0655:                            + ")");
0656:                }
0657:
0658:                // *** Distributed transaction.
0659:                Terminator term = myCtx.getTerminator();
0660:
0661:                if (term != null) {
0662:                    // Rollback the Transaction
0663:                    try {
0664:                        propagateCtx = false;
0665:                        term.rollback();
0666:                        propagateCtx = true;
0667:                    } catch (java.rmi.ServerException e) {
0668:                        // HeuristicCommit ????
0669:                        throw new IllegalStateException(
0670:                                "Exception on rollback:" + e.detail);
0671:                    } catch (Exception e) {
0672:                        Current.getCurrent().forgetTx(getXid());
0673:                        throw new SystemException(
0674:                                "Unexpected Exception on rollback");
0675:                    }
0676:
0677:                    if (subcoord == null) {
0678:                        // if no coordinator, timer will not be unset by JTM.
0679:                        unsetTimer();
0680:                    }
0681:
0682:                    // release this object.
0683:                    Current.getCurrent().forgetTx(getXid());
0684:                    return;
0685:                }
0686:
0687:                // *** Local transaction.
0688:                // if no coordinator, nothing to do.
0689:
0690:                if (subcoord != null) {
0691:                    try {
0692:                        subcoord.rollback();
0693:                    } catch (RemoteException e) {
0694:                        Current.getCurrent().forgetTx(getXid());
0695:                        throw new IllegalStateException(
0696:                                "Exception on rollback:" + e);
0697:                    }
0698:
0699:                } else {
0700:                    // if no coordinator, just unset the timer.
0701:                    unsetTimer();
0702:                }
0703:
0704:                // release this object.
0705:                Current.getCurrent().forgetTx(getXid());
0706:            }
0707:
0708:            /**
0709:             * Prepare the transaction represented by this Transaction object.
0710:             *
0711:             * @exception IllegalStateException Thrown if the transaction in the 
0712:             *    target object is in prepared state or the transaction is inactive.
0713:             *
0714:             * @exception SystemException Thrown if the transaction manager 
0715:             *    encounters an unexpected error condition
0716:             *
0717:             */
0718:
0719:            public int prepare() throws IllegalStateException, SystemException {
0720:                if (TraceTm.jta.isDebugEnabled()) {
0721:                    TraceTm.jta.debug("TransactionImpl.prepare(tx= " + this 
0722:                            + ")");
0723:                }
0724:
0725:                int ret = 0;
0726:                if (subcoord != null) {
0727:                    try {
0728:                        ret = subcoord.prepare();
0729:                    } catch (RemoteException e) {
0730:                        TraceTm.jotm.error("Unexpected Exception on prepare:",
0731:                                e);
0732:                        throw new SystemException(
0733:                                "Unexpected Exception on prepare");
0734:                    }
0735:                }
0736:
0737:                return ret;
0738:            }
0739:
0740:            /**
0741:             * Modify the transaction associated with the current thread such that
0742:             * the only possible outcome of the transaction is to roll back the
0743:             * transaction.
0744:             *
0745:             * @exception IllegalStateException Thrown if the current thread is
0746:             *    not associated with any transaction.
0747:             *
0748:             * @exception SystemException Thrown if the transaction manager 
0749:             *    encounters an unexpected error condition
0750:             *
0751:             */
0752:
0753:            public void setRollbackOnly() throws IllegalStateException,
0754:                    SystemException {
0755:                if (TraceTm.jta.isDebugEnabled()) {
0756:                    TraceTm.jta.debug("TransactionImpl.setRollbackOnly(tx= "
0757:                            + this  + ")");
0758:                }
0759:
0760:                // *** Distributed transaction
0761:                Coordinator coord = myCtx.getCoordinator();
0762:
0763:                if (coord != null) {
0764:                    try {
0765:                        coord.rollback_only();
0766:                    } catch (RemoteException e) {
0767:                        TraceTm.jotm.error(
0768:                                "Cannot perform coordinator rollback only", e);
0769:                    }
0770:                }
0771:
0772:                // perform the if within this else, resolves bugs 300077, 300078
0773:                // subbcoord.setRollbackOnly sets the 'status' variable to
0774:                // "rollbackonly", checked in SubCoordinator.commit_one_phase
0775:                // } else {
0776:                // *** Local transaction
0777:                // The status is kept in the subcoordinator
0778:
0779:                if (subcoord == null) {
0780:                    // make a subCoordinator object if not existing yet
0781:                    makeSubCoord();
0782:                }
0783:
0784:                subcoord.setRollbackOnly();
0785:                // }
0786:            }
0787:
0788:            // ------------------------------------------------------------------
0789:            // TimerEventListener implementation
0790:            // ------------------------------------------------------------------
0791:
0792:            /**
0793:             * timeout for that transaction has expired
0794:             */
0795:
0796:            public void timeoutExpired(Object arg) {
0797:                if (TraceTm.jta.isDebugEnabled()) {
0798:                    TraceTm.jta.debug("TransactionImpl.timeoutExpired");
0799:                }
0800:
0801:                // increment counter for management
0802:                Current.getCurrent().incrementExpiredCounter();
0803:
0804:                // make the subcoordinator object, if not existing yet.
0805:
0806:                if (subcoord == null) {
0807:                    // if this is a proxy, just forget this object. The JTM will
0808:                    // rollback transaction with its own timer.
0809:                    Terminator term = myCtx.getTerminator();
0810:
0811:                    if (term != null) {
0812:                        TraceTm.jotm.info("forget tx (tx=" + this  + ")");
0813:                        Current.getCurrent().forgetTx(getXid());
0814:                        return;
0815:                    }
0816:
0817:                    makeSubCoord();
0818:                }
0819:
0820:                // Try to set it "rollback only"
0821:                // avoids a rollback while SQL requests are in progress
0822:                TraceTm.jotm.info("set rollback only (tx=" + this  + ")");
0823:
0824:                try {
0825:                    subcoord.setRollbackOnly();
0826:                } catch (Exception e) {
0827:                    TraceTm.jotm.error("cannot rollbackonly:" + e);
0828:                    return;
0829:                }
0830:            }
0831:
0832:            // ------------------------------------------------------------------
0833:            // This object is used as an HashTable index
0834:            // ------------------------------------------------------------------
0835:
0836:            /**
0837:             * return true if objects are identical
0838:             */
0839:
0840:            public boolean equals(Object obj2) {
0841:                TransactionImpl tx2 = (TransactionImpl) obj2;
0842:
0843:                // trivial cases
0844:                if (tx2 == this ) {
0845:                    return true;
0846:                }
0847:                if (tx2 == null) {
0848:                    return false;
0849:                }
0850:
0851:                // compare otids
0852:                return getXid().equals(tx2.getXid());
0853:            }
0854:
0855:            /**
0856:             * return a hashcode value for this object
0857:             */
0858:
0859:            public int hashCode() {
0860:                if (!genXidhashcode) {
0861:                    genXidhashcode = true;
0862:                    myXidhashcode = getXid().hashCode();
0863:                }
0864:
0865:                return myXidhashcode;
0866:                // return getXid().hashCode();
0867:            }
0868:
0869:            // ------------------------------------------------------------------
0870:            // Other methods
0871:            // ------------------------------------------------------------------
0872:
0873:            /**
0874:             * string form
0875:             */
0876:
0877:            public String toString() {
0878:                if (!genXidtostring) {
0879:                    genXidtostring = true;
0880:                    myXidtostring = getXid().toString();
0881:                }
0882:
0883:                return myXidtostring;
0884:                // return getXid().toString();
0885:            }
0886:
0887:            /**
0888:             * Return associated PropagationContext
0889:             * Used for implicit Context propagation.
0890:             *
0891:             * @return PropagationContext associated with the transaction.
0892:             */
0893:
0894:            public synchronized TransactionContext getPropagationContext(
0895:                    boolean hold) {
0896:
0897:                if (propagateCtx) {
0898:                    if (hold) {
0899:                        ucount++;
0900:                    }
0901:                    return myCtx;
0902:                } else {
0903:                    return null;
0904:                }
0905:            }
0906:
0907:            /**
0908:             * set a timer for the transaction
0909:             */
0910:
0911:            public void setTimer(TimerEvent timer) {
0912:                if (TraceTm.jta.isDebugEnabled()) {
0913:                    TraceTm.jta.debug("set timer for tx (timer=" + timer
0914:                            + ", tx=" + this  + ")");
0915:                }
0916:                this .timer = timer;
0917:            }
0918:
0919:            /**
0920:             * unset the timer
0921:             */
0922:
0923:            public void unsetTimer() {
0924:                if (TraceTm.jta.isDebugEnabled()) {
0925:                    TraceTm.jta.debug("unset timer for tx (timer=" + timer
0926:                            + ", tx=" + this  + ")");
0927:                }
0928:                if (timer != null) {
0929:                    timer.unset();
0930:                    timer = null;
0931:                }
0932:            }
0933:
0934:            /**
0935:             * set the date time stamp for the transaction
0936:             */
0937:
0938:            public void setTxDate(String date) {
0939:                if (TraceTm.jta.isDebugEnabled()) {
0940:                    TraceTm.jta.debug("set date for tx (data=" + date + ", tx="
0941:                            + this  + ")");
0942:                }
0943:                txDate = date;
0944:            }
0945:
0946:            /**
0947:             * get the date time stamp for the transaction
0948:             */
0949:
0950:            public String getTxDate() {
0951:                if (TraceTm.jta.isDebugEnabled()) {
0952:                    TraceTm.jta.debug("get date for tx (date=" + txDate
0953:                            + ", tx=" + this  + ")");
0954:                }
0955:                return txDate;
0956:            }
0957:
0958:            /**
0959:             * update the propagation context
0960:             * We should be inside the reply of a request involved in a tx here!
0961:             */
0962:
0963:            public synchronized void updatePropagationContext(
0964:                    TransactionContext pctx) {
0965:                if (TraceTm.jta.isDebugEnabled()) {
0966:                    TraceTm.jta
0967:                            .debug("TransactionImpl.updatePropagationContext");
0968:                }
0969:
0970:                Coordinator remoteCoord = pctx.getCoordinator();
0971:
0972:                if (remoteCoord == null && myCtx.getCoordinator() != null) {
0973:                    TraceTm.jotm
0974:                            .error("setPropagationContext: Bad Coordinator");
0975:                    TraceTm.jotm.error("remoteCoord = " + remoteCoord);
0976:                    TraceTm.jotm.error("myCtx.getCoordinator()= "
0977:                            + myCtx.getCoordinator());
0978:                    return;
0979:                }
0980:
0981:                // release count of users
0982:                ucount--;
0983:
0984:                // Interpose subCoordinator if newly distributed Tx
0985:                if (remoteCoord != null && myCtx.getCoordinator() == null) {
0986:                    myCtx.setCoordinator(pctx.getCoordinator());
0987:
0988:                    if (subcoord != null) {
0989:                        // register the subCoordinator as a Resource.
0990:                        try {
0991:                            recoveryCoord = remoteCoord
0992:                                    .register_resource(subcoord);
0993:                        } catch (RemoteException e) {
0994:                            TraceTm.jotm.error("Cannot make interposition:", e);
0995:                            return;
0996:                        }
0997:                    }
0998:                }
0999:
1000:                if (pctx.getTerminator() != null) {
1001:                    myCtx.setTerminator(pctx.getTerminator());
1002:                }
1003:            }
1004:
1005:            /**
1006:             * Get the Xid of the transaction
1007:             */
1008:
1009:            public Xid getXid() {
1010:                return myXid;
1011:            }
1012:
1013:            /**
1014:             * make a SubCoordinator for this Transaction object
1015:             */
1016:
1017:            private void makeSubCoord() {
1018:                if (TraceTm.jta.isDebugEnabled()) {
1019:                    TraceTm.jta.debug("make subcoordinator");
1020:                }
1021:
1022:                // Build the SubCoordinator object
1023:                try {
1024:                    subcoord = new SubCoordinator(this , getXid());
1025:                } catch (RemoteException e) {
1026:                    // should never go here.
1027:                    TraceTm.jotm.error("new SubCoordinator raised exception: ",
1028:                            e);
1029:                    return;
1030:                }
1031:
1032:                // If interposition must be done: do it now!
1033:                // Each time we have a remoteCoord + a subCoord, we must interpose.
1034:                Coordinator remoteCoord = myCtx.getCoordinator();
1035:
1036:                // First of all, create the Control object on JTM
1037:                // if it was not created before, if interpose flag is set.
1038:
1039:                if (interpose && remoteCoord == null) {
1040:                    try {
1041:                        // XXX Note that the JTM will build another Xid
1042:                        // This must be clarified
1043:                        if (TraceTm.jta.isDebugEnabled()) {
1044:                            TraceTm.jta
1045:                                    .debug("Creating a remote Control on JTM for a distributed transaction");
1046:                        }
1047:
1048:                        remoteCoord = (Coordinator) javax.rmi.PortableRemoteObject
1049:                                .narrow(Current.getJTM().create(
1050:                                        myCtx.getTimeout()), Coordinator.class);
1051:
1052:                    } catch (RemoteException e) {
1053:                        TraceTm.jotm.error(
1054:                                "Cannot create distributed transaction:", e);
1055:                        return;
1056:                    }
1057:
1058:                    myCtx.setCoordinator(remoteCoord);
1059:
1060:                    // fix for transaction context propagation with
1061:                    // the Jeremie protocol
1062:
1063:                    if (myCtx.getTerminator() == null) {
1064:                        myCtx.setTerminator((Terminator) remoteCoord);
1065:                    }
1066:                }
1067:
1068:                // Achieve interposition if not already done:
1069:                // - register the subCoordinator as a Resource.
1070:                if (remoteCoord != null && recoveryCoord == null) {
1071:                    try {
1072:                        recoveryCoord = remoteCoord.register_resource(subcoord);
1073:                    } catch (RemoteException e) {
1074:                        TraceTm.jotm.error("Cannot make interposition:", e);
1075:                        return;
1076:                    }
1077:                }
1078:            }
1079:
1080:            /**
1081:             * return true if object is no more used (= removable)
1082:             */
1083:
1084:            public boolean isRemovable() {
1085:                return (ucount == 0 && subcoord == null);
1086:            }
1087:
1088:        }
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.