001: /*
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */
017:
018: package org.apache.commons.dbcp;
019:
020: import java.sql.Connection;
021: import java.sql.Statement;
022: import java.sql.ResultSet;
023: import java.sql.SQLException;
024: import org.apache.commons.pool.KeyedObjectPool;
025: import org.apache.commons.pool.KeyedObjectPoolFactory;
026: import org.apache.commons.pool.PoolableObjectFactory;
027: import org.apache.commons.pool.ObjectPool;
028:
029: /**
030: * A {@link PoolableObjectFactory} that creates
031: * {@link PoolableConnection}s.
032: *
033: * @author Rodney Waldhoff
034: * @author Glenn L. Nielsen
035: * @author James House
036: * @author Dirk Verbeeck
037: * @version $Revision: 479187 $ $Date: 2006-11-25 13:13:45 -0700 (Sat, 25 Nov 2006) $
038: */
039: public class PoolableConnectionFactory implements PoolableObjectFactory {
040: /**
041: * Create a new <tt>PoolableConnectionFactory</tt>.
042: * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
043: * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
044: * @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
045: * @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.
046: * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
047: * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
048: */
049: public PoolableConnectionFactory(ConnectionFactory connFactory,
050: ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory,
051: String validationQuery, boolean defaultReadOnly,
052: boolean defaultAutoCommit) {
053: _connFactory = connFactory;
054: _pool = pool;
055: _pool.setFactory(this );
056: _stmtPoolFactory = stmtPoolFactory;
057: _validationQuery = validationQuery;
058: _defaultReadOnly = defaultReadOnly ? Boolean.TRUE
059: : Boolean.FALSE;
060: _defaultAutoCommit = defaultAutoCommit;
061: }
062:
063: /**
064: * Create a new <tt>PoolableConnectionFactory</tt>.
065: * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
066: * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
067: * @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
068: * @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.
069: * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
070: * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
071: * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
072: */
073: public PoolableConnectionFactory(ConnectionFactory connFactory,
074: ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory,
075: String validationQuery, boolean defaultReadOnly,
076: boolean defaultAutoCommit, int defaultTransactionIsolation) {
077: _connFactory = connFactory;
078: _pool = pool;
079: _pool.setFactory(this );
080: _stmtPoolFactory = stmtPoolFactory;
081: _validationQuery = validationQuery;
082: _defaultReadOnly = defaultReadOnly ? Boolean.TRUE
083: : Boolean.FALSE;
084: _defaultAutoCommit = defaultAutoCommit;
085: _defaultTransactionIsolation = defaultTransactionIsolation;
086: }
087:
088: /**
089: * Create a new <tt>PoolableConnectionFactory</tt>.
090: * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
091: * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
092: * @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
093: * @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.
094: * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
095: * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
096: * @param config the AbandonedConfig if tracing SQL objects
097: * @deprecated AbandonedConfig is now deprecated.
098: */
099: public PoolableConnectionFactory(ConnectionFactory connFactory,
100: ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory,
101: String validationQuery, boolean defaultReadOnly,
102: boolean defaultAutoCommit, AbandonedConfig config) {
103:
104: _connFactory = connFactory;
105: _pool = pool;
106: _config = config;
107: _pool.setFactory(this );
108: _stmtPoolFactory = stmtPoolFactory;
109: _validationQuery = validationQuery;
110: _defaultReadOnly = defaultReadOnly ? Boolean.TRUE
111: : Boolean.FALSE;
112: _defaultAutoCommit = defaultAutoCommit;
113: }
114:
115: /**
116: * Create a new <tt>PoolableConnectionFactory</tt>.
117: * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
118: * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
119: * @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
120: * @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.
121: * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
122: * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
123: * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
124: * @param config the AbandonedConfig if tracing SQL objects
125: * @deprecated AbandonedConfig is now deprecated.
126: */
127: public PoolableConnectionFactory(ConnectionFactory connFactory,
128: ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory,
129: String validationQuery, boolean defaultReadOnly,
130: boolean defaultAutoCommit, int defaultTransactionIsolation,
131: AbandonedConfig config) {
132:
133: _connFactory = connFactory;
134: _pool = pool;
135: _config = config;
136: _pool.setFactory(this );
137: _stmtPoolFactory = stmtPoolFactory;
138: _validationQuery = validationQuery;
139: _defaultReadOnly = defaultReadOnly ? Boolean.TRUE
140: : Boolean.FALSE;
141: _defaultAutoCommit = defaultAutoCommit;
142: _defaultTransactionIsolation = defaultTransactionIsolation;
143: }
144:
145: /**
146: * Create a new <tt>PoolableConnectionFactory</tt>.
147: * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
148: * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
149: * @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
150: * @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.
151: * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
152: * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
153: * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
154: * @param defaultCatalog the default "catalog" setting for returned {@link Connection}s
155: * @param config the AbandonedConfig if tracing SQL objects
156: * @deprecated AbandonedConfig is now deprecated.
157: */
158: public PoolableConnectionFactory(ConnectionFactory connFactory,
159: ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory,
160: String validationQuery, boolean defaultReadOnly,
161: boolean defaultAutoCommit, int defaultTransactionIsolation,
162: String defaultCatalog, AbandonedConfig config) {
163:
164: _connFactory = connFactory;
165: _pool = pool;
166: _config = config;
167: _pool.setFactory(this );
168: _stmtPoolFactory = stmtPoolFactory;
169: _validationQuery = validationQuery;
170: _defaultReadOnly = defaultReadOnly ? Boolean.TRUE
171: : Boolean.FALSE;
172: _defaultAutoCommit = defaultAutoCommit;
173: _defaultTransactionIsolation = defaultTransactionIsolation;
174: _defaultCatalog = defaultCatalog;
175: }
176:
177: /**
178: * Create a new <tt>PoolableConnectionFactory</tt>.
179: * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
180: * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
181: * @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
182: * @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.
183: * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
184: * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
185: * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
186: * @param defaultCatalog the default "catalog" setting for returned {@link Connection}s
187: * @param config the AbandonedConfig if tracing SQL objects
188: */
189: public PoolableConnectionFactory(ConnectionFactory connFactory,
190: ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory,
191: String validationQuery, Boolean defaultReadOnly,
192: boolean defaultAutoCommit, int defaultTransactionIsolation,
193: String defaultCatalog, AbandonedConfig config) {
194:
195: _connFactory = connFactory;
196: _pool = pool;
197: _config = config;
198: _pool.setFactory(this );
199: _stmtPoolFactory = stmtPoolFactory;
200: _validationQuery = validationQuery;
201: _defaultReadOnly = defaultReadOnly;
202: _defaultAutoCommit = defaultAutoCommit;
203: _defaultTransactionIsolation = defaultTransactionIsolation;
204: _defaultCatalog = defaultCatalog;
205: }
206:
207: /**
208: * Sets the {@link ConnectionFactory} from which to obtain base {@link Connection}s.
209: * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
210: */
211: synchronized public void setConnectionFactory(
212: ConnectionFactory connFactory) {
213: _connFactory = connFactory;
214: }
215:
216: /**
217: * Sets the query I use to {@link #validateObject validate} {@link Connection}s.
218: * Should return at least one row.
219: * Using <tt>null</tt> turns off validation.
220: * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s.
221: */
222: synchronized public void setValidationQuery(String validationQuery) {
223: _validationQuery = validationQuery;
224: }
225:
226: /**
227: * Sets the {@link ObjectPool} in which to pool {@link Connection}s.
228: * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
229: */
230: synchronized public void setPool(ObjectPool pool) {
231: if (null != _pool && pool != _pool) {
232: try {
233: _pool.close();
234: } catch (Exception e) {
235: // ignored !?!
236: }
237: }
238: _pool = pool;
239: }
240:
241: public ObjectPool getPool() {
242: return _pool;
243: }
244:
245: /**
246: * Sets the {@link KeyedObjectPoolFactory} I use to create {@link KeyedObjectPool}s
247: * for pooling {@link java.sql.PreparedStatement}s.
248: * Set to <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling.
249: * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s
250: */
251: synchronized public void setStatementPoolFactory(
252: KeyedObjectPoolFactory stmtPoolFactory) {
253: _stmtPoolFactory = stmtPoolFactory;
254: }
255:
256: /**
257: * Sets the default "read only" setting for borrowed {@link Connection}s
258: * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
259: */
260: public void setDefaultReadOnly(boolean defaultReadOnly) {
261: _defaultReadOnly = defaultReadOnly ? Boolean.TRUE
262: : 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(
278: int defaultTransactionIsolation) {
279: _defaultTransactionIsolation = defaultTransactionIsolation;
280: }
281:
282: /**
283: * Sets the default "catalog" setting for borrowed {@link Connection}s
284: * @param defaultCatalog the default "catalog" setting for borrowed {@link Connection}s
285: */
286: public void setDefaultCatalog(String defaultCatalog) {
287: _defaultCatalog = defaultCatalog;
288: }
289:
290: synchronized public Object makeObject() throws Exception {
291: Connection conn = _connFactory.createConnection();
292: if (null != _stmtPoolFactory) {
293: KeyedObjectPool stmtpool = _stmtPoolFactory.createPool();
294: conn = new PoolingConnection(conn, stmtpool);
295: stmtpool.setFactory((PoolingConnection) conn);
296: }
297: return new PoolableConnection(conn, _pool, _config);
298: }
299:
300: public void destroyObject(Object obj) throws Exception {
301: if (obj instanceof PoolableConnection) {
302: ((PoolableConnection) obj).reallyClose();
303: }
304: }
305:
306: public boolean validateObject(Object obj) {
307: if (obj instanceof Connection) {
308: try {
309: validateConnection((Connection) obj);
310: return true;
311: } catch (Exception e) {
312: return false;
313: }
314: } else {
315: return false;
316: }
317: }
318:
319: public void validateConnection(Connection conn) throws SQLException {
320: String query = _validationQuery;
321: if (conn.isClosed()) {
322: throw new SQLException(
323: "validateConnection: connection closed");
324: }
325: if (null != query) {
326: Statement stmt = null;
327: ResultSet rset = null;
328: try {
329: stmt = conn.createStatement();
330: rset = stmt.executeQuery(query);
331: if (!rset.next()) {
332: throw new SQLException(
333: "validationQuery didn't return a row");
334: }
335: } finally {
336: if (rset != null) {
337: try {
338: rset.close();
339: } catch (Exception t) {
340: // ignored
341: }
342: }
343: if (stmt != null) {
344: try {
345: stmt.close();
346: } catch (Exception t) {
347: // ignored
348: }
349: }
350: }
351: }
352: }
353:
354: public void passivateObject(Object obj) throws Exception {
355: if (obj instanceof Connection) {
356: Connection conn = (Connection) obj;
357: if (!conn.getAutoCommit() && !conn.isReadOnly()) {
358: conn.rollback();
359: }
360: conn.clearWarnings();
361: if (!conn.getAutoCommit()) {
362: conn.setAutoCommit(true);
363: }
364: }
365: if (obj instanceof DelegatingConnection) {
366: ((DelegatingConnection) obj).passivate();
367: }
368: }
369:
370: public void activateObject(Object obj) throws Exception {
371: if (obj instanceof DelegatingConnection) {
372: ((DelegatingConnection) obj).activate();
373: }
374: if (obj instanceof Connection) {
375: Connection conn = (Connection) obj;
376: if (conn.getAutoCommit() != _defaultAutoCommit) {
377: conn.setAutoCommit(_defaultAutoCommit);
378: }
379: if ((_defaultTransactionIsolation != UNKNOWN_TRANSACTIONISOLATION)
380: && (conn.getTransactionIsolation() != _defaultTransactionIsolation)) {
381: conn
382: .setTransactionIsolation(_defaultTransactionIsolation);
383: }
384: if ((_defaultReadOnly != null)
385: && (conn.isReadOnly() != _defaultReadOnly
386: .booleanValue())) {
387: conn.setReadOnly(_defaultReadOnly.booleanValue());
388: }
389: if ((_defaultCatalog != null)
390: && (!_defaultCatalog.equals(conn.getCatalog()))) {
391: conn.setCatalog(_defaultCatalog);
392: }
393: }
394: }
395:
396: protected ConnectionFactory _connFactory = null;
397: protected String _validationQuery = null;
398: protected ObjectPool _pool = null;
399: protected KeyedObjectPoolFactory _stmtPoolFactory = null;
400: protected Boolean _defaultReadOnly = null;
401: protected boolean _defaultAutoCommit = true;
402: protected int _defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION;
403: protected String _defaultCatalog;
404:
405: /**
406: * @deprecated AbandonedConfig is now deprecated.
407: */
408: protected AbandonedConfig _config = null;
409:
410: /**
411: * Internal constant to indicate the level is not set.
412: */
413: static final int UNKNOWN_TRANSACTIONISOLATION = -1;
414: }
|