View Javadoc
1 /* 2 * PROJECT : DAR Runtime and Tools 3 * COPYRIGHT : Copyright (C) 1999-2004 tim.stephenson@enableit.org 4 * LICENSE : GNU LESSER GENERAL PUBLIC LICENSE 5 * Version 2.1, February 1999 6 * 7 * This program is free software; you can redistribute it and/or modify 8 * it under the terms of the GNU General Public License as published by 9 * the Free Software Foundation; either version 2 of the License, or 10 * (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA 20 */ 21 package org.enableit.db; 22 23 24 // Java Imports 25 import java.io.IOException; 26 import java.io.InputStream; 27 import java.sql.Connection; 28 import java.sql.DriverManager; 29 import java.sql.SQLException; 30 import java.util.Enumeration; 31 import java.util.HashMap; 32 import java.util.HashSet; 33 import java.util.Properties; 34 import java.util.Set; 35 36 import org.apache.log4j.Category; 37 import org.enableit.db.beans.Provider; 38 import org.enableit.db.beans.ProviderExt; 39 40 41 /*** 42 * General class intended to hide the process of obtaining 43 * database connections to any database. 44 * 45 * <p>Over time this class has evolved to fulfil different goals, but is 46 * maintained for backwards compatibility. There are two principle uses: 47 * <ol> 48 * <li>Connection to a single database when no runtime configuration 49 * mechanism (e.g. JNDI / user login form) exists. </li> 50 * <li>Connection to one or more databases whether or not runtime 51 * configuration exists (If such a mechanism exists you are advised 52 * to use it).</li> 53 * </ol> 54 * It is important not to mix these two usages as unexpected results may ensue. 55 * </p> 56 * 57 * <p>In the first case, the connection properties such as server name, 58 * username/password etc. 59 * are all stored in a file named db.properties in the package level 60 * directory matching this class (i.e. <code>org.enableit.db</code>). These 61 * may be overridden by the use of the <code>setProperty</code> method.</p> 62 * 63 * <p>In the second case this class is simply for encapsulation. In other words 64 * it offers a way to hide the actual mechanism 65 * of finding the database connection to the higher level (application) logic. 66 * This allows a J2EE application to use JNDI to obtain connections and a 67 * thick-client application configured by a logon screen to both employ common 68 * logic whilst this factory 69 * takes care of how to find connections at runtime.</p> 70 * 71 * <p>This class has been tested with the following database drivers: 72 * <ul> 73 * <li>ASE/ASA (Sybase jConnect 5.x)</li> 74 * <li>MySQL (MM.MySQL driver)</li> 75 * </ul> 76 * </p> 77 * 78 * @version v1.0 79 * 80 * @author __AUTHOR__ 81 * @deprecated This is just the legacy code, 82 * things of ongoing use are in the new ancestor. 83 */ 84 public class ConnectionFactory extends ConnFactory { 85 /* 86 * Properties 87 */ 88 89 /*** 90 * Holds the <code>Provider</code> instances that have been configured as 91 * data sources. 92 * @see org.enableit.db.beans.Provider 93 */ 94 private static HashMap connConfigs = new HashMap(); 95 96 /*** 97 * The Log4J <code>Category</code> doing the logging. 98 * Same <code>Category</code> is used throughout the package. 99 */ 100 protected static Category logger = Category.getInstance(ConnectionFactory.class); 101 102 /*** 103 * Reference to the singleton instance 104 * 105 * NB the singleton status is not enforced via a synchronise statement 106 */ 107 private static ConnectionFactory me; 108 109 /*** 110 * The current database properties to make connections with 111 */ 112 private static Properties props = new Properties(); 113 114 /*** 115 * Information on the exact CVS version accessible after compilation 116 */ 117 public static final String ABOUT = "$Revision: 1.11 $"; 118 119 /* 120 * Constructors 121 */ 122 123 /*** 124 * Default Constructor 125 */ 126 private ConnectionFactory() { 127 logger.info("METHOD_ENTRY constructor"); 128 129 // Need to initialise with something, use props file in case no JNDI available 130 props = new Properties(); 131 132 try { 133 // Check class instance and get source properties 134 InputStream is = this.getClass().getResourceAsStream("db.properties"); 135 136 props.load(is); 137 138 configureFromProps(); 139 } catch (NullPointerException e) { 140 logger.warn("Unable to read db connection properties: " 141 + e.getMessage()); 142 } catch (IOException e) { 143 logger.warn("Unable to read db connection properties: " 144 + e.getMessage()); 145 146 // throw new DBException("ERROR: Getting db connection properties: " + e.getMessage()) ; 147 } 148 149 logger.info("METHOD_EXIT constructor"); 150 } 151 152 /* 153 * Methods 154 */ 155 156 /*** 157 * Factory method to obtain the connection factory itself. 158 * @return The <code>ConnectionFactory</code> singleton. 159 */ 160 public static synchronized ConnectionFactory getInstance() { 161 logger.info("METHOD_ENTRY getInstance"); 162 163 if (me == null) { 164 me = new ConnectionFactory(); 165 } 166 167 logger.info("METHOD_EXIT getInstance"); 168 169 return me; 170 } 171 172 /*** 173 * Set a connection property dynamically. 174 * <p>This will override defaults changing the behaviour of the 175 * <code>ConnectionFactory</code> singleton.</p> 176 */ 177 public static void setProperty(String key, String value) { 178 logger.info("METHOD_ENTRY setProperty"); 179 180 // Ensure we are initialised 181 getInstance(); 182 props.setProperty(key, value); 183 } 184 185 /*** 186 * Interpretes the props to create a Provider for each distinct data source 187 * configuration. 188 * throws DBException If the properties are invalid in some way 189 */ 190 private void configureFromProps() { 191 logger.info("METHOD_ENTRY configureFromProps"); 192 193 try { 194 // Find all config names, use USER to distinguish 195 for (Enumeration enum = props.propertyNames(); 196 enum.hasMoreElements();) { 197 String name = (String) enum.nextElement(); 198 199 if (name.indexOf("USER") > -1) { 200 String s = null; 201 int i = name.indexOf(".USER"); 202 203 if (i > -1) { 204 s = name.substring(0, i); 205 206 ProviderExt prov = new ProviderExt(); 207 208 prov.setConnectionProperties(props.getProperty(s 209 + ".DRIVER"), props.getProperty(s + ".URL"), 210 props.getProperty(s + ".USER"), 211 props.getProperty(s + ".PASSWORD"), 212 props.getProperty(s + ".SCHEMA")); 213 System.out.println("Found db config named: " + s + ", " 214 + ProviderExt.toString(prov)); 215 connConfigs.put(s, prov); 216 } else { 217 s = "default"; 218 219 // Clearly there can be only one of these! 220 ProviderExt prov = new ProviderExt(); 221 222 prov.setConnectionProperties(props.getProperty("DRIVER"), 223 props.getProperty("URL"), 224 props.getProperty("USER"), 225 props.getProperty("PASSWORD"), 226 props.getProperty("SCHEMA")); 227 System.out.println("Found db config named: " + s + ", " 228 + ProviderExt.toString(prov)); 229 connConfigs.put(s, prov); 230 } 231 } 232 } 233 } catch (Exception e) { 234 logger.warn(e.getMessage(), e); 235 236 //throw new DBException(e.getMessage()); 237 } 238 239 logger.info("METHOD_EXIT configureFromProps"); 240 } 241 242 /*** 243 * Returns the names of configured database connections. 244 * 245 * <p>These are names that may be used successfully with 246 * <code> </code>. 247 * 248 * @return <code>java.util.Set</code> of connection names (of type 249 * <code>String</code>). 250 * @see #getProvider 251 */ 252 public Set getConnectionNames() { 253 logger.info("METHOD_ENTRY getConnectionNames"); 254 255 // TODO: Add JNDI-bound names 256 Set names = null; 257 258 if (connConfigs == null) { 259 names = new HashSet(); 260 } else { 261 names = connConfigs.keySet(); 262 } 263 264 logger.info("METHOD_EXIT getConnectionNames, returning =" + names); 265 266 return names; 267 } 268 269 /*** 270 * Obtain connection details for the named configuration. 271 * 272 * @param name configuration name. 273 * @return Provider holding the connection details 274 * @throws DBException If the named configuration is not found. 275 * @see #getConnectionNames 276 */ 277 public Provider getProvider(String name) 278 throws DBException { 279 logger.info("METHOD_ENTRY getProvider name=" + name); 280 281 Provider provider = null; 282 283 logger.debug("Configured connections: " + connConfigs); 284 285 if ((connConfigs == null) || connConfigs.isEmpty() 286 || !connConfigs.containsKey(name)) { 287 throw new DBException("No connection configuration exists " 288 + "with name: " + name); 289 } else { 290 provider = (Provider) connConfigs.get(name); 291 } 292 293 logger.info("METHOD_EXIT getProvider"); 294 295 return provider; 296 } 297 298 /*** 299 * Returns a connection to the database identified by the 300 * class's resource properties. 301 * <p>This is a very simplistic configuration option for applications 302 * that do not have any JNDI or user-maintained configuration options. 303 * It is not recommended.</p> 304 * 305 * @return Connection 306 * 307 * @throws DBException 308 * in the event of a problem creating the connection 309 */ 310 public static Connection getConnection() 311 throws DBException { 312 logger.info("METHOD_ENTRY getConnection"); 313 314 Connection conn = null; 315 316 try { 317 conn = getInstance().getConnection(props); 318 } catch (DBException dbe) { 319 // simply rethrow 320 throw dbe; 321 } catch (Exception e) { 322 logger.error("ERROR: " + e.getMessage()); 323 324 throw new DBException("ERROR: " + e.getMessage()); 325 } 326 327 if (conn == null) { 328 logger.error("ERROR: Unable to create connection"); 329 throw new DBException("ERROR: Unable to create connection: "); 330 } 331 332 logger.info("METHOD_EXIT"); 333 334 return conn; 335 } 336 337 /*** 338 * Returns a connection to the database identified by the 339 * supplied properties. 340 * <p> 341 * Parameters may be empty strings, but may not be null. 342 * 343 * @param driver 344 * @param database 345 * @param server 346 * @param port 347 * @param protocol 348 * @param user 349 * @param password 350 * 351 * @return Connection 352 * 353 * @throws DBException 354 * in the event of a problem creating the connection 355 */ 356 public static Connection getConnection(String driver, String database, 357 String server, String port, String protocol, String user, 358 String password) 359 throws DBException { 360 logger.info("METHOD_ENTRY getConnection, driver=" + driver 361 + ", database=" + database + ", server=" + server + ", port=" 362 + port + ", protocol=" + protocol + ", user=" + user 363 + ", password=" + password); 364 365 Connection conn = null; 366 367 try { 368 // Check class instance and get propsource properties 369 getInstance(); 370 371 props.put("DRIVER", driver); 372 props.put("DATABASE_NAME", database); 373 props.put("SERVER_NAME", server); 374 props.put("PORT", port); 375 props.put("PROTOCOL", protocol); 376 props.put("USER", user); 377 props.put("PASSWORD", password); 378 379 conn = getInstance().getConnection(props); 380 } catch (DBException dbe) { 381 // simply rethrow 382 throw dbe; 383 } catch (Exception e) { 384 logger.error("ERROR: " + e.getMessage()); 385 386 throw new DBException("ERROR: " + e.getMessage()); 387 } 388 389 if (conn == null) { 390 logger.error("ERROR: Unable to create connection"); 391 throw new DBException("ERROR: Unable to create connection: "); 392 } 393 394 logger.info("METHOD_EXIT getConnection"); 395 396 return conn; 397 } 398 399 /*** 400 * Returns a connection to the database identified by the 401 * supplied properties. 402 * <p> 403 * Parameters may be empty strings, but may not be null. 404 * 405 * @param driver 406 * @param url 407 * @param user 408 * @param password 409 * 410 * @return Connection 411 * 412 * @throws DBException 413 * in the event of a problem creating the connection 414 */ 415 public static Connection getConnection(String driver, String url, 416 String user, String password) 417 throws DBException { 418 logger.info("METHOD_ENTRY getConnection, driver=" + driver + ", url=" 419 + url + ", user=" + user + ", password=" + password); 420 421 Connection conn = null; 422 423 try { 424 // Check class instance and set source properties 425 getInstance(); 426 427 props.put("DRIVER", driver); 428 props.put("URL", url); 429 props.put("USER", user); 430 props.put("PASSWORD", password); 431 432 conn = getInstance().getConnection(props); 433 } catch (DBException dbe) { 434 // simply rethrow 435 throw dbe; 436 437 /*} catch (Exception e) { 438 logger.error(e.getClass().getName() + ":" + e.getMessage(), e) ; 439 440 throw new DBException("ERROR: " + e.getMessage()) ;*/ 441 } 442 443 if (conn == null) { 444 logger.error("ERROR: Unable to create connection"); 445 throw new DBException("ERROR: Unable to create connection: "); 446 } 447 448 logger.info("METHOD_EXIT getConnection"); 449 450 return conn; 451 } 452 453 /*** 454 * Returns a connection to the database identified by the 455 * <code>Properties</code> supplied 456 * 457 * @return Connection 458 * 459 * @throws DBException 460 * in the event of a problem creating the connection 461 */ 462 private Connection getConnection(Properties props) 463 throws DBException { 464 logger.info("METHOD_ENTRY getConnection, Properties="); 465 466 Connection conn = null; 467 468 try { 469 if (props.getProperty("URL") != null) { 470 conn = getUrlConnection(props); 471 } else { 472 String driver = props.getProperty("DRIVER"); 473 474 if (driver.equals("org.gjt.mm.mysql.Driver")) { 475 conn = getMySQLConnection(props); 476 } else if (driver.equals("com.sybase.jdbc2.jdbc.SybDriver")) { 477 conn = getSybConnection(props); 478 } else { 479 logger.error("ERROR: Unsupported driver: " + driver); 480 throw new DBException("ERROR: Unsupported driver: " 481 + driver); 482 } 483 } 484 } catch (SQLException sqle) { 485 logger.error("ERROR: Getting connection: " + sqle.getMessage()); 486 487 //TODO: URL Property may be null, should retire properties based connection 488 throw new DBException("Error getting connection to: " 489 + props.getProperty("URL"), sqle); 490 } catch (DBException e) { 491 // simply rethrow 492 throw e; 493 } catch (Exception e) { 494 logger.error("ERROR: " + e.getMessage()); 495 496 //e.printStackTrace() ; 497 throw new DBException("ERROR: " + e.getMessage()); 498 } 499 500 if (conn == null) { 501 logger.error("ERROR: Unable to create connection"); 502 throw new DBException("ERROR: Unable to create connection: "); 503 } 504 505 logger.info("METHOD_EXIT getConnection"); 506 507 return conn; 508 } 509 510 private Connection getMySQLConnection(Properties props) 511 throws java.sql.SQLException, DBException { 512 logger.info("METHOD_ENTRY getConnection, Properties=" + props); 513 514 Object driver = getDriver(props.getProperty("DRIVER")); 515 516 String connectionString = "jdbc:"; 517 518 connectionString += props.getProperty("PROTOCOL"); 519 connectionString += "://"; 520 connectionString += props.getProperty("SERVER_NAME"); 521 connectionString += "/"; 522 connectionString += props.getProperty("DATABASE_NAME"); 523 connectionString += "?"; 524 connectionString += "user="; 525 connectionString += props.getProperty("USER"); 526 connectionString += "&"; 527 connectionString += "password="; 528 connectionString += props.getProperty("PASSWORD"); 529 530 logger.info("Connection string: " + connectionString); 531 532 Connection conn = DriverManager.getConnection(connectionString); 533 534 logger.info("METHOD_EXIT getMySQLConnection"); 535 536 return conn; 537 } 538 539 private Connection getSybConnection(Properties props) 540 throws java.sql.SQLException, DBException { 541 logger.info("METHOD_ENTRY, props=" + props); 542 543 Object driver = getDriver(props.getProperty("DRIVER")); 544 545 String connectionString = null; 546 547 if (props.getProperty("URL") == null) { 548 connectionString = "jdbc:sybase:"; 549 connectionString += props.getProperty("PROTOCOL"); 550 connectionString += ":"; 551 connectionString += props.getProperty("SERVER_NAME"); 552 connectionString += ":"; 553 connectionString += props.getProperty("PORT"); 554 } else { 555 connectionString = props.getProperty("URL"); 556 } 557 558 Properties jcprops = new Properties(); 559 560 jcprops.put("user", props.getProperty("USER")); 561 jcprops.put("password", props.getProperty("PASSWORD")); 562 563 logger.info("Connection string: " + connectionString); 564 565 Connection conn = DriverManager.getConnection(connectionString, jcprops); 566 567 logger.info("METHOD_EXIT getSybConnection"); 568 569 return conn; 570 } 571 572 private Connection getUrlConnection(Properties props) 573 throws java.sql.SQLException, DBException { 574 logger.info("METHOD_ENTRY getUrlConnection, props=" + props); 575 576 registerDriver(props.getProperty("DRIVER")); 577 registerDriverFromUrl(props.getProperty("URL")); 578 579 String connectionString = props.getProperty("URL"); 580 581 Properties jcprops = new Properties(); 582 583 jcprops.put("user", props.getProperty("USER")); 584 jcprops.put("password", props.getProperty("PASSWORD")); 585 586 logger.info("Connection string: " + connectionString); 587 588 Connection conn = DriverManager.getConnection(connectionString, jcprops); 589 590 logger.info("METHOD_EXIT getUrlConnection"); 591 592 return conn; 593 } 594 595 /*** 596 * Obtain a JDBC driver class. 597 */ 598 protected Object getDriver(String className) 599 throws DBException { 600 logger.info("METHOD_ENTRY: getDriver, className=" + className); 601 602 Object driver = null; 603 604 try { 605 ClassLoader cl = ConnectionFactory.class.getClassLoader(); 606 607 driver = cl.loadClass(className).newInstance(); 608 } catch (IllegalAccessException iae) { 609 logger.error(iae.getMessage()); 610 throw new DBException("Problem getting db connection properties: " 611 + iae.getMessage()); 612 } catch (ClassNotFoundException cnfe) { 613 logger.error(cnfe.getMessage()); 614 615 logger.debug("Searched classpath:" 616 + System.getProperty("java.class.path")); 617 618 try { 619 logger.warn("Attempting to find driver thru system classloader"); 620 621 ClassLoader scl = ClassLoader.getSystemClassLoader(); 622 623 driver = scl.loadClass(className).newInstance(); 624 } catch (Exception e2) { 625 throw new DBException("Driver class not found: " 626 + e2.getMessage()); 627 } 628 } catch (InstantiationException ie) { 629 logger.error(ie.getMessage()); 630 throw new DBException("Problem getting db connection properties: " 631 + ie.getMessage()); 632 } 633 634 logger.info("METHOD_EXIT: getDriver"); 635 636 return driver; 637 } 638 }

This page was automatically generated by Maven