KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > ashkelon > db > DBMgr


1 package org.ashkelon.db;
2 /**
3  * Copyright UptoData Inc. 2001
4  * March 2001
5  */

6
7 import java.sql.Connection JavaDoc;
8 import java.sql.DriverManager JavaDoc;
9 import java.sql.SQLException JavaDoc;
10 import java.util.Collection JavaDoc;
11 import java.util.HashMap JavaDoc;
12 import java.util.Iterator JavaDoc;
13 import java.util.Map JavaDoc;
14 import java.util.MissingResourceException JavaDoc;
15 import java.util.PropertyResourceBundle JavaDoc;
16 import java.util.ResourceBundle JavaDoc;
17
18 import org.ashkelon.util.Logger;
19
20 /**
21  * A singleton class for managing database connections.
22  *
23  * This class currently designed to read connection information from the
24  * properties resource bundle org.ashkelon.db.conn-info providing values for the
25  * following keys: jdbcDriverName, connectionURL, user, password.
26  *
27  * for example:
28  * jdbcDriverName=oracle.lite.poljdbc.POLJDBCDriver
29  * connectionURL=jdbc:Polite:ashkelon
30  * user=system
31  * password=passwd
32  *
33  * will probably be revised at a later time to provide this info more
34  * flexibly
35  *
36  * @author Eitan Suez
37  */

38 public class DBMgr
39 {
40    private static DBMgr _instance = null;
41
42    private String JavaDoc dbtype;
43    private String JavaDoc jdbcDriverName;
44    private String JavaDoc connectionURL;
45    private String JavaDoc user;
46    private String JavaDoc password;
47    
48    private boolean targetSet = false;
49    private String JavaDoc defaultTarget = "org.ashkelon.db.conn-info";
50
51    private ResourceBundle JavaDoc statements;
52    
53    private Logger log;
54    
55    private Map JavaDoc pool;
56    private int maxpoolsize = 20;
57    
58    private static final int BUSY = 1;
59    private static final int FREE = 2;
60    
61    
62    private DBMgr()
63    {
64       log = Logger.getInstance();
65    }
66
67    public void setTarget(String JavaDoc resourceName)
68    {
69       if (targetSet) { return; } // don't allow switching of targets (for now)
70

71       log.verbose("loading connection settings from "+resourceName);
72       
73       ResourceBundle JavaDoc bundle = PropertyResourceBundle.getBundle(resourceName);
74       setTarget(bundle);
75    }
76    
77    public void setTarget(ResourceBundle JavaDoc connectionBundle)
78    {
79       if (targetSet) { return; } // don't allow switching of targets (for now)
80

81       loadConnectionInfo(connectionBundle);
82       statements = PropertyResourceBundle.getBundle("org.ashkelon.db.statements");
83    
84       log.verbose("Connection url is: "+connectionURL);
85       log.verbose("User is: "+user);
86       //log.verbose("password is: "+password);
87

88       loadDriver();
89    
90       log.verbose("jdbc driver: " + jdbcDriverName + " loaded");
91    
92       pool = new HashMap JavaDoc(maxpoolsize);
93       targetSet = true;
94    }
95    
96    public static DBMgr getInstance()
97    {
98       if (_instance == null)
99       {
100          _instance = new DBMgr();
101       }
102       return _instance;
103    }
104    
105    private void loadConnectionInfo(ResourceBundle JavaDoc bundle) throws MissingResourceException JavaDoc
106    {
107       dbtype = bundle.getString("dbtype");
108       jdbcDriverName = bundle.getString("jdbcDriverName");
109       connectionURL = bundle.getString("connectionURL");
110       
111       if (webContext && connectionURL.equals("jdbc:mckoi:local://./db.conf"))
112       {
113          // need to translate relative path to an absolute path to
114
// resolve the proper location of the db
115
connectionURL = "jdbc:mckoi:local://"+realPath+"WEB-INF/db/db.conf";
116          // decision to place db in WEB-INF/db is simply a convention
117
}
118       
119       user = bundle.getString("user");
120       password = bundle.getString("password");
121    }
122    
123    public String JavaDoc getStatement(String JavaDoc key)
124    {
125       try
126       {
127          return statements.getString(key);
128       }
129       catch (MissingResourceException JavaDoc ex)
130       {
131          log.error("No sql statement corresponding to key: "+key);
132          return "";
133       }
134    }
135    
136    private String JavaDoc realPath = "";
137    private boolean webContext = false;
138    public void setWebApp(javax.servlet.ServletContext JavaDoc webapp)
139    {
140       webContext = true;
141       realPath = webapp.getRealPath("/");
142       log.brief("Running in a web context. Real Path is: "+realPath);
143    }
144    
145    private void loadDriver()
146    {
147       try
148       {
149          Class.forName(jdbcDriverName);
150       }
151       catch (ClassNotFoundException JavaDoc ex)
152       {
153          log.error("ClassNotFoundException: "+ex.getMessage());
154          // System.exit(1);
155
}
156    }
157    
158    public synchronized void setPoolSize(int poolsize)
159    {
160       maxpoolsize = poolsize;
161    }
162    
163    /**
164     * @return a java.sql.connection object
165     */

166    public synchronized Connection JavaDoc getConnection() throws SQLException JavaDoc
167    {
168       if (!targetSet) // use default
169
{
170          setTarget(defaultTarget);
171       }
172       
173       if (haveAConnection())
174       {
175          PooledConnection conn = getAvailableConnection();
176          conn.setState(BUSY);
177          getPoolStatus();
178          return conn.getConnection();
179       }
180       else
181       {
182          if (pool.size() >= maxpoolsize)
183          {
184             getPoolStatus();
185             throw new SQLException JavaDoc("org.ashkelon.db.DBMgr: No more connections available");
186          }
187          else
188          {
189             PooledConnection conn = makeNewConnection();
190             conn.setState(BUSY);
191             pool.put(conn.getConnection(), conn);
192             getPoolStatus();
193             return conn.getConnection();
194          }
195       }
196    }
197    
198
199    private boolean haveAConnection()
200    {
201       if (pool.size() > maxpoolsize)
202       {
203          Collection JavaDoc conns = pool.values();
204          Iterator JavaDoc itr = conns.iterator();
205          PooledConnection pc;
206          int busycount = 0;
207          while (itr.hasNext())
208          {
209             pc = (PooledConnection) itr.next();
210             if (pc.getState() == BUSY)
211             {
212                busycount++;
213             }
214          }
215          if (busycount > maxpoolsize)
216          {
217             return false;
218          }
219       }
220       
221       Collection JavaDoc conns = pool.values();
222       Iterator JavaDoc itr = conns.iterator();
223       PooledConnection pc;
224       while (itr.hasNext())
225       {
226          pc = (PooledConnection) itr.next();
227          if (pc.getState() == FREE)
228          {
229             return true;
230          }
231       }
232       return false;
233    }
234    
235    
236    private PooledConnection getAvailableConnection()
237    {
238       Collection JavaDoc conns = pool.values();
239       Iterator JavaDoc itr = conns.iterator();
240       PooledConnection pc;
241       while (itr.hasNext())
242       {
243          pc = (PooledConnection) itr.next();
244          if (pc.getState() == FREE)
245          {
246             return pc;
247          }
248       }
249       return null; // what's the saying? somewhere along the way something went terribly wrong.
250
}
251    
252    private PooledConnection makeNewConnection() throws SQLException JavaDoc
253    {
254       Connection JavaDoc conn = DriverManager.getConnection(connectionURL, user, password);
255       PooledConnection pc = new PooledConnection(conn);
256       return pc;
257    }
258    
259    
260    public synchronized void releaseConnection(Connection JavaDoc conn)
261    {
262       PooledConnection pc = (PooledConnection) pool.get(conn);
263       if (pc != null)
264          pc.setState(FREE);
265    }
266    
267    public void resetConnections()
268    {
269       synchronized(this)
270       {
271          int numreset = 0;
272          int numfailed = 0;
273          log.traceln("about to reset connections");
274          // close all connections
275
Collection JavaDoc conns = pool.keySet();
276          Iterator JavaDoc itr = conns.iterator();
277          Connection JavaDoc c;
278          while (itr.hasNext())
279          {
280             c = (Connection JavaDoc) itr.next();
281             try {
282                c.close();
283                numreset++;
284             } catch (SQLException JavaDoc ex)
285             {
286                numfailed++;
287             }
288          }
289          log.traceln("successfully reset "+numreset+" connections");
290          log.traceln("failed to reset "+numreset+" connections");
291          pool = new HashMap JavaDoc(maxpoolsize);
292       }
293    }
294    
295    public String JavaDoc getPoolStatus()
296    {
297       Iterator JavaDoc itr = pool.values().iterator();
298       PooledConnection pc = null;
299       int numUsed = 0;
300       int numFree = 0;
301       while (itr.hasNext())
302       {
303          pc = (PooledConnection) itr.next();
304          if (pc.getState() == BUSY) {
305              numUsed++;
306          } else {
307              numFree++;
308          }
309       }
310       String JavaDoc statusmsg = "Used/Free/Max: " + numUsed + "/" + numFree + "/" + maxpoolsize;
311       log.verbose(statusmsg);
312       return statusmsg;
313    }
314    
315    protected void finalize() throws Throwable JavaDoc
316    {
317       resetConnections();
318       pool = null;
319       log.verbose("DBMgr finalized");
320       log = null;
321    }
322    
323    public String JavaDoc getDbtype()
324    {
325       return dbtype;
326    }
327    public boolean isOracle() { return "oracle".equals(dbtype); }
328    public boolean isAnsiSql()
329    {
330       return "mysql".equals(dbtype) || "postgres".equals(dbtype);
331    }
332    
333    /**
334     * get the value of the connectionURL in use
335     */

336    public String JavaDoc getConnectionURL()
337    {
338       return connectionURL;
339    }
340    /**
341     * get the value of the jdbc driver name in use
342     */

343    public String JavaDoc getJdbcDriverName()
344    {
345       return jdbcDriverName;
346    }
347
348    class PooledConnection
349    {
350       private Connection JavaDoc conn;
351       private int state;
352
353       public PooledConnection(Connection JavaDoc conn)
354       {
355          setConnection(conn);
356          setState(FREE);
357       }
358
359       public int getState() { return state; }
360       public void setState(int state) { this.state = state; }
361
362       public Connection JavaDoc getConnection() { return conn; }
363       private void setConnection(Connection JavaDoc conn) { this.conn = conn; }
364    }
365
366 }
367
Popular Tags