Docjar: A Java Source and Docuemnt Enginecom.*    java.*    javax.*    org.*    all    new    plug-in

Quick Search    Search Deep

Source code: org/enableit/db/ConnectionFactory.java


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