KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > xalan > lib > sql > DefaultConnectionPool


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  * $Id: DefaultConnectionPool.java,v 1.20 2004/02/23 10:29:35 aruny Exp $
18  */

19 package org.apache.xalan.lib.sql;
20
21 import java.sql.Connection JavaDoc;
22 import java.sql.DatabaseMetaData JavaDoc;
23 import java.sql.Driver JavaDoc;
24 import java.sql.DriverManager JavaDoc;
25 import java.sql.SQLException JavaDoc;
26 import java.util.Enumeration JavaDoc;
27 import java.util.Properties JavaDoc;
28 import java.util.Vector JavaDoc;
29
30 import org.apache.xalan.res.XSLMessages;
31 import org.apache.xalan.res.XSLTErrorResources;
32
33 /**
34  * For internal connectiones, i.e. Connection information supplies in the
35  * Stylesheet. The Default Connection Pool will be used.
36  */

37 public class DefaultConnectionPool implements ConnectionPool
38 {
39   /**
40    * A placeholder thast will keep the driver loaded
41    * between calls.
42    */

43   private Driver JavaDoc m_Driver = null;
44   /**
45    */

46   private static final boolean DEBUG = false;
47
48   /**
49    * The basic information to make a JDBC Connection
50    */

51   private String JavaDoc m_driver = new String JavaDoc("");
52   /**
53    */

54   private String JavaDoc m_url = new String JavaDoc("");
55
56
57   /**
58    * The mimimum size of the connection pool, if the
59    * number of available connections falls below this
60    * mark, min connections will be allocated. The Connection
61    * Pool will always be somewhere between MinSize and MinSize*2
62    */

63   private int m_PoolMinSize = 1;
64
65
66   /**
67    * Always implement the properties mechinism, if the Password
68    * or Username is set seperatly then we will add them to the
69    * property manually.
70    */

71   private Properties JavaDoc m_ConnectionProtocol = new Properties JavaDoc();
72
73   /**
74    * Storage for the PooledConnections
75    */

76   private Vector JavaDoc m_pool = new Vector JavaDoc();
77
78   /**
79    * Are we active ??
80    */

81   private boolean m_IsActive = false;
82
83   /**
84    */

85   public DefaultConnectionPool( ) {}
86
87
88   /**
89    * Return our current Active state
90    *
91    */

92   public boolean isEnabled( )
93   {
94     return m_IsActive;
95   }
96
97   /**
98    * Set the driver call to be used to create connections
99    * @param d
100    *
101    */

102   public void setDriver( String JavaDoc d )
103   {
104     m_driver = d;
105   }
106
107   /**
108    * Set the url used to connect to the database
109    * @param url
110    *
111    */

112   public void setURL( String JavaDoc url )
113   {
114     m_url = url;
115   }
116
117   /**
118    * Go through the connection pool and release any connections
119    * that are not InUse;
120    *
121    */

122   public void freeUnused( )
123   {
124     // Iterate over the entire pool closing the
125
// JDBC Connections.
126
for ( int x = 0; x < m_pool.size(); x++ )
127     {
128
129
130       PooledConnection pcon =
131         (PooledConnection) m_pool.elementAt(x);
132
133       // If the PooledConnection is not in use, close it
134
if ( pcon.inUse() == false )
135       {
136         if (DEBUG)
137         {
138           System.err.println("Closing JDBC Connection " + x);
139         }
140
141         pcon.close();
142       }
143     }
144
145   }
146
147   /**
148    * Is our ConnectionPool have any connections that are still in Use ??
149    *
150    */

151   public boolean hasActiveConnections( )
152   {
153     return (m_pool.size() > 0);
154   }
155
156
157   /**
158    * Set the password in the property set.
159    * @param p
160    *
161    */

162   public void setPassword( String JavaDoc p )
163   {
164     m_ConnectionProtocol.put("password", p);
165   }
166
167   /**
168    * Set the user name in the property set
169    * @param u
170    *
171    */

172   public void setUser( String JavaDoc u )
173   {
174     m_ConnectionProtocol.put("user", u);
175   }
176
177   /**
178    * The Protocol string is used to pass in other connection
179    * properties. A properties file is a general purpose container
180    *
181    * @param p
182    *
183    */

184   public void setProtocol( Properties JavaDoc p )
185   {
186     Enumeration JavaDoc e = p.keys();
187     while (e.hasMoreElements())
188     {
189       String JavaDoc key = (String JavaDoc) e.nextElement();
190       m_ConnectionProtocol.put(key, p.getProperty(key));
191     }
192   }
193
194
195   /**
196    * Override the current number of connections to keep in the pool. This
197    * setting will only have effect on a new pool or when a new connection
198    * is requested and there is less connections that this setting.
199    * @param n
200    *
201    */

202   public void setMinConnections( int n )
203   {
204     m_PoolMinSize = n;
205   }
206
207   /**
208    * Try to aquire a new connection, if it succeeds then return
209    * true, else return false.
210    * Note: This method will cause the connection pool to be built.
211    *
212    */

213   public boolean testConnection( )
214   {
215     try
216     {
217       if (DEBUG)
218       {
219         System.out.println("Testing Connection");
220       }
221
222       Connection JavaDoc conn = getConnection();
223
224       if (DEBUG)
225       {
226         DatabaseMetaData JavaDoc dma = conn.getMetaData();
227
228         System.out.println("\nConnected to " + dma.getURL());
229         System.out.println("Driver " + dma.getDriverName());
230         System.out.println("Version " + dma.getDriverVersion());
231         System.out.println("");
232       }
233
234       if (conn == null) return false;
235
236       releaseConnection(conn);
237
238       if (DEBUG)
239       {
240         System.out.println("Testing Connection, SUCCESS");
241       }
242
243       return true;
244     }
245     catch(Exception JavaDoc e)
246     {
247       if (DEBUG)
248       {
249         System.out.println("Testing Connection, FAILED");
250         e.printStackTrace();
251       }
252
253       return false;
254     }
255
256   }
257
258
259   // Find an available connection
260
/**
261    * @return Connection
262    * @throws SQLException
263    * @throws IllegalArgumentException
264    */

265   public synchronized Connection JavaDoc getConnection( )throws IllegalArgumentException JavaDoc, SQLException JavaDoc
266   {
267
268     PooledConnection pcon = null;
269
270     // We will fill up the pool any time it is less than the
271
// Minimum. THis could be cause by the enableing and disabling
272
// or the pool.
273
//
274
if ( m_pool.size() < m_PoolMinSize ) { initializePool(); }
275
276     // find a connection not in use
277
for ( int x = 0; x < m_pool.size(); x++ )
278     {
279
280       pcon = (PooledConnection) m_pool.elementAt(x);
281
282       // Check to see if the Connection is in use
283
if ( pcon.inUse() == false )
284       {
285         // Mark it as in use
286
pcon.setInUse(true);
287         // return the JDBC Connection stored in the
288
// PooledConnection object
289
return pcon.getConnection();
290       }
291     }
292
293     // Could not find a free connection,
294
// create and add a new one
295

296     // Create a new JDBC Connection
297
Connection JavaDoc con = createConnection();
298
299     // Create a new PooledConnection, passing it the JDBC
300
// Connection
301
pcon = new PooledConnection(con);
302
303     // Mark the connection as in use
304
pcon.setInUse(true);
305
306     // Add the new PooledConnection object to the pool
307
m_pool.addElement(pcon);
308
309     // return the new Connection
310
return pcon.getConnection();
311   }
312
313   /**
314    * @param con
315    *
316    * @throws SQLException
317    */

318   public synchronized void releaseConnection( Connection JavaDoc con )throws SQLException JavaDoc
319   {
320
321     // find the PooledConnection Object
322
for ( int x = 0; x < m_pool.size(); x++ )
323     {
324
325       PooledConnection pcon =
326         (PooledConnection) m_pool.elementAt(x);
327
328       // Check for correct Connection
329
if ( pcon.getConnection() == con )
330       {
331         if (DEBUG)
332         {
333           System.out.println("Releasing Connection " + x);
334         }
335
336         if (! isEnabled())
337         {
338           con.close();
339           m_pool.removeElementAt(x);
340           if (DEBUG)
341           {
342             System.out.println("-->Inactive Pool, Closing connection");
343           }
344
345         }
346         else
347         {
348           // Set it's inuse attribute to false, which
349
// releases it for use
350
pcon.setInUse(false);
351         }
352
353         break;
354       }
355     }
356   }
357
358
359   /**
360    * @param con
361    *
362    * @throws SQLException
363    */

364   public synchronized void releaseConnectionOnError( Connection JavaDoc con )throws SQLException JavaDoc
365   {
366
367     // find the PooledConnection Object
368
for ( int x = 0; x < m_pool.size(); x++ )
369     {
370
371       PooledConnection pcon =
372         (PooledConnection) m_pool.elementAt(x);
373
374       // Check for correct Connection
375
if ( pcon.getConnection() == con )
376       {
377         if (DEBUG)
378         {
379           System.out.println("Releasing Connection On Error" + x);
380         }
381
382         con.close();
383         m_pool.removeElementAt(x);
384         if (DEBUG)
385         {
386           System.out.println("-->Inactive Pool, Closing connection");
387         }
388         break;
389       }
390     }
391   }
392
393
394   /**
395    *
396    * @throws SQLException
397    */

398   private Connection JavaDoc createConnection( )throws SQLException JavaDoc
399   {
400     Connection JavaDoc con = null;
401
402     // Create a Connection directly from the Driver that was loaded
403
// with the context class loader. This is to support JDK1.4
404
con = m_Driver.connect(m_url, m_ConnectionProtocol );
405
406     return con;
407   }
408
409   // Initialize the pool
410
/**
411    *
412    * @throws IllegalArgumentException
413    * @throws SQLException
414    */

415   public synchronized void initializePool( )throws IllegalArgumentException JavaDoc, SQLException JavaDoc
416   {
417
418      // Check our initial values
419
if ( m_driver == null )
420      {
421        throw new IllegalArgumentException JavaDoc(XSLMessages.createMessage(XSLTErrorResources.ER_NO_DRIVER_NAME_SPECIFIED, null));
422        // "No Driver Name Specified!");
423
}
424
425      if ( m_url == null )
426      {
427        throw new IllegalArgumentException JavaDoc(XSLMessages.createMessage(XSLTErrorResources.ER_NO_URL_SPECIFIED, null));
428        // "No URL Specified!");
429
}
430
431      if ( m_PoolMinSize < 1 )
432      {
433        throw new IllegalArgumentException JavaDoc(XSLMessages.createMessage(XSLTErrorResources.ER_POOLSIZE_LESS_THAN_ONE, null));
434        // "Pool size is less than 1!");
435
}
436
437      // Create the Connections
438
// Load the Driver class file
439

440      try
441      {
442         // We have also had problems with drivers unloading
443
// load an instance that will get freed with the class.
444
m_Driver = (Driver JavaDoc) ObjectFactory.newInstance(
445           m_driver, ObjectFactory.findClassLoader(), true);
446
447         // Register the Driver that was loaded with the Context Classloader
448
// but we will ask for connections directly from the Driver
449
// instance
450
DriverManager.registerDriver(m_Driver);
451      }
452      catch(ObjectFactory.ConfigurationError e)
453      {
454        throw new IllegalArgumentException JavaDoc(XSLMessages.createMessage(XSLTErrorResources.ER_INVALID_DRIVER_NAME, null));
455        // "Invalid Driver Name Specified!");
456
}
457      catch(Exception JavaDoc e)
458      {
459        throw new IllegalArgumentException JavaDoc(XSLMessages.createMessage(XSLTErrorResources.ER_INVALID_DRIVER_NAME, null));
460      }
461
462      // IF we are not active, don't actuall build a pool yet
463
// Just set up the driver and periphal items.
464
if ( !m_IsActive) return;
465
466     // Create Connections based on the size member
467
do
468     {
469
470       Connection JavaDoc con = createConnection();
471
472       if ( con != null )
473       {
474
475         // Create a PooledConnection to encapsulate the
476
// real JDBC Connection
477
PooledConnection pcon = new PooledConnection(con);
478
479         // Add the Connection the pool.
480
addConnection(pcon);
481
482         if (DEBUG) System.out.println("Adding DB Connection to the Pool");
483       }
484     }
485     while (m_pool.size() < m_PoolMinSize);
486   }
487
488   // Adds the PooledConnection to the pool
489
/**
490    * @param value
491    *
492    */

493   private void addConnection( PooledConnection value )
494   {
495     // Add the PooledConnection Object to the vector
496
m_pool.addElement(value);
497   }
498
499
500   /**
501    *
502    * @throws Throwable
503    */

504   protected void finalize( )throws Throwable JavaDoc
505   {
506     if (DEBUG)
507     {
508       System.out.println("In Default Connection Pool, Finalize");
509     }
510
511     // Iterate over the entire pool closing the
512
// JDBC Connections.
513
for ( int x = 0; x < m_pool.size(); x++ )
514     {
515
516       if (DEBUG)
517       {
518         System.out.println("Closing JDBC Connection " + x);
519       }
520
521       PooledConnection pcon =
522         (PooledConnection) m_pool.elementAt(x);
523
524       // If the PooledConnection is not in use, close it
525
if ( pcon.inUse() == false ) { pcon.close(); }
526       else
527       {
528         if (DEBUG)
529         {
530           System.out.println("--> Force close");
531         }
532
533         // If it still in use, sleep for 30 seconds and
534
// force close.
535
try
536         {
537           java.lang.Thread.sleep(30000);
538           pcon.close();
539         }
540         catch (InterruptedException JavaDoc ie)
541         {
542           if (DEBUG) System.err.println(ie.getMessage());
543         }
544       }
545     }
546
547     if (DEBUG)
548     {
549       System.out.println("Exit Default Connection Pool, Finalize");
550     }
551
552     super.finalize();
553   }
554
555   /**
556    * The Pool can be Enabled and Disabled. Disabling the pool
557    * closes all the outstanding Unused connections and any new
558    * connections will be closed upon release.
559    *
560    * @param flag Control the Connection Pool.
561    * If it is enabled then Connections will actuall be held
562    * around. If disabled then all unused connections will be instantly
563    * closed and as connections are released they are closed and removed
564    * from the pool.
565    *
566    *
567    */

568   public void setPoolEnabled( boolean flag )
569   {
570      m_IsActive = flag;
571      if ( ! flag )
572       freeUnused();
573   }
574
575 }
576
Popular Tags