1 /**
2 *
3 * Licensed to the Apache Software Foundation (ASF) under one or more
4 * contributor license agreements. See the NOTICE file distributed with
5 * this work for additional information regarding copyright ownership.
6 * The ASF licenses this file to You under the Apache License, Version 2.0
7 * (the "License"); you may not use this file except in compliance with
8 * the License. You may obtain a copy of the License at
9 *
10 * http://www.apache.org/licenses/LICENSE-2.0
11 *
12 * Unless required by applicable law or agreed to in writing, software
13 * distributed under the License is distributed on an "AS IS" BASIS,
14 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
15 * See the License for the specific language governing permissions and
16 * limitations under the License.
17 */
18 package org.apache.geronimo.connector;
19
20 import java.util.Map;
21 import java.util.HashMap;
22 import java.util.Iterator;
23
24 import javax.transaction.Transaction;
25 import javax.transaction.Synchronization;
26 import javax.transaction.RollbackException;
27 import javax.transaction.SystemException;
28
29 import edu.emory.mathcs.backport.java.util.concurrent.ConcurrentHashMap;
30 import org.apache.geronimo.connector.outbound.TransactionCachingInterceptor;
31
32 /**
33 * @version $Rev: 470597 $ $Date: 2006-11-02 15:30:55 -0800 (Thu, 02 Nov 2006) $
34 */
35 public class ConnectorTransactionContext {
36 private static final ConcurrentHashMap DATA_INDEX = new ConcurrentHashMap();
37
38 public static ConnectorTransactionContext get(Transaction transaction) {
39 if (transaction == null) {
40 throw new NullPointerException("transaction is null");
41 }
42
43 ConnectorTransactionContext ctx = (ConnectorTransactionContext) DATA_INDEX.get(transaction);
44 if (ctx == null) {
45 ctx = new ConnectorTransactionContext();
46
47 try {
48 transaction.registerSynchronization(new ConnectorSynchronization(ctx, transaction));
49 } catch (RollbackException e) {
50 throw (IllegalStateException) new IllegalStateException("Transaction is already rolled back").initCause(e);
51 } catch (SystemException e) {
52 throw new RuntimeException("Unable to register ejb transaction synchronization callback", e);
53 }
54
55
56
57
58
59 DATA_INDEX.putIfAbsent(transaction, ctx);
60 }
61 return ctx;
62 }
63
64 public static TransactionCachingInterceptor.ManagedConnectionInfos get(Transaction transaction, ConnectionReleaser key) {
65 ConnectorTransactionContext ctx = get(transaction);
66 TransactionCachingInterceptor.ManagedConnectionInfos infos = ctx.getManagedConnectionInfo(key);
67 if (infos == null) {
68 infos = new TransactionCachingInterceptor.ManagedConnectionInfos();
69 ctx.setManagedConnectionInfo(key, infos);
70 }
71 return infos;
72 }
73
74 private static void remove(Transaction transaction) {
75 DATA_INDEX.remove(transaction);
76 }
77
78 private Map managedConnections;
79
80 private synchronized TransactionCachingInterceptor.ManagedConnectionInfos getManagedConnectionInfo(ConnectionReleaser key) {
81 if (managedConnections == null) {
82 return null;
83 }
84 return (TransactionCachingInterceptor.ManagedConnectionInfos) managedConnections.get(key);
85 }
86
87 private synchronized void setManagedConnectionInfo(ConnectionReleaser key, TransactionCachingInterceptor.ManagedConnectionInfos info) {
88 if (managedConnections == null) {
89 managedConnections = new HashMap();
90 }
91 managedConnections.put(key, info);
92 }
93
94 private static class ConnectorSynchronization implements Synchronization {
95 private final ConnectorTransactionContext ctx;
96 private final Transaction transaction;
97
98 public ConnectorSynchronization(ConnectorTransactionContext ctx, Transaction transaction) {
99 this.ctx = ctx;
100 this.transaction = transaction;
101 }
102
103 public void beforeCompletion() {
104 }
105
106 public void afterCompletion(int status) {
107 try {
108 synchronized (ctx) {
109 if (ctx.managedConnections != null) {
110 for (Iterator entries = ctx.managedConnections.entrySet().iterator(); entries.hasNext();) {
111 Map.Entry entry = (Map.Entry) entries.next();
112 ConnectionReleaser key = (ConnectionReleaser) entry.getKey();
113 key.afterCompletion(entry.getValue());
114 }
115
116
117 ctx.managedConnections.clear();
118 }
119 }
120 } finally {
121 remove(transaction);
122 }
123 }
124 }
125 }