1 package org.ashkelon.db; 2 6 7 import java.sql.Connection ; 8 import java.sql.DriverManager ; 9 import java.sql.SQLException ; 10 import java.util.Collection ; 11 import java.util.HashMap ; 12 import java.util.Iterator ; 13 import java.util.Map ; 14 import java.util.MissingResourceException ; 15 import java.util.PropertyResourceBundle ; 16 import java.util.ResourceBundle ; 17 18 import org.ashkelon.util.Logger; 19 20 38 public class DBMgr 39 { 40 private static DBMgr _instance = null; 41 42 private String dbtype; 43 private String jdbcDriverName; 44 private String connectionURL; 45 private String user; 46 private String password; 47 48 private boolean targetSet = false; 49 private String defaultTarget = "org.ashkelon.db.conn-info"; 50 51 private ResourceBundle statements; 52 53 private Logger log; 54 55 private Map 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 resourceName) 68 { 69 if (targetSet) { return; } 71 log.verbose("loading connection settings from "+resourceName); 72 73 ResourceBundle bundle = PropertyResourceBundle.getBundle(resourceName); 74 setTarget(bundle); 75 } 76 77 public void setTarget(ResourceBundle connectionBundle) 78 { 79 if (targetSet) { return; } 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 88 loadDriver(); 89 90 log.verbose("jdbc driver: " + jdbcDriverName + " loaded"); 91 92 pool = new HashMap (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 bundle) throws MissingResourceException 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 connectionURL = "jdbc:mckoi:local://"+realPath+"WEB-INF/db/db.conf"; 116 } 118 119 user = bundle.getString("user"); 120 password = bundle.getString("password"); 121 } 122 123 public String getStatement(String key) 124 { 125 try 126 { 127 return statements.getString(key); 128 } 129 catch (MissingResourceException ex) 130 { 131 log.error("No sql statement corresponding to key: "+key); 132 return ""; 133 } 134 } 135 136 private String realPath = ""; 137 private boolean webContext = false; 138 public void setWebApp(javax.servlet.ServletContext 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 ex) 152 { 153 log.error("ClassNotFoundException: "+ex.getMessage()); 154 } 156 } 157 158 public synchronized void setPoolSize(int poolsize) 159 { 160 maxpoolsize = poolsize; 161 } 162 163 166 public synchronized Connection getConnection() throws SQLException 167 { 168 if (!targetSet) { 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 ("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 conns = pool.values(); 204 Iterator 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 conns = pool.values(); 222 Iterator 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 conns = pool.values(); 239 Iterator 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; } 251 252 private PooledConnection makeNewConnection() throws SQLException 253 { 254 Connection conn = DriverManager.getConnection(connectionURL, user, password); 255 PooledConnection pc = new PooledConnection(conn); 256 return pc; 257 } 258 259 260 public synchronized void releaseConnection(Connection 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 Collection conns = pool.keySet(); 276 Iterator itr = conns.iterator(); 277 Connection c; 278 while (itr.hasNext()) 279 { 280 c = (Connection ) itr.next(); 281 try { 282 c.close(); 283 numreset++; 284 } catch (SQLException 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 (maxpoolsize); 292 } 293 } 294 295 public String getPoolStatus() 296 { 297 Iterator 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 statusmsg = "Used/Free/Max: " + numUsed + "/" + numFree + "/" + maxpoolsize; 311 log.verbose(statusmsg); 312 return statusmsg; 313 } 314 315 protected void finalize() throws Throwable 316 { 317 resetConnections(); 318 pool = null; 319 log.verbose("DBMgr finalized"); 320 log = null; 321 } 322 323 public String 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 336 public String getConnectionURL() 337 { 338 return connectionURL; 339 } 340 343 public String getJdbcDriverName() 344 { 345 return jdbcDriverName; 346 } 347 348 class PooledConnection 349 { 350 private Connection conn; 351 private int state; 352 353 public PooledConnection(Connection 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 getConnection() { return conn; } 363 private void setConnection(Connection conn) { this.conn = conn; } 364 } 365 366 } 367 | Popular Tags |