1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17 package org.apache.commons.dbcp2.managed;
18
19 import java.sql.SQLException;
20
21 import javax.sql.DataSource;
22 import javax.sql.XADataSource;
23 import javax.transaction.TransactionManager;
24 import javax.transaction.TransactionSynchronizationRegistry;
25
26 import org.apache.commons.dbcp2.BasicDataSource;
27 import org.apache.commons.dbcp2.ConnectionFactory;
28 import org.apache.commons.dbcp2.PoolableConnection;
29 import org.apache.commons.dbcp2.PoolableConnectionFactory;
30 import org.apache.commons.dbcp2.PoolingDataSource;
31 import org.apache.commons.dbcp2.Utils;
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52 public class BasicManagedDataSource extends BasicDataSource {
53
54
55 private TransactionRegistry transactionRegistry;
56
57
58 private transient TransactionManager transactionManager;
59
60
61 private String xaDataSource;
62
63
64 private XADataSource xaDataSourceInstance;
65
66
67 private transient TransactionSynchronizationRegistry transactionSynchronizationRegistry;
68
69 @Override
70 protected ConnectionFactory createConnectionFactory() throws SQLException {
71 if (transactionManager == null) {
72 throw new SQLException("Transaction manager must be set before a connection can be created");
73 }
74
75
76
77 if (xaDataSource == null) {
78 final ConnectionFactory connectionFactory = super.createConnectionFactory();
79 final XAConnectionFactory xaConnectionFactory = new LocalXAConnectionFactory(getTransactionManager(),
80 getTransactionSynchronizationRegistry(), connectionFactory);
81 transactionRegistry = xaConnectionFactory.getTransactionRegistry();
82 return xaConnectionFactory;
83 }
84
85
86 if (xaDataSourceInstance == null) {
87 Class<?> xaDataSourceClass = null;
88 try {
89 xaDataSourceClass = Class.forName(xaDataSource);
90 } catch (final Exception e) {
91 throw new SQLException("Cannot load XA data source class '" + xaDataSource + "'", e);
92 }
93
94 try {
95 xaDataSourceInstance = (XADataSource) xaDataSourceClass.getConstructor().newInstance();
96 } catch (final Exception e) {
97 throw new SQLException("Cannot create XA data source of class '" + xaDataSource + "'", e);
98 }
99 }
100
101
102 final XAConnectionFactory xaConnectionFactory = new DataSourceXAConnectionFactory(getTransactionManager(),
103 xaDataSourceInstance, getUserName(), Utils.toCharArray(getPassword()), getTransactionSynchronizationRegistry());
104 transactionRegistry = xaConnectionFactory.getTransactionRegistry();
105 return xaConnectionFactory;
106 }
107
108 @Override
109 protected DataSource createDataSourceInstance() throws SQLException {
110 final PoolingDataSource<PoolableConnection> pds = new ManagedDataSource<>(getConnectionPool(),
111 transactionRegistry);
112 pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
113 return pds;
114 }
115
116
117
118
119
120
121
122
123
124 @Override
125 protected PoolableConnectionFactory createPoolableConnectionFactory(final ConnectionFactory driverConnectionFactory)
126 throws SQLException {
127 PoolableConnectionFactory connectionFactory = null;
128 try {
129 connectionFactory = new PoolableManagedConnectionFactory((XAConnectionFactory) driverConnectionFactory,
130 getRegisteredJmxName());
131 connectionFactory.setValidationQuery(getValidationQuery());
132 connectionFactory.setValidationQueryTimeout(getValidationQueryTimeoutDuration());
133 connectionFactory.setConnectionInitSql(getConnectionInitSqls());
134 connectionFactory.setDefaultReadOnly(getDefaultReadOnly());
135 connectionFactory.setDefaultAutoCommit(getDefaultAutoCommit());
136 connectionFactory.setDefaultTransactionIsolation(getDefaultTransactionIsolation());
137 connectionFactory.setDefaultCatalog(getDefaultCatalog());
138 connectionFactory.setDefaultSchema(getDefaultSchema());
139 connectionFactory.setCacheState(getCacheState());
140 connectionFactory.setPoolStatements(isPoolPreparedStatements());
141 connectionFactory.setClearStatementPoolOnReturn(isClearStatementPoolOnReturn());
142 connectionFactory.setMaxOpenPreparedStatements(getMaxOpenPreparedStatements());
143 connectionFactory.setMaxConn(getMaxConnDuration());
144 connectionFactory.setRollbackOnReturn(getRollbackOnReturn());
145 connectionFactory.setAutoCommitOnReturn(getAutoCommitOnReturn());
146 connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeoutDuration());
147 connectionFactory.setFastFailValidation(getFastFailValidation());
148 connectionFactory.setDisconnectionSqlCodes(getDisconnectionSqlCodes());
149 validateConnectionFactory(connectionFactory);
150 } catch (final RuntimeException e) {
151 throw e;
152 } catch (final Exception e) {
153 throw new SQLException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e);
154 }
155 return connectionFactory;
156 }
157
158
159
160
161
162
163 public TransactionManager getTransactionManager() {
164 return transactionManager;
165 }
166
167
168
169
170
171
172 protected synchronized TransactionRegistry getTransactionRegistry() {
173 return transactionRegistry;
174 }
175
176
177
178
179
180
181
182 public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() {
183 return transactionSynchronizationRegistry;
184 }
185
186
187
188
189
190
191 public synchronized String getXADataSource() {
192 return xaDataSource;
193 }
194
195
196
197
198
199
200 public synchronized XADataSource getXaDataSourceInstance() {
201 return xaDataSourceInstance;
202 }
203
204
205
206
207
208
209
210 public void setTransactionManager(final TransactionManager transactionManager) {
211 this.transactionManager = transactionManager;
212 }
213
214
215
216
217
218
219
220
221 public void setTransactionSynchronizationRegistry(
222 final TransactionSynchronizationRegistry transactionSynchronizationRegistry) {
223 this.transactionSynchronizationRegistry = transactionSynchronizationRegistry;
224 }
225
226
227
228
229
230
231
232 public synchronized void setXADataSource(final String xaDataSource) {
233 this.xaDataSource = xaDataSource;
234 }
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249 public synchronized void setXaDataSourceInstance(final XADataSource xaDataSourceInstance) {
250 this.xaDataSourceInstance = xaDataSourceInstance;
251 xaDataSource = xaDataSourceInstance == null ? null : xaDataSourceInstance.getClass().getName();
252 }
253 }