1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.geronimo.connector;
18
19 import java.util.HashMap;
20 import java.util.Map;
21 import java.util.concurrent.ConcurrentHashMap;
22
23 import javax.transaction.Status;
24 import javax.transaction.Synchronization;
25 import javax.transaction.SystemException;
26 import javax.transaction.Transaction;
27
28 import org.apache.geronimo.connector.outbound.TransactionCachingInterceptor;
29 import org.apache.geronimo.transaction.manager.TransactionImpl;
30
31
32
33
34 public class ConnectorTransactionContext {
35 private static final ConcurrentHashMap<Transaction, ConnectorTransactionContext> DATA_INDEX = new ConcurrentHashMap<Transaction, ConnectorTransactionContext>();
36
37 public static ConnectorTransactionContext get(Transaction transaction) {
38 if (transaction == null) {
39 throw new NullPointerException("transaction is null");
40 }
41
42 ConnectorTransactionContext ctx = DATA_INDEX.get(transaction);
43 if (ctx == null) {
44 ctx = new ConnectorTransactionContext();
45
46 try {
47 int status = transaction.getStatus();
48 if (status != Status.STATUS_COMMITTED && status != Status.STATUS_ROLLEDBACK && status != Status.STATUS_UNKNOWN) {
49 ((TransactionImpl)transaction).registerInterposedSynchronization(new ConnectorSynchronization(ctx, transaction));
50
51
52
53
54 DATA_INDEX.putIfAbsent(transaction, ctx);
55 }
56
57
58 } catch (SystemException e) {
59 throw new RuntimeException("Unable to register ejb transaction synchronization callback", e);
60 }
61
62 }
63 return ctx;
64 }
65
66 public static TransactionCachingInterceptor.ManagedConnectionInfos get(Transaction transaction, ConnectionReleaser key) {
67 ConnectorTransactionContext ctx = get(transaction);
68 TransactionCachingInterceptor.ManagedConnectionInfos infos = ctx.getManagedConnectionInfo(key);
69 if (infos == null) {
70 infos = new TransactionCachingInterceptor.ManagedConnectionInfos();
71 ctx.setManagedConnectionInfo(key, infos);
72 }
73 return infos;
74 }
75
76 private static void remove(Transaction transaction) {
77 DATA_INDEX.remove(transaction);
78 }
79
80 private Map<ConnectionReleaser, TransactionCachingInterceptor.ManagedConnectionInfos> managedConnections;
81
82 private synchronized TransactionCachingInterceptor.ManagedConnectionInfos getManagedConnectionInfo(ConnectionReleaser key) {
83 if (managedConnections == null) {
84 return null;
85 }
86 return managedConnections.get(key);
87 }
88
89 private synchronized void setManagedConnectionInfo(ConnectionReleaser key, TransactionCachingInterceptor.ManagedConnectionInfos info) {
90 if (managedConnections == null) {
91 managedConnections = new HashMap<ConnectionReleaser, TransactionCachingInterceptor.ManagedConnectionInfos>();
92 }
93 managedConnections.put(key, info);
94 }
95
96 private static class ConnectorSynchronization implements Synchronization {
97 private final ConnectorTransactionContext ctx;
98 private final Transaction transaction;
99
100 public ConnectorSynchronization(ConnectorTransactionContext ctx, Transaction transaction) {
101 this.ctx = ctx;
102 this.transaction = transaction;
103 }
104
105 public void beforeCompletion() {
106 }
107
108 public void afterCompletion(int status) {
109 try {
110 synchronized (ctx) {
111 if (ctx.managedConnections != null) {
112 for (Map.Entry<ConnectionReleaser, TransactionCachingInterceptor.ManagedConnectionInfos> entry : ctx.managedConnections.entrySet()) {
113 ConnectionReleaser key = entry.getKey();
114 key.afterCompletion(entry.getValue());
115 }
116
117
118 ctx.managedConnections.clear();
119 }
120 }
121 } finally {
122 remove(transaction);
123 }
124 }
125 }
126 }