KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > derby > jdbc > EmbedXAResource


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

21
22 package org.apache.derby.jdbc;
23
24 import java.sql.SQLException JavaDoc;
25 import javax.transaction.xa.XAResource JavaDoc;
26 import javax.transaction.xa.Xid JavaDoc;
27 import javax.transaction.xa.XAException JavaDoc;
28
29 import org.apache.derby.iapi.error.StandardException;
30 import org.apache.derby.iapi.jdbc.BrokeredConnection;
31 import org.apache.derby.iapi.jdbc.ResourceAdapter;
32 import org.apache.derby.iapi.reference.SQLState;
33 import org.apache.derby.iapi.reference.JDBC30Translation;
34 import org.apache.derby.iapi.services.context.ContextManager;
35 import org.apache.derby.iapi.services.context.ContextService;
36 import org.apache.derby.iapi.services.info.JVMInfo;
37 import org.apache.derby.iapi.store.access.XATransactionController;
38 import org.apache.derby.iapi.store.access.xa.XAResourceManager;
39 import org.apache.derby.iapi.store.access.xa.XAXactId;
40 import org.apache.derby.impl.jdbc.EmbedConnection;
41 import org.apache.derby.impl.jdbc.TransactionResourceImpl;
42
43 /**
44  * Implements XAResource
45  */

46 class EmbedXAResource implements XAResource JavaDoc {
47
48     private EmbedPooledConnection con;
49     private ResourceAdapter ra;
50     private XAXactId currentXid;
51     
52     EmbedXAResource (EmbedPooledConnection con, ResourceAdapter ra) {
53         this.con = con;
54         this.ra = ra;
55     }
56     
57     /**
58      * Commit the global transaction specified by xid.
59      * @param xid A global transaction identifier
60      * @param onePhase If true, the resource manager should use a one-phase
61      * commit protocol to commit the work done on behalf of xid.
62
63      * @exception XAException An error has occurred. Possible XAExceptions are
64      * XA_HEURHAZ, XA_HEURCOM, XA_HEURRB, XA_HEURMIX, XAER_RMERR,
65      * XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO.
66      * <P>If the resource manager did not commit the transaction and
67      * the paramether onePhase is set to true, the resource manager
68      * may throw one of the XA_RB* exceptions. Upon return, the
69      * resource manager has rolled back the branch's work and has
70      * released all held resources.
71      */

72     public final synchronized void commit(Xid JavaDoc xid, boolean onePhase)
73                                             throws XAException JavaDoc {
74         checkXAActive();
75         // ensure immtable and correct equals method.
76
XAXactId xid_im = new XAXactId(xid);
77         XATransactionState tranState = getTransactionState(xid_im);
78         
79         if (tranState == null) {
80             XAResourceManager rm = ra.getXAResourceManager();
81             ContextManager inDoubtCM = rm.find(xid);
82             // RM also does not know about this xid.
83
if (inDoubtCM == null)
84                 throw new XAException JavaDoc(XAException.XAER_NOTA);
85             ContextService csf = ContextService.getFactory();
86             csf.setCurrentContextManager(inDoubtCM);
87             try {
88                 rm.commit(inDoubtCM, xid_im, onePhase);
89                 
90                 // close the connection/transaction since it can never
91
// be used again.
92
inDoubtCM.cleanupOnError(StandardException.closeException());
93                 return;
94             } catch (StandardException se) {
95                 // The rm threw an exception, clean it up in the approprate
96
// context. There is no transactionResource to handle the
97
// exception for us.
98
inDoubtCM.cleanupOnError(se);
99                 throw wrapInXAException(se);
100             } finally {
101                 csf.resetCurrentContextManager(inDoubtCM);
102             }
103             
104         }
105         
106         synchronized (tranState) {
107             checkUserCredentials(tranState.creatingResource);
108             
109             // Check the transaction is no associated with
110
// any XAResource.
111
switch (tranState.associationState) {
112                 case XATransactionState.T0_NOT_ASSOCIATED:
113                     break;
114                     
115                 case XATransactionState.TRO_FAIL:
116                     throw new XAException JavaDoc(tranState.rollbackOnlyCode);
117                     
118                 default:
119                     throw new XAException JavaDoc(XAException.XAER_PROTO);
120             }
121             
122             if (tranState.suspendedList != null && tranState.suspendedList.size() != 0)
123                 throw new XAException JavaDoc(XAException.XAER_PROTO);
124             
125             if (tranState.isPrepared == onePhase)
126                 throw new XAException JavaDoc(XAException.XAER_PROTO);
127             
128             EmbedConnection conn = tranState.conn;
129             
130             try {
131                 conn.xa_commit(onePhase);
132             } catch (SQLException JavaDoc sqle) {
133                 throw wrapInXAException(sqle);
134             } finally {
135                 returnConnectionToResource(tranState, xid_im);
136             }
137         }
138     }
139
140     /**
141      * Ends the work performed on behalf of a transaction branch. The resource
142      * manager disassociates the XA resource from the transaction branch
143      * specified and let the transaction be completed.
144      *
145      * <p> If TMSUSPEND is specified in flags, the transaction branch is
146      * temporarily suspended in incomplete state. The transaction context
147      * is in suspened state and must be resumed via start with TMRESUME
148      * specified.
149      *
150      * <p> If TMFAIL is specified, the portion of work has failed. The
151      * resource manager may mark the transaction as rollback-only
152      *
153      * <p> If TMSUCCESS is specified, the portion of work has completed
154      * successfully.
155      *
156      * @param xid A global transaction identifier that is the same as what was
157      * used previously in the start method.
158      * @param flags One of TMSUCCESS, TMFAIL, or TMSUSPEND
159      *
160      * @exception XAException An error has occurred.
161      * Possible XAException values are XAER_RMERR, XAER_RMFAILED, XAER_NOTA,
162      * XAER_INVAL, XAER_PROTO, or XA_RB*.
163      */

164     public final synchronized void end(Xid JavaDoc xid, int flags) throws XAException JavaDoc {
165         checkXAActive();
166         
167         try {
168             // It is possible that the isolation level state in connection
169
// handle has gotten out of sync with the real isolation level.
170
// This can happen if SLQ instead of JDBC api has been used to
171
// set the isolation level. The code below will check if isolation
172
// was set using JDBC or SQL and if yes, then it will update the
173
// isolation state in BrokeredConnection with EmbedConnection's
174
// isolation level.
175
if (con.currentConnectionHandle != null)
176                 con.currentConnectionHandle.getIsolationUptoDate();
177         } catch (SQLException JavaDoc sqle) {
178             throw wrapInXAException(sqle);
179         }
180         
181         // ensure immtable and correct equals method.
182
XAXactId xid_im = new XAXactId(xid);
183         
184         boolean endingCurrentXid = false;
185         
186         // must match the Xid from start()
187
if (currentXid != null) {
188             if (!currentXid.equals(xid_im))
189                 throw new XAException JavaDoc(XAException.XAER_PROTO);
190             endingCurrentXid = true;
191         }
192         
193         XATransactionState tranState = getTransactionState(xid_im);
194         if (tranState == null)
195             throw new XAException JavaDoc(XAException.XAER_NOTA);
196         
197         boolean rollbackOnly = tranState.end(this, flags, endingCurrentXid);
198         
199         // RESOLVE - what happens to the connection on a fail
200
// where we are not ending the current XID.
201
if (endingCurrentXid) {
202             currentXid = null;
203             con.realConnection = null;
204         }
205         
206         if (rollbackOnly)
207             throw new XAException JavaDoc(tranState.rollbackOnlyCode);
208     }
209
210     /**
211      * Ask the resource manager to prepare for a transaction commit of the
212      * transaction specified in xid.
213      *
214      * @param xid A global transaction identifier
215      *
216      * @return A value indicating the resource manager's vote on the outcome
217      * of the transaction. The possible values are: XA_RDONLY or XA_OK. If the
218      * resource manager wants to roll back the transaction, it should do so by
219      * raising an appropriate XAException in the prepare method.
220      *
221      * @exception XAException An error has occurred. Possible exception values
222      * are: XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or
223      * XAER_PROTO.
224      *
225      */

226     public final synchronized int prepare(Xid JavaDoc xid) throws XAException JavaDoc {
227         checkXAActive();
228         
229         // ensure immtable and correct equals method.
230
XAXactId xid_im = new XAXactId(xid);
231         
232         XATransactionState tranState = getTransactionState(xid_im);
233         
234         if (tranState == null) {
235             XAResourceManager rm = ra.getXAResourceManager();
236             
237             ContextManager inDoubtCM = rm.find(xid);
238             
239             // RM also does not know about this xid.
240
if (inDoubtCM == null)
241                 throw new XAException JavaDoc(XAException.XAER_NOTA);
242             
243             // cannot prepare in doubt transactions
244
throw new XAException JavaDoc(XAException.XAER_PROTO);
245             
246         }
247         
248         synchronized (tranState) {
249             
250             checkUserCredentials(tranState.creatingResource);
251             
252             // Check the transaction is no associated with
253
// any XAResource.
254
switch (tranState.associationState) {
255                 case XATransactionState.T0_NOT_ASSOCIATED:
256                     break;
257                     
258                 case XATransactionState.TRO_FAIL:
259                     throw new XAException JavaDoc(tranState.rollbackOnlyCode);
260                     
261                 default:
262                     throw new XAException JavaDoc(XAException.XAER_PROTO);
263             }
264             
265             if (tranState.suspendedList != null
266                     && tranState.suspendedList.size() != 0)
267                 throw new XAException JavaDoc(XAException.XAER_PROTO);
268             
269             if (tranState.isPrepared)
270                 throw new XAException JavaDoc(XAException.XAER_PROTO);
271             
272             EmbedConnection conn = tranState.conn;
273             
274             try {
275                 
276                 int ret = conn.xa_prepare();
277                 
278                 if (ret == XATransactionController.XA_OK) {
279                     tranState.isPrepared = true;
280                     
281                     return XAResource.XA_OK;
282                 } else {
283                     
284                     returnConnectionToResource(tranState, xid_im);
285                     return XAResource.XA_RDONLY;
286                 }
287             } catch (SQLException JavaDoc sqle) {
288                 throw wrapInXAException(sqle);
289             }
290         }
291         
292     }
293
294     /**
295      * Obtain the current transaction timeout value set for this XAResource
296      * instance. If XAResource.setTransactionTimeout was not use prior to
297      * invoking this method, the return value is the default timeout set for
298      * the resource manager; otherwise, the value used in the previous
299      * setTransactionTimeout call is returned.
300      *
301      * @return the transaction timeout value in seconds.
302      */

303     public int getTransactionTimeout() {
304         return 0;
305     }
306
307     /**
308      * This method is called to determine if the resource manager instance
309      * represented by the target object is the same as the resouce manager
310      * instance represented by the parameter xares.
311      *
312      * @param xares An XAResource object whose resource manager instance is to
313      * be compared with the resource manager instance of the target object.
314      *
315      * @return true if it's the same RM instance; otherwise false.
316      * @exception XAException An error has occurred. Possible exception values
317      * are XAER_RMERR, XAER_RMFAIL.
318      */

319     public final synchronized boolean isSameRM(XAResource JavaDoc xares)
320                                                         throws XAException JavaDoc {
321         checkXAActive();
322         if (xares instanceof EmbedXAResource) {
323             return ra == ((EmbedXAResource) xares).ra;
324         }
325         return false;
326     }
327     
328     /**
329      * Obtain a list of prepared transaction branches from a resource
330      * manager. The transaction manager calls this method during recovery to
331      * obtain the list of transaction branches that are currently in prepared
332      * or heuristically completed states.
333      *
334      * @param flag One of TMSTARTRSCAN, TMENDRSCAN, TMNOFLAGS. TMNOFLAGS must
335      * be used when no other flags are set in flags.
336      *
337      * @return The resource manager returns zero or more XIDs for the
338      * transaction branches that are currently in a prepared or heuristically
339      * completed state. If an error occurs during the operation, the resource
340      * manager should throw the appropriate XAException.
341      *
342      * @exception XAException An error has occurred. Possible values are
343      * XAER_RMERR, XAER_RMFAIL, XAER_INVAL, and XAER_PROTO.
344      *
345      */

346     public final synchronized Xid JavaDoc[] recover(int flag) throws XAException JavaDoc {
347         checkXAActive();
348         
349         try {
350             return ra.getXAResourceManager().recover(flag);
351         } catch (StandardException se) {
352             throw wrapInXAException(se);
353         }
354     }
355     
356     /**
357      * Tell the resource manager to forget about a heuristically completed
358      * transaction branch.
359      *
360      * @param xid A global transaction identifier
361      * @exception XAException An error has occurred. Possible exception values
362      * are XAER_RMERR, XAER_RMFAIL, XAER_NOTA, XAER_INVAL, or XAER_PROTO.
363      */

364     public final synchronized void forget(Xid JavaDoc xid) throws XAException JavaDoc {
365         
366         checkXAActive();
367         
368         // ensure immtable and correct equals method.
369
XAXactId xid_im = new XAXactId(xid);
370         
371         XATransactionState tranState = getTransactionState(xid_im);
372         if (tranState == null) {
373             XAResourceManager rm = ra.getXAResourceManager();
374             
375             ContextManager inDoubtCM = rm.find(xid);
376             
377             // RM also does not know about this xid.
378
if (inDoubtCM == null)
379                 throw new XAException JavaDoc(XAException.XAER_NOTA);
380             
381             ContextService csf = ContextService.getFactory();
382             
383             csf.setCurrentContextManager(inDoubtCM);
384             try {
385                 rm.forget(inDoubtCM, xid_im);
386                 
387                 // close the connection/transaction since it can never be used again.
388
inDoubtCM.cleanupOnError(StandardException.closeException());
389                 return;
390             } catch (StandardException se) {
391                 // The rm threw an exception, clean it up in the approprate
392
// context. There is no transactionResource to handle the
393
// exception for us.
394
inDoubtCM.cleanupOnError(se);
395                 throw wrapInXAException(se);
396             } finally {
397                 csf.resetCurrentContextManager(inDoubtCM);
398             }
399             
400         }
401         
402         throw new XAException JavaDoc(tranState.isPrepared
403             ? XAException.XAER_NOTA
404             : XAException.XAER_PROTO);
405     }
406
407     /**
408      * Inform the resource manager to roll back work done on behalf of a
409      * transaction branch
410      *
411      * @param xid A global transaction identifier
412      * @exception XAException - An error has occurred
413      */

414     public final synchronized void rollback(Xid JavaDoc xid) throws XAException JavaDoc {
415         checkXAActive();
416         
417         // ensure immtable and correct equals method.
418
XAXactId xid_im = new XAXactId(xid);
419         
420         XATransactionState tranState = getTransactionState(xid_im);
421         
422         if (tranState == null) {
423             XAResourceManager rm = ra.getXAResourceManager();
424             
425             ContextManager inDoubtCM = rm.find(xid);
426             
427             // RM also does not know about this xid.
428
if (inDoubtCM == null)
429                 throw new XAException JavaDoc(XAException.XAER_NOTA);
430             
431             ContextService csf = ContextService.getFactory();
432             
433             csf.setCurrentContextManager(inDoubtCM);
434             try {
435                 rm.rollback(inDoubtCM, xid_im);
436                 
437                 // close the connection/transaction since it can never be used again.
438
inDoubtCM.cleanupOnError(StandardException.closeException());
439                 return;
440             } catch (StandardException se) {
441                 // The rm threw an exception, clean it up in the approprate
442
// context. There is no transactionResource to handle the
443
// exception for us.
444
inDoubtCM.cleanupOnError(se);
445                 throw wrapInXAException(se);
446             } finally {
447                 csf.resetCurrentContextManager(inDoubtCM);
448             }
449             
450         }
451         
452         synchronized (tranState) {
453             
454             // Check the transaction is no associated with
455
// any XAResource.
456
switch (tranState.associationState) {
457                 case XATransactionState.T0_NOT_ASSOCIATED:
458                 case XATransactionState.TRO_FAIL:
459                     break;
460                     
461                 default:
462                     throw new XAException JavaDoc(XAException.XAER_PROTO);
463             }
464             
465             if (tranState.suspendedList != null
466                     && tranState.suspendedList.size() != 0)
467                 throw new XAException JavaDoc(XAException.XAER_PROTO);
468             
469             checkUserCredentials(tranState.creatingResource);
470             
471             try {
472                 
473                 tranState.conn.xa_rollback();
474             } catch (SQLException JavaDoc sqle) {
475                 throw wrapInXAException(sqle);
476             } finally {
477                 returnConnectionToResource(tranState, xid_im);
478             }
479         }
480     }
481
482
483     /**
484      * Set the current transaction timeout value for this XAResource
485      * instance. Once set, this timeout value is effective until
486      * setTransactionTimeout is invoked again with a different value. To reset
487      * the timeout value to the default value used by the resource manager,
488      * set the value to zero. If the timeout operation is performed
489      * successfully, the method returns true; otherwise false. If a resource
490      * manager does not support transaction timeout value to be set
491      * explicitly, this method returns false.
492      *
493      * @param seconds the transaction timeout value in seconds.
494      * @return true if transaction timeout value is set successfully;
495      * otherwise false.
496      *
497      * @exception XAException - An error has occurred. Possible exception
498      * values are XAER_RMERR, XAER_RMFAIL, or XAER_INVAL.
499      */

500     public boolean setTransactionTimeout(int seconds) {
501         return false;
502     }
503
504     /**
505      * Start work on behalf of a transaction branch specified in xid If TMJOIN
506      * is specified, the start is for joining a transaction previously seen by
507      * the resource manager. If TMRESUME is specified, the start is to resume
508      * a suspended transaction specified in the parameter xid. If neither
509      * TMJOIN nor TMRESUME is specified and the transaction specified by xid
510      * has previously been seen by the resource manager, the resource manager
511      * throws the XAException exception with XAER_DUPID error code.
512      *
513      * @param xid A global transaction identifier to be associated with the
514      * resource
515      * @param flags One of TMNOFLAGS, TMJOIN, or TMRESUME
516      *
517      * @exception XAException An error has occurred. Possible exceptions are
518      * XA_RB*, XAER_RMERR, XAER_RMFAIL, XAER_DUPID, XAER_OUTSIDE, XAER_NOTA,
519      * XAER_INVAL, or XAER_PROTO.
520      */

521     public final synchronized void start(Xid JavaDoc xid,
522                                         int flags) throws XAException JavaDoc {
523         checkXAActive();
524         
525         // JDBC 3.0 section 12.3 - One transaction associated with a XAConnection
526
if (currentXid != null)
527             throw new XAException JavaDoc(XAException.XAER_PROTO);
528         
529         // ensure immtable and correct equals method.
530
XAXactId xid_im = new XAXactId(xid);
531         
532         XATransactionState tranState = getTransactionState(xid_im);
533         
534         switch (flags) {
535             case XAResource.TMNOFLAGS:
536                 if (tranState != null)
537                     throw new XAException JavaDoc(XAException.XAER_DUPID);
538                 
539                 try {
540                     
541                     if (con.realConnection == null) {
542                         con.openRealConnection();
543                         
544                         if (con.currentConnectionHandle != null) {
545                             
546                             // since this is a new connection, set its complete
547
// state according to the application's Connection
548
// handle view of the world.
549
con.currentConnectionHandle.setState(true);
550                             con.realConnection.setApplicationConnection
551                                     (con.currentConnectionHandle);
552                         }
553                         
554                     } else {
555                         
556                         // XAResource.start() auto commits in DB2 when in
557
// auto commit mode.
558
if (con.currentConnectionHandle != null) {
559                             if (con.currentConnectionHandle.getAutoCommit())
560                                 con.currentConnectionHandle.rollback();
561                         }
562                         if (!con.realConnection.transactionIsIdle())
563                             throw new XAException JavaDoc(XAException.XAER_OUTSIDE);
564                         
565                         if (con.currentConnectionHandle != null) {
566                             // It is possible that the isolation level state
567
// in connection handle has gotten out of sync
568
// with the real isolation level. This can happen
569
// if SLQ instead of JDBC api has been used to set
570
// the isolation level. The code below will check
571
// if isolation was set using JDBC or SQL and if
572
// yes, then it will update the isolation state
573
// in BrokeredConnection with EmbedConnection's
574
// isolation level.
575
con.currentConnectionHandle.getIsolationUptoDate();
576                             // we have a current handle so we need to keep
577
// the connection state of the current connection.
578
con.currentConnectionHandle.setState(true);
579                             
580                             // At the local to global transition we need
581
// to discard and close any open held result
582
// sets, a rollback will do this.
583
con.realConnection.rollback();
584                         } else {
585                             con.resetRealConnection();
586                         }
587                         
588                     }
589                     
590                     // Global connections are always in auto commit false mode.
591
con.realConnection.setAutoCommit(false);
592                     
593                     // and holdability false (cannot hold cursors across
594
// XA transactions.
595
con.realConnection.setHoldability(
596                             JDBC30Translation.CLOSE_CURSORS_AT_COMMIT);
597                     
598                     con.realConnection.getLanguageConnection().
599                             getTransactionExecute().
600                             createXATransactionFromLocalTransaction(
601                                                 xid_im.getFormatId(),
602                                                 xid_im.getGlobalTransactionId(),
603                                                 xid_im.getBranchQualifier());
604                     
605                     
606                 } catch (StandardException se) {
607                     throw wrapInXAException(se);
608                 } catch (SQLException JavaDoc sqle) {
609                     throw wrapInXAException(sqle);
610                 }
611                 
612                 
613                 if (!ra.addConnection(xid_im,
614                         new XATransactionState(
615                         con.realConnection.getContextManager(),
616                         con.realConnection, this, xid_im)))
617                     throw new XAException JavaDoc(XAException.XAER_DUPID);
618                 
619                 break;
620                 
621             case XAResource.TMRESUME:
622             case XAResource.TMJOIN:
623                 if (tranState == null)
624                     throw new XAException JavaDoc(XAException.XAER_NOTA);
625                 
626                 tranState.start(this, flags);
627                 
628                 if (tranState.conn != con.realConnection) {
629                     
630                     if (con.realConnection != null) {
631                         
632                         if (!con.realConnection.transactionIsIdle())
633                             throw new XAException JavaDoc(XAException.XAER_OUTSIDE);
634                         
635                         // We need to get the isolation level up to date same
636
// way as it is done at start of a transaction. Before
637
// joining the transaction, it is possible that the
638
// isolation level was updated using SQL. We need to
639
// get this state and store in the connection handle so
640
// that we can restore the isolation when we are in the
641
// local mode.
642
try {
643                             if (con.currentConnectionHandle != null) {
644                                 con.currentConnectionHandle.getIsolationUptoDate();
645                             }
646                         } catch (SQLException JavaDoc sqle) {
647                             throw wrapInXAException(sqle);
648                         }
649                         
650                         closeUnusedConnection(con.realConnection);
651                     }
652                     con.realConnection = tranState.conn;
653                     
654                     if (con.currentConnectionHandle != null) {
655                         
656                         try {
657                             // only reset the non-transaction specific
658
// Connection state.
659
con.currentConnectionHandle.setState(false);
660                             con.realConnection.setApplicationConnection(
661                                     con.currentConnectionHandle);
662                         } catch (SQLException JavaDoc sqle) {
663                             throw wrapInXAException(sqle);
664                         }
665                     }
666                     
667                 }
668                 
669                 
670                 break;
671                 
672             default:
673                 throw new XAException JavaDoc(XAException.XAER_INVAL);
674         }
675         
676         currentXid = xid_im;
677     }
678     
679     /**
680      * Resturns currently active xid
681      * @return Xid
682      */

683     Xid JavaDoc getCurrentXid () {
684         return currentXid;
685     }
686
687     /**
688      * Returns the XATransactionState of the the transaction
689      * @param xid_im
690      * @return XATransactionState
691      */

692     private XATransactionState getTransactionState(XAXactId xid_im) {
693         return (XATransactionState) ra.findConnection(xid_im);
694     }
695
696     /**
697      * Compares the user name and password of the XAResource with
698      * user name and password of this and throws XAException if there is
699      * a mismatch
700      * @param original EmbedXAResource
701      */

702     private void checkUserCredentials(EmbedXAResource original)
703                                                         throws XAException JavaDoc {
704         if (original == this)
705             return;
706         if (original.con.getPassword().equals(con.getPassword()) &&
707                 (original.con.getUsername().equals(con.getUsername())))
708             return;
709         throw new XAException JavaDoc(XAException.XA_RBINTEGRITY);
710     }
711     
712     /**
713      * Checks if currently associated connection is active
714      * throws exception if not
715      */

716     private void checkXAActive() throws XAException JavaDoc {
717         try {
718             con.checkActive();
719         } catch (SQLException JavaDoc sqle) {
720             throw wrapInXAException(sqle);
721         }
722     }
723     
724     /**
725      * Map a SQL exception to appropriate XAException.
726      * Return the mapped XAException.
727      */

728     private static XAException JavaDoc wrapInXAException(SQLException JavaDoc se) {
729         // Map interesting exceptions to XAException
730
String JavaDoc sqlstate = se.getSQLState();
731         String JavaDoc message = se.getMessage();
732         
733         XAException JavaDoc xae;
734         
735         if (sqlstate == null) {
736             // no idea what was wrong, throw non-descript error.
737
if (message != null)
738                 xae = new XAException JavaDoc(message);
739             else
740                 xae = new XAException JavaDoc(XAException.XAER_RMERR);
741         } else if (sqlstate.equals(StandardException.getSQLStateFromIdentifier(
742                             SQLState.STORE_XA_XAER_DUPID)))
743             xae = new XAException JavaDoc(XAException.XAER_DUPID);
744         else if (sqlstate.equals(StandardException.getSQLStateFromIdentifier(
745                                 SQLState.STORE_XA_PROTOCOL_VIOLATION)))
746             xae = new XAException JavaDoc(XAException.XA_RBPROTO);
747         else if (sqlstate.equals(SQLState.DEADLOCK))
748             xae = new XAException JavaDoc(XAException.XA_RBDEADLOCK);
749         else if (sqlstate.equals(SQLState.LOCK_TIMEOUT))
750             xae = new XAException JavaDoc(XAException.XA_RBTIMEOUT);
751         else if (message != null)
752             xae = new XAException JavaDoc(message);
753         else
754             xae = new XAException JavaDoc(XAException.XAER_RMERR);
755         
756         if (JVMInfo.JDK_ID >= JVMInfo.J2SE_14)
757             xae.initCause(se);
758         return xae;
759     }
760     
761     /**
762      * Map a Standard exception to appropriate XAException.
763      * Return the mapped XAException.
764      */

765     private static XAException JavaDoc wrapInXAException(StandardException se) {
766         return wrapInXAException(
767                 TransactionResourceImpl.wrapInSQLException(
768                 (SQLException JavaDoc) null, se));
769     }
770     
771     /**
772      * Return an underlying connection object back to its XAResource
773      * if possible. If not close the connection.
774      * @param tranState
775      * @param xid_im
776      */

777     private void returnConnectionToResource(XATransactionState tranState,
778                                                             XAXactId xid_im) {
779         
780         removeXATransaction(xid_im);
781         synchronized (tranState) {
782             // global transaction is over.
783
tranState.associationState = XATransactionState.TC_COMPLETED;
784             tranState.notifyAll();
785             
786             EmbedConnection conn = tranState.conn;
787             
788             // already set in its own resource
789
// or can it be returned to its original resource?
790
if ((tranState.creatingResource.con.realConnection == conn) ||
791                     (tranState.creatingResource.con.realConnection == null)) {
792                 
793                 tranState.creatingResource.con.realConnection = conn;
794                 
795                 BrokeredConnection handle =
796                         tranState.creatingResource.con.currentConnectionHandle;
797                 
798                 conn.setApplicationConnection(handle);
799                 
800                 if (handle != null) {
801                     try {
802                         handle.setState(true);
803                     } catch (SQLException JavaDoc sqle) {
804                         
805                         // couldn't reset the connection
806
closeUnusedConnection(tranState.conn);
807                         tranState.creatingResource.con.realConnection = null;
808                     }
809                 }
810                 return;
811             }
812         }
813         
814         // nowhere to place it, close it.
815
closeUnusedConnection(tranState.conn);
816     }
817
818
819     /**
820      * Close an underlying connection object when there is
821      * no active XAResource to hand it to.
822      * @param conn
823      */

824     private static void closeUnusedConnection(EmbedConnection conn) {
825         if (conn != null) {
826             try {
827                 conn.close();
828             } catch (SQLException JavaDoc sqle) {
829                 
830             }
831         }
832     }
833
834     /**
835      * Removes the xid from currently active transactions
836      * @param xid_im
837      */

838     private void removeXATransaction(XAXactId xid_im) {
839         XATransactionState tranState =
840                 (XATransactionState) ra.removeConnection(xid_im);
841         if (tranState != null)
842             tranState.popMe();
843     }
844     
845 }
846
Popular Tags