KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > dbcp > BasicDataSource


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.io.PrintWriter JavaDoc;
20 import java.util.Properties JavaDoc;
21 import java.sql.Connection JavaDoc;
22 import java.sql.Driver JavaDoc;
23 import java.sql.DriverManager JavaDoc;
24 import java.sql.SQLException JavaDoc;
25 import javax.sql.DataSource JavaDoc;
26
27 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
28 import org.apache.commons.pool.impl.GenericKeyedObjectPoolFactory;
29 import org.apache.commons.pool.impl.GenericObjectPool;
30
31
32 /**
33  * <p>Basic implementation of <code>javax.sql.DataSource</code> that is
34  * configured via JavaBeans properties. This is not the only way to
35  * combine the <em>commons-dbcp</em> and <em>commons-pool</em> packages,
36  * but provides a "one stop shopping" solution for basic requirements.</p>
37  *
38  * @author Glenn L. Nielsen
39  * @author Craig R. McClanahan
40  * @author Dirk Verbeeck
41  * @version $Revision: 1.37 $ $Date: 2004/06/09 18:21:23 $
42  */

43 public class BasicDataSource implements DataSource JavaDoc {
44
45     // ------------------------------------------------------------- Properties
46

47     /**
48      * The default auto-commit state of connections created by this pool.
49      */

50     protected boolean defaultAutoCommit = true;
51
52     public synchronized boolean getDefaultAutoCommit() {
53         return this.defaultAutoCommit;
54     }
55
56     public synchronized void setDefaultAutoCommit(boolean defaultAutoCommit) {
57         this.defaultAutoCommit = defaultAutoCommit;
58         this.restartNeeded = true;
59     }
60
61
62     /**
63      * The default read-only state of connections created by this pool.
64      */

65     protected Boolean JavaDoc defaultReadOnly = null;
66
67     public synchronized boolean getDefaultReadOnly() {
68         if (this.defaultReadOnly != null) {
69             return this.defaultReadOnly.booleanValue();
70         }
71         return false;
72     }
73
74     public synchronized void setDefaultReadOnly(boolean defaultReadOnly) {
75         this.defaultReadOnly = defaultReadOnly ? Boolean.TRUE : Boolean.FALSE;
76         this.restartNeeded = true;
77     }
78
79     /**
80      * The default TransactionIsolation state of connections created by this pool.
81      */

82     protected int defaultTransactionIsolation = PoolableConnectionFactory.UNKNOWN_TRANSACTIONISOLATION;
83
84     public synchronized int getDefaultTransactionIsolation() {
85         return this.defaultTransactionIsolation;
86     }
87
88     public synchronized void setDefaultTransactionIsolation(int defaultTransactionIsolation) {
89         this.defaultTransactionIsolation = defaultTransactionIsolation;
90         this.restartNeeded = true;
91     }
92
93
94     /**
95      * The default "catalog" of connections created by this pool.
96      */

97     protected String JavaDoc defaultCatalog = null;
98
99     public synchronized String JavaDoc getDefaultCatalog() {
100         return this.defaultCatalog;
101     }
102
103     public synchronized void setDefaultCatalog(String JavaDoc defaultCatalog) {
104         if ((defaultCatalog != null) && (defaultCatalog.trim().length() > 0)) {
105             this.defaultCatalog = defaultCatalog;
106         }
107         else {
108             this.defaultCatalog = null;
109         }
110         this.restartNeeded = true;
111     }
112
113   
114     /**
115      * The fully qualified Java class name of the JDBC driver to be used.
116      */

117     protected String JavaDoc driverClassName = null;
118
119     public synchronized String JavaDoc getDriverClassName() {
120         return this.driverClassName;
121     }
122
123     public synchronized void setDriverClassName(String JavaDoc driverClassName) {
124         if ((driverClassName != null) && (driverClassName.trim().length() > 0)) {
125             this.driverClassName = driverClassName;
126         }
127         else {
128             this.driverClassName = null;
129         }
130         this.restartNeeded = true;
131     }
132
133
134     /**
135      * The maximum number of active connections that can be allocated from
136      * this pool at the same time, or zero for no limit.
137      */

138     protected int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
139
140     public synchronized int getMaxActive() {
141         return this.maxActive;
142     }
143
144     public synchronized void setMaxActive(int maxActive) {
145         this.maxActive = maxActive;
146         if (connectionPool != null) {
147             connectionPool.setMaxActive(maxActive);
148         }
149     }
150
151
152     /**
153      * The maximum number of active connections that can remain idle in the
154      * pool, without extra ones being released, or zero for no limit.
155      */

156     protected int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;;
157
158     public synchronized int getMaxIdle() {
159         return this.maxIdle;
160     }
161
162     public synchronized void setMaxIdle(int maxIdle) {
163         this.maxIdle = maxIdle;
164         if (connectionPool != null) {
165             connectionPool.setMaxIdle(maxIdle);
166         }
167     }
168
169     /**
170      * The minimum number of active connections that can remain idle in the
171      * pool, without extra ones being created, or 0 to create none.
172      */

173     protected int minIdle = GenericObjectPool.DEFAULT_MIN_IDLE;;
174
175     public synchronized int getMinIdle() {
176         return this.minIdle;
177     }
178
179     public synchronized void setMinIdle(int minIdle) {
180        this.minIdle = minIdle;
181        if (connectionPool != null) {
182            connectionPool.setMinIdle(minIdle);
183        }
184     }
185
186     /**
187      * The initial number of connections that are created when the pool
188      * is started.
189      * @since 1.2
190      */

191     protected int initialSize = 0;
192     
193     public synchronized int getInitialSize() {
194         return this.initialSize;
195     }
196     
197     public synchronized void setInitialSize(int initialSize) {
198         this.initialSize = initialSize;
199         this.restartNeeded = true;
200     }
201
202     /**
203      * The maximum number of milliseconds that the pool will wait (when there
204      * are no available connections) for a connection to be returned before
205      * throwing an exception, or -1 to wait indefinitely.
206      */

207     protected long maxWait = GenericObjectPool.DEFAULT_MAX_WAIT;
208
209     public synchronized long getMaxWait() {
210         return this.maxWait;
211     }
212
213     public synchronized void setMaxWait(long maxWait) {
214         this.maxWait = maxWait;
215         if (connectionPool != null) {
216             connectionPool.setMaxWait(maxWait);
217         }
218     }
219
220     /**
221      * Prepared statement pooling for this pool.
222      */

223     protected boolean poolPreparedStatements = false;
224     
225     /**
226      * Returns true if we are pooling statements.
227      * @return boolean
228      */

229     public synchronized boolean isPoolPreparedStatements() {
230         return this.poolPreparedStatements;
231     }
232
233     /**
234      * Sets whether to pool statements or not.
235      * @param poolPreparedStatements pooling on or off
236      */

237     public synchronized void setPoolPreparedStatements(boolean poolingStatements) {
238         this.poolPreparedStatements = poolingStatements;
239         this.restartNeeded = true;
240     }
241
242     /**
243      * The maximum number of open statements that can be allocated from
244      * the statement pool at the same time, or zero for no limit. Since
245      * a connection usually only uses one or two statements at a time, this is
246      * mostly used to help detect resource leaks.
247      */

248     protected int maxOpenPreparedStatements = GenericKeyedObjectPool.DEFAULT_MAX_TOTAL;
249
250     public synchronized int getMaxOpenPreparedStatements() {
251         return this.maxOpenPreparedStatements;
252     }
253
254     public synchronized void setMaxOpenPreparedStatements(int maxOpenStatements) {
255         this.maxOpenPreparedStatements = maxOpenStatements;
256         this.restartNeeded = true;
257     }
258
259     /**
260      * The indication of whether objects will be validated before being
261      * borrowed from the pool. If the object fails to validate, it will be
262      * dropped from the pool, and we will attempt to borrow another.
263      */

264     protected boolean testOnBorrow = true;
265
266     public synchronized boolean getTestOnBorrow() {
267         return this.testOnBorrow;
268     }
269
270     public synchronized void setTestOnBorrow(boolean testOnBorrow) {
271         this.testOnBorrow = testOnBorrow;
272         if (connectionPool != null) {
273             connectionPool.setTestOnBorrow(testOnBorrow);
274         }
275     }
276
277     /**
278      * The indication of whether objects will be validated before being
279      * returned to the pool.
280      */

281     protected boolean testOnReturn = false;
282
283     public synchronized boolean getTestOnReturn() {
284         return this.testOnReturn;
285     }
286
287     public synchronized void setTestOnReturn(boolean testOnReturn) {
288         this.testOnReturn = testOnReturn;
289         if (connectionPool != null) {
290             connectionPool.setTestOnReturn(testOnReturn);
291         }
292     }
293
294
295     /**
296      * The number of milliseconds to sleep between runs of the idle object
297      * evictor thread. When non-positive, no idle object evictor thread will
298      * be run.
299      */

300     protected long timeBetweenEvictionRunsMillis =
301         GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS;
302         
303     public synchronized long getTimeBetweenEvictionRunsMillis() {
304         return this.timeBetweenEvictionRunsMillis;
305     }
306
307     public synchronized void setTimeBetweenEvictionRunsMillis(long timeBetweenEvictionRunsMillis) {
308         this.timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
309         if (connectionPool != null) {
310             connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
311         }
312     }
313
314
315     /**
316      * The number of objects to examine during each run of the idle object
317      * evictor thread (if any).
318      */

319     protected int numTestsPerEvictionRun =
320         GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
321
322     public synchronized int getNumTestsPerEvictionRun() {
323         return this.numTestsPerEvictionRun;
324     }
325
326     public synchronized void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
327         this.numTestsPerEvictionRun = numTestsPerEvictionRun;
328         if (connectionPool != null) {
329             connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
330         }
331     }
332
333
334     /**
335      * The minimum amount of time an object may sit idle in the pool before it
336      * is eligable for eviction by the idle object evictor (if any).
337      */

338     protected long minEvictableIdleTimeMillis =
339         GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS;
340
341     public synchronized long getMinEvictableIdleTimeMillis() {
342         return this.minEvictableIdleTimeMillis;
343     }
344
345     public synchronized void setMinEvictableIdleTimeMillis(long minEvictableIdleTimeMillis) {
346         this.minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
347         if (connectionPool != null) {
348             connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
349         }
350     }
351
352     /**
353      * The indication of whether objects will be validated by the idle object
354      * evictor (if any). If an object fails to validate, it will be dropped
355      * from the pool.
356      */

357     protected boolean testWhileIdle = false;
358
359     public synchronized boolean getTestWhileIdle() {
360         return this.testWhileIdle;
361     }
362
363     public synchronized void setTestWhileIdle(boolean testWhileIdle) {
364         this.testWhileIdle = testWhileIdle;
365         if (connectionPool != null) {
366             connectionPool.setTestWhileIdle(testWhileIdle);
367         }
368     }
369
370     /**
371      * [Read Only] The current number of active connections that have been
372      * allocated from this data source.
373      */

374     public synchronized int getNumActive() {
375         if (connectionPool != null) {
376             return connectionPool.getNumActive();
377         } else {
378             return 0;
379         }
380     }
381
382
383     /**
384      * [Read Only] The current number of idle connections that are waiting
385      * to be allocated from this data source.
386      */

387     public synchronized int getNumIdle() {
388         if (connectionPool != null) {
389             return connectionPool.getNumIdle();
390         } else {
391             return 0;
392         }
393     }
394
395
396     /**
397      * The connection password to be passed to our JDBC driver to establish
398      * a connection.
399      */

400     protected String JavaDoc password = null;
401
402     public synchronized String JavaDoc getPassword() {
403         return this.password;
404     }
405
406     public synchronized void setPassword(String JavaDoc password) {
407         this.password = password;
408         this.restartNeeded = true;
409     }
410
411
412     /**
413      * The connection URL to be passed to our JDBC driver to establish
414      * a connection.
415      */

416     protected String JavaDoc url = null;
417
418     public synchronized String JavaDoc getUrl() {
419         return this.url;
420     }
421
422     public synchronized void setUrl(String JavaDoc url) {
423         this.url = url;
424         this.restartNeeded = true;
425     }
426
427
428     /**
429      * The connection username to be passed to our JDBC driver to
430      * establish a connection.
431      */

432     protected String JavaDoc username = null;
433
434     public synchronized String JavaDoc getUsername() {
435         return this.username;
436     }
437
438     public synchronized void setUsername(String JavaDoc username) {
439         this.username = username;
440         this.restartNeeded = true;
441     }
442
443
444     /**
445      * The SQL query that will be used to validate connections from this pool
446      * before returning them to the caller. If specified, this query
447      * <strong>MUST</strong> be an SQL SELECT statement that returns at least
448      * one row.
449      */

450     protected String JavaDoc validationQuery = null;
451
452     public synchronized String JavaDoc getValidationQuery() {
453         return this.validationQuery;
454     }
455
456     public synchronized void setValidationQuery(String JavaDoc validationQuery) {
457         if ((validationQuery != null) && (validationQuery.trim().length() > 0)) {
458             this.validationQuery = validationQuery;
459         } else {
460             this.validationQuery = null;
461         }
462         this.restartNeeded = true;
463     }
464
465     /**
466      * Controls access to the underlying connection
467      */

468     private boolean accessToUnderlyingConnectionAllowed = false;
469
470     /**
471      * Returns the value of the accessToUnderlyingConnectionAllowed property.
472      *
473      * @return true if access to the underlying is allowed, false otherwise.
474      */

475     public synchronized boolean isAccessToUnderlyingConnectionAllowed() {
476         return this.accessToUnderlyingConnectionAllowed;
477     }
478
479     /**
480      * Sets the value of the accessToUnderlyingConnectionAllowed property.
481      * It controls if the PoolGuard allows access to the underlying connection.
482      * (Default: false)
483      *
484      * @param allow Access to the underlying connection is granted when true.
485      */

486     public synchronized void setAccessToUnderlyingConnectionAllowed(boolean allow) {
487         this.accessToUnderlyingConnectionAllowed = allow;
488         this.restartNeeded = true;
489     }
490
491     // ----------------------------------------------------- Instance Variables
492

493     // TODO: review & make isRestartNeeded() public, restartNeeded protected
494

495     private boolean restartNeeded = false;
496     
497     /**
498      * Returns whether or not a restart is needed.
499      * @return true if a restart is needed
500      */

501     private synchronized boolean isRestartNeeded() {
502         return restartNeeded;
503     }
504
505     /**
506      * The object pool that internally manages our connections.
507      */

508     protected GenericObjectPool connectionPool = null;
509     
510     /**
511      * The connection properties that will be sent to our JDBC driver when
512      * establishing new connections. <strong>NOTE</strong> - The "user" and
513      * "password" properties will be passed explicitly, so they do not need
514      * to be included here.
515      */

516     protected Properties JavaDoc connectionProperties = new Properties JavaDoc();
517
518     /**
519      * The data source we will use to manage connections. This object should
520      * be acquired <strong>ONLY</strong> by calls to the
521      * <code>createDataSource()</code> method.
522      */

523     protected DataSource JavaDoc dataSource = null;
524
525     /**
526      * The PrintWriter to which log messages should be directed.
527      */

528     protected PrintWriter JavaDoc logWriter = new PrintWriter JavaDoc(System.out);
529
530
531     // ----------------------------------------------------- DataSource Methods
532

533
534     /**
535      * Create (if necessary) and return a connection to the database.
536      *
537      * @exception SQLException if a database access error occurs
538      */

539     public Connection JavaDoc getConnection() throws SQLException JavaDoc {
540         return createDataSource().getConnection();
541     }
542
543
544     /**
545      * Create (if necessary) and return a connection to the database.
546      *
547      * @param username Database user on whose behalf the Connection
548      * is being made
549      * @param password The database user's password
550      *
551      * @exception SQLException if a database access error occurs
552      */

553     public Connection JavaDoc getConnection(String JavaDoc username, String JavaDoc password) throws SQLException JavaDoc {
554         return createDataSource().getConnection(username, password);
555     }
556
557
558     /**
559      * Return the login timeout (in seconds) for connecting to the database.
560      *
561      * @exception SQLException if a database access error occurs
562      */

563     public int getLoginTimeout() throws SQLException JavaDoc {
564         return createDataSource().getLoginTimeout();
565     }
566
567
568     /**
569      * Return the log writer being used by this data source.
570      *
571      * @exception SQLException if a database access error occurs
572      */

573     public PrintWriter JavaDoc getLogWriter() throws SQLException JavaDoc {
574         return createDataSource().getLogWriter();
575     }
576
577
578     /**
579      * Set the login timeout (in seconds) for connecting to the database.
580      *
581      * @param loginTimeout The new login timeout, or zero for no timeout
582      *
583      * @exception SQLException if a database access error occurs
584      */

585     public void setLoginTimeout(int loginTimeout) throws SQLException JavaDoc {
586         createDataSource().setLoginTimeout(loginTimeout);
587     }
588
589
590     /**
591      * Set the log writer being used by this data source.
592      *
593      * @param logWriter The new log writer
594      *
595      * @exception SQLException if a database access error occurs
596      */

597     public void setLogWriter(PrintWriter JavaDoc logWriter) throws SQLException JavaDoc {
598         createDataSource().setLogWriter(logWriter);
599         this.logWriter = logWriter;
600     }
601
602     private AbandonedConfig abandonedConfig;
603
604     /**
605      * Flag to remove abandoned connections if they exceed the
606      * removeAbandonedTimout.
607      *
608      * Set to true or false, default false.
609      * If set to true a connection is considered abandoned and eligible
610      * for removal if it has been idle longer than the removeAbandonedTimeout.
611      * Setting this to true can recover db connections from poorly written
612      * applications which fail to close a connection.
613      * @deprecated
614      */

615     public boolean getRemoveAbandoned() {
616         if (abandonedConfig != null) {
617             return abandonedConfig.getRemoveAbandoned();
618         }
619         return false;
620     }
621                                  
622     /**
623      * @deprecated
624      * @param removeAbandoned
625      */

626     public void setRemoveAbandoned(boolean removeAbandoned) {
627         if (abandonedConfig == null) {
628             abandonedConfig = new AbandonedConfig();
629         }
630         abandonedConfig.setRemoveAbandoned(removeAbandoned);
631         this.restartNeeded = true;
632     }
633                                                
634     /**
635      * Timeout in seconds before an abandoned connection can be removed.
636      *
637      * Defaults to 300 seconds.
638      * @deprecated
639      */

640     public int getRemoveAbandonedTimeout() {
641         if (abandonedConfig != null) {
642             return abandonedConfig.getRemoveAbandonedTimeout();
643         }
644         return 300;
645     }
646
647     /**
648      * @deprecated
649      * @param removeAbandonedTimeout
650      */

651     public void setRemoveAbandonedTimeout(int removeAbandonedTimeout) {
652         if (abandonedConfig == null) {
653             abandonedConfig = new AbandonedConfig();
654         }
655         abandonedConfig.setRemoveAbandonedTimeout(removeAbandonedTimeout);
656         this.restartNeeded = true;
657     }
658                                                              
659     /**
660      * Flag to log stack traces for application code which abandoned
661      * a Statement or Connection.
662      *
663      * Defaults to false.
664      *
665      * Logging of abandoned Statements and Connections adds overhead
666      * for every Connection open or new Statement because a stack
667      * trace has to be generated.
668      * @deprecated
669      */

670     public boolean getLogAbandoned() {
671         if (abandonedConfig != null) {
672             return abandonedConfig.getLogAbandoned();
673         }
674         return false;
675     }
676
677     /**
678      * @deprecated
679      * @param logAbandoned
680      */

681     public void setLogAbandoned(boolean logAbandoned) {
682         if (abandonedConfig == null) {
683             abandonedConfig = new AbandonedConfig();
684         }
685         abandonedConfig.setLogAbandoned(logAbandoned);
686         this.restartNeeded = true;
687     }
688
689     // --------------------------------------------------------- Public Methods
690

691     /**
692      * Add a custom connection property to the set that will be passed to our
693      * JDBC driver. This <strong>MUST</strong> be called before the first
694      * connection is retrieved (along with all the other configuration
695      * property setters).
696      *
697      * @param name Name of the custom connection property
698      * @param value Value of the custom connection property
699      */

700     public void addConnectionProperty(String JavaDoc name, String JavaDoc value) {
701         connectionProperties.put(name, value);
702         this.restartNeeded = true;
703     }
704
705     public void removeConnectionProperty(String JavaDoc name) {
706         connectionProperties.remove(name);
707         this.restartNeeded = true;
708     }
709
710     /**
711      * Close and release all connections that are currently stored in the
712      * connection pool associated with our data source.
713      *
714      * @exception SQLException if a database error occurs
715      */

716     public synchronized void close() throws SQLException JavaDoc {
717         GenericObjectPool oldpool = connectionPool;
718         connectionPool = null;
719         dataSource = null;
720         try {
721             if (oldpool != null) {
722                 oldpool.close();
723             }
724         } catch(SQLException JavaDoc e) {
725             throw e;
726         } catch(RuntimeException JavaDoc e) {
727             throw e;
728         } catch(Exception JavaDoc e) {
729             throw new SQLNestedException("Cannot close connection pool", e);
730         }
731     }
732
733
734     // ------------------------------------------------------ Protected Methods
735

736
737     /**
738      * <p>Create (if necessary) and return the internal data source we are
739      * using to manage our connections.</p>
740      *
741      * <p><strong>IMPLEMENTATION NOTE</strong> - It is tempting to use the
742      * "double checked locking" idiom in an attempt to avoid synchronizing
743      * on every single call to this method. However, this idiom fails to
744      * work correctly in the face of some optimizations that are legal for
745      * a JVM to perform.</p>
746      *
747      * @exception SQLException if the object pool cannot be created.
748      */

749     protected synchronized DataSource JavaDoc createDataSource()
750         throws SQLException JavaDoc {
751
752         // Return the pool if we have already created it
753
if (dataSource != null) {
754             return (dataSource);
755         }
756
757         // Load the JDBC driver class
758
if (driverClassName != null) {
759             try {
760                 Class.forName(driverClassName);
761             } catch (Throwable JavaDoc t) {
762                 String JavaDoc message = "Cannot load JDBC driver class '" +
763                     driverClassName + "'";
764                 logWriter.println(message);
765                 t.printStackTrace(logWriter);
766                 throw new SQLNestedException(message, t);
767             }
768         }
769
770         // Create a JDBC driver instance
771
Driver JavaDoc driver = null;
772         try {
773             driver = DriverManager.getDriver(url);
774         } catch (Throwable JavaDoc t) {
775             String JavaDoc message = "Cannot create JDBC driver of class '" +
776                 (driverClassName != null ? driverClassName : "") +
777                 "' for connect URL '" + url + "'";
778             logWriter.println(message);
779             t.printStackTrace(logWriter);
780             throw new SQLNestedException(message, t);
781         }
782
783         // Can't test without a validationQuery
784
if (validationQuery == null) {
785             setTestOnBorrow(false);
786             setTestOnReturn(false);
787             setTestWhileIdle(false);
788         }
789
790         // Create an object pool to contain our active connections
791
if ((abandonedConfig != null) && (abandonedConfig.getRemoveAbandoned() == true)) {
792             connectionPool = new AbandonedObjectPool(null,abandonedConfig);
793         }
794         else {
795             connectionPool = new GenericObjectPool();
796         }
797         connectionPool.setMaxActive(maxActive);
798         connectionPool.setMaxIdle(maxIdle);
799         connectionPool.setMinIdle(minIdle);
800         connectionPool.setMaxWait(maxWait);
801         connectionPool.setTestOnBorrow(testOnBorrow);
802         connectionPool.setTestOnReturn(testOnReturn);
803         connectionPool.setTimeBetweenEvictionRunsMillis(timeBetweenEvictionRunsMillis);
804         connectionPool.setNumTestsPerEvictionRun(numTestsPerEvictionRun);
805         connectionPool.setMinEvictableIdleTimeMillis(minEvictableIdleTimeMillis);
806         connectionPool.setTestWhileIdle(testWhileIdle);
807         
808         // Set up statement pool, if desired
809
GenericKeyedObjectPoolFactory statementPoolFactory = null;
810         if (isPoolPreparedStatements()) {
811             statementPoolFactory = new GenericKeyedObjectPoolFactory(null,
812                         -1, // unlimited maxActive (per key)
813
GenericKeyedObjectPool.WHEN_EXHAUSTED_FAIL,
814                         0, // maxWait
815
1, // maxIdle (per key)
816
maxOpenPreparedStatements);
817         }
818
819         // Set up the driver connection factory we will use
820
if (username != null) {
821             connectionProperties.put("user", username);
822         } else {
823             log("DBCP DataSource configured without a 'username'");
824         }
825         
826         if (password != null) {
827             connectionProperties.put("password", password);
828         } else {
829             log("DBCP DataSource configured without a 'password'");
830         }
831         
832         DriverConnectionFactory driverConnectionFactory =
833             new DriverConnectionFactory(driver, url, connectionProperties);
834
835         // Set up the poolable connection factory we will use
836
PoolableConnectionFactory connectionFactory = null;
837         try {
838             connectionFactory =
839                 new PoolableConnectionFactory(driverConnectionFactory,
840                                               connectionPool,
841                                               statementPoolFactory,
842                                               validationQuery,
843                                               defaultReadOnly,
844                                               defaultAutoCommit,
845                                               defaultTransactionIsolation,
846                                               defaultCatalog,
847                                               abandonedConfig);
848             if (connectionFactory == null) {
849                 throw new SQLException JavaDoc("Cannot create PoolableConnectionFactory");
850             }
851             validateConnectionFactory(connectionFactory);
852         } catch (RuntimeException JavaDoc e) {
853             throw e;
854         } catch (Exception JavaDoc e) {
855             throw new SQLNestedException("Cannot create PoolableConnectionFactory (" + e.getMessage() + ")", e);
856         }
857
858         // Create and return the pooling data source to manage the connections
859
dataSource = new PoolingDataSource(connectionPool);
860         ((PoolingDataSource) dataSource).setAccessToUnderlyingConnectionAllowed(isAccessToUnderlyingConnectionAllowed());
861         dataSource.setLogWriter(logWriter);
862         
863         try {
864             for (int i = 0 ; i < initialSize ; i++) {
865                 connectionPool.addObject();
866             }
867         } catch (Exception JavaDoc e) {
868             throw new SQLNestedException("Error preloading the connection pool", e);
869         }
870         
871         return dataSource;
872     }
873
874     private static void validateConnectionFactory(PoolableConnectionFactory connectionFactory) throws Exception JavaDoc {
875         Connection JavaDoc conn = null;
876         try {
877             conn = (Connection JavaDoc) connectionFactory.makeObject();
878             connectionFactory.activateObject(conn);
879             connectionFactory.validateConnection(conn);
880             connectionFactory.passivateObject(conn);
881         }
882         finally {
883             connectionFactory.destroyObject(conn);
884         }
885     }
886
887     private void restart() {
888         try {
889             close();
890         } catch (SQLException JavaDoc e) {
891             log("Could not restart DataSource, cause: " + e.getMessage());
892         }
893     }
894
895     private void log(String JavaDoc message) {
896         if (logWriter != null) {
897             logWriter.println(message);
898         }
899     }
900 }
901
Popular Tags