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 java.util.Collection;
025    import java.util.Iterator;
026    import org.apache.commons.pool.KeyedObjectPool;
027    import org.apache.commons.pool.KeyedObjectPoolFactory;
028    import org.apache.commons.pool.PoolableObjectFactory;
029    import org.apache.commons.pool.ObjectPool;
030    
031    /**
032     * A {@link PoolableObjectFactory} that creates
033     * {@link PoolableConnection}s.
034     *
035     * @author Rodney Waldhoff
036     * @author Glenn L. Nielsen
037     * @author James House
038     * @author Dirk Verbeeck
039     * @version $Revision: 892307 $ $Date: 2013-12-31 23:27:28 +0000 (Tue, 31 Dec 2013) $
040     */
041    public class PoolableConnectionFactory implements PoolableObjectFactory {
042        /**
043         * Create a new <tt>PoolableConnectionFactory</tt>.
044         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
045         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
046         * @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
047         * @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.
048         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
049         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
050         */
051        public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, boolean defaultReadOnly, boolean defaultAutoCommit) {
052            _connFactory = connFactory;
053            _pool = pool;
054            _pool.setFactory(this);
055            _stmtPoolFactory = stmtPoolFactory;
056            _validationQuery = validationQuery;
057            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
058            _defaultAutoCommit = defaultAutoCommit;
059        }
060    
061        /**
062         * Create a new <tt>PoolableConnectionFactory</tt>.
063         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
064         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
065         * @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
066         * @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.
067         * @param connectionInitSqls a Collection of SQL statements to initialize {@link Connection}s. Using <tt>null</tt> turns off initialization.
068         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
069         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
070         * @since 1.3
071         */
072        public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, Collection connectionInitSqls, boolean defaultReadOnly, boolean defaultAutoCommit) {
073            _connFactory = connFactory;
074            _pool = pool;
075            _pool.setFactory(this);
076            _stmtPoolFactory = stmtPoolFactory;
077            _validationQuery = validationQuery;
078            _connectionInitSqls = connectionInitSqls;
079            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
080            _defaultAutoCommit = defaultAutoCommit;
081        }
082        
083        /**
084         * Create a new <tt>PoolableConnectionFactory</tt>.
085         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
086         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
087         * @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
088         * @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.
089         * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
090         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
091         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
092         * @since 1.3
093         */
094        public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, int validationQueryTimeout, boolean defaultReadOnly, boolean defaultAutoCommit) {
095            _connFactory = connFactory;
096            _pool = pool;
097            _pool.setFactory(this);
098            _stmtPoolFactory = stmtPoolFactory;
099            _validationQuery = validationQuery;
100            _validationQueryTimeout = validationQueryTimeout;
101            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
102            _defaultAutoCommit = defaultAutoCommit;
103        }
104        
105        /**
106         * Create a new <tt>PoolableConnectionFactory</tt>.
107         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
108         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
109         * @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
110         * @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.
111         * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
112         * @param connectionInitSqls a Collection of SQL statements to initialize {@link Connection}s. Using <tt>null</tt> turns off initialization.
113         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
114         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
115         * @since 1.3
116         */
117        public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, int validationQueryTimeout, Collection connectionInitSqls, boolean defaultReadOnly, boolean defaultAutoCommit) {
118            _connFactory = connFactory;
119            _pool = pool;
120            _pool.setFactory(this);
121            _stmtPoolFactory = stmtPoolFactory;
122            _validationQuery = validationQuery;
123            _validationQueryTimeout = validationQueryTimeout;
124            _connectionInitSqls = connectionInitSqls;
125            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
126            _defaultAutoCommit = defaultAutoCommit;
127        }
128    
129        /**
130         * Create a new <tt>PoolableConnectionFactory</tt>.
131         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
132         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
133         * @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
134         * @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.
135         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
136         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
137         * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
138         */
139        public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, boolean defaultReadOnly, boolean defaultAutoCommit, int defaultTransactionIsolation) {
140            _connFactory = connFactory;
141            _pool = pool;
142            _pool.setFactory(this);
143            _stmtPoolFactory = stmtPoolFactory;
144            _validationQuery = validationQuery;
145            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
146            _defaultAutoCommit = defaultAutoCommit;
147            _defaultTransactionIsolation = defaultTransactionIsolation;
148        }
149    
150        /**
151         * Create a new <tt>PoolableConnectionFactory</tt>.
152         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
153         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
154         * @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
155         * @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.
156         * @param connectionInitSqls a Collection of SQL statement to initialize {@link Connection}s. Using <tt>null</tt> turns off initialization.
157         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
158         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
159         * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
160         * @since 1.3
161         */
162        public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, Collection connectionInitSqls, boolean defaultReadOnly, boolean defaultAutoCommit, int defaultTransactionIsolation) {
163            _connFactory = connFactory;
164            _pool = pool;
165            _pool.setFactory(this);
166            _stmtPoolFactory = stmtPoolFactory;
167            _validationQuery = validationQuery;
168            _connectionInitSqls = connectionInitSqls;
169            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
170            _defaultAutoCommit = defaultAutoCommit;
171            _defaultTransactionIsolation = defaultTransactionIsolation;
172        }
173        
174        /**
175         * Create a new <tt>PoolableConnectionFactory</tt>.
176         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
177         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
178         * @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
179         * @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.
180         * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
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         * @since 1.3
185         */
186        public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, int validationQueryTimeout, boolean defaultReadOnly, boolean defaultAutoCommit, int defaultTransactionIsolation) {
187            _connFactory = connFactory;
188            _pool = pool;
189            _pool.setFactory(this);
190            _stmtPoolFactory = stmtPoolFactory;
191            _validationQuery = validationQuery;
192            _validationQueryTimeout = validationQueryTimeout;
193            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
194            _defaultAutoCommit = defaultAutoCommit;
195            _defaultTransactionIsolation = defaultTransactionIsolation;
196        }
197        
198        /**
199         * Create a new <tt>PoolableConnectionFactory</tt>.
200         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
201         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
202         * @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
203         * @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.
204         * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
205         * @param connectionInitSqls a Collection of SQL statement to initialize {@link Connection}s. Using <tt>null</tt> turns off initialization.
206         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
207         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
208         * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
209         * @since 1.3
210         */
211        public PoolableConnectionFactory(ConnectionFactory connFactory, ObjectPool pool, KeyedObjectPoolFactory stmtPoolFactory, String validationQuery, int validationQueryTimeout, Collection connectionInitSqls, boolean defaultReadOnly, boolean defaultAutoCommit, int defaultTransactionIsolation) {
212            _connFactory = connFactory;
213            _pool = pool;
214            _pool.setFactory(this);
215            _stmtPoolFactory = stmtPoolFactory;
216            _validationQuery = validationQuery;
217            _validationQueryTimeout = validationQueryTimeout;
218            _connectionInitSqls = connectionInitSqls;
219            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
220            _defaultAutoCommit = defaultAutoCommit;
221            _defaultTransactionIsolation = defaultTransactionIsolation;
222        }
223    
224        /**
225         * Create a new <tt>PoolableConnectionFactory</tt>.
226         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
227         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
228         * @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
229         * @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.
230         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
231         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
232         * @param config the AbandonedConfig if tracing SQL objects
233         */
234        public PoolableConnectionFactory(
235            ConnectionFactory connFactory,
236            ObjectPool pool,
237            KeyedObjectPoolFactory stmtPoolFactory,
238            String validationQuery,
239            boolean defaultReadOnly,
240            boolean defaultAutoCommit,
241            AbandonedConfig config) {
242    
243            _connFactory = connFactory;
244            _pool = pool;
245            _config = config;
246            _pool.setFactory(this);
247            _stmtPoolFactory = stmtPoolFactory;
248            _validationQuery = validationQuery;
249            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
250            _defaultAutoCommit = defaultAutoCommit;
251        }
252    
253        /**
254         * Create a new <tt>PoolableConnectionFactory</tt>.
255         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
256         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
257         * @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
258         * @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.
259         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
260         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
261         * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
262         * @param config the AbandonedConfig if tracing SQL objects
263         */
264        public PoolableConnectionFactory(
265            ConnectionFactory connFactory,
266            ObjectPool pool,
267            KeyedObjectPoolFactory stmtPoolFactory,
268            String validationQuery,
269            boolean defaultReadOnly,
270            boolean defaultAutoCommit,
271            int defaultTransactionIsolation,
272            AbandonedConfig config) {
273    
274            _connFactory = connFactory;
275            _pool = pool;
276            _config = config;
277            _pool.setFactory(this);
278            _stmtPoolFactory = stmtPoolFactory;
279            _validationQuery = validationQuery;
280            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
281            _defaultAutoCommit = defaultAutoCommit;
282            _defaultTransactionIsolation = defaultTransactionIsolation;
283        }
284    
285        /**
286         * Create a new <tt>PoolableConnectionFactory</tt>.
287         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
288         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
289         * @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
290         * @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.
291         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
292         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
293         * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
294         * @param defaultCatalog the default "catalog" setting for returned {@link Connection}s
295         * @param config the AbandonedConfig if tracing SQL objects
296         */
297        public PoolableConnectionFactory(
298            ConnectionFactory connFactory,
299            ObjectPool pool,
300            KeyedObjectPoolFactory stmtPoolFactory,
301            String validationQuery,
302            boolean defaultReadOnly,
303            boolean defaultAutoCommit,
304            int defaultTransactionIsolation,
305            String defaultCatalog,
306            AbandonedConfig config) {
307    
308            _connFactory = connFactory;
309            _pool = pool;
310            _config = config;
311            _pool.setFactory(this);
312            _stmtPoolFactory = stmtPoolFactory;
313            _validationQuery = validationQuery;
314            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
315            _defaultAutoCommit = defaultAutoCommit;
316            _defaultTransactionIsolation = defaultTransactionIsolation;
317            _defaultCatalog = defaultCatalog;
318        }
319    
320        /**
321         * Create a new <tt>PoolableConnectionFactory</tt>.
322         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
323         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
324         * @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
325         * @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.
326         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
327         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
328         * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
329         * @param defaultCatalog the default "catalog" setting for returned {@link Connection}s
330         * @param config the AbandonedConfig if tracing SQL objects
331         */
332        public PoolableConnectionFactory(
333            ConnectionFactory connFactory,
334            ObjectPool pool,
335            KeyedObjectPoolFactory stmtPoolFactory,
336            String validationQuery,
337            Boolean defaultReadOnly,
338            boolean defaultAutoCommit,
339            int defaultTransactionIsolation,
340            String defaultCatalog,
341            AbandonedConfig config) {
342    
343            _connFactory = connFactory;
344            _pool = pool;
345            _config = config;
346            _pool.setFactory(this);
347            _stmtPoolFactory = stmtPoolFactory;
348            _validationQuery = validationQuery;
349            _defaultReadOnly = defaultReadOnly;
350            _defaultAutoCommit = defaultAutoCommit;
351            _defaultTransactionIsolation = defaultTransactionIsolation;
352            _defaultCatalog = defaultCatalog;
353        }
354    
355        /**
356         * Create a new <tt>PoolableConnectionFactory</tt>.
357         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
358         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
359         * @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
360         * @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.
361         * @param connectionInitSqls a Collection of SQL statements to initialize {@link Connection}s. Using <tt>null</tt> turns off initialization.
362         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
363         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
364         * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
365         * @param defaultCatalog the default "catalog" setting for returned {@link Connection}s
366         * @param config the AbandonedConfig if tracing SQL objects
367         * @since 1.3
368         */
369        public PoolableConnectionFactory(
370            ConnectionFactory connFactory,
371            ObjectPool pool,
372            KeyedObjectPoolFactory stmtPoolFactory,
373            String validationQuery,
374            Collection connectionInitSqls,
375            Boolean defaultReadOnly,
376            boolean defaultAutoCommit,
377            int defaultTransactionIsolation,
378            String defaultCatalog,
379            AbandonedConfig config) {
380    
381            _connFactory = connFactory;
382            _pool = pool;
383            _config = config;
384            _pool.setFactory(this);
385            _stmtPoolFactory = stmtPoolFactory;
386            _validationQuery = validationQuery;
387            _connectionInitSqls = connectionInitSqls;
388            _defaultReadOnly = defaultReadOnly;
389            _defaultAutoCommit = defaultAutoCommit;
390            _defaultTransactionIsolation = defaultTransactionIsolation;
391            _defaultCatalog = defaultCatalog;
392        }
393        
394        /**
395         * Create a new <tt>PoolableConnectionFactory</tt>.
396         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
397         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
398         * @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
399         * @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.
400         * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
401         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
402         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
403         * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
404         * @param defaultCatalog the default "catalog" setting for returned {@link Connection}s
405         * @param config the AbandonedConfig if tracing SQL objects
406         * @since 1.3
407         */
408        public PoolableConnectionFactory(
409            ConnectionFactory connFactory,
410            ObjectPool pool,
411            KeyedObjectPoolFactory stmtPoolFactory,
412            String validationQuery,
413            int validationQueryTimeout,
414            Boolean defaultReadOnly,
415            boolean defaultAutoCommit,
416            int defaultTransactionIsolation,
417            String defaultCatalog,
418            AbandonedConfig config) {
419    
420            _connFactory = connFactory;
421            _pool = pool;
422            _config = config;
423            _pool.setFactory(this);
424            _stmtPoolFactory = stmtPoolFactory;
425            _validationQuery = validationQuery;
426            _validationQueryTimeout = validationQueryTimeout;
427            _defaultReadOnly = defaultReadOnly;
428            _defaultAutoCommit = defaultAutoCommit;
429            _defaultTransactionIsolation = defaultTransactionIsolation;
430            _defaultCatalog = defaultCatalog;
431        }
432        
433        /**
434         * Create a new <tt>PoolableConnectionFactory</tt>.
435         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
436         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
437         * @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
438         * @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.
439         * @param validationQueryTimeout the number of seconds that validation queries will wait for database response before failing.  Use a value less than or equal to 0 for no timeout.
440         * @param connectionInitSqls a Collection of SQL statements to initialize {@link Connection}s. Using <tt>null</tt> turns off initialization.
441         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
442         * @param defaultAutoCommit the default "auto commit" setting for returned {@link Connection}s
443         * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
444         * @param defaultCatalog the default "catalog" setting for returned {@link Connection}s
445         * @param config the AbandonedConfig if tracing SQL objects
446         * @since 1.3
447         */
448        public PoolableConnectionFactory(
449            ConnectionFactory connFactory,
450            ObjectPool pool,
451            KeyedObjectPoolFactory stmtPoolFactory,
452            String validationQuery,
453            int validationQueryTimeout,
454            Collection connectionInitSqls,
455            Boolean defaultReadOnly,
456            boolean defaultAutoCommit,
457            int defaultTransactionIsolation,
458            String defaultCatalog,
459            AbandonedConfig config) {
460    
461            _connFactory = connFactory;
462            _pool = pool;
463            _config = config;
464            _pool.setFactory(this);
465            _stmtPoolFactory = stmtPoolFactory;
466            _validationQuery = validationQuery;
467            _validationQueryTimeout = validationQueryTimeout;
468            _connectionInitSqls = connectionInitSqls;
469            _defaultReadOnly = defaultReadOnly;
470            _defaultAutoCommit = defaultAutoCommit;
471            _defaultTransactionIsolation = defaultTransactionIsolation;
472            _defaultCatalog = defaultCatalog;
473        }
474    
475        /**
476         * Sets the {@link ConnectionFactory} from which to obtain base {@link Connection}s.
477         * @param connFactory the {@link ConnectionFactory} from which to obtain base {@link Connection}s
478         */
479        public void setConnectionFactory(ConnectionFactory connFactory) {
480            _connFactory = connFactory;
481        }
482    
483        /**
484         * Sets the query I use to {@link #validateObject validate} {@link Connection}s.
485         * Should return at least one row.
486         * Using <tt>null</tt> turns off validation.
487         * @param validationQuery a query to use to {@link #validateObject validate} {@link Connection}s.
488         */
489        public void setValidationQuery(String validationQuery) {
490            _validationQuery = validationQuery;
491        }
492        
493        /**
494         * Sets the validation query timeout, the amount of time, in seconds, that
495         * connection validation will wait for a response from the database when
496         * executing a validation query.  Use a value less than or equal to 0 for
497         * no timeout.
498         *
499         * @param timeout new validation query timeout value in seconds
500         * @since 1.3
501         */
502        public void setValidationQueryTimeout(int timeout) {
503            _validationQueryTimeout = timeout;
504        }
505    
506        /**
507         * Sets the SQL statements I use to initialize newly created {@link Connection}s.
508         * Using <tt>null</tt> turns off connection initialization.
509         * @param connectionInitSqls SQL statement to initialize {@link Connection}s.
510         * @since 1.3
511         */
512        synchronized public void setConnectionInitSql(Collection connectionInitSqls) {
513            _connectionInitSqls = connectionInitSqls;
514        }
515    
516        /**
517         * Sets the {@link ObjectPool} in which to pool {@link Connection}s.
518         * @param pool the {@link ObjectPool} in which to pool those {@link Connection}s
519         */
520        synchronized public void setPool(ObjectPool pool) {
521            if(null != _pool && pool != _pool) {
522                try {
523                    _pool.close();
524                } catch(Exception e) {
525                    // ignored !?!
526                }
527            }
528            _pool = pool;
529        }
530    
531        /**
532         * Returns the {@link ObjectPool} in which {@link Connection}s are pooled.
533         * @return the connection pool
534         */
535        public synchronized ObjectPool getPool() {
536            return _pool;
537        }
538    
539        /**
540         * Sets the {@link KeyedObjectPoolFactory} I use to create {@link KeyedObjectPool}s
541         * for pooling {@link java.sql.PreparedStatement}s.
542         * Set to <tt>null</tt> to disable {@link java.sql.PreparedStatement} pooling.
543         * @param stmtPoolFactory the {@link KeyedObjectPoolFactory} to use to create {@link KeyedObjectPool}s for pooling {@link java.sql.PreparedStatement}s
544         */
545        public void setStatementPoolFactory(KeyedObjectPoolFactory stmtPoolFactory) {
546            _stmtPoolFactory = stmtPoolFactory;
547        }
548    
549        /**
550         * Sets the default "read only" setting for borrowed {@link Connection}s
551         * @param defaultReadOnly the default "read only" setting for borrowed {@link Connection}s
552         */
553        public void setDefaultReadOnly(boolean defaultReadOnly) {
554            _defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
555        }
556    
557        /**
558         * Sets the default "auto commit" setting for borrowed {@link Connection}s
559         * @param defaultAutoCommit the default "auto commit" setting for borrowed {@link Connection}s
560         */
561        public void setDefaultAutoCommit(boolean defaultAutoCommit) {
562            _defaultAutoCommit = defaultAutoCommit;
563        }
564    
565        /**
566         * Sets the default "Transaction Isolation" setting for borrowed {@link Connection}s
567         * @param defaultTransactionIsolation the default "Transaction Isolation" setting for returned {@link Connection}s
568         */
569        public void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
570            _defaultTransactionIsolation = defaultTransactionIsolation;
571        }
572    
573        /**
574         * Sets the default "catalog" setting for borrowed {@link Connection}s
575         * @param defaultCatalog the default "catalog" setting for borrowed {@link Connection}s
576         */
577        public void setDefaultCatalog(String defaultCatalog) {
578            _defaultCatalog = defaultCatalog;
579        }
580    
581        public Object makeObject() throws Exception {
582            Connection conn = _connFactory.createConnection();
583            if (conn == null) {
584                throw new IllegalStateException("Connection factory returned null from createConnection");
585            }
586            initializeConnection(conn);
587            if(null != _stmtPoolFactory) {
588                KeyedObjectPool stmtpool = _stmtPoolFactory.createPool();
589                conn = new PoolingConnection(conn,stmtpool);
590                stmtpool.setFactory((PoolingConnection)conn);
591            }
592            return new PoolableConnection(conn,_pool,_config);
593        }
594    
595        protected void initializeConnection(Connection conn) throws SQLException {
596            Collection sqls = _connectionInitSqls;
597            if(conn.isClosed()) {
598                throw new SQLException("initializeConnection: connection closed");
599            }
600            if(null != sqls) {
601                Statement stmt = null;
602                try {
603                    stmt = conn.createStatement();
604                    for (Iterator iterator = sqls.iterator(); iterator.hasNext();)
605                    {
606                        Object o = iterator.next();
607                        if (o == null) {
608                            throw new NullPointerException("null connectionInitSqls element");
609                        }
610                        // o might not be a String instance
611                        String sql = o.toString();
612                        stmt.execute(sql);
613                    }
614                } finally {
615                    if (stmt != null) {
616                        try {
617                            stmt.close();
618                        } catch(Exception t) {
619                            // ignored
620                        }
621                    }
622                }
623            }
624        }
625    
626        public void destroyObject(Object obj) throws Exception {
627            if(obj instanceof PoolableConnection) {
628                ((PoolableConnection)obj).reallyClose();
629            }
630        }
631    
632        public boolean validateObject(Object obj) {
633            if(obj instanceof Connection) {
634                try {
635                    validateConnection((Connection) obj);
636                    return true;
637                } catch(Exception e) {
638                    return false;
639                }
640            } else {
641                return false;
642            }
643        }
644    
645        public void validateConnection(Connection conn) throws SQLException {
646            String query = _validationQuery;
647            if(conn.isClosed()) {
648                throw new SQLException("validateConnection: connection closed");
649            }
650            if(null != query) {
651                Statement stmt = null;
652                ResultSet rset = null;
653                try {
654                    stmt = conn.createStatement();
655                    if (_validationQueryTimeout > 0) {
656                        stmt.setQueryTimeout(_validationQueryTimeout);
657                    }
658                    rset = stmt.executeQuery(query);
659                    if(!rset.next()) {
660                        throw new SQLException("validationQuery didn't return a row");
661                    }
662                } finally {
663                    if (rset != null) {
664                        try {
665                            rset.close();
666                        } catch(Exception t) {
667                            // ignored
668                        }
669                    }
670                    if (stmt != null) {
671                        try {
672                            stmt.close();
673                        } catch(Exception t) {
674                            // ignored
675                        }
676                    }
677                }
678            }
679        }
680    
681        public void passivateObject(Object obj) throws Exception {
682            if(obj instanceof Connection) {
683                Connection conn = (Connection)obj;
684                if(!conn.getAutoCommit() && !conn.isReadOnly()) {
685                    conn.rollback();
686                }
687                conn.clearWarnings();
688                if(!conn.getAutoCommit()) {
689                    conn.setAutoCommit(true);
690                }
691            }
692            if(obj instanceof DelegatingConnection) {
693                ((DelegatingConnection)obj).passivate();
694            }
695        }
696    
697        public void activateObject(Object obj) throws Exception {
698            if(obj instanceof DelegatingConnection) {
699                ((DelegatingConnection)obj).activate();
700            }
701            if(obj instanceof Connection) {
702                Connection conn = (Connection)obj;
703                if (conn.getAutoCommit() != _defaultAutoCommit) {
704                    conn.setAutoCommit(_defaultAutoCommit);
705                }
706                if ((_defaultTransactionIsolation != UNKNOWN_TRANSACTIONISOLATION) 
707                        && (conn.getTransactionIsolation() != 
708                        _defaultTransactionIsolation)) {
709                    conn.setTransactionIsolation(_defaultTransactionIsolation);
710                }
711                if ((_defaultReadOnly != null) && 
712                        (conn.isReadOnly() != _defaultReadOnly.booleanValue())) {
713                    conn.setReadOnly(_defaultReadOnly.booleanValue());
714                }
715                if ((_defaultCatalog != null) &&
716                        (!_defaultCatalog.equals(conn.getCatalog()))) {
717                    conn.setCatalog(_defaultCatalog);
718                }
719            }
720        }
721    
722        protected volatile ConnectionFactory _connFactory = null;
723        protected volatile String _validationQuery = null;
724        protected volatile int _validationQueryTimeout = -1;
725        protected Collection _connectionInitSqls = null;
726        protected volatile ObjectPool _pool = null;
727        protected volatile KeyedObjectPoolFactory _stmtPoolFactory = null;
728        protected Boolean _defaultReadOnly = null;
729        protected boolean _defaultAutoCommit = true;
730        protected int _defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION;
731        protected String _defaultCatalog;
732    
733        /**
734         * Configuration for removing abandoned connections.
735         */
736        protected AbandonedConfig _config = null;
737    
738        /**
739         * Internal constant to indicate the level is not set.
740         */
741        static final int UNKNOWN_TRANSACTIONISOLATION = -1;
742    }