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
70
71
72 public BasicManagedDataSource() {
73
74 }
75
76 @Override
77 protected synchronized ConnectionFactory createConnectionFactory() throws SQLException {
78 if (transactionManager == null) {
79 throw new SQLException("Transaction manager must be set before a connection can be created");
80 }
81
82
83
84 if (xaDataSource == null) {
85 final ConnectionFactory connectionFactory = super.createConnectionFactory();
86 final XAConnectionFactory xaConnectionFactory = new LocalXAConnectionFactory(getTransactionManager(),
87 getTransactionSynchronizationRegistry(), connectionFactory);
88 transactionRegistry = xaConnectionFactory.getTransactionRegistry();
89 return xaConnectionFactory;
90 }
91
92
93 if (xaDataSourceInstance == null) {
94 Class<?> xaDataSourceClass = null;
95 try {
96 xaDataSourceClass = Class.forName(xaDataSource);
97 } catch (final Exception e) {
98 throw new SQLException("Cannot load XA data source class '" + xaDataSource + "'", e);
99 }
100
101 try {
102 xaDataSourceInstance = (XADataSource) xaDataSourceClass.getConstructor().newInstance();
103 } catch (final Exception e) {
104 throw new SQLException("Cannot create XA data source of class '" + xaDataSource + "'", e);
105 }
106 }
107
108
109 final XAConnectionFactory xaConnectionFactory = new DataSourceXAConnectionFactory(getTransactionManager(),
110 xaDataSourceInstance, getUserName(), Utils.toCharArray(getPassword()), getTransactionSynchronizationRegistry());
111 transactionRegistry = xaConnectionFactory.getTransactionRegistry();
112 return xaConnectionFactory;
113 }
114
115 @Override
116 protected DataSource createDataSourceInstance() throws SQLException {
117 final PoolingDataSource<PoolableConnection> pds = new ManagedDataSource<>(getConnectionPool(),
118 transactionRegistry);
119 pds.setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
120 return pds;
121 }
122
123
124
125
126
127
128
129
130
131 @Override
132 protected PoolableConnectionFactory createPoolableConnectionFactory(final ConnectionFactory driverConnectionFactory)
133 throws SQLException {
134 PoolableConnectionFactory connectionFactory = null;
135 try {
136 connectionFactory = new PoolableManagedConnectionFactory((XAConnectionFactory) driverConnectionFactory, getRegisteredJmxName());
137 connectionFactory.setValidationQuery(getValidationQuery());
138 connectionFactory.setValidationQueryTimeout(getValidationQueryTimeoutDuration());
139 connectionFactory.setConnectionInitSql(getConnectionInitSqls());
140 connectionFactory.setDefaultReadOnly(getDefaultReadOnly());
141 connectionFactory.setDefaultAutoCommit(getDefaultAutoCommit());
142 connectionFactory.setDefaultTransactionIsolation(getDefaultTransactionIsolation());
143 connectionFactory.setDefaultCatalog(getDefaultCatalog());
144 connectionFactory.setDefaultSchema(getDefaultSchema());
145 connectionFactory.setCacheState(getCacheState());
146 connectionFactory.setPoolStatements(isPoolPreparedStatements());
147 connectionFactory.setClearStatementPoolOnReturn(isClearStatementPoolOnReturn());
148 connectionFactory.setMaxOpenPreparedStatements(getMaxOpenPreparedStatements());
149 connectionFactory.setMaxConn(getMaxConnDuration());
150 connectionFactory.setRollbackOnReturn(getRollbackOnReturn());
151 connectionFactory.setAutoCommitOnReturn(getAutoCommitOnReturn());
152 connectionFactory.setDefaultQueryTimeout(getDefaultQueryTimeoutDuration());
153 connectionFactory.setFastFailValidation(getFastFailValidation());
154 connectionFactory.setDisconnectionSqlCodes(getDisconnectionSqlCodes());
155 connectionFactory.setDisconnectionIgnoreSqlCodes(getDisconnectionIgnoreSqlCodes());
156 validateConnectionFactory(connectionFactory);
157 } catch (final RuntimeException e) {
158 throw e;
159 } catch (final Exception e) {
160 throw new SQLException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e);
161 }
162 return connectionFactory;
163 }
164
165
166
167
168
169
170 public TransactionManager getTransactionManager() {
171 return transactionManager;
172 }
173
174
175
176
177
178
179 protected synchronized TransactionRegistry getTransactionRegistry() {
180 return transactionRegistry;
181 }
182
183
184
185
186
187
188
189 public TransactionSynchronizationRegistry getTransactionSynchronizationRegistry() {
190 return transactionSynchronizationRegistry;
191 }
192
193
194
195
196
197
198 public synchronized String getXADataSource() {
199 return xaDataSource;
200 }
201
202
203
204
205
206
207 public synchronized XADataSource getXaDataSourceInstance() {
208 return xaDataSourceInstance;
209 }
210
211
212
213
214
215
216
217 public void setTransactionManager(final TransactionManager transactionManager) {
218 this.transactionManager = transactionManager;
219 }
220
221
222
223
224
225
226
227
228 public void setTransactionSynchronizationRegistry(
229 final TransactionSynchronizationRegistry transactionSynchronizationRegistry) {
230 this.transactionSynchronizationRegistry = transactionSynchronizationRegistry;
231 }
232
233
234
235
236
237
238
239 public synchronized void setXADataSource(final String xaDataSource) {
240 this.xaDataSource = xaDataSource;
241 }
242
243
244
245
246
247
248
249
250
251
252
253 public synchronized void setXaDataSourceInstance(final XADataSource xaDataSourceInstance) {
254 this.xaDataSourceInstance = xaDataSourceInstance;
255 xaDataSource = xaDataSourceInstance == null ? null : xaDataSourceInstance.getClass().getName();
256 }
257 }