KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > caucho > sql > DBPool


1 /*
2  * Copyright (c) 1998-2006 Caucho Technology -- all rights reserved
3  *
4  * This file is part of Resin(R) Open Source
5  *
6  * Each copy or derived work must preserve the copyright notice and this
7  * notice unmodified.
8  *
9  * Resin Open Source is free software; you can redistribute it and/or modify
10  * it under the terms of the GNU General Public License as published by
11  * the Free Software Foundation; either version 2 of the License, or
12  * (at your option) any later version.
13  *
14  * Resin Open Source is distributed in the hope that it will be useful,
15  * but WITHOUT ANY WARRANTY; without even the implied warranty of
16  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE, or any warranty
17  * of NON-INFRINGEMENT. See the GNU General Public License for more
18  * details.
19  *
20  * You should have received a copy of the GNU General Public License
21  * along with Resin Open Source; if not, write to the
22  *
23  * Free Software Foundation, Inc.
24  * 59 Temple Place, Suite 330
25  * Boston, MA 02111-1307 USA
26  *
27  * @author Scott Ferguson
28  */

29
30 package com.caucho.sql;
31
32 import com.caucho.config.ConfigException;
33 import com.caucho.config.types.InitParam;
34 import com.caucho.config.types.Period;
35 import com.caucho.jca.ConnectionPool;
36 import com.caucho.jca.ResourceManagerImpl;
37 import com.caucho.loader.EnvironmentLocal;
38 import com.caucho.log.Log;
39 import com.caucho.management.j2ee.J2EEManagedObject;
40 import com.caucho.management.j2ee.JDBCDataSource;
41 import com.caucho.management.j2ee.JDBCResource;
42 import com.caucho.naming.Jndi;
43 import com.caucho.transaction.TransactionManagerImpl;
44 import com.caucho.util.L10N;
45
46 import javax.annotation.PostConstruct;
47 import javax.resource.spi.ManagedConnectionFactory JavaDoc;
48 import javax.sql.ConnectionPoolDataSource JavaDoc;
49 import javax.sql.DataSource JavaDoc;
50 import javax.sql.XADataSource JavaDoc;
51 import java.io.IOException JavaDoc;
52 import java.io.PrintWriter JavaDoc;
53 import java.sql.Connection JavaDoc;
54 import java.sql.Driver JavaDoc;
55 import java.sql.SQLException JavaDoc;
56 import java.util.logging.Logger JavaDoc;
57
58 /**
59  * Manages a pool of database connections. In addition, DBPool configures
60  * the database connection from a configuration file.
61  *
62  * <p>Like JDBC 2.0 pooling, DBPool returns a wrapped Connection.
63  * Applications can use that connection just like an unpooled connection.
64  * It is more important than ever to <code>close()</code> the connection,
65  * because the close returns the connection to the connection pool.
66  *
67  * <h4>Example using DataSource JNDI style (recommended)</h4>
68  *
69  * <pre><code>
70  * Context env = (Context) new InitialContext().lookup("java:comp/env");
71  * DataSource pool = (DataSource) env.lookup("jdbc/test");
72  * Connection conn = pool.getConnection();
73  * try {
74  * ... // normal connection stuff
75  * } finally {
76  * conn.close();
77  * }
78  * </code></pre>
79  *
80  * <h4>Configuration</h4>
81  *
82  * <pre><code>
83  * &lt;database name='jdbc/test'>
84  * &lt;init>
85  * &lt;driver>postgresql.Driver&lt;/driver>
86  * &lt;url>jdbc:postgresql://localhost/test&lt;/url>
87  * &lt;user>ferg&lt;/user>
88  * &lt;password>foobar&lt;/password>
89  * &lt;/init>
90  * &lt;/database>
91  * </code></pre>
92  *
93  * <h4>Pool limits and timeouts</h4>
94  *
95  * The pool will only allow getMaxConnections() connections alive at a time.
96  * If <code>getMaxConnection</code> connections are already active,
97  * <code>getPooledConnection</code> will block waiting for an available
98  * connection. The wait is timed. If connection-wait-time passes
99  * and there is still no connection, <code>getPooledConnection</code>
100  * create a new connection anyway.
101  *
102  * <p>Connections will only stay in the pool for about 5 seconds. After
103  * that they will be removed and closed. This reduces the load on the DB
104  * and also protects against the database dropping old connections.
105  */

106 public class DBPool implements DataSource {
107   protected static final Logger JavaDoc log = Log.open(DBPool.class);
108   private static final L10N L = new L10N(DBPool.class);
109
110   private static int _g_id;
111   
112   private EnvironmentLocal<DBPoolImpl> _localPoolImpl;
113   private EnvironmentLocal<DataSource> _localDataSourceImpl;
114
115   private String JavaDoc _var;
116   private String JavaDoc _jndiName;
117   private String JavaDoc _tmpName;
118
119   private ResourceManagerImpl _resourceManager;
120   private ConnectionPool _connectionPool;
121
122   private DBPoolImpl _poolImpl;
123   private DataSource _dataSource;
124   private DataSourceImpl _resinDataSource;
125
126   /**
127    * Null constructor for the Driver interface; called by the JNDI
128    * configuration. Applications should not call this directly.
129    */

130   public DBPool()
131   {
132     _poolImpl = new DBPoolImpl();
133
134     _resourceManager = ResourceManagerImpl.createLocalManager();
135     _connectionPool = _resourceManager.createConnectionPool();
136   }
137
138   /**
139    * Returns the Pool's name
140    */

141   public String JavaDoc getJndiName()
142   {
143     return _jndiName;
144   }
145
146   /**
147    * Sets the Pool's JNDI name. Also puts the pool in the classloader's
148    * list of pools.
149    */

150   public void setJndiName(String JavaDoc name)
151   {
152     _jndiName = name;
153
154     if (_var == null)
155       getPool().setName(name);
156   }
157
158   /**
159    * Sets the Pool's var.
160    */

161   public void setVar(String JavaDoc var)
162   {
163     _var = var;
164
165     getPool().setName(var);
166   }
167
168   /**
169    * Returns the Pool's name
170    */

171   public String JavaDoc getName()
172   {
173     if (_var != null)
174       return _var;
175     else if (getJndiName() != null)
176       return getJndiName();
177     else {
178       _tmpName = "dbpool-" + _g_id++;
179       return _tmpName;
180     }
181       
182   }
183
184   /**
185    * Sets a custom driver (or data source)
186    */

187   public DriverConfig createDriver()
188     throws ConfigException
189   {
190     return getPool().createDriver();
191   }
192
193   /**
194    * Sets a custom driver (or data source)
195    */

196   public DriverConfig createBackupDriver()
197     throws ConfigException
198   {
199     return getPool().createBackupDriver();
200   }
201
202   /**
203    * Sets a driver parameter (compat).
204    */

205   public void setInitParam(InitParam init)
206   {
207     getPool().setInitParam(init);
208   }
209
210   /**
211    * Sets the jdbc-driver config.
212    */

213   public void setJDBCDriver(Driver JavaDoc jdbcDriver)
214     throws SQLException JavaDoc
215   {
216     getPool().setJDBCDriver(jdbcDriver);
217   }
218
219   /**
220    * Configure the initial connection
221    */

222   public ConnectionConfig createConnection()
223     throws ConfigException
224   {
225     return getPool().createConnection();
226   }
227
228   /**
229    * Sets the jdbc-driver config.
230    */

231   public void setPoolDataSource(ConnectionPoolDataSource JavaDoc poolDataSource)
232     throws SQLException JavaDoc
233   {
234     getPool().setPoolDataSource(poolDataSource);
235   }
236
237   /**
238    * Sets the jdbc-driver config.
239    */

240   public void setXADataSource(XADataSource JavaDoc xaDataSource)
241     throws SQLException JavaDoc
242   {
243     getPool().setXADataSource(xaDataSource);
244   }
245
246   /**
247    * Sets the jdbc-driver URL
248    */

249   public void setURL(String JavaDoc url)
250     throws ConfigException
251   {
252     getPool().setURL(url);
253   }
254
255   /**
256    * Returns the connection's user (compat).
257    */

258   public String JavaDoc getUser()
259   {
260     return getPool().getUser();
261   }
262
263   /**
264    * Sets the connection's user.
265    */

266   public void setUser(String JavaDoc user)
267   {
268     getPool().setUser(user);
269   }
270
271   /**
272    * Returns the connection's password
273    */

274   public String JavaDoc getPassword()
275   {
276     return getPool().getPassword();
277   }
278
279   /**
280    * Sets the connection's password
281    */

282   public void setPassword(String JavaDoc password)
283   {
284     getPool().setPassword(password);
285   }
286
287   /**
288    * Get the maximum number of pooled connections.
289    */

290   public int getMaxConnections()
291   {
292     return _connectionPool.getMaxConnections();
293   }
294
295   /**
296    * Sets the maximum number of pooled connections.
297    */

298   public void setMaxConnections(int maxConnections)
299     throws ConfigException
300   {
301     _connectionPool.setMaxConnections(maxConnections);
302   }
303
304   /**
305    * Get the total number of connections
306    */

307   public int getTotalConnections()
308   {
309     return _connectionPool.getConnectionCount();
310   }
311
312   /**
313    * Sets the time to wait for a connection when all are used.
314    */

315   public void setConnectionWaitTime(Period waitTime)
316   {
317     _connectionPool.setConnectionWaitTime(waitTime);
318   }
319
320   /**
321    * Gets the time to wait for a connection when all are used.
322    */

323   public long getConnectionWaitTime()
324   {
325     return _connectionPool.getConnectionWaitTime();
326   }
327
328   /**
329    * The number of connections to overflow if the connection pool fills
330    * and there's a timeout.
331    */

332   public void setMaxOverflowConnections(int maxOverflowConnections)
333   {
334     _connectionPool.setMaxOverflowConnections(maxOverflowConnections);
335   }
336
337   /**
338    * The number of connections to create at any one time.
339    */

340   public void setMaxCreateConnections(int maxCreateConnections)
341     throws ConfigException
342   {
343     _connectionPool.setMaxCreateConnections(maxCreateConnections);
344   }
345
346   /**
347    * Set true if the stack trace should be saved on allocation.
348    */

349   public void setSaveAllocationStackTrace(boolean save)
350   {
351     _connectionPool.setSaveAllocationStackTrace(save);
352   }
353
354   /**
355    * The number of connections to overflow if the connection pool fills
356    * and there's a timeout.
357    */

358   public int getMaxOverflowConnections()
359   {
360     return _connectionPool.getMaxOverflowConnections();
361   }
362
363   /**
364    * Get the total number of connections in use by the program.
365    */

366   public int getActiveConnections()
367   {
368     return _connectionPool.getConnectionActiveCount();
369   }
370
371   /**
372    * Get the time in milliseconds a connection will remain in the pool before
373    * being closed.
374    */

375   public long getMaxIdleTime()
376   {
377     return _connectionPool.getMaxIdleTime();
378   }
379
380   /**
381    * Set the time in milliseconds a connection will remain in the pool before
382    * being closed.
383    */

384   public void setMaxIdleTime(Period idleTime)
385   {
386     _connectionPool.setMaxIdleTime(idleTime.getPeriod());
387   }
388
389   /**
390    * Get the time in milliseconds a connection will remain in the pool before
391    * being closed.
392    */

393   public long getMaxPoolTime()
394   {
395     return _connectionPool.getMaxPoolTime();
396   }
397
398   /**
399    * Set the time in milliseconds a connection will remain in the pool before
400    * being closed.
401    */

402   public void setMaxPoolTime(Period maxPoolTime)
403   {
404     _connectionPool.setMaxPoolTime(maxPoolTime.getPeriod());
405   }
406
407   /**
408    * Get the time in milliseconds a connection can remain active.
409    */

410   public long getMaxActiveTime()
411   {
412     return _connectionPool.getMaxActiveTime();
413   }
414
415   /**
416    * Set the time in milliseconds a connection can remain active.
417    */

418   public void setMaxActiveTime(Period maxActiveTime)
419   {
420     _connectionPool.setMaxActiveTime(maxActiveTime.getPeriod());
421   }
422
423   /**
424    * Get the table to 'ping' to see if the connection is still live.
425    */

426   public String JavaDoc getPingTable()
427   {
428     return getPool().getPingTable();
429   }
430
431   /**
432    * Set the table to 'ping' to see if the connection is still live.
433    *
434    * @param pingTable name of the SQL table to ping.
435    */

436   public void setPingTable(String JavaDoc pingTable)
437   {
438     getPool().setPingTable(pingTable);
439   }
440
441   /**
442    * If true, the pool will ping when attempting to reuse a connection.
443    */

444   public boolean getPingOnReuse()
445   {
446     return getPool().getPingOnReuse();
447   }
448
449   /**
450    * Set the table to 'ping' to see if the connection is still live.
451    */

452   public void setPingOnReuse(boolean pingOnReuse)
453   {
454     getPool().setPingOnReuse(pingOnReuse);
455   }
456
457   /**
458    * If true, the pool will ping in the idle pool.
459    */

460   public boolean getPingOnIdle()
461   {
462     return getPool().getPingOnIdle();
463   }
464
465   /**
466    * Set the table to 'ping' to see if the connection is still live.
467    */

468   public void setPingOnIdle(boolean pingOnIdle)
469   {
470     getPool().setPingOnIdle(pingOnIdle);
471   }
472
473   /**
474    * Set the table to 'ping' to see if the connection is still live.
475    */

476   public void setPing(boolean ping)
477   {
478     getPool().setPing(ping);
479   }
480
481   /**
482    * Sets the time to ping for ping-on-idle
483    */

484   public void setPingInterval(Period interval)
485   {
486     getPool().setPingInterval(interval);
487   }
488
489   /**
490    * Gets how often the ping for ping-on-idle
491    */

492   public long getPingInterval()
493  {
494     return getPool().getPingInterval();
495   }
496
497   /**
498    * Returns the prepared statement cache size.
499    */

500   public int getPreparedStatementCacheSize()
501   {
502     return getPool().getPreparedStatementCacheSize();
503   }
504
505   /**
506    * Sets the prepared statement cache size.
507    */

508   public void setPreparedStatementCacheSize(int size)
509   {
510     getPool().setPreparedStatementCacheSize(size);
511   }
512
513   /**
514    * Set the transaction manager for this pool.
515    */

516   public void setTransactionManager(TransactionManagerImpl tm)
517   {
518     getPool().setTransactionManager(tm);
519   }
520
521   /**
522    * Set true if statement should be wrapped.
523    */

524   public void setWrapStatements(boolean isWrap)
525   {
526     getPool().setWrapStatements(isWrap);
527   }
528
529   /**
530    * Returns the transaction manager.
531    */

532   /*
533   public TransactionManager getTransactionManager()
534   {
535     return getPool().getTransactionManager();
536   }
537   */

538
539   /**
540    * Sets the transaction timeout.
541    */

542   public void setTransactionTimeout(Period period)
543   {
544     getPool().setTransactionTimeout(period);
545   }
546
547   /**
548    * Returns true if this is transactional.
549    */

550   public boolean isXA()
551   {
552     return getPool().isXA();
553   }
554
555   /**
556    * Returns true if this is transactional.
557    */

558   public void setXA(boolean isTransactional)
559   {
560     getPool().setXA(isTransactional);
561   }
562
563   /**
564    * Returns true if this is transactional.
565    */

566   public void setXAForbidSameRM(boolean isXAForbidSameRM)
567   {
568     getPool().setXAForbidSameRM(isXAForbidSameRM);
569   }
570
571   /**
572    * Set the output for spying.
573    */

574   public void setSpy(boolean isSpy)
575     throws IOException JavaDoc
576   {
577     getPool().setSpy(isSpy);
578   }
579
580   /**
581    * Initialize the pool.
582    */

583   @PostConstruct
584   public void init()
585     throws Exception JavaDoc
586   {
587     _localPoolImpl = new EnvironmentLocal<DBPoolImpl>("caucho.db-pool." + getName());
588     _localPoolImpl.set(_poolImpl);
589
590     _poolImpl.init();
591
592     _connectionPool.setName(getName());
593
594     _connectionPool.setShareable(true);
595     _connectionPool.setXATransaction(_poolImpl.isXATransaction());
596     _connectionPool.setLocalTransaction(_poolImpl.isLocalTransaction());
597
598     ManagedConnectionFactory JavaDoc mcf = _poolImpl.getManagedConnectionFactory();
599     
600     
601     _dataSource = (DataSource) _connectionPool.init(mcf);
602     _connectionPool.start();
603
604     _localDataSourceImpl = new EnvironmentLocal<DataSource>("caucho.data-source." + getName());
605     _localDataSourceImpl.set(_dataSource);
606
607     if (_jndiName != null) {
608       String JavaDoc name = _jndiName;
609       if (! name.startsWith("java:"))
610         name = "java:comp/env/" + name;
611
612       log.config("database " + name + " starting");
613
614       Jndi.bindDeep(name, this);
615     }
616
617     J2EEManagedObject.register(new JDBCResource(this));
618     J2EEManagedObject.register(new JDBCDataSource(this));
619   }
620
621   /**
622    * Returns a new or pooled connection.
623    */

624   public Connection JavaDoc getConnection() throws SQLException JavaDoc
625   {
626     return getDataSource().getConnection();
627   }
628
629   /**
630    * Return a connection. The connection will only be pooled if
631    * user and password match the configuration. In general, applications
632    * should use the null-argument getConnection().
633    *
634    * @param user database user
635    * @param password database password
636    * @return a database connection
637    */

638   public Connection JavaDoc getConnection(String JavaDoc user, String JavaDoc password)
639     throws SQLException JavaDoc
640   {
641     return getDataSource().getConnection(user, password);
642   }
643
644   /**
645    * Clears the pool.
646    */

647   public void closeIdleConnections()
648   {
649     ConnectionPool connectionPool = _connectionPool;
650     
651     if (connectionPool != null)
652       connectionPool.clear();
653   }
654
655   /**
656    * Returns the login timeout
657    */

658   public int getLoginTimeout() throws SQLException JavaDoc
659   {
660     return getDataSource().getLoginTimeout();
661   }
662
663   /**
664    * Sets the login timeout
665    */

666   public void setLoginTimeout(int timeout) throws SQLException JavaDoc
667   {
668     getDataSource().setLoginTimeout(timeout);
669   }
670
671   /**
672    * Gets the log writer
673    */

674   public PrintWriter JavaDoc getLogWriter() throws SQLException JavaDoc
675   {
676     return getDataSource().getLogWriter();
677   }
678
679   /**
680    * Sets the log writer
681    */

682   public void setLogWriter(PrintWriter JavaDoc log) throws SQLException JavaDoc
683   {
684     getDataSource().setLogWriter(log);
685   }
686
687   /**
688    * Returns the underlying pool.
689    */

690   private DBPoolImpl getPool()
691   {
692     if (_poolImpl == null || _poolImpl.isClosed()) {
693       _poolImpl = _localPoolImpl.get();
694
695       if (_poolImpl == null)
696         throw new IllegalStateException JavaDoc(L.l("DBPool `{0}' no longer exists.",
697                                             getName()));
698     }
699
700     return _poolImpl;
701   }
702
703   /**
704    * Returns the underlying data source.
705    */

706   private DataSource getDataSource()
707   {
708     if (_dataSource == null ||
709     _resinDataSource != null && _resinDataSource.isClosed()) {
710       _dataSource = _localDataSourceImpl.get();
711
712       if (_dataSource instanceof DataSourceImpl)
713     _resinDataSource = (DataSourceImpl) _dataSource;
714       else
715     _resinDataSource = null;
716
717       if (_dataSource == null)
718         throw new IllegalStateException JavaDoc(L.l("DBPool `{0}' no longer exists.",
719                                             getName()));
720     }
721
722     return _dataSource;
723   }
724
725   /**
726    * Returns a string description of the pool.
727    */

728   public String JavaDoc toString()
729   {
730     return "DBPool[" + getName() + "]";
731   }
732 }
733
734
Popular Tags