KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > dbcp > datasources > InstanceKeyDataSource


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.datasources;
18
19 import java.io.Serializable JavaDoc;
20 import java.io.PrintWriter JavaDoc;
21 import java.sql.Connection JavaDoc;
22 import java.sql.SQLException JavaDoc;
23 import java.util.NoSuchElementException JavaDoc;
24 import java.util.Properties JavaDoc;
25
26 import javax.naming.Context JavaDoc;
27 import javax.naming.InitialContext JavaDoc;
28 import javax.naming.NamingException JavaDoc;
29 import javax.naming.Reference JavaDoc;
30 import javax.naming.StringRefAddr JavaDoc;
31 import javax.naming.Referenceable JavaDoc;
32 import javax.sql.ConnectionPoolDataSource JavaDoc;
33 import javax.sql.DataSource JavaDoc;
34 import javax.sql.PooledConnection JavaDoc;
35
36 import org.apache.commons.dbcp.SQLNestedException;
37 import org.apache.commons.pool.impl.GenericObjectPool;
38
39 /**
40  * <p>The base class for <code>SharedPoolDataSource</code> and
41  * <code>PerUserPoolDataSource</code>. Many of the configuration properties
42  * are shared and defined here. This class is declared public in order
43  * to allow particular usage with commons-beanutils; do not make direct
44  * use of it outside of commons-dbcp.
45  * </p>
46  *
47  * <p>
48  * A J2EE container will normally provide some method of initializing the
49  * <code>DataSource</code> whose attributes are presented
50  * as bean getters/setters and then deploying it via JNDI. It is then
51  * available to an application as a source of pooled logical connections to
52  * the database. The pool needs a source of physical connections. This
53  * source is in the form of a <code>ConnectionPoolDataSource</code> that
54  * can be specified via the {@link #setDataSourceName(String)} used to
55  * lookup the source via JNDI.
56  * </p>
57  *
58  * <p>
59  * Although normally used within a JNDI environment, A DataSource
60  * can be instantiated and initialized as any bean. In this case the
61  * <code>ConnectionPoolDataSource</code> will likely be instantiated in
62  * a similar manner. This class allows the physical source of connections
63  * to be attached directly to this pool using the
64  * {@link #setConnectionPoolDataSource(ConnectionPoolDataSource)} method.
65  * </p>
66  *
67  * <p>
68  * The dbcp package contains an adapter,
69  * {@link org.apache.commons.dbcp.cpdsadapter.DriverAdapterCPDS},
70  * that can be used to allow the use of <code>DataSource</code>'s based on this
71  * class with jdbc driver implementations that do not supply a
72  * <code>ConnectionPoolDataSource</code>, but still
73  * provide a {@link java.sql.Driver} implementation.
74  * </p>
75  *
76  * <p>
77  * The <a HREF="package-summary.html">package documentation</a> contains an
78  * example using catalina and JNDI and it also contains a non-JNDI example.
79  * </p>
80  *
81  * @author John D. McNally
82  * @version $Revision: 1.11 $ $Date: 2004/02/28 12:18:17 $
83  */

84 public abstract class InstanceKeyDataSource
85         implements DataSource JavaDoc, Referenceable JavaDoc, Serializable JavaDoc {
86     private static final String JavaDoc GET_CONNECTION_CALLED
87             = "A Connection was already requested from this source, "
88             + "further initialization is not allowed.";
89     private static final String JavaDoc BAD_TRANSACTION_ISOLATION
90         = "The requested TransactionIsolation level is invalid.";
91     /**
92     * Internal constant to indicate the level is not set.
93     */

94     protected static final int UNKNOWN_TRANSACTIONISOLATION = -1;
95
96     private boolean getConnectionCalled = false;
97
98     private ConnectionPoolDataSource JavaDoc cpds = null;
99     /** DataSource Name used to find the ConnectionPoolDataSource */
100     private String JavaDoc dataSourceName = null;
101     private boolean defaultAutoCommit = false;
102     private int defaultTransactionIsolation = UNKNOWN_TRANSACTIONISOLATION;
103     private int maxActive = GenericObjectPool.DEFAULT_MAX_ACTIVE;
104     private int maxIdle = GenericObjectPool.DEFAULT_MAX_IDLE;
105     private int maxWait = (int)Math.min((long)Integer.MAX_VALUE,
106         GenericObjectPool.DEFAULT_MAX_WAIT);
107     private boolean defaultReadOnly = false;
108     /** Description */
109     private String JavaDoc description = null;
110     /** Environment that may be used to set up a jndi initial context. */
111     Properties JavaDoc jndiEnvironment = null;
112     /** Login TimeOut in seconds */
113     private int loginTimeout = 0;
114     /** Log stream */
115     private PrintWriter JavaDoc logWriter = null;
116     private boolean _testOnBorrow = GenericObjectPool.DEFAULT_TEST_ON_BORROW;
117     private boolean _testOnReturn = GenericObjectPool.DEFAULT_TEST_ON_RETURN;
118     private int _timeBetweenEvictionRunsMillis = (int)
119         Math.min((long)Integer.MAX_VALUE,
120                  GenericObjectPool.DEFAULT_TIME_BETWEEN_EVICTION_RUNS_MILLIS);
121     private int _numTestsPerEvictionRun =
122         GenericObjectPool.DEFAULT_NUM_TESTS_PER_EVICTION_RUN;
123     private int _minEvictableIdleTimeMillis = (int)
124     Math.min((long)Integer.MAX_VALUE,
125              GenericObjectPool.DEFAULT_MIN_EVICTABLE_IDLE_TIME_MILLIS);
126     private boolean _testWhileIdle = GenericObjectPool.DEFAULT_TEST_WHILE_IDLE;
127     private String JavaDoc validationQuery = null;
128     private boolean testPositionSet = false;
129
130     protected String JavaDoc instanceKey = null;
131
132     /**
133      * Default no-arg constructor for Serialization
134      */

135     public InstanceKeyDataSource() {
136         defaultAutoCommit = true;
137     }
138
139     /**
140      * Throws an IllegalStateException, if a PooledConnection has already
141      * been requested.
142      */

143     protected void assertInitializationAllowed()
144         throws IllegalStateException JavaDoc {
145         if (getConnectionCalled) {
146             throw new IllegalStateException JavaDoc(GET_CONNECTION_CALLED);
147         }
148     }
149
150     /**
151      * Close pool being maintained by this datasource.
152      */

153     public abstract void close() throws Exception JavaDoc;
154
155     // -------------------------------------------------------------------
156
// Properties
157

158     /**
159      * Get the value of connectionPoolDataSource. This method will return
160      * null, if the backing datasource is being accessed via jndi.
161      *
162      * @return value of connectionPoolDataSource.
163      */

164     public ConnectionPoolDataSource JavaDoc getConnectionPoolDataSource() {
165         return cpds;
166     }
167     
168     /**
169      * Set the backend ConnectionPoolDataSource. This property should not be
170      * set if using jndi to access the datasource.
171      *
172      * @param v Value to assign to connectionPoolDataSource.
173      */

174     public void setConnectionPoolDataSource(ConnectionPoolDataSource JavaDoc v) {
175         assertInitializationAllowed();
176         if (dataSourceName != null) {
177             throw new IllegalStateException JavaDoc(
178                 "Cannot set the DataSource, if JNDI is used.");
179         }
180         if (cpds != null)
181         {
182             throw new IllegalStateException JavaDoc(
183                 "The CPDS has already been set. It cannot be altered.");
184         }
185         cpds = v;
186         instanceKey = InstanceKeyObjectFactory.registerNewInstance(this);
187     }
188
189     /**
190      * Get the name of the ConnectionPoolDataSource which backs this pool.
191      * This name is used to look up the datasource from a jndi service
192      * provider.
193      *
194      * @return value of dataSourceName.
195      */

196     public String JavaDoc getDataSourceName() {
197         return dataSourceName;
198     }
199     
200     /**
201      * Set the name of the ConnectionPoolDataSource which backs this pool.
202      * This name is used to look up the datasource from a jndi service
203      * provider.
204      *
205      * @param v Value to assign to dataSourceName.
206      */

207     public void setDataSourceName(String JavaDoc v) {
208         assertInitializationAllowed();
209         if (cpds != null) {
210             throw new IllegalStateException JavaDoc(
211                 "Cannot set the JNDI name for the DataSource, if already " +
212                 "set using setConnectionPoolDataSource.");
213         }
214         if (dataSourceName != null)
215         {
216             throw new IllegalStateException JavaDoc(
217                 "The DataSourceName has already been set. " +
218                 "It cannot be altered.");
219         }
220         this.dataSourceName = v;
221         instanceKey = InstanceKeyObjectFactory.registerNewInstance(this);
222     }
223
224     /**
225      * Get the value of defaultAutoCommit, which defines the state of
226      * connections handed out from this pool. The value can be changed
227      * on the Connection using Connection.setAutoCommit(boolean).
228      * The default is true.
229      *
230      * @return value of defaultAutoCommit.
231      */

232     public boolean isDefaultAutoCommit() {
233         return defaultAutoCommit;
234     }
235     
236     /**
237      * Set the value of defaultAutoCommit, which defines the state of
238      * connections handed out from this pool. The value can be changed
239      * on the Connection using Connection.setAutoCommit(boolean).
240      * The default is true.
241      *
242      * @param v Value to assign to defaultAutoCommit.
243      */

244     public void setDefaultAutoCommit(boolean v) {
245         assertInitializationAllowed();
246         this.defaultAutoCommit = v;
247     }
248
249     /**
250      * Get the value of defaultReadOnly, which defines the state of
251      * connections handed out from this pool. The value can be changed
252      * on the Connection using Connection.setReadOnly(boolean).
253      * The default is false.
254      *
255      * @return value of defaultReadOnly.
256      */

257     public boolean isDefaultReadOnly() {
258         return defaultReadOnly;
259     }
260     
261     /**
262      * Set the value of defaultReadOnly, which defines the state of
263      * connections handed out from this pool. The value can be changed
264      * on the Connection using Connection.setReadOnly(boolean).
265      * The default is false.
266      *
267      * @param v Value to assign to defaultReadOnly.
268      */

269     public void setDefaultReadOnly(boolean v) {
270         assertInitializationAllowed();
271         this.defaultReadOnly = v;
272     }
273
274     /**
275      * Get the value of defaultTransactionIsolation, which defines the state of
276      * connections handed out from this pool. The value can be changed
277      * on the Connection using Connection.setTransactionIsolation(int).
278      * If this method returns -1, the default is JDBC driver dependent.
279      *
280      * @return value of defaultTransactionIsolation.
281      */

282     public int getDefaultTransactionIsolation() {
283             return defaultTransactionIsolation;
284     }
285
286     /**
287      * Set the value of defaultTransactionIsolation, which defines the state of
288      * connections handed out from this pool. The value can be changed
289      * on the Connection using Connection.setTransactionIsolation(int).
290      * The default is JDBC driver dependent.
291      *
292      * @param v Value to assign to defaultTransactionIsolation
293      */

294     public void setDefaultTransactionIsolation(int v) {
295         assertInitializationAllowed();
296         switch (v) {
297         case Connection.TRANSACTION_NONE:
298         case Connection.TRANSACTION_READ_COMMITTED:
299         case Connection.TRANSACTION_READ_UNCOMMITTED:
300         case Connection.TRANSACTION_REPEATABLE_READ:
301         case Connection.TRANSACTION_SERIALIZABLE:
302             break;
303         default:
304             throw new IllegalArgumentException JavaDoc(BAD_TRANSACTION_ISOLATION);
305         }
306         this.defaultTransactionIsolation = v;
307     }
308     
309     /**
310      * Get the description. This property is defined by jdbc as for use with
311      * GUI (or other) tools that might deploy the datasource. It serves no
312      * internal purpose.
313      *
314      * @return value of description.
315      */

316     public String JavaDoc getDescription() {
317         return description;
318     }
319     
320     /**
321      * Set the description. This property is defined by jdbc as for use with
322      * GUI (or other) tools that might deploy the datasource. It serves no
323      * internal purpose.
324      *
325      * @param v Value to assign to description.
326      */

327     public void setDescription(String JavaDoc v) {
328         this.description = v;
329     }
330         
331     /**
332      * Get the value of jndiEnvironment which is used when instantiating
333      * a jndi InitialContext. This InitialContext is used to locate the
334      * backend ConnectionPoolDataSource.
335      *
336      * @return value of jndiEnvironment.
337      */

338     public String JavaDoc getJndiEnvironment(String JavaDoc key) {
339         String JavaDoc value = null;
340         if (jndiEnvironment != null) {
341             value = jndiEnvironment.getProperty(key);
342         }
343         return value;
344     }
345     
346     /**
347      * Set the value of jndiEnvironment which is used when instantiating
348      * a jndi InitialContext. This InitialContext is used to locate the
349      * backend ConnectionPoolDataSource.
350      *
351      * @param v Value to assign to jndiEnvironment.
352      */

353     public void setJndiEnvironment(String JavaDoc key, String JavaDoc value) {
354         if (jndiEnvironment == null) {
355             jndiEnvironment = new Properties JavaDoc();
356         }
357         jndiEnvironment.setProperty(key, value);
358     }
359     
360     /**
361      * Get the value of loginTimeout.
362      * @return value of loginTimeout.
363      */

364     public int getLoginTimeout() {
365         return loginTimeout;
366     }
367     
368     /**
369      * Set the value of loginTimeout.
370      * @param v Value to assign to loginTimeout.
371      */

372     public void setLoginTimeout(int v) {
373         this.loginTimeout = v;
374     }
375         
376     /**
377      * Get the value of logWriter.
378      * @return value of logWriter.
379      */

380     public PrintWriter JavaDoc getLogWriter() {
381         if (logWriter == null) {
382             logWriter = new PrintWriter JavaDoc(System.out);
383         }
384         return logWriter;
385     }
386     
387     /**
388      * Set the value of logWriter.
389      * @param v Value to assign to logWriter.
390      */

391     public void setLogWriter(PrintWriter JavaDoc v) {
392         this.logWriter = v;
393     }
394     
395     /**
396      * @see #getTestOnBorrow
397      */

398     public final boolean isTestOnBorrow() {
399         return getTestOnBorrow();
400     }
401     
402     /**
403      * When <tt>true</tt>, objects will be
404      * {*link PoolableObjectFactory#validateObject validated}
405      * before being returned by the {*link #borrowObject}
406      * method. If the object fails to validate,
407      * it will be dropped from the pool, and we will attempt
408      * to borrow another.
409      *
410      * @see #setTestOnBorrow
411      */

412     public boolean getTestOnBorrow() {
413         return _testOnBorrow;
414     }
415
416     /**
417      * When <tt>true</tt>, objects will be
418      * {*link PoolableObjectFactory#validateObject validated}
419      * before being returned by the {*link #borrowObject}
420      * method. If the object fails to validate,
421      * it will be dropped from the pool, and we will attempt
422      * to borrow another.
423      *
424      * @see #getTestOnBorrow
425      */

426     public void setTestOnBorrow(boolean testOnBorrow) {
427         assertInitializationAllowed();
428         _testOnBorrow = testOnBorrow;
429         testPositionSet = true;
430     }
431
432     /**
433      * @see #getTestOnReturn
434      */

435     public final boolean isTestOnReturn() {
436         return getTestOnReturn();
437     }
438     
439     /**
440      * When <tt>true</tt>, objects will be
441      * {*link PoolableObjectFactory#validateObject validated}
442      * before being returned to the pool within the
443      * {*link #returnObject}.
444      *
445      * @see #setTestOnReturn
446      */

447     public boolean getTestOnReturn() {
448         return _testOnReturn;
449     }
450
451     /**
452      * When <tt>true</tt>, objects will be
453      * {*link PoolableObjectFactory#validateObject validated}
454      * before being returned to the pool within the
455      * {*link #returnObject}.
456      *
457      * @see #getTestOnReturn
458      */

459     public void setTestOnReturn(boolean testOnReturn) {
460         assertInitializationAllowed();
461         _testOnReturn = testOnReturn;
462         testPositionSet = true;
463     }
464
465     /**
466      * Returns the number of milliseconds to sleep between runs of the
467      * idle object evictor thread.
468      * When non-positive, no idle object evictor thread will be
469      * run.
470      *
471      * @see #setTimeBetweenEvictionRunsMillis
472      */

473     public int getTimeBetweenEvictionRunsMillis() {
474         return _timeBetweenEvictionRunsMillis;
475     }
476
477     /**
478      * Sets the number of milliseconds to sleep between runs of the
479      * idle object evictor thread.
480      * When non-positive, no idle object evictor thread will be
481      * run.
482      *
483      * @see #getTimeBetweenEvictionRunsMillis
484      */

485     public void
486         setTimeBetweenEvictionRunsMillis(int timeBetweenEvictionRunsMillis) {
487         assertInitializationAllowed();
488             _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
489     }
490
491     /**
492      * Returns the number of objects to examine during each run of the
493      * idle object evictor thread (if any).
494      *
495      * @see #setNumTestsPerEvictionRun
496      * @see #setTimeBetweenEvictionRunsMillis
497      */

498     public int getNumTestsPerEvictionRun() {
499         return _numTestsPerEvictionRun;
500     }
501
502     /**
503      * Sets the number of objects to examine during each run of the
504      * idle object evictor thread (if any).
505      * <p>
506      * When a negative value is supplied, <tt>ceil({*link #numIdle})/abs({*link #getNumTestsPerEvictionRun})</tt>
507      * tests will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
508      * idle objects will be tested per run.
509      *
510      * @see #getNumTestsPerEvictionRun
511      * @see #setTimeBetweenEvictionRunsMillis
512      */

513     public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
514         assertInitializationAllowed();
515         _numTestsPerEvictionRun = numTestsPerEvictionRun;
516     }
517
518     /**
519      * Returns the minimum amount of time an object may sit idle in the pool
520      * before it is eligable for eviction by the idle object evictor
521      * (if any).
522      *
523      * @see #setMinEvictableIdleTimeMillis
524      * @see #setTimeBetweenEvictionRunsMillis
525      */

526     public int getMinEvictableIdleTimeMillis() {
527         return _minEvictableIdleTimeMillis;
528     }
529
530     /**
531      * Sets the minimum amount of time an object may sit idle in the pool
532      * before it is eligable for eviction by the idle object evictor
533      * (if any).
534      * When non-positive, no objects will be evicted from the pool
535      * due to idle time alone.
536      *
537      * @see #getMinEvictableIdleTimeMillis
538      * @see #setTimeBetweenEvictionRunsMillis
539      */

540     public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
541         assertInitializationAllowed();
542         _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
543     }
544
545     /**
546      * @see #getTestWhileIdle
547      */

548     public final boolean isTestWhileIdle() {
549         return getTestWhileIdle();
550     }
551     
552     /**
553      * When <tt>true</tt>, objects will be
554      * {*link PoolableObjectFactory#validateObject validated}
555      * by the idle object evictor (if any). If an object
556      * fails to validate, it will be dropped from the pool.
557      *
558      * @see #setTestWhileIdle
559      * @see #setTimeBetweenEvictionRunsMillis
560      */

561     public boolean getTestWhileIdle() {
562         return _testWhileIdle;
563     }
564
565     /**
566      * When <tt>true</tt>, objects will be
567      * {*link PoolableObjectFactory#validateObject validated}
568      * by the idle object evictor (if any). If an object
569      * fails to validate, it will be dropped from the pool.
570      *
571      * @see #getTestWhileIdle
572      * @see #setTimeBetweenEvictionRunsMillis
573      */

574     public void setTestWhileIdle(boolean testWhileIdle) {
575         assertInitializationAllowed();
576         _testWhileIdle = testWhileIdle;
577         testPositionSet = true;
578     }
579
580     /**
581      * The SQL query that will be used to validate connections from this pool
582      * before returning them to the caller. If specified, this query
583      * <strong>MUST</strong> be an SQL SELECT statement that returns at least
584      * one row.
585      */

586     public String JavaDoc getValidationQuery() {
587         return (this.validationQuery);
588     }
589
590     /**
591      * The SQL query that will be used to validate connections from this pool
592      * before returning them to the caller. If specified, this query
593      * <strong>MUST</strong> be an SQL SELECT statement that returns at least
594      * one row. Default behavior is to test the connection when it is
595      * borrowed.
596      */

597     public void setValidationQuery(String JavaDoc validationQuery) {
598         assertInitializationAllowed();
599         this.validationQuery = validationQuery;
600         if (!testPositionSet) {
601             setTestOnBorrow(true);
602         }
603     }
604
605     // ----------------------------------------------------------------------
606
// Instrumentation Methods
607

608     // ----------------------------------------------------------------------
609
// DataSource implementation
610

611     /**
612      * Attempt to establish a database connection.
613      */

614     public Connection JavaDoc getConnection() throws SQLException JavaDoc {
615         return getConnection(null, null);
616     }
617
618     /**
619      * Attempt to establish a database connection.
620      */

621     public Connection JavaDoc getConnection(String JavaDoc username, String JavaDoc password)
622             throws SQLException JavaDoc {
623         if (instanceKey == null) {
624             throw new SQLException JavaDoc("Must set the ConnectionPoolDataSource "
625                     + "through setDataSourceName or setConnectionPoolDataSource"
626                     + " before calling getConnection.");
627         }
628         getConnectionCalled = true;
629         PooledConnectionAndInfo info = null;
630         try {
631             info = getPooledConnectionAndInfo(username, password);
632         } catch (NoSuchElementException JavaDoc e) {
633             closeDueToException(info);
634             throw new SQLNestedException("Cannot borrow connection from pool", e);
635         } catch (RuntimeException JavaDoc e) {
636             closeDueToException(info);
637             throw e;
638         } catch (SQLException JavaDoc e) {
639             closeDueToException(info);
640             throw e;
641         } catch (Exception JavaDoc e) {
642             closeDueToException(info);
643             throw new SQLNestedException("Cannot borrow connection from pool", e);
644         }
645         
646         if (!(null == password ? null == info.getPassword()
647                 : password.equals(info.getPassword()))) {
648             closeDueToException(info);
649             throw new SQLException JavaDoc("Given password did not match password used"
650                                    + " to create the PooledConnection.");
651         }
652
653         Connection JavaDoc con = info.getPooledConnection().getConnection();
654         setupDefaults(con, username);
655         con.clearWarnings();
656         return con;
657     }
658
659     protected abstract PooledConnectionAndInfo
660         getPooledConnectionAndInfo(String JavaDoc username, String JavaDoc password)
661         throws SQLException JavaDoc;
662
663     protected abstract void setupDefaults(Connection JavaDoc con, String JavaDoc username)
664         throws SQLException JavaDoc;
665
666         
667     private void closeDueToException(PooledConnectionAndInfo info) {
668         if (info != null) {
669             try {
670                 info.getPooledConnection().getConnection().close();
671             } catch (Exception JavaDoc e) {
672                 // do not throw this exception because we are in the middle
673
// of handling another exception. But record it because
674
// it potentially leaks connections from the pool.
675
getLogWriter().println("[ERROR] Could not return connection to "
676                     + "pool during exception handling. " + e.getMessage());
677             }
678         }
679     }
680
681     protected ConnectionPoolDataSource JavaDoc
682         testCPDS(String JavaDoc username, String JavaDoc password)
683         throws javax.naming.NamingException JavaDoc, SQLException JavaDoc {
684         // The source of physical db connections
685
ConnectionPoolDataSource JavaDoc cpds = this.cpds;
686         if (cpds == null) {
687             Context JavaDoc ctx = null;
688             if (jndiEnvironment == null) {
689                 ctx = new InitialContext JavaDoc();
690             } else {
691                 ctx = new InitialContext JavaDoc(jndiEnvironment);
692             }
693             Object JavaDoc ds = ctx.lookup(dataSourceName);
694             if (ds instanceof ConnectionPoolDataSource JavaDoc) {
695                 cpds = (ConnectionPoolDataSource JavaDoc) ds;
696             } else {
697                 throw new SQLException JavaDoc("Illegal configuration: "
698                     + "DataSource " + dataSourceName
699                     + " (" + ds.getClass().getName() + ")"
700                     + " doesn't implement javax.sql.ConnectionPoolDataSource");
701             }
702         }
703         
704         // try to get a connection with the supplied username/password
705
PooledConnection JavaDoc conn = null;
706         try {
707             if (username != null) {
708                 conn = cpds.getPooledConnection(username, password);
709             }
710             else {
711                 conn = cpds.getPooledConnection();
712             }
713             if (conn == null) {
714                 throw new SQLException JavaDoc(
715                     "Cannot connect using the supplied username/password");
716             }
717         }
718         finally {
719             if (conn != null) {
720                 try {
721                     conn.close();
722                 }
723                 catch (SQLException JavaDoc e) {
724                     // at least we could connect
725
}
726             }
727         }
728         return cpds;
729     }
730
731     protected byte whenExhaustedAction(int maxActive, int maxWait) {
732         byte whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_BLOCK;
733         if (maxActive <= 0) {
734             whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_GROW;
735         } else if (maxWait == 0) {
736             whenExhausted = GenericObjectPool.WHEN_EXHAUSTED_FAIL;
737         }
738         return whenExhausted;
739     }
740
741     // ----------------------------------------------------------------------
742
// Referenceable implementation
743

744     /**
745      * <CODE>Referenceable</CODE> implementation prepares object for
746      * binding in jndi.
747      */

748     public Reference JavaDoc getReference() throws NamingException JavaDoc {
749         Reference JavaDoc ref = new Reference JavaDoc(getClass().getName(),
750             InstanceKeyObjectFactory.class.getName(), null);
751         ref.add(new StringRefAddr JavaDoc("instanceKey", instanceKey));
752         return ref;
753     }
754 }
755
Popular Tags