KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > commons > dbcp > cpdsadapter > DriverAdapterCPDS


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.cpdsadapter;
18
19 import java.util.Hashtable JavaDoc;
20 import java.io.PrintWriter JavaDoc;
21 import java.io.Serializable JavaDoc;
22 import java.sql.DriverManager JavaDoc;
23 import java.sql.SQLException JavaDoc;
24 import javax.sql.PooledConnection JavaDoc;
25 import javax.sql.ConnectionPoolDataSource JavaDoc;
26 import javax.naming.Name JavaDoc;
27 import javax.naming.Context JavaDoc;
28 import javax.naming.Referenceable JavaDoc;
29 import javax.naming.spi.ObjectFactory JavaDoc;
30 import javax.naming.Reference JavaDoc;
31 import javax.naming.RefAddr JavaDoc;
32 import javax.naming.StringRefAddr JavaDoc;
33 import javax.naming.NamingException JavaDoc;
34
35 import org.apache.commons.pool.KeyedObjectPool;
36 import org.apache.commons.pool.impl.GenericKeyedObjectPool;
37
38 /**
39  * <p>
40  * An adapter for jdbc drivers that do not include an implementation
41  * of {@link javax.sql.ConnectionPoolDataSource}, but still include a
42  * {@link java.sql.DriverManager} implementation.
43  * <code>ConnectionPoolDataSource</code>s are not used within general
44  * applications. They are used by <code>DataSource</code> implementations
45  * that pool <code>Connection</code>s, such as
46  * {@link org.apache.commons.dbcp.datasources.SharedPoolDataSource}. A J2EE
47  * container will normally provide some method of initializing the
48  * <code>ConnectionPoolDataSource</code> whose attributes are presented
49  * as bean getters/setters and then deploying it via JNDI. It is then
50  * available as a source of physical connections to the database, when
51  * the pooling <code>DataSource</code> needs to create a new
52  * physical connection.
53  * </p>
54  *
55  * <p>
56  * Although normally used within a JNDI environment, the DriverAdapterCPDS
57  * can be instantiated and initialized as any bean and then attached
58  * directly to a pooling <code>DataSource</code>.
59  * <code>Jdbc2PoolDataSource</code> can use the
60  * <code>ConnectionPoolDataSource</code> with or without the use of JNDI.
61  * </p>
62  *
63  * <p>
64  * The DriverAdapterCPDS also provides <code>PreparedStatement</code> pooling
65  * which is not generally available in jbdc2
66  * <code>ConnectionPoolDataSource</code> implementation, but is
67  * addressed within the jdbc3 specification. The <code>PreparedStatement</code>
68  * pool in DriverAdapterCPDS has been in the dbcp package for some time, but
69  * it has not undergone extensive testing in the configuration used here.
70  * It should be considered experimental and can be toggled with the
71  * poolPreparedStatements attribute.
72  * </p>
73  *
74  * <p>
75  * The <a HREF="package-summary.html">package documentation</a> contains an
76  * example using catalina and JNDI. The <a
77  * HREF="../datasources/package-summary.html">datasources package documentation</a>
78  * shows how to use <code>DriverAdapterCPDS</code> as a source for
79  * <code>Jdbc2PoolDataSource</code> without the use of JNDI.
80  * </p>
81  *
82  * @author John D. McNally
83  * @version $Revision: 1.8 $ $Date: 2004/02/28 12:18:17 $
84  */

85 public class DriverAdapterCPDS
86     implements ConnectionPoolDataSource JavaDoc, Referenceable JavaDoc, Serializable JavaDoc,
87                ObjectFactory JavaDoc {
88                    
89     private static final String JavaDoc GET_CONNECTION_CALLED
90             = "A PooledConnection was already requested from this source, "
91             + "further initialization is not allowed.";
92
93     /** Description */
94     private String JavaDoc description;
95     /** Password */
96     private String JavaDoc password;
97     /** Url name */
98     private String JavaDoc url;
99     /** User name */
100     private String JavaDoc user;
101     /** Driver class name */
102     private String JavaDoc driver;
103
104     /** Login TimeOut in seconds */
105     private int loginTimeout;
106     /** Log stream */
107     private PrintWriter JavaDoc logWriter = null;
108
109     // PreparedStatement pool properties
110
private boolean poolPreparedStatements;
111     private int maxActive = 10;
112     private int maxIdle = 10;
113     private int _timeBetweenEvictionRunsMillis = -1;
114     private int _numTestsPerEvictionRun = -1;
115     private int _minEvictableIdleTimeMillis = -1;
116
117     private boolean getConnectionCalled = false;
118
119     /**
120      * Default no-arg constructor for Serialization
121      */

122     public DriverAdapterCPDS() {
123     }
124
125     /**
126      * Attempt to establish a database connection using the default
127      * user and password.
128      */

129     public PooledConnection JavaDoc getPooledConnection() throws SQLException JavaDoc {
130         return getPooledConnection(getUser(), getPassword());
131     }
132                      
133     /**
134      * Attempt to establish a database connection.
135      */

136     public PooledConnection JavaDoc getPooledConnection(String JavaDoc username,
137                                                 String JavaDoc password)
138             throws SQLException JavaDoc {
139         getConnectionCalled = true;
140         /*
141         public GenericKeyedObjectPool(KeyedPoolableObjectFactory factory,
142         int maxActive, byte whenExhaustedAction, long maxWait,
143         int maxIdle, boolean testOnBorrow, boolean testOnReturn,
144         long timeBetweenEvictionRunsMillis,
145         int numTestsPerEvictionRun, long minEvictableIdleTimeMillis,
146         boolean testWhileIdle) {
147         */

148         KeyedObjectPool stmtPool = null;
149         if (isPoolPreparedStatements()) {
150             stmtPool = new GenericKeyedObjectPool(null,
151                 getMaxActive(), GenericKeyedObjectPool.WHEN_EXHAUSTED_GROW, 0,
152                 getMaxIdle(), false, false, getTimeBetweenEvictionRunsMillis(),
153                 getNumTestsPerEvictionRun(),
154                 getMinEvictableIdleTimeMillis(), false);
155         }
156         
157         // Workaround for buggy WebLogic 5.1 classloader - ignore the
158
// exception upon first invocation.
159
try {
160             return new PooledConnectionImpl(
161                     DriverManager.getConnection(getUrl(), username, password),
162                     stmtPool );
163         }
164         catch (ClassCircularityError JavaDoc e)
165         {
166             return new PooledConnectionImpl(
167                     DriverManager.getConnection(getUrl(), username, password),
168                     stmtPool );
169         }
170     }
171
172     // ----------------------------------------------------------------------
173
// Referenceable implementation
174

175     /**
176      * <CODE>Referenceable</CODE> implementation.
177      */

178     public Reference JavaDoc getReference() throws NamingException JavaDoc {
179         // this class implements its own factory
180
String JavaDoc factory = getClass().getName();
181         
182         Reference JavaDoc ref = new Reference JavaDoc(getClass().getName(), factory, null);
183
184         ref.add(new StringRefAddr JavaDoc("description", getDescription()));
185         ref.add(new StringRefAddr JavaDoc("driver", getDriver()));
186         ref.add(new StringRefAddr JavaDoc("loginTimeout",
187                                   String.valueOf(getLoginTimeout())));
188         ref.add(new StringRefAddr JavaDoc("password", getPassword()));
189         ref.add(new StringRefAddr JavaDoc("user", getUser()));
190         ref.add(new StringRefAddr JavaDoc("url", getUrl()));
191
192         ref.add(new StringRefAddr JavaDoc("poolPreparedStatements",
193                                   String.valueOf(isPoolPreparedStatements())));
194         ref.add(new StringRefAddr JavaDoc("maxActive",
195                                   String.valueOf(getMaxActive())));
196         ref.add(new StringRefAddr JavaDoc("maxIdle",
197                                   String.valueOf(getMaxIdle())));
198         ref.add(new StringRefAddr JavaDoc("timeBetweenEvictionRunsMillis",
199             String.valueOf(getTimeBetweenEvictionRunsMillis())));
200         ref.add(new StringRefAddr JavaDoc("numTestsPerEvictionRun",
201             String.valueOf(getNumTestsPerEvictionRun())));
202         ref.add(new StringRefAddr JavaDoc("minEvictableIdleTimeMillis",
203             String.valueOf(getMinEvictableIdleTimeMillis())));
204
205         return ref;
206     }
207
208
209     // ----------------------------------------------------------------------
210
// ObjectFactory implementation
211

212     /**
213      * implements ObjectFactory to create an instance of this class
214      */

215     public Object JavaDoc getObjectInstance(Object JavaDoc refObj, Name JavaDoc name,
216                                     Context JavaDoc context, Hashtable JavaDoc env)
217             throws Exception JavaDoc {
218         // The spec says to return null if we can't create an instance
219
// of the reference
220
DriverAdapterCPDS cpds = null;
221         if (refObj instanceof Reference JavaDoc) {
222             Reference JavaDoc ref = (Reference JavaDoc)refObj;
223             if (ref.getClassName().equals(getClass().getName())) {
224                 RefAddr JavaDoc ra = ref.get("description");
225                 if (ra != null && ra.getContent() != null) {
226                     setDescription(ra.getContent().toString());
227                 }
228
229                 ra = ref.get("driver");
230                 if (ra != null && ra.getContent() != null) {
231                     setDriver(ra.getContent().toString());
232                 }
233                 ra = ref.get("url");
234                 if (ra != null && ra.getContent() != null) {
235                     setUrl(ra.getContent().toString());
236                 }
237                 ra = ref.get("user");
238                 if (ra != null && ra.getContent() != null) {
239                     setUser(ra.getContent().toString());
240                 }
241                 ra = ref.get("password");
242                 if (ra != null && ra.getContent() != null) {
243                     setPassword(ra.getContent().toString());
244                 }
245
246                 ra = ref.get("poolPreparedStatements");
247                 if (ra != null && ra.getContent() != null) {
248                     setPoolPreparedStatements(
249                         Boolean.getBoolean(ra.getContent().toString()));
250                 }
251                 ra = ref.get("maxActive");
252                 if (ra != null && ra.getContent() != null) {
253                     setMaxActive(Integer.parseInt(ra.getContent().toString()));
254                 }
255
256                 ra = ref.get("maxIdle");
257                 if (ra != null && ra.getContent() != null) {
258                     setMaxIdle(Integer.parseInt(ra.getContent().toString()));
259                 }
260
261                 ra = ref.get("timeBetweenEvictionRunsMillis");
262                 if (ra != null && ra.getContent() != null) {
263                     setTimeBetweenEvictionRunsMillis(
264                         Integer.parseInt(ra.getContent().toString()));
265                 }
266
267                 ra = ref.get("numTestsPerEvictionRun");
268                 if (ra != null && ra.getContent() != null) {
269                     setNumTestsPerEvictionRun(
270                         Integer.parseInt(ra.getContent().toString()));
271                 }
272
273                 ra = ref.get("minEvictableIdleTimeMillis");
274                 if (ra != null && ra.getContent() != null) {
275                     setMinEvictableIdleTimeMillis(
276                         Integer.parseInt(ra.getContent().toString()));
277                 }
278
279                 cpds = this;
280             }
281         }
282         return cpds;
283     }
284
285     /**
286      * Throws an IllegalStateException, if a PooledConnection has already
287      * been requested.
288      */

289     private void assertInitializationAllowed() throws IllegalStateException JavaDoc {
290         if (getConnectionCalled) {
291             throw new IllegalStateException JavaDoc(GET_CONNECTION_CALLED);
292         }
293     }
294
295     // ----------------------------------------------------------------------
296
// Properties
297

298     /**
299      * Get the value of description. This property is here for use by
300      * the code which will deploy this datasource. It is not used
301      * internally.
302      *
303      * @return value of description.
304      */

305     public String JavaDoc getDescription() {
306         return description;
307     }
308     
309     /**
310      * Set the value of description. This property is here for use by
311      * the code which will deploy this datasource. It is not used
312      * internally.
313      *
314      * @param v Value to assign to description.
315      */

316     public void setDescription(String JavaDoc v) {
317         this.description = v;
318     }
319
320     /**
321      * Get the value of password for the default user.
322      * @return value of password.
323      */

324     public String JavaDoc getPassword() {
325         return password;
326     }
327     
328     /**
329      * Set the value of password for the default user.
330      * @param v Value to assign to password.
331      */

332     public void setPassword(String JavaDoc v) {
333         assertInitializationAllowed();
334         this.password = v;
335     }
336
337     /**
338      * Get the value of url used to locate the database for this datasource.
339      * @return value of url.
340      */

341     public String JavaDoc getUrl() {
342         return url;
343     }
344     
345     /**
346      * Set the value of url used to locate the database for this datasource.
347      * @param v Value to assign to url.
348      */

349     public void setUrl(String JavaDoc v) {
350         assertInitializationAllowed();
351         this.url = v;
352     }
353
354     /**
355      * Get the value of default user (login or username).
356      * @return value of user.
357      */

358     public String JavaDoc getUser() {
359         return user;
360     }
361     
362     /**
363      * Set the value of default user (login or username).
364      * @param v Value to assign to user.
365      */

366     public void setUser(String JavaDoc v) {
367         assertInitializationAllowed();
368         this.user = v;
369     }
370
371     /**
372      * Get the driver classname.
373      * @return value of driver.
374      */

375     public String JavaDoc getDriver() {
376         return driver;
377     }
378     
379     /**
380      * Set the driver classname. Setting the driver classname cause the
381      * driver to be registered with the DriverManager.
382      * @param v Value to assign to driver.
383      */

384     public void setDriver(String JavaDoc v) throws ClassNotFoundException JavaDoc {
385         assertInitializationAllowed();
386         this.driver = v;
387         // make sure driver is registered
388
Class.forName(v);
389     }
390     
391     /**
392      * Gets the maximum time in seconds that this data source can wait
393      * while attempting to connect to a database. NOT USED.
394      */

395     public int getLoginTimeout() {
396         return loginTimeout;
397     }
398                            
399     /**
400      * Get the log writer for this data source. NOT USED.
401      */

402     public PrintWriter JavaDoc getLogWriter() {
403         return logWriter;
404     }
405                            
406     /**
407      * Sets the maximum time in seconds that this data source will wait
408      * while attempting to connect to a database. NOT USED.
409      */

410     public void setLoginTimeout(int seconds) {
411         loginTimeout = seconds;
412     }
413                            
414     /**
415      * Set the log writer for this data source. NOT USED.
416      */

417     public void setLogWriter(java.io.PrintWriter JavaDoc out) {
418         logWriter = out;
419     }
420
421
422     // ------------------------------------------------------------------
423
// PreparedStatement pool properties
424

425     
426     /**
427      * Flag to toggle the pooling of <code>PreparedStatement</code>s
428      * @return value of poolPreparedStatements.
429      */

430     public boolean isPoolPreparedStatements() {
431         return poolPreparedStatements;
432     }
433     
434     /**
435      * Flag to toggle the pooling of <code>PreparedStatement</code>s
436      * @param v true to pool statements.
437      */

438     public void setPoolPreparedStatements(boolean v) {
439         assertInitializationAllowed();
440         this.poolPreparedStatements = v;
441     }
442
443     /**
444      * The maximum number of active statements that can be allocated from
445      * this pool at the same time, or zero for no limit.
446      */

447     public int getMaxActive() {
448         return (this.maxActive);
449     }
450
451     /**
452      * The maximum number of active statements that can be allocated from
453      * this pool at the same time, or zero for no limit.
454      */

455     public void setMaxActive(int maxActive) {
456         assertInitializationAllowed();
457         this.maxActive = maxActive;
458     }
459
460     /**
461      * The maximum number of statements that can remain idle in the
462      * pool, without extra ones being released, or zero for no limit.
463      */

464     public int getMaxIdle() {
465         return (this.maxIdle);
466     }
467
468     /**
469      * The maximum number of statements that can remain idle in the
470      * pool, without extra ones being released, or zero for no limit.
471      */

472     public void setMaxIdle(int maxIdle) {
473         assertInitializationAllowed();
474         this.maxIdle = maxIdle;
475     }
476
477     /**
478      * Returns 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 #setTimeBetweenEvictionRunsMillis
484      */

485     public int getTimeBetweenEvictionRunsMillis() {
486         return _timeBetweenEvictionRunsMillis;
487     }
488
489     /**
490      * Sets the number of milliseconds to sleep between runs of the
491      * idle object evictor thread.
492      * When non-positive, no idle object evictor thread will be
493      * run.
494      *
495      * *see #getTimeBetweenEvictionRunsMillis
496      */

497     public void setTimeBetweenEvictionRunsMillis(
498             int timeBetweenEvictionRunsMillis) {
499         assertInitializationAllowed();
500         _timeBetweenEvictionRunsMillis = timeBetweenEvictionRunsMillis;
501     }
502
503     /**
504      * Returns the number of statements to examine during each run of the
505      * idle object evictor thread (if any).
506      *
507      * *see #setNumTestsPerEvictionRun
508      * *see #setTimeBetweenEvictionRunsMillis
509      */

510     public int getNumTestsPerEvictionRun() {
511         return _numTestsPerEvictionRun;
512     }
513
514     /**
515      * Sets the number of statements to examine during each run of the
516      * idle object evictor thread (if any).
517      * <p>
518      * When a negative value is supplied, <tt>ceil({*link #numIdle})/abs({*link #getNumTestsPerEvictionRun})</tt>
519      * tests will be run. I.e., when the value is <i>-n</i>, roughly one <i>n</i>th of the
520      * idle objects will be tested per run.
521      *
522      * *see #getNumTestsPerEvictionRun
523      * *see #setTimeBetweenEvictionRunsMillis
524      */

525     public void setNumTestsPerEvictionRun(int numTestsPerEvictionRun) {
526         assertInitializationAllowed();
527         _numTestsPerEvictionRun = numTestsPerEvictionRun;
528     }
529
530     /**
531      * Returns the minimum amount of time a statement may sit idle in the pool
532      * before it is eligible for eviction by the idle object evictor
533      * (if any).
534      *
535      * *see #setMinEvictableIdleTimeMillis
536      * *see #setTimeBetweenEvictionRunsMillis
537      */

538     public int getMinEvictableIdleTimeMillis() {
539         return _minEvictableIdleTimeMillis;
540     }
541
542     /**
543      * Sets the minimum amount of time a statement may sit idle in the pool
544      * before it is eligable for eviction by the idle object evictor
545      * (if any).
546      * When non-positive, no objects will be evicted from the pool
547      * due to idle time alone.
548      *
549      * *see #getMinEvictableIdleTimeMillis
550      * *see #setTimeBetweenEvictionRunsMillis
551      */

552     public void setMinEvictableIdleTimeMillis(int minEvictableIdleTimeMillis) {
553         assertInitializationAllowed();
554         _minEvictableIdleTimeMillis = minEvictableIdleTimeMillis;
555     }
556 }
557
Popular Tags