1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53 package org.objectweb.jotm;
54
55 import java.rmi.NoSuchObjectException;
56 import java.rmi.RemoteException;
57 import java.util.ArrayList;
58 import java.util.Collections;
59 import java.util.Date;
60 import java.util.HashMap;
61 import java.util.List;
62 import java.util.Map;
63
64 import javax.rmi.PortableRemoteObject;
65 import javax.transaction.HeuristicMixedException;
66 import javax.transaction.HeuristicRollbackException;
67 import javax.transaction.RollbackException;
68 import javax.transaction.Status;
69 import javax.transaction.Synchronization;
70 import javax.transaction.SystemException;
71 import javax.transaction.Transaction;
72 import javax.transaction.TransactionRolledbackException;
73 import javax.transaction.xa.XAException;
74 import javax.transaction.xa.XAResource;
75
76
77
78
79
80
81
82
83 public class TransactionImpl implements Transaction, TimerEventListener {
84
85
86
87
88 private SubCoordinator subcoord = null;
89 private TransactionContext myCtx = null;
90 private Xid myXid = null;
91 private boolean genXidhashcode = false;
92 private boolean genXidtostring = false;
93 private int myXidhashcode = 0;
94 private String myXidtostring = null;
95 private Date txDate = null;
96 private TimerEvent timer = null;
97 private RecoveryCoordinator recoveryCoord = null;
98
99 private List<XAResource> enlistedXARes = Collections.synchronizedList(new ArrayList<XAResource>());
100
101 private List<XAResource> delistedXARes = null;
102
103
104
105
106
107 private boolean propagateCtx = true;
108 private List<javax.transaction.xa.Xid> enlistedJavaxXid = Collections
109 .synchronizedList(new ArrayList<javax.transaction.xa.Xid>());
110 private Map<Object, Object> userResourceMap = null;
111
112
113
114
115 private int localstatus = Status.STATUS_ACTIVE;
116
117 private boolean toremove = false;
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133 public TransactionImpl(Xid xid, int timeout) throws SystemException {
134 if (TraceTm.jta.isDebugEnabled()) {
135 TraceTm.jta.debug("xid= " + xid);
136 TraceTm.jta.debug("timeout= " + timeout);
137 }
138
139
140 myXid = xid;
141 myCtx = new InternalTransactionContext(timeout, null, xid);
142 }
143
144
145
146
147
148
149
150
151 public TransactionImpl(TransactionContext pctx) {
152
153 if (pctx == null) {
154 TraceTm.jotm.error("TransactionImpl: null PropagationContext");
155 return;
156 }
157 myCtx = pctx;
158 myXid = pctx.getXid();
159
160
161
162
163 try {
164 makeSubCoord(true, true);
165 } catch (RollbackException e) {
166 toremove = true;
167 TraceTm.jotm.debug("already rolled back");
168 localstatus = Status.STATUS_ROLLEDBACK;
169 } catch (SystemException e) {
170 toremove = true;
171 TraceTm.jotm.error("cannot make subcoordinator");
172 localstatus = Status.STATUS_ROLLEDBACK;
173 }
174 }
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190 public synchronized void putUserResource(Object key, Object value) {
191
192 if (userResourceMap == null) {
193 userResourceMap = Collections.synchronizedMap(new HashMap<Object, Object>());
194 }
195 userResourceMap.put(key, value);
196 }
197
198
199
200
201
202
203
204
205
206
207 public synchronized Object getUserResource(Object key) {
208
209 if (userResourceMap == null) {
210 return null;
211 }
212
213 return userResourceMap.get(key);
214 }
215
216
217
218
219
220
221
222
223
224 public void registerInterposedSynchronization(Synchronization sync) throws IllegalStateException {
225 try {
226 registerSynchronization(sync);
227 } catch (Exception e) {
228 throw new IllegalStateException();
229 }
230 }
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260 @Override
261 public void commit() throws RollbackException, HeuristicMixedException, HeuristicRollbackException,
262 SecurityException, SystemException {
263
264 if (TraceTm.jta.isDebugEnabled()) {
265 TraceTm.jta.debug("TransactionImpl.commit (tx= " + this + ")");
266 }
267
268
269 Terminator term = myCtx.getTerminator();
270
271 if (term != null) {
272
273 try {
274 propagateCtx = false;
275 term.commit(true);
276 } catch (TransactionRolledbackException e) {
277 Current.getCurrent().forgetTx(getXid());
278 if (TraceTm.jta.isDebugEnabled()) {
279 TraceTm.jta.debug("Commit distributed transaction -> rolled back!");
280 }
281 localstatus = Status.STATUS_ROLLEDBACK;
282 RollbackException ex = new RollbackException();
283 ex.initCause(e);
284 throw ex;
285 } catch (RemoteException e) {
286
287 if (TraceTm.jta.isWarnEnabled()) {
288 TraceTm.jta.warn("got a RemoteException", e);
289 }
290
291 if (e.detail instanceof TransactionRolledbackException) {
292 Current.getCurrent().forgetTx(getXid());
293 if (TraceTm.jta.isDebugEnabled()) {
294 TraceTm.jta.debug("Commit distributed transaction -> rolled back!");
295 }
296 localstatus = Status.STATUS_ROLLEDBACK;
297 RollbackException ex = new RollbackException();
298 ex.initCause(e.detail);
299 throw ex;
300 }
301
302 if (e.detail instanceof HeuristicMixed) {
303 TraceTm.jotm.info("Commit distributed transaction -> Heuristic mixed!");
304 throw new HeuristicMixedException();
305 } else {
306 SystemException ex = new SystemException("Unexpected RemoteException on commit:"
307 + e.detail.getMessage());
308 ex.initCause(e.detail);
309 throw ex;
310 }
311 } catch (Exception e) {
312 TraceTm.jotm.error("Unexpected Exception on commit:", e);
313 SystemException ex = new SystemException("Unexpected Exception on commit");
314 ex.initCause(e);
315 throw ex;
316 } finally {
317 propagateCtx = true;
318 if (subcoord == null) {
319
320 unsetTimer();
321 }
322 }
323 Current.getCurrent().forgetTx(getXid());
324 localstatus = Status.STATUS_COMMITTED;
325 return;
326 }
327
328
329
330
331 if (subcoord != null) {
332 try {
333 subcoord.commit_one_phase();
334 } catch (TransactionRolledbackException e) {
335 if (TraceTm.jta.isDebugEnabled()) {
336 TraceTm.jta.debug("Commit local transaction -> rolled back!");
337 }
338 Current.getCurrent().forgetTx(getXid());
339 localstatus = Status.STATUS_ROLLEDBACK;
340 RollbackException ex = new RollbackException();
341 ex.initCause(e);
342 throw ex;
343 } catch (RemoteException e) {
344 TraceTm.jotm.error("Unexpected Exception on commit_one_phase:", e);
345 Current.getCurrent().forgetTx(getXid());
346 localstatus = Status.STATUS_UNKNOWN;
347 SystemException ex = new SystemException("Unexpected Exception on commit_one_phase");
348 ex.initCause(e);
349 throw ex;
350 }
351 } else {
352
353 unsetTimer();
354 Current.getCurrent().forgetTx(getXid());
355 localstatus = Status.STATUS_COMMITTED;
356 }
357 }
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376 @Override
377 public boolean delistResource(XAResource xares, int flag) throws IllegalStateException, SystemException {
378
379 if (TraceTm.jta.isDebugEnabled()) {
380 TraceTm.jta.debug("TransactionImpl.delistResource");
381 TraceTm.jta.debug("xares= " + xares + ", flag= " + flag);
382 }
383
384 if (enlistedXARes == null) {
385 if (TraceTm.jta.isDebugEnabled()) {
386 TraceTm.jta.error("No XA resources enlisted by JOTM");
387 }
388 return false;
389 }
390
391
392
393 if (!enlistedXARes.contains(xares)) {
394 if (TraceTm.jta.isDebugEnabled()) {
395 TraceTm.jta.error("XAResouce " + xares + " not enlisted by JOTM");
396 }
397 return false;
398 }
399
400 javax.transaction.xa.Xid javaxxid = subcoord.getJavaxXid(subcoord.getXaresIndex(xares));
401
402 if (!enlistedJavaxXid.contains(javaxxid)) {
403 if (TraceTm.jta.isDebugEnabled()) {
404 TraceTm.jta.error("XAResouce " + xares + " not enlisted by JOTM");
405 }
406 return false;
407 }
408
409 int javaxxidindex = enlistedJavaxXid.indexOf(javaxxid);
410 javax.transaction.xa.Xid myjavaxxid = enlistedJavaxXid.get(javaxxidindex);
411
412 if (TraceTm.jta.isDebugEnabled()) {
413 TraceTm.jta.debug("delisted with resource= " + xares);
414 TraceTm.jta.debug("end myjavaxxid= " + myjavaxxid);
415 }
416
417
418 try {
419 xares.end(myjavaxxid, flag);
420 } catch (XAException e) {
421 String error = "Cannot send XA end:" + e + " (error code = " + e.errorCode + ") --" + e.getMessage();
422 TraceTm.jotm.error(error);
423 if (TraceTm.jta.isDebugEnabled()) {
424 TraceTm.jotm.debug("xares.end= " + xares);
425 }
426 throw new SystemException(error);
427 }
428
429 if (TraceTm.jta.isDebugEnabled()) {
430 TraceTm.jta.debug("enlistedXAres.remove xares= " + xares);
431 }
432
433
434 enlistedXARes.remove(xares);
435 enlistedJavaxXid.remove(javaxxid);
436 return true;
437 }
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458 @Override
459 public boolean enlistResource(XAResource xares) throws RollbackException, IllegalStateException, SystemException {
460
461 if (TraceTm.jta.isDebugEnabled()) {
462 TraceTm.jta.debug("TransactionImpl.enlistResource");
463 TraceTm.jta.debug("xares= " + xares);
464 }
465
466
467 if (xares == null) {
468 TraceTm.jotm.error("enlistResource: null argument");
469 throw new SystemException("enlistResource: null argument");
470 }
471
472 if (myCtx == null) {
473 throw new SystemException("enlistResource: no Transactional Context");
474 }
475
476
477 if (subcoord == null) {
478 makeSubCoord(false, true);
479 if (subcoord == null) {
480 TraceTm.jotm.error("enlistResource: could not create subcoordinator");
481 throw new SystemException("enlistResource: could not create subcoordinator");
482 }
483 }
484
485 boolean found;
486
487 try {
488 found = subcoord.addResource(xares);
489 } catch (IllegalStateException e) {
490 throw new IllegalStateException("enlistResource: could not addResource " + xares);
491 }
492
493
494
495
496
497
498 int flag = found ? XAResource.TMJOIN : XAResource.TMNOFLAGS;
499
500 if ((delistedXARes != null) && delistedXARes.contains(xares)) {
501 flag = XAResource.TMRESUME;
502 }
503
504 Xid resXid = new XidImpl(getXid(), subcoord.getXaresIndex(xares));
505 javax.transaction.xa.Xid javaxxid = new JavaXidImpl(resXid);
506
507 if (TraceTm.jta.isDebugEnabled()) {
508 TraceTm.jta.debug("enlisted with resource= " + xares);
509 TraceTm.jta.debug("start javaxxid= " + javaxxid);
510 }
511
512 if (!found) {
513 subcoord.addJavaxXid(javaxxid);
514 }
515
516 try {
517 xares.start(javaxxid, flag);
518 } catch (XAException e) {
519 String error = "Cannot send XA(" + xares + ") start:" + e + " (error code = " + e.errorCode + ") --"
520 + e.getMessage();
521 TraceTm.jotm.error(error);
522 throw new SystemException(error);
523 }
524
525 if (!enlistedXARes.contains(xares)) {
526
527 enlistedXARes.add(xares);
528 enlistedJavaxXid.add(javaxxid);
529 }
530
531 int status = this.getStatus();
532
533 switch (status) {
534 case Status.STATUS_ACTIVE:
535 case Status.STATUS_PREPARING:
536 break;
537 case Status.STATUS_PREPARED:
538 throw new IllegalStateException("Transaction already prepared.");
539 case Status.STATUS_COMMITTING:
540
541 break;
542 case Status.STATUS_COMMITTED:
543 throw new IllegalStateException("Transaction already committed.");
544 case Status.STATUS_MARKED_ROLLBACK:
545 throw new RollbackException("Transaction already marked for rollback");
546 case Status.STATUS_ROLLING_BACK:
547 throw new RollbackException("Transaction already started rolling back.");
548 case Status.STATUS_ROLLEDBACK:
549 throw new RollbackException("Transaction already rolled back.");
550 case Status.STATUS_NO_TRANSACTION:
551 throw new IllegalStateException("No current transaction.");
552 case Status.STATUS_UNKNOWN:
553 throw new IllegalStateException("Unknown transaction status");
554 default:
555 throw new IllegalStateException("Illegal transaction status: " + status);
556 }
557
558 return true;
559 }
560
561
562
563
564 public void doDetach(int flag) throws SystemException {
565 if (TraceTm.jta.isDebugEnabled()) {
566 TraceTm.jta.debug("TransactionImpl.doDetach flag= " + XAResourceHelper.getFlagName(flag));
567 TraceTm.jta.debug("number of enlisted= " + enlistedXARes.size());
568 }
569
570
571
572 delistedXARes = new ArrayList<XAResource>(enlistedXARes);
573 for (XAResource xar : delistedXARes) {
574 delistResource(xar, flag);
575 }
576 }
577
578
579
580
581 public void doAttach(int flag) throws SystemException, RollbackException {
582 if (TraceTm.jta.isDebugEnabled()) {
583 TraceTm.jta.debug("TransactionImpl.doAttach flag= " + XAResourceHelper.getFlagName(flag));
584 TraceTm.jta.debug("number of enlisted= " + enlistedXARes.size());
585 }
586
587 boolean rollbackonenlist = false;
588 RollbackException mye = null;
589
590
591
592 if (flag == XAResource.TMRESUME) {
593
594
595 for (int i = 0; (delistedXARes != null) && (i < delistedXARes.size()); i++) {
596
597 try {
598 enlistResource(delistedXARes.get(i));
599 } catch (RollbackException e) {
600 if (!rollbackonenlist) {
601 rollbackonenlist = true;
602 mye = e;
603 }
604 }
605 }
606 }
607
608 delistedXARes = null;
609
610 if (rollbackonenlist) {
611 throw new RollbackException(mye.getMessage());
612 }
613 }
614
615
616
617
618 public List getEnlistedXAResource() {
619 if (TraceTm.jta.isDebugEnabled()) {
620 TraceTm.jta.debug("getEnlistedXAResource size= " + enlistedXARes.size());
621 }
622 return new ArrayList<XAResource>(enlistedXARes);
623 }
624
625
626
627
628
629
630
631
632
633
634
635 @Override
636 public int getStatus() throws SystemException {
637 if (TraceTm.jta.isDebugEnabled()) {
638 TraceTm.jta.debug("TransactionImpl.getStatus()");
639 }
640
641
642 Coordinator coord = myCtx.getCoordinator();
643
644 if (coord != null) {
645
646 int ret;
647 try {
648 propagateCtx = false;
649 ret = coord.get_status();
650 } catch (Exception e) {
651 TraceTm.jotm.error("cannot reach JTM:", e);
652 return Status.STATUS_NO_TRANSACTION;
653 } finally {
654 propagateCtx = true;
655 }
656 return ret;
657 }
658
659
660
661 if (subcoord != null) {
662 return subcoord.getStatus();
663 } else {
664 return localstatus;
665 }
666 }
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686 @Override
687 public void registerSynchronization(Synchronization sync) throws RollbackException, IllegalStateException,
688 SystemException {
689 if (TraceTm.jta.isDebugEnabled()) {
690 TraceTm.jta.debug("Synchro=" + sync);
691 }
692
693
694 if (subcoord == null) {
695 makeSubCoord(false, true);
696 }
697
698
699
700 subcoord.addSynchronization(sync);
701 }
702
703
704
705
706
707
708
709
710
711
712
713
714 @Override
715 public void rollback() throws IllegalStateException, SystemException {
716 if (TraceTm.jta.isDebugEnabled()) {
717 TraceTm.jta.debug("TransactionImpl.rollback(tx= " + this + ")");
718 }
719
720
721 Terminator term = myCtx.getTerminator();
722
723 if (term != null) {
724
725 try {
726 propagateCtx = false;
727 term.rollback();
728 } catch (java.rmi.ServerException e) {
729
730 throw new IllegalStateException("Exception on rollback:" + e);
731 } catch (Exception e) {
732 Current.getCurrent().forgetTx(getXid());
733 localstatus = Status.STATUS_UNKNOWN;
734
735 clearUserResourceMap();
736
737 throw new SystemException("Unexpected Exception on rollback");
738 } finally {
739 propagateCtx = true;
740 }
741
742 if (subcoord == null) {
743
744 unsetTimer();
745 }
746
747
748 Current.getCurrent().forgetTx(getXid());
749 localstatus = Status.STATUS_ROLLEDBACK;
750
751 clearUserResourceMap();
752
753 return;
754 }
755
756
757
758
759 if (subcoord != null) {
760 try {
761 subcoord.rollback();
762 } catch (RemoteException e) {
763 Current.getCurrent().forgetTx(getXid());
764 localstatus = Status.STATUS_UNKNOWN;
765
766 clearUserResourceMap();
767
768 throw new IllegalStateException("Exception on rollback:" + e);
769 }
770
771 } else {
772
773 unsetTimer();
774 }
775
776
777 Current.getCurrent().forgetTx(getXid());
778 localstatus = Status.STATUS_ROLLEDBACK;
779
780 clearUserResourceMap();
781 }
782
783
784
785
786
787
788
789
790
791
792
793
794
795 public int prepare() throws IllegalStateException, SystemException {
796 if (TraceTm.jta.isDebugEnabled()) {
797 TraceTm.jta.debug("TransactionImpl.prepare(tx= " + this + ")");
798 }
799
800 int ret = 0;
801 if (subcoord != null) {
802 try {
803 ret = subcoord.prepare();
804 } catch (RemoteException e) {
805 TraceTm.jotm.error("Unexpected Exception on prepare:", e);
806 throw new SystemException("Unexpected Exception on prepare");
807 }
808 }
809 return ret;
810 }
811
812
813
814
815
816
817
818
819
820
821
822
823 @Override
824 public void setRollbackOnly() throws IllegalStateException, SystemException {
825 if (TraceTm.jta.isDebugEnabled()) {
826 TraceTm.jta.debug("Tx=" + this);
827 }
828
829 Coordinator coord = myCtx.getCoordinator();
830
831 if (coord != null) {
832
833 try {
834 propagateCtx = false;
835 coord.rollback_only();
836 } catch (RemoteException e) {
837 TraceTm.jotm.error("Cannot perform coordinator rollback only", e);
838 } finally {
839 propagateCtx = true;
840 }
841 }
842
843
844
845 if (subcoord == null) {
846
847 try {
848 makeSubCoord(false, false);
849 } catch (RollbackException e) {
850 TraceTm.jotm.debug("already rolled back");
851 return;
852 }
853 }
854 subcoord.setRollbackOnly();
855 }
856
857
858
859
860
861
862
863
864
865 @Override
866 public void timeoutExpired(Object arg) {
867 if (TraceTm.jta.isDebugEnabled()) {
868 TraceTm.jta.debug("TransactionImpl.timeoutExpired");
869 }
870
871
872 Current.getCurrent().incrementExpiredCounter();
873
874
875
876 if (subcoord == null) {
877
878
879 Terminator term = myCtx.getTerminator();
880
881 if (term != null) {
882 if (TraceTm.jta.isDebugEnabled()) {
883 TraceTm.jta.debug("forget tx (tx=" + this + ")");
884 }
885 Current.getCurrent().forgetTx(getXid());
886 localstatus = Status.STATUS_ROLLEDBACK;
887 return;
888 }
889 try {
890 makeSubCoord(false, false);
891 } catch (RollbackException e) {
892 TraceTm.jotm.debug("already rolled back");
893 localstatus = Status.STATUS_ROLLEDBACK;
894 return;
895 } catch (SystemException e) {
896 TraceTm.jotm.error("cannot make subcoordinator");
897 localstatus = Status.STATUS_ROLLEDBACK;
898 return;
899 }
900 }
901
902
903
904 if (TraceTm.jta.isDebugEnabled()) {
905 TraceTm.jta.debug("set rollback only (tx=" + this + ")");
906 }
907
908 try {
909 subcoord.setRollbackOnly();
910 } catch (Exception e) {
911 TraceTm.jotm.error("cannot rollbackonly:" + e);
912 }
913 }
914
915
916
917
918
919
920
921
922 @Override
923 public boolean equals(Object obj2) {
924 if (obj2 instanceof TransactionImpl) {
925 TransactionImpl tx2 = (TransactionImpl) obj2;
926
927
928 if (tx2 == this) {
929 return true;
930 }
931
932
933 return getXid().equals(tx2.getXid());
934 } else {
935 return false;
936 }
937 }
938
939
940
941
942 @Override
943 public int hashCode() {
944 if (!genXidhashcode) {
945 genXidhashcode = true;
946 myXidhashcode = getXid().hashCode();
947 }
948
949 return myXidhashcode;
950 }
951
952
953
954
955
956
957
958
959 @Override
960 public String toString() {
961 if (!genXidtostring) {
962 genXidtostring = true;
963 myXidtostring = getXid().toString();
964 }
965 return myXidtostring;
966 }
967
968
969
970
971
972
973
974
975 public synchronized TransactionContext getPropagationContext(boolean hold) {
976 if (propagateCtx) {
977 return myCtx;
978 } else {
979 return null;
980 }
981 }
982
983
984
985
986
987
988
989 public void setTimer(TimerEvent timer) {
990 if (TraceTm.jta.isDebugEnabled()) {
991 TraceTm.jta.debug("set timer for tx (timer=" + timer + ", tx=" + this + ")");
992 }
993 this.timer = timer;
994 }
995
996
997
998
999 public void unsetTimer() {
1000 if (TraceTm.jta.isDebugEnabled()) {
1001 TraceTm.jta.debug("unset timer for tx (timer=" + timer + ", tx=" + this + ")");
1002 }
1003 if (timer != null) {
1004 timer.unset();
1005 timer = null;
1006 }
1007 }
1008
1009
1010
1011
1012
1013
1014
1015 public void setTxDate(Date date) {
1016 if (TraceTm.jta.isDebugEnabled()) {
1017 TraceTm.jta.debug("set date for tx (data=" + date + ", tx=" + this + ")");
1018 }
1019 txDate = (Date) date.clone();
1020 }
1021
1022
1023
1024
1025
1026
1027 public Date getTxDate() {
1028 if (TraceTm.jta.isDebugEnabled()) {
1029 TraceTm.jta.debug("get date for tx (date=" + txDate + ", tx=" + this + ")");
1030 }
1031 return (Date) txDate.clone();
1032 }
1033
1034
1035
1036
1037
1038
1039
1040 public synchronized void updatePropagationContext(TransactionContext pctx) {
1041 if (TraceTm.jta.isDebugEnabled()) {
1042 TraceTm.jta.debug("TransactionImpl.updatePropagationContext");
1043 }
1044
1045 Coordinator remoteCoord = pctx.getCoordinator();
1046
1047 if (remoteCoord == null && myCtx.getCoordinator() != null) {
1048 TraceTm.jotm.error("setPropagationContext: Bad Coordinator");
1049 TraceTm.jotm.error("remoteCoord = " + remoteCoord);
1050 TraceTm.jotm.error("myCtx.getCoordinator()= " + myCtx.getCoordinator());
1051 return;
1052 }
1053
1054
1055 if (remoteCoord != null && myCtx.getCoordinator() == null) {
1056 myCtx.setCoordinator(pctx.getCoordinator());
1057
1058 if (subcoord != null) {
1059
1060 TraceTm.jta.debug("register the subCoordinator as a Resource");
1061 try {
1062 propagateCtx = false;
1063 recoveryCoord = remoteCoord.register_resource(subcoord);
1064 } catch (RemoteException e) {
1065 TraceTm.jotm.warn("Cannot make interposition :" + e.getCause());
1066 return;
1067 } finally {
1068 propagateCtx = true;
1069 }
1070 }
1071 }
1072
1073 if (pctx.getTerminator() != null) {
1074 myCtx.setTerminator(pctx.getTerminator());
1075 }
1076 }
1077
1078
1079
1080
1081
1082
1083 public Xid getXid() {
1084 return myXid;
1085 }
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095 private void makeSubCoord(boolean interpose, boolean active) throws RollbackException, SystemException {
1096 if (TraceTm.jta.isDebugEnabled()) {
1097 TraceTm.jta.debug("make subcoordinator");
1098 }
1099
1100
1101 try {
1102 subcoord = new SubCoordinator(this, getXid());
1103 } catch (RemoteException e) {
1104
1105 TraceTm.jotm.error("new SubCoordinator raised exception: ", e);
1106 return;
1107 }
1108 if (!active) {
1109
1110
1111 return;
1112 }
1113
1114
1115
1116 Coordinator remoteCoord = myCtx.getCoordinator();
1117
1118
1119
1120 if (interpose && remoteCoord == null) {
1121 try {
1122 if (TraceTm.jta.isDebugEnabled()) {
1123 TraceTm.jta.debug("Creating a remote Control on JTM for a distributed transaction");
1124 }
1125 propagateCtx = false;
1126
1127
1128 Control coord = Current.getJTM().recreate(myCtx);
1129 remoteCoord = (Coordinator) javax.rmi.PortableRemoteObject.narrow(coord, Coordinator.class);
1130
1131 } catch (RemoteException e) {
1132 TraceTm.jotm.error("Cannot create distributed transaction:", e);
1133 cleanup();
1134 return;
1135 } finally {
1136 propagateCtx = true;
1137 }
1138
1139 myCtx.setCoordinator(remoteCoord);
1140
1141
1142
1143
1144 if (myCtx.getTerminator() == null) {
1145 myCtx.setTerminator((Terminator) remoteCoord);
1146 }
1147 }
1148
1149
1150
1151 if (remoteCoord != null && recoveryCoord == null) {
1152 try {
1153 propagateCtx = false;
1154 recoveryCoord = remoteCoord.register_resource(subcoord);
1155 } catch (RemoteException e) {
1156
1157
1158 cleanup();
1159 if (e.getCause() instanceof TransactionRolledbackException) {
1160 TraceTm.jotm.warn("Cannot Make Interposition: rolled back occured");
1161 throw new RollbackException("Cannot Make Interposition");
1162 } else {
1163 TraceTm.jotm.warn("Cannot make Interposition:" + e.getCause());
1164 throw new SystemException("Cannot Make Interposition");
1165 }
1166 } finally {
1167 propagateCtx = true;
1168 }
1169 }
1170
1171 Current.getCurrent().incrementBeginCounter();
1172 }
1173
1174 public boolean toRemove() {
1175 return toremove;
1176 }
1177
1178 public void cleanup() {
1179 if (subcoord != null) {
1180 TraceTm.jta.debug("unexport SubCoordinator");
1181 try {
1182 PortableRemoteObject.unexportObject(subcoord);
1183 } catch (NoSuchObjectException e) {
1184 TraceTm.jta.debug("Cannot unexport subcoord:" + e);
1185 }
1186 subcoord = null;
1187 }
1188 }
1189
1190
1191
1192
1193 private synchronized void clearUserResourceMap() {
1194
1195 if ((userResourceMap != null) && !(userResourceMap.isEmpty())) {
1196 userResourceMap.clear();
1197 userResourceMap = null;
1198 }
1199 }
1200
1201 }