Source code: org/apache/commons/dbcp/PoolableConnectionFactory.java
1 /*
2 * Copyright 1999-2004 The Apache Software Foundation.
3 *
4 * Licensed under the Apache License, Version 2.0 (the "License");
5 * you may not use this file except in compliance with the License.
6 * You may obtain a copy of the License at
7 *
8 * http://www.apache.org/licenses/LICENSE-2.0
9 *
10 * Unless required by applicable law or agreed to in writing, software
11 * distributed under the License is distributed on an "AS IS" BASIS,
12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
13 * See the License for the specific language governing permissions and
14 * limitations under the License.
15 */
16
17 package org.apache.commons.dbcp;
18
19 import java.sql.Connection;
20 import java.sql.Statement;
21 import java.sql.ResultSet;
22 import java.sql.SQLException;
23 import org.apache.commons.pool.*;
24
25 /**
26 * A {@link PoolableObjectFactory} that creates
27 * {@link PoolableConnection}s.
28 *
29 * @author Rodney Waldhoff
30 * @author Glenn L. Nielsen
31 * @author James House
32 * @author Dirk Verbeeck
33 * @version $Revision: 1.23 $ $Date: 2004/06/09 18:21:23 $
34 */
35 public class PoolableConnectionFactory implements PoolableObjectFactory {
36 /**
37 * Create a new <tt>PoolableConnectionFactory</tt>.
38 * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
39 * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
40 * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
41 * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. Using <tt>null</tt> turns off validation.
42 * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
43 * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
44 */
45 public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, boolean defaultReadOnly, boolean defaultAutoCommit) {
46 _connFactory = connFactory;
47 _pool = pool;
48 _pool.setFactory(this);
49 _stmtPoolFactory = stmtPoolFactory;
50 _validationQuery = validationQuery;
51 _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
52 _defaultAutoCommit = defaultAutoCommit;
53 }
54
55 /**
56 * Create a new <tt>PoolableConnectionFactory</tt>.
57 * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
58 * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
59 * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
60 * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. Using <tt>null</tt> turns off validation.
61 * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
62 * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
63 * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
64 */
65 public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, boolean defaultReadOnly, boolean defaultAutoCommit, int defaultTransactionIsolation) {
66 _connFactory = connFactory;
67 _pool = pool;
68 _pool.setFactory(this);
69 _stmtPoolFactory = stmtPoolFactory;
70 _validationQuery = validationQuery;
71 _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
72 _defaultAutoCommit = defaultAutoCommit;
73 _defaultTransactionIsolation = defaultTransactionIsolation;
74 }
75
76 /**
77 * Create a new <tt>PoolableConnectionFactory</tt>.
78 * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
79 * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
80 * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
81 * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. Using <tt>null</tt> turns off validation.
82 * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
83 * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
84 * @param config the AbandonedConfig if tracing SQL objects
85 * @deprecated AbandonedConfig is now deprecated.
86 */
87 public PoolableConnectionFactory(
88 ConnectionFactory connFactory,
89 ObjectPool pool,
90 KeyedObjectPoolFactory stmtPoolFactory,
91 String validationQuery,
92 boolean defaultReadOnly,
93 boolean defaultAutoCommit,
94 AbandonedConfig config) {
95
96 _connFactory = connFactory;
97 _pool = pool;
98 _config = config;
99 _pool.setFactory(this);
100 _stmtPoolFactory = stmtPoolFactory;
101 _validationQuery = validationQuery;
102 _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
103 _defaultAutoCommit = defaultAutoCommit;
104 }
105
106 /**
107 * Create a new <tt>PoolableConnectionFactory</tt>.
108 * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
109 * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
110 * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
111 * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. Using <tt>null</tt> turns off validation.
112 * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
113 * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
114 * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
115 * @param config the AbandonedConfig if tracing SQL objects
116 * @deprecated AbandonedConfig is now deprecated.
117 */
118 public PoolableConnectionFactory(
119 ConnectionFactory connFactory,
120 ObjectPool pool,
121 KeyedObjectPoolFactory stmtPoolFactory,
122 String validationQuery,
123 boolean defaultReadOnly,
124 boolean defaultAutoCommit,
125 int defaultTransactionIsolation,
126 AbandonedConfig config) {
127
128 _connFactory = connFactory;
129 _pool = pool;
130 _config = config;
131 _pool.setFactory(this);
132 _stmtPoolFactory = stmtPoolFactory;
133 _validationQuery = validationQuery;
134 _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
135 _defaultAutoCommit = defaultAutoCommit;
136 _defaultTransactionIsolation = defaultTransactionIsolation;
137 }
138
139 /**
140 * Create a new <tt>PoolableConnectionFactory</tt>.
141 * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
142 * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
143 * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
144 * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. Using <tt>null</tt> turns off validation.
145 * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
146 * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
147 * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
148 * @param defaultCatalog the default "catalog" setting for returned {@link Connection}s
149 * @param config the AbandonedConfig if tracing SQL objects
150 * @deprecated AbandonedConfig is now deprecated.
151 */
152 public PoolableConnectionFactory(
153 ConnectionFactory connFactory,
154 ObjectPool pool,
155 KeyedObjectPoolFactory stmtPoolFactory,
156 String validationQuery,
157 boolean defaultReadOnly,
158 boolean defaultAutoCommit,
159 int defaultTransactionIsolation,
160 String defaultCatalog,
161 AbandonedConfig config) {
162
163 _connFactory = connFactory;
164 _pool = pool;
165 _config = config;
166 _pool.setFactory(this);
167 _stmtPoolFactory = stmtPoolFactory;
168 _validationQuery = validationQuery;
169 _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
170 _defaultAutoCommit = defaultAutoCommit;
171 _defaultTransactionIsolation = defaultTransactionIsolation;
172 _defaultCatalog = defaultCatalog;
173 }
174
175 /**
176 * Create a new <tt>PoolableConnectionFactory</tt>.
177 * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
178 * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
179 * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s, or <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling
180 * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s. Should return at least one row. Using <tt>null</tt> turns off validation.
181 * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
182 * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
183 * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
184 * @param defaultCatalog the default "catalog" setting for returned {@link Connection}s
185 * @param config the AbandonedConfig if tracing SQL objects
186 */
187 public PoolableConnectionFactory(
188 ConnectionFactory connFactory,
189 ObjectPool pool,
190 KeyedObjectPoolFactory stmtPoolFactory,
191 String validationQuery,
192 Boolean defaultReadOnly,
193 boolean defaultAutoCommit,
194 int defaultTransactionIsolation,
195 String defaultCatalog,
196 AbandonedConfig config) {
197
198 _connFactory = connFactory;
199 _pool = pool;
200 _config = config;
201 _pool.setFactory(this);
202 _stmtPoolFactory = stmtPoolFactory;
203 _validationQuery = validationQuery;
204 _defaultReadOnly = defaultReadOnly;
205 _defaultAutoCommit = defaultAutoCommit;
206 _defaultTransactionIsolation = defaultTransactionIsolation;
207 _defaultCatalog = defaultCatalog;
208 }
209
210 /**
211 * Sets the {@link ConnectionFactory} from which to obtain base {@link Connection}s.
212 * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
213 */
214 synchronized public void setConnectionFactory(ConnectionFactory connFactory) {
215 _connFactory = connFactory;
216 }
217
218 /**
219 * Sets the query I use to {@link #validateObject validate} {@link Connection}s.
220 * Should return at least one row.
221 * Using <tt>null</tt> turns off validation.
222 * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s.
223 */
224 synchronized public void setValidationQuery(String validationQuery) {
225 _validationQuery = validationQuery;
226 }
227
228 /**
229 * Sets the {@link ObjectPool} in which to pool {@link Connection}s.
230 * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
231 */
232 synchronized public void setPool(ObjectPool pool) {
233 if(null != _pool && pool != _pool) {
234 try {
235 _pool.close();
236 } catch(Exception e) {
237 // ignored !?!
238 }
239 }
240 _pool = pool;
241 }
242
243 public ObjectPool getPool() {
244 return _pool;
245 }
246
247 /**
248 * Sets the {@link KeyedObjectPoolFactory} I use to create {@link KeyedObjectPool}s
249 * for pooling {@link java.sql.PreparedStatement}s.
250 * Set to <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling.
251 * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s
252 */
253 synchronized public void setStatementPoolFactory(KeyedObjectPoolFactory stmtPoolFactory) {
254 _stmtPoolFactory = stmtPoolFactory;
255 }
256
257 /**
258 * Sets the default "read only" setting for borrowed {@link Connection}s
259 * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
260 */
261 public void setDefaultReadOnly(boolean defaultReadOnly) {
262 _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
263 }
264
265 /**
266 * Sets the default "auto commit" setting for borrowed {@link Connection}s
267 * @param defaultAutoCommit the default "auto commit" setting for borrowed {@link Connection}s
268 */
269 public void setDefaultAutoCommit(boolean defaultAutoCommit) {
270 _defaultAutoCommit = defaultAutoCommit;
271 }
272
273 /**
274 * Sets the default "Transaction Isolation" setting for borrowed {@link Connection}s
275 * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
276 */
277 public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
278 _defaultTransactionIsolation = defaultTransactionIsolation;
279 }
280
281 /**
282 * Sets the default "catalog" setting for borrowed {@link Connection}s
283 * @param defaultCatalog the default "catalog" setting for borrowed {@link Connection}s
284 */
285 public void setDefaultCatalog(String defaultCatalog) {
286 _defaultCatalog = defaultCatalog;
287 }
288
289 synchronized public Object makeObject() throws Exception {
290 Connection conn = _connFactory.createConnection();
291 if(null != _stmtPoolFactory) {
292 KeyedObjectPool stmtpool = _stmtPoolFactory.createPool();
293 conn = new PoolingConnection(conn,stmtpool);
294 stmtpool.setFactory((PoolingConnection)conn);
295 }
296 return new PoolableConnection(conn,_pool,_config);
297 }
298
299 public void destroyObject(Object obj) throws Exception {
300 if(obj instanceof PoolableConnection) {
301 ((PoolableConnection)obj).reallyClose();
302 }
303 }
304
305 public boolean validateObject(Object obj) {
306 if(obj instanceof Connection) {
307 try {
308 validateConnection((Connection) obj);
309 return true;
310 } catch(Exception e) {
311 return false;
312 }
313 } else {
314 return false;
315 }
316 }
317
318 public void validateConnection(Connection conn) throws SQLException {
319 String query = _validationQuery;
320 if(conn.isClosed()) {
321 throw new SQLException("validateConnection: connection closed");
322 }
323 if(null != query) {
324 Statement stmt = null;
325 ResultSet rset = null;
326 try {
327 stmt = conn.createStatement();
328 rset = stmt.executeQuery(query);
329 if(!rset.next()) {
330 throw new SQLException("validationQuery didn't return a row");
331 }
332 } finally {
333 try {
334 rset.close();
335 } catch(Exception t) {
336 // ignored
337 }
338 try {
339 stmt.close();
340 } catch(Exception t) {
341 // ignored
342 }
343
344 }
345 }
346 }
347
348 public void passivateObject(Object obj) throws Exception {
349 if(obj instanceof Connection) {
350 Connection conn = (Connection)obj;
351 if(!conn.getAutoCommit() && !conn.isReadOnly()) {
352 conn.rollback();
353 }
354 conn.clearWarnings();
355 conn.setAutoCommit(true);
356 }
357 if(obj instanceof DelegatingConnection) {
358 ((DelegatingConnection)obj).passivate();
359 }
360 }
361
362 public void activateObject(Object obj) throws Exception {
363 if(obj instanceof DelegatingConnection) {
364 ((DelegatingConnection)obj).activate();
365 }
366 if(obj instanceof Connection) {
367 Connection conn = (Connection)obj;
368 conn.setAutoCommit(_defaultAutoCommit);
369 if (_defaultTransactionIsolation != UNKNOWN_TRANSACTIONISOLATION) {
370 conn.setTransactionIsolation(_defaultTransactionIsolation);
371 }
372 if (_defaultReadOnly != null) {
373 conn.setReadOnly(_defaultReadOnly.booleanValue());
374 }
375 if (_defaultCatalog != null) {
376 conn.setCatalog(_defaultCatalog);
377 }
378 }
379 }
380
381 protected ConnectionFactory _connFactory = null;
382 protected String _validationQuery = null;
383 protected ObjectPool _pool = null;
384 protected KeyedObjectPoolFactory _stmtPoolFactory = null;
385 protected Boolean _defaultReadOnly = null;
386 protected boolean _defaultAutoCommit = true;
387 protected int _defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION;
388 protected String _defaultCatalog;
389
390 /**
391 * @deprecated AbandonedConfig is now deprecated.
392 */
393 protected AbandonedConfig _config = null;
394
395 /**
396 * Internal constant to indicate the level is not set.
397 */
398 static final int UNKNOWN_TRANSACTIONISOLATION = -1;
399 }