KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > protomatter > jdbc > pool > JdbcConnectionPoolDataSource


1 package com.protomatter.jdbc.pool;
2
3 /**
4  * {{{ The Protomatter Software License, Version 1.0
5  * derived from The Apache Software License, Version 1.1
6  *
7  * Copyright (c) 1998-2002 Nate Sammons. All rights reserved.
8  *
9  * Redistribution and use in source and binary forms, with or without
10  * modification, are permitted provided that the following conditions
11  * are met:
12  *
13  * 1. Redistributions of source code must retain the above copyright
14  * notice, this list of conditions and the following disclaimer.
15  *
16  * 2. Redistributions in binary form must reproduce the above copyright
17  * notice, this list of conditions and the following disclaimer in
18  * the documentation and/or other materials provided with the
19  * distribution.
20  *
21  * 3. The end-user documentation included with the redistribution,
22  * if any, must include the following acknowledgment:
23  * "This product includes software developed for the
24  * Protomatter Software Project
25  * (http://protomatter.sourceforge.net/)."
26  * Alternately, this acknowledgment may appear in the software itself,
27  * if and wherever such third-party acknowledgments normally appear.
28  *
29  * 4. The names "Protomatter" and "Protomatter Software Project" must
30  * not be used to endorse or promote products derived from this
31  * software without prior written permission. For written
32  * permission, please contact support@protomatter.com.
33  *
34  * 5. Products derived from this software may not be called "Protomatter",
35  * nor may "Protomatter" appear in their name, without prior written
36  * permission of the Protomatter Software Project
37  * (support@protomatter.com).
38  *
39  * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
40  * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
41  * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
42  * DISCLAIMED. IN NO EVENT SHALL THE PROTOMATTER SOFTWARE PROJECT OR
43  * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
44  * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
45  * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
46  * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
47  * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
48  * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
49  * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
50  * SUCH DAMAGE. }}}
51  */

52
53 import com.protomatter.util.*;
54 import com.protomatter.pool.*;
55 import com.protomatter.syslog.Syslog;
56 import java.util.*;
57 import java.io.*;
58 import java.sql.*;
59 import java.text.MessageFormat JavaDoc;
60 import javax.sql.*;
61
62 /**
63  * An implementation of the <tt>javax.sql.DataSource</tt> and
64  * <tt>javax.sql.ConnectionPoolDataSource</tt> interfaces.
65  *
66  * @see javax.sql.DataSource
67  * @see javax.sql.ConnectionPoolDataSource
68  * @see JdbcConnectionPool
69  * @see JdbcConnectionPoolDriver
70  * @see JdbcConnectionPoolConnection
71  */

72 public class JdbcConnectionPoolDataSource
73 implements DataSource, ConnectionPoolDataSource
74 {
75   private String JavaDoc poolName = null;
76   private PrintWriter logWriter = null;
77   private int loginTimeout = 0;
78   private JdbcConnectionPool pool = null;
79
80   /**
81    * Create a new <tt>DataSource</tt> attached to the given JDBC
82    * connection pool. The pool must already exist.
83    *
84    * @see JdbcConnectionPool
85    * @throw SQLException If the given pool does not exist.
86    */

87   public JdbcConnectionPoolDataSource(String JavaDoc poolName)
88   throws SQLException
89   {
90     pool = JdbcConnectionPoolDriver.getPool(poolName);
91     if (pool == null)
92       throw new SQLException(MessageFormat.format(
93         PoolResources.getResourceString(MessageConstants.UNKNOWN_POOL_MESSAGE),
94         new Object JavaDoc[] { poolName }));
95     this.poolName = poolName;
96   }
97
98   /**
99    * Get a connection from this <tt>DataSource</tt>. If the login timeout
100    * has been set to zero, this method will block indefinately. If the timeout
101    * has been set to something other than zero, this method is guaranteed to
102    * return (or throw a <tt>SQLException</tt>) within the specified time period.
103    *
104    * @see javax.sql.DataSource
105    */

106   public Connection getConnection()
107   throws SQLException
108   {
109     Connection c = null;
110
111     // limit the time we wait for a connection.
112
if (loginTimeout > 0)
113     {
114       // use a background thread to get a connection so we can
115
// implement this login timeout stuff.
116
GetConnectionSlaveThread t = new GetConnectionSlaveThread(pool);
117       t.start();
118
119       // when should we stop?
120
int timeout = loginTimeout;
121       long end = System.currentTimeMillis();
122       end += (long)((long)loginTimeout * (long)1000);
123
124       // just in case we can get a connection immediately,
125
// first sleep for as little time as we can.
126
try { Thread.sleep(1); } catch (InterruptedException JavaDoc x) { ; }
127
128       // now, wait 10 milliseconds between checks to see if
129
// we could get a connection or not.
130
while ((t.getConnection() == null) && (t.isAlive()) && (System.currentTimeMillis() < end))
131       {
132         try { Thread.sleep(10); } catch (InterruptedException JavaDoc x) { ; }
133         Thread.yield(); // tight loops are bad.
134
}
135
136       // remove the thread from the list of waiters that
137
// are in line to get a connection.
138
pool.removeWaiter(t);
139
140       // see if we were able to get a connection.
141
c = t.getConnection();
142       if (c == null) // thread hasn't got a connection yet
143
{
144         if (t.isAlive()) // still running?
145
t.interrupt(); // not anymore
146

147         if (t.getException() != null) // throw the exception that the thread ran into.
148
throw t.getException();
149         else // just give up.
150
throw new SQLException(MessageFormat.format(
151             PoolResources.getResourceString(MessageConstants.CANNOT_GET_CONNECTION_TIMEOUT_MESSAGE),
152             new Object JavaDoc[] { String.valueOf(timeout) }));
153       }
154     }
155     else
156     {
157       // don't limit the time we take to get a connection.
158
c = DriverManager.getConnection(JdbcConnectionPoolDriver.URL_PREFIX + poolName);
159     }
160
161     // success... finally.
162
return c;
163   }
164
165   /**
166    * Get a connection from this <tt>DataSource</tt>. The <tt>user</tt>
167    * and <tt>password</tt> are ignored.
168    * If the login timeout
169    * has been set to zero, this method will block indefinately. If the timeout
170    * has been set to something other than zero, this method is guaranteed to
171    * return (or throw a <tt>SQLException</tt>) within the specified time period.
172    *
173    * @see javax.sql.DataSource
174    */

175   public Connection getConnection(String JavaDoc user, String JavaDoc password)
176   throws SQLException
177   {
178     return getConnection();
179   }
180
181   /**
182    * Get the log writer.
183    *
184    * @see javax.sql.DataSource
185    */

186   public PrintWriter getLogWriter()
187   throws SQLException
188   {
189     return this.logWriter;
190   }
191
192   /**
193    * Set the log writer.
194    *
195    * @see javax.sql.DataSource
196    */

197   public void setLogWriter(PrintWriter logWriter)
198   throws SQLException
199   {
200     this.logWriter = logWriter;
201   }
202
203   /**
204    * Get the login timeout. The value specified is in seconds.
205    *
206    * @see javax.sql.DataSource
207    */

208   public int getLoginTimeout()
209   throws SQLException
210   {
211     return this.loginTimeout;
212   }
213
214   /**
215    * Set the login timeout (in seconds). If this value is set to
216    * something other than zero, any method that gets a connection
217    * is guaranteed to return (or throw a <tt>SQLException</tt>) within the
218    * specified amount of time. If this value is set to zero,
219    * any method that gets a connection will block indefinately
220    * until a connection is available. The default value is zero.
221    *
222    * @see javax.sql.DataSource
223    */

224   public void setLoginTimeout(int loginTimeout)
225   throws SQLException
226   {
227     this.loginTimeout = loginTimeout;
228   }
229
230   /**
231    * Get a <tt>PooledConnection</tt> from this <tt>ConnectionPoolDataSource</tt>.
232    * The <tt>user</tt> and <tt>password</tt> are currently ignored.
233    * If the login timeout
234    * has been set to zero, this method will block indefinately. If the timeout
235    * has been set to something other than zero, this method is guaranteed to
236    * return (or throw a <tt>SQLException</tt>) within the specified time period.
237    *
238    * @see javax.sql.ConnectionPoolDataSource
239    */

240   public PooledConnection getPooledConnection(String JavaDoc user, String JavaDoc password)
241   throws SQLException
242   {
243     return getPooledConnection();
244   }
245
246   /**
247    * Get a <tt>PooledConnection</tt> from this <tt>ConnectionPoolDataSource</tt>.
248    * If the login timeout
249    * has been set to zero, this method will block indefinately. If the timeout
250    * has been set to something other than zero, this method is guaranteed to
251    * return (or throw a <tt>SQLException</tt>) within the specified time period.
252    *
253    * @see javax.sql.ConnectionPoolDataSource
254    */

255   public PooledConnection getPooledConnection()
256   throws SQLException
257   {
258     return new JdbcConnectionPoolPooledConnection((JdbcConnectionPoolConnection)getConnection());
259   }
260
261   /**
262    * This is a support class for getting connections in the background.
263    */

264   private class GetConnectionSlaveThread
265   extends Thread JavaDoc
266   {
267     private JdbcConnectionPool pool = null;
268     private Connection connection = null;
269     private SQLException exception = null;
270
271     public GetConnectionSlaveThread(JdbcConnectionPool pool)
272     {
273       super();
274       setDaemon(true);
275       this.pool = pool;
276     }
277
278     public void run()
279     {
280       try
281       {
282         connection = DriverManager.getConnection(JdbcConnectionPoolDriver.URL_PREFIX + pool.getName());
283       }
284       catch (SQLException sqlx)
285       {
286         pool.removeWaiter(this);
287         exception = sqlx;
288         close();
289       }
290       catch (Exception JavaDoc x) // most likely we were interrupted.
291
{
292         pool.removeWaiter(this);
293         close();
294       }
295     }
296
297     private void close()
298     {
299       if (connection != null)
300       {
301         try
302         {
303           connection.close();
304         }
305         catch (Exception JavaDoc x)
306         {
307           if (pool.useSyslog())
308           {
309             Syslog.error(this, MessageFormat.format(
310               PoolResources.getResourceString(MessageConstants.CANNOT_CLOSE_OPEN_CONNECTION_MESSAGE),
311               new Object JavaDoc[] { pool.getName() }), x);
312           }
313           else
314           {
315             PrintWriter pw = DriverManager.getLogWriter();
316             if (pw != null)
317             {
318               pw.println("JdbcConnectionPoolDataSource: " +
319                 MessageFormat.format(PoolResources.getResourceString(MessageConstants.CANNOT_CLOSE_OPEN_CONNECTION_MESSAGE),
320                 new Object JavaDoc[] { pool.getName() }));
321               x.printStackTrace(pw);
322             }
323           }
324         }
325       }
326     }
327
328     public Connection getConnection()
329     {
330       return this.connection;
331     }
332
333     public SQLException getException()
334     {
335       return this.exception;
336     }
337   }
338 }
339
Popular Tags