View Javadoc

1   /*
2    * $Header: /cvsroot/jdbforms/dbforms/src/org/dbforms/config/DbConnection.java,v 1.15 2006/01/25 20:05:32 hkollmann Exp $
3    * $Revision: 1.15 $
4    * $Date: 2006/01/25 20:05:32 $
5    *
6    * DbForms - a Rapid Application Development Framework
7    * Copyright (C) 2001 Joachim Peer <joepeer@excite.com>
8    *
9    * This library is free software; you can redistribute it and/or
10   * modify it under the terms of the GNU Lesser General Public
11   * License as published by the Free Software Foundation; either
12   * version 2.1 of the License, or (at your option) any later version.
13   *
14   * This library is distributed in the hope that it will be useful,
15   * but WITHOUT ANY WARRANTY; without even the implied warranty of
16   * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
17   * Lesser General Public License for more details.
18   *
19   * You should have received a copy of the GNU Lesser General Public
20   * License along with this library; if not, write to the Free Software
21   * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307 USA
22   */
23  
24  package org.dbforms.config;
25  
26  import org.apache.commons.logging.Log;
27  import org.apache.commons.logging.LogFactory;
28  
29  import org.dbforms.conprovider.ConnectionFactory;
30  import org.dbforms.conprovider.ConnectionProviderPrefs;
31  
32  import org.dbforms.util.Util;
33  
34  import java.io.PrintWriter;
35  
36  import java.sql.Connection;
37  import java.sql.DriverManager;
38  import java.sql.SQLException;
39  
40  import java.util.Properties;
41  
42  import javax.naming.Context;
43  import javax.naming.InitialContext;
44  import javax.naming.NamingException;
45  
46  import javax.sql.DataSource;
47  
48  
49  
50  /***
51   * This class represents datastructures like to following examples: <br>
52   * <pre>
53   *
54   *  &lt;dbconnection
55   *           name   = "jdbc/dbformstest"
56   *           isJndi = "true"
57   *  /&gt;
58   * </pre>
59   *
60   * <p>
61   * (in the example above dbforms asumes that the jndi-entry "jdbc/dbformstest"
62   * is correctly configured in the application-server's database configuration
63   * [i.e. date-sources.xml])
64   * </p>
65   *
66   * <p>
67   * or:
68   * </p>
69   * <pre>
70   *  &lt;dbconnection
71   *          name   = "jdbc:poolman://dbformstest"
72   *          isJndi = "false"
73   *          class  = "com.codestudio.sql.PoolMan"
74   *  /&gt;
75   * </pre>
76   *
77   * <p>
78   * (in the example above dbforms asumes that the connectionpool-entry
79   * "dbformstest" is correctly configured in the associated connection pool
80   * properties file).
81   * </p>
82   *
83   * <p>
84   * As these examples show, the configuration of datasources is beyond the scope
85   * of dbforms. That is a task of the underlying applicationserver/jsp-engine!
86   * </p>
87   *
88   * @author Joe Peer
89   * @version 0.8.3 Kevin Dangoor added Username and Passwort properties
90   */
91  public class DbConnection implements javax.sql.DataSource {
92     private static Log logCat = LogFactory.getLog(DbConnection.class);
93  
94     /*** connection factory instance */
95     private ConnectionFactory connectionFactory = ConnectionFactory.instance();
96  
97     /*** connection pool properties */
98     private Properties poolProperties;
99  
100    /*** JDBC properties */
101    private Properties properties;
102 
103    /*** JDBC drivermanager class */
104    private String conClass;
105 
106    /*** connection provider URL */
107    private String connectionPoolURL;
108 
109    /*** connection provider class */
110    private String connectionProviderClass;
111 
112    /***
113     * ContextDS flag. If set, an existing DataSource from Context-Scope would
114     * be used (e.g. from Struts)
115     */
116    private String contextDataSource;
117 
118    /*** connection id */
119    private String id;
120 
121    /*** JNDI flag */
122    private String isJndi = "false";
123 
124    /*** connection name */
125    private String name;
126 
127    /*** database password */
128    private String password;
129 
130    /*** database user name */
131    private String username;
132 
133    /*** default connection flag */
134    private boolean defaultConnection = false;
135 
136    /***
137     * connection factory configuration flag. If true, the connection factory is
138     * already configured
139     */
140    private boolean isFactorySetup = false;
141 
142    /*** */
143    private boolean isPropSetup = false;
144 
145    /*** JNDI flag. Sei it to true to get connection objects from a JNDI service */
146    private boolean jndi = false;
147 
148    /***
149     * connection factory flag. Set it to true to use connection factory to get
150     * JDBC connection objects
151     */
152    private boolean pow2 = false;
153 
154    /***
155     * Constructor.
156     */
157    public DbConnection() {
158       properties     = new java.util.Properties();
159       poolProperties = new java.util.Properties();
160    }
161 
162    /***
163     * Sets the conClass attribute of the DbConnection object
164     *
165     * @param conClass The new conClass value
166     */
167    public void setConClass(String conClass) {
168       this.conClass = conClass;
169    }
170 
171 
172    /***
173     * Gets the conClass attribute of the DbConnection object
174     *
175     * @return The conClass value
176     */
177    public String getConClass() {
178       return conClass;
179    }
180 
181 
182    /***
183     * Gets a JDBC connection object.
184     *
185     * @return the connection object, or null if any error occurs
186     */
187    public Connection getConnection() {
188       Connection con = null;
189 
190       // get connection via Application Server's JNDI table;
191       // name attribute is used as JNDI lookup string;
192       if (jndi) {
193          con = getConnectionFromJNDI(name);
194       }
195       // get connection using the connection factory library
196       // by Luca Fossato <fossato@pow2.com>
197       else if (pow2) {
198          con = getConnectionFromFactory();
199       }
200       // get connection from DriverManager
201       else {
202          con = getConnectionFromDriverManager();
203       }
204 
205       return con;
206    }
207 
208 
209    /***
210     * returns a Connection
211     *
212     * @param username DOCUMENT ME!
213     * @param password DOCUMENT ME!
214     *
215     * @return DOCUMENT ME!
216     */
217    public Connection getConnection(String p_username,
218                                    String p_password) throws SQLException {
219       setUsername(p_username);
220       setPassword(p_password);
221 
222       return getConnection();
223    }
224 
225 
226    /***
227     * Sets the connectionPoolURL attribute of the DbConnection object
228     *
229     * @param url The new connectionPoolURL value
230     */
231    public void setConnectionPoolURL(String url) {
232       connectionPoolURL = url;
233    }
234 
235 
236    /***
237     * Gets the connectionPoolURL attribute of the DbConnection object
238     *
239     * @return The connectionPoolURL value
240     */
241    public String getConnectionPoolURL() {
242       return connectionPoolURL;
243    }
244 
245 
246    /***
247     * Sets the connectionProviderClass attribute of the DbConnection object
248     *
249     * @param cpc The new connectionProviderClass value
250     */
251    public void setConnectionProviderClass(String cpc) {
252       connectionProviderClass = cpc;
253    }
254 
255 
256    /***
257     * Gets the connectionProviderClass attribute of the DbConnection object
258     *
259     * @return The connectionProviderClass value
260     */
261    public String getConnectionProviderClass() {
262       return connectionProviderClass;
263    }
264 
265 
266    /***
267     * sets the name of the parameter from context-Scope which  contains a
268     * DataSource-Object
269     *
270     * @param contextDataSource
271     */
272    public void setContextDataSource(String contextDataSource) {
273       this.contextDataSource = contextDataSource;
274    }
275 
276 
277    /***
278     * returns the name of the parameter from context-Scope which  contains a
279     * DataSource-Object
280     *
281     * @return contextDataSource - the name
282     */
283    public String getContextDataSource() {
284       return contextDataSource;
285    }
286 
287 
288    /***
289     * Sets the defaultConnection attribute of the DbConnection object
290     *
291     * @param defaultConnection The new defaultConnection value
292     */
293    public void setDefaultConnection(boolean defaultConnection) {
294       this.defaultConnection = defaultConnection;
295    }
296 
297 
298    /***
299     * Gets the defaultConnection attribute of the DbConnection object
300     *
301     * @return The defaultConnection value
302     */
303    public boolean isDefaultConnection() {
304       return defaultConnection;
305    }
306 
307 
308    /***
309     * DataSource interface
310     *
311     * @param driverClassName DOCUMENT ME!
312     */
313    public void setDriverClassName(String driverClassName) {
314       setConClass(driverClassName);
315    }
316 
317 
318    /***
319     * Sets the id attribute of the DbConnection object
320     *
321     * @param id The new id value
322     */
323    public void setId(String id) {
324       this.id = id;
325    }
326 
327 
328    /***
329     * Gets the id attribute of the DbConnection object
330     *
331     * @return The id value
332     */
333    public String getId() {
334       return id;
335    }
336 
337 
338    /***
339     * Sets the isJndi attribute of the DbConnection object
340     *
341     * @param isJndi The new isJndi value
342     */
343    public void setIsJndi(String isJndi) {
344       this.isJndi = isJndi;
345       jndi        = Util.getTrue(isJndi);
346    }
347 
348 
349    /***
350     * Sets the isPow2 attribute of the DbConnection object
351     *
352     * @param isPow2 The new isPow2 value
353     */
354    public void setIsPow2(String isPow2) {
355       pow2 = Util.getTrue(isPow2);
356    }
357 
358 
359    /***
360     * DOCUMENT ME!
361     *
362     * @param jdbcURL DOCUMENT ME!
363     */
364    public void setJdbcURL(String jdbcURL) {
365       setName(jdbcURL);
366    }
367 
368 
369    /***
370     * Always throws a SQLException. Not supported.
371     *
372     * @param out DOCUMENT ME!
373     */
374    public void setLogWriter(PrintWriter out) throws SQLException {
375       throw new SQLException("dbforms.error.not_supported");
376    }
377 
378 
379    /***
380     * Always throws a SQLException. Not supported.
381     *
382     * @return DOCUMENT ME!
383     */
384    public PrintWriter getLogWriter() throws SQLException {
385       throw new SQLException("dbforms.error.not_supported");
386    }
387 
388 
389    /***
390     * Always throws a SQLException. Not supported.
391     *
392     * @param seconds DOCUMENT ME!
393     */
394    public void setLoginTimeout(int seconds) throws SQLException {
395       throw new SQLException("dbforms.error.not_supported");
396    }
397 
398 
399    /***
400     * Always throws a SQLException. Not supported.
401     *
402     * @return DOCUMENT ME!
403     */
404    public int getLoginTimeout() throws SQLException {
405       throw new SQLException("dbforms.error.not_supported");
406    }
407 
408 
409    /***
410     * Sets the name attribute of the DbConnection object
411     *
412     * @param name The new name value
413     */
414    public void setName(String name) {
415       this.name = name;
416    }
417 
418 
419    /***
420     * Gets the name attribute of the DbConnection object
421     *
422     * @return The name value
423     */
424    public String getName() {
425       return name;
426    }
427 
428 
429    /***
430     * Sets the password attribute of the DbConnection object
431     *
432     * @param newpass The new password value
433     */
434    public void setPassword(String newpass) {
435       this.password = newpass;
436    }
437 
438 
439    /***
440     * Gets the password attribute of the DbConnection object
441     *
442     * @return The password value
443     */
444    public String getPassword() {
445       return password;
446    }
447 
448 
449    /***
450     * Sets the username attribute of the DbConnection object
451     *
452     * @param newuser The new username value
453     */
454    public void setUsername(String newuser) {
455       this.username = newuser;
456    }
457 
458 
459    /***
460     * Gets the username attribute of the DbConnection object
461     *
462     * @return The username value
463     */
464    public String getUsername() {
465       return username;
466    }
467 
468 
469    /***
470     * Adds a new pool property - used while parsing XML file
471     *
472     * @param prop The feature to be added to the PoolProperty attribute
473     */
474    public void addPoolProperty(String name, String prop) {
475       poolProperties.put(prop, prop);
476    }
477 
478 
479    /***
480     * Adds a new property - used while parsing XML file
481     *
482     * @param prop The feature to be added to the Property attribute
483     */
484    public void addProperty(String name, String prop) {
485       properties.put(prop, prop);
486    }
487 
488 
489    /***
490     * Description of the Method
491     *
492     * @return Description of the Return Value
493     */
494    public String getisJndi() {
495       return isJndi;
496    }
497 
498 
499    /***
500     * Gets the string representation of this object.
501     *
502     * @return the string representation of this object
503     */
504    public String toString() {
505       StringBuffer buf = new StringBuffer("DbConnection = ");
506 
507       buf.append("id=" + id)
508          .append(", name=" + name)
509          .append(", jndi=" + isJndi)
510          .append(", conClass=" + conClass)
511          .append(", username=" + username)
512          .append(", default=" + defaultConnection);
513 
514       if (pow2) {
515          buf.append(", connectionProviderClass=" + connectionProviderClass)
516             .append(", connectionPoolURL=" + connectionPoolURL);
517       }
518 
519       if (!properties.isEmpty()) {
520          buf.append(", jdbc properties: ")
521             .append(properties);
522       }
523 
524       if (!poolProperties.isEmpty()) {
525          buf.append(", connection pool properties: ")
526             .append(poolProperties);
527       }
528 
529       //buf.append(",password="+password);  Not such a good idea!
530       return buf.toString();
531    }
532 
533 
534    /***
535     * Gets a JDBC connection object from the DriverManager class specified by
536     * the conClass member attribute.
537     *
538     * @return the JDBC connection object, or null if any error occurs
539     */
540    private Connection getConnectionFromDriverManager() {
541       Connection con = null;
542 
543       try {
544          Class.forName(conClass)
545               .newInstance();
546 
547          if (!properties.isEmpty()) {
548             if (!isPropSetup) {
549                properties.put("user", getUsername());
550                properties.put("password", getPassword());
551                isPropSetup = true;
552             }
553 
554             con = DriverManager.getConnection(name, properties);
555          } else if (username != null) {
556             con = DriverManager.getConnection(name, username, password);
557          } else {
558             con = DriverManager.getConnection(name);
559          }
560       } catch (Exception e) {
561          logCat.error("::getConnectionFromDriverManager - cannot retrieve a connection from DriverManager",
562                       e);
563       }
564 
565       return con;
566    }
567 
568 
569    /***
570     * Gets a JDBC connection object from the connection factory.
571     *
572     * @return the JDBC connection object, or null if any error occurs
573     */
574    private Connection getConnectionFromFactory() {
575       Connection con = null;
576 
577       try {
578          if (!isFactorySetup) {
579             setupConnectionFactory();
580          }
581 
582          con = connectionFactory.getConnection();
583       } catch (Exception se) {
584          logCat.error("::getConnectionFromFactory - cannot retrieve a connection from the connectionFactory",
585                       se);
586       }
587 
588       return con;
589    }
590 
591 
592    /***
593     * PRIVATE METHODs here
594     *
595     * @param lookupString DOCUMENT ME!
596     *
597     * @return DOCUMENT ME!
598     */
599    /***
600     * Gets a JDBC connection object from a JNDI server.
601     *
602     * @param lookupString the string used to lookup the datasource object from
603     *        the JNDI server
604     *
605     * @return the JDBC connection object, or null if the lookup fails
606     */
607    private Connection getConnectionFromJNDI(String lookupString) {
608       Connection con = null;
609 
610       // a useful source of examples for Tomcat 4.1:
611       // http://jakarta.apache.org/tomcat/tomcat-4.1-doc/jndi-datasource-examples-howto.html
612       try {
613          Context    ctx = new InitialContext();
614          DataSource ds = (DataSource) ctx.lookup(lookupString);
615 
616          if (ds != null) {
617             con = ds.getConnection();
618          } else {
619             logCat.error("::getConnectionFromJNDI - DataSource object is null");
620          }
621       } catch (NamingException ne) {
622          logCat.error("::getConnectionFromJNDI - cannot retrieve a connection from JNDI:",
623                       ne);
624       } catch (Exception e) {
625          logCat.error("::getConnectionFromJNDI - exception:", e);
626       }
627 
628       return con;
629    }
630 
631 
632    /***
633     * Set up the ConnectionFactory
634     *
635     * @exception Exception if any error occurs
636     */
637    private void setupConnectionFactory() throws Exception {
638       ConnectionProviderPrefs prefs = new ConnectionProviderPrefs();
639 
640       prefs.setConnectionProviderClass(connectionProviderClass);
641       prefs.setConnectionPoolURL(connectionPoolURL);
642       prefs.setJdbcDriver(conClass);
643       prefs.setJdbcURL(name);
644       prefs.setUser(username);
645       prefs.setPassword(password);
646       prefs.setProperties(properties);
647       prefs.setPoolProperties(poolProperties);
648       prefs.setServletContext(DbFormsConfigRegistry.instance().lookup().getServletContext());
649       connectionFactory.setProvider(prefs);
650       isFactorySetup = true;
651    }
652 }