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