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