KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > opensubsystems > core > persist > db > DatabaseConnectionFactoryImpl


1 /*
2  * Copyright (c) 2003 - 2007 OpenSubsystems s.r.o. Slovak Republic. All rights reserved.
3  *
4  * Project: OpenSubsystems
5  *
6  * $Id: DatabaseConnectionFactoryImpl.java,v 1.21 2007/01/07 06:14:18 bastafidli Exp $
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; version 2 of the License.
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
22 package org.opensubsystems.core.persist.db;
23
24 import java.sql.Connection JavaDoc;
25 import java.sql.SQLException JavaDoc;
26 import java.util.Properties JavaDoc;
27 import java.util.logging.Logger JavaDoc;
28
29 import javax.transaction.SystemException JavaDoc;
30
31 import org.opensubsystems.core.error.OSSConfigException;
32 import org.opensubsystems.core.error.OSSDatabaseAccessException;
33 import org.opensubsystems.core.error.OSSException;
34 import org.opensubsystems.core.persist.db.connectionpool.DBCPDatabaseConnectionFactoryImpl;
35 import org.opensubsystems.core.persist.db.connectionpool.J2EEDatabaseConnectionFactoryImpl;
36 import org.opensubsystems.core.util.ClassFactory;
37 import org.opensubsystems.core.util.Config;
38 import org.opensubsystems.core.util.GlobalConstants;
39 import org.opensubsystems.core.util.J2EEUtils;
40 import org.opensubsystems.core.util.Log;
41
42 /**
43  * Base class for implementation of factories for retrieving and returning of
44  * database connections.
45  *
46  * Most likely one project will use only one implementation of connection factory
47  * therefore this class contains factory methods to instantiate and return
48  * default instance of connection factory even though it still allows multiple
49  * instances of connection factory to exist since all attributes are non-static.
50  *
51  * @version $Id: DatabaseConnectionFactoryImpl.java,v 1.21 2007/01/07 06:14:18 bastafidli Exp $
52  * @author Miro Halas
53  * @code.reviewer Miro Halas
54  * @code.reviewed 1.14 2006/04/05 04:58:41 bastafidli
55  */

56 public abstract class DatabaseConnectionFactoryImpl implements DatabaseConnectionFactory
57 {
58    // Configuration settings ///////////////////////////////////////////////////
59

60    /**
61     * Name of the property containing driver to use to connect to the database,
62     * e.g. "oracle.jdbc.driver.OracleDriver"
63     */

64    public static final String JavaDoc DATABASE_DRIVER = "oss.datasource.driver";
65
66    /**
67     * Name of the property containing URL to connect to the database,
68     * e.g. "jdbc:oracle:thin:@server:1521:database"
69     */

70    public static final String JavaDoc DATABASE_URL = "oss.datasource.url";
71
72    /**
73     * Name of the property containing user name to connect to the database,
74     * e.g. "bastafidli"
75     */

76    public static final String JavaDoc DATABASE_USER = "oss.datasource.user";
77
78    /**
79     * Name of the property containing user password to connect to the database,
80     * e.g. "password"
81     */

82    public static final String JavaDoc DATABASE_PASSWORD = "oss.datasource.password";
83
84    /**
85     * Name of the property containing user name to connect to the database,
86     * as an administrator e.g. "bastafidli"
87     */

88    public static final String JavaDoc DATABASE_ADMIN_USER = "oss.datasource.adminuser";
89
90    /**
91     * Name of the property containing user password to connect to the database,
92     * as administrator e.g. "password"
93     */

94    public static final String JavaDoc DATABASE_ADMIN_PASSWORD = "oss.datasource.adminpassword";
95
96    /**
97     * Name of the property specifying if to use an separate datasource to obtain
98     * administration connection instead of just using the default data source
99     * with separate credentials. This have to be set to true when using J2EE
100     * capabilities in WebLogic 9.x
101     */

102    public static final String JavaDoc DATABASE_USE_ADMIN_DATAROURCE
103                                  = "oss.datasource.admindatasource";
104    
105    // Constants ////////////////////////////////////////////////////////////////
106

107    /**
108     * Default value for flag specifying if to use separate datasource for admin
109     * connections.
110     */

111    public static final boolean DATABASE_USE_ADMIN_DATAROURCE_DEFAULT = false;
112    
113    /**
114     * Lock used in synchronized sections.
115     */

116    private static final String JavaDoc DBCF_IMPL_LOCK = "DBCF_IMPL_LOCK";
117
118    /**
119     * This string is used to identify JDBC spy driver. If this driver is
120     * setup to be used, then we need to lookup real driver as well.
121     */

122    public static final String JavaDoc SPY_DRIVER_IDENTIFICATION = "p6spy";
123    
124    /**
125     * Name of the configuration file for the spy driver.
126     */

127    public static final String JavaDoc SPY_CONFIG_FILE_NAME = "spy.properties";
128    
129    /**
130     * Name of the property which contains identification of real driver user
131     * by the spy driver.
132     */

133    public static final String JavaDoc SPY_REALDRIVER = "realdriver";
134    
135    /**
136     * Name that will be used for datasource which should have administration
137     * priviledges to setup the database. Make this name somehow meaningful
138     * because for example for J2EE CF this name has to be configured in external
139     * configuration file.
140     */

141    public static final String JavaDoc ADMIN_DATASOURCE_NAME = "OSSADMDS";
142
143    // Cached values ////////////////////////////////////////////////////////////
144

145    /**
146     * Logger for this class
147     */

148    private static Logger JavaDoc s_logger = Log.getInstance(DatabaseConnectionFactoryImpl.class);
149   
150    /**
151     * Reference to the default instance
152     */

153    private static DatabaseConnectionFactory s_defaultInstance = null;
154
155    /**
156     * This is concrete implementation of database transaction factory, which
157     * will be used to manage transactions across connections allocated
158     * by this database connection factory. This is a concrete class and not
159     * and interface because these two classes are tightly coupled together
160     * to make connections transaction aware.
161     */

162    protected DatabaseTransactionFactoryImpl m_transactionFactory = null;
163    
164    // Attributes ///////////////////////////////////////////////////////////////
165

166    /**
167     * How many connections were requested and not returned.
168     * This is here for debugging purposes to check if somebody is not returning
169     * connection.
170     */

171    protected int m_iRequestedConnectionCount;
172    
173    /**
174     * Driver to use to connect to the database, e.g. "com.sap.dbtech.jdbc.DriverSapDB".
175     * This can also be spy driver which just wraps around real driver. This spy
176     * driver should be used to access to database but if you really need to
177     * know what is the real driver, look at the read database driver attribute.
178     * @see #m_strRealDatabaseDriver
179     */

180    protected String JavaDoc m_strDatabaseDriver = null;
181
182    /**
183     * Real driver which is used to connect to database. This can be wrapper
184     * for example in a spy driver.
185     */

186    protected String JavaDoc m_strRealDatabaseDriver = null;
187
188    /**
189     * URL to connect to the database, e.g. "jdbc:oracle:thin:@server:1521:database"
190     * @see #DATABASE_URL
191     */

192    protected String JavaDoc m_strDatabaseURL = null;
193    
194    /**
195     * User name to connect to the database, e.g. "bastafidli".
196     * @see #DATABASE_USER
197     */

198    protected String JavaDoc m_strDatabaseUser = null;
199    
200    /**
201     * Password to connect to the database, e.g. "password".
202     * @see #DATABASE_PASSWORD
203     */

204    protected String JavaDoc m_strDatabasePassword = null;
205
206    /**
207     * User name with administration priviledges to connect
208     * to the database, e.g. "bastafidli".
209     *
210     * @see #DATABASE_USER
211     */

212    protected String JavaDoc m_strDatabaseAdminUser = null;
213    
214    /**
215     * Password for user with with administration priviledges to connect
216     * to the database, e.g. "password".
217     *
218     * @see #DATABASE_PASSWORD
219     */

220    protected String JavaDoc m_strDatabaseAdminPassword = null;
221
222    /**
223     * If true then use an separate datasource to obtain administration connection
224     * instead of just using the default data source with separate credentials.
225     * This have to be set to true when using J2EE capabilities in WebLogic 9.x
226     *
227     * @see #DATABASE_USE_ADMIN_DATAROURCE
228     */

229    protected boolean m_bUseAdminDataSource = false;
230    
231    // Constructors /////////////////////////////////////////////////////////////
232

233    /**
234     * Default constructor.
235     */

236    public DatabaseConnectionFactoryImpl(
237    )
238    {
239       this(null);
240    }
241
242    /**
243     * Default constructor.
244     *
245     * @param transactionFactory - transaction factory to use for this
246     * connection factory, can be null
247     */

248    public DatabaseConnectionFactoryImpl(
249       DatabaseTransactionFactoryImpl transactionFactory
250    )
251    {
252       super();
253       
254       // Do not invoke loadDefaultDatabaseProperties here in case the derived
255
// class wants to use some different database properties. If it doesn't
256
// it can call the method on it's own
257
m_iRequestedConnectionCount = 0;
258       m_transactionFactory = transactionFactory;
259    }
260
261    /**
262     * Constructor with explicitely specified JDBC driver.
263     *
264     * @param strDriver - JDBC driver to connect to the database
265     * @param strURL - URL of database to connect to
266     * @param strUser - user name to connect to the database
267     * @param strPassword - password to the database
268     * @param transactionFactory - transaction factory to use for this
269     * connection factory, can be null
270     * @throws OSSConfigException - problem accessing or locating the config file.
271     * @throws OSSDatabaseAccessException - an error has occured accessing
272     * the database
273     */

274    public DatabaseConnectionFactoryImpl(
275       String JavaDoc strDriver,
276       String JavaDoc strURL,
277       String JavaDoc strUser,
278       String JavaDoc strPassword,
279       DatabaseTransactionFactoryImpl transactionFactory
280    ) throws OSSConfigException,
281             OSSDatabaseAccessException
282    {
283       super();
284       
285       // Try load database driver and establish connection to the database
286
initializeDriver(strDriver);
287       
288       // Everything worked, now set the default values
289
setDatabaseDriver(strDriver);
290       setDatabaseURL(strURL);
291       setDatabaseUser(strUser);
292       setDatabasePassword(strPassword);
293
294       m_iRequestedConnectionCount = 0;
295       m_transactionFactory = transactionFactory;
296    }
297
298    // Factory methods //////////////////////////////////////////////////////////
299

300    /**
301     * Get the default database connection factory. This method is here to make
302     * the database connection factory configurable. Once can specify in
303     * configuration file derived class to used instead of this one
304     * [DatabaseConnectionFactory.class]=new class to use
305     *
306     * @return DatabaseConnectionFactory
307     * @throws OSSException - problem connecting to database
308     */

309    public static DatabaseConnectionFactory getInstance(
310    ) throws OSSException
311    {
312       if (s_defaultInstance == null)
313       {
314          // Only if the defautl connection factory wasn't set by other means,
315
// create a new one
316
// Synchronize just for the creation
317
synchronized (DBCF_IMPL_LOCK)
318          {
319             if (s_defaultInstance == null)
320             {
321                DatabaseConnectionFactory connectionFactory;
322                DatabaseTransactionFactory transactionFactory;
323
324                transactionFactory = DatabaseTransactionFactoryImpl.getInstance();
325                
326                // Use DBCPDatabaseConnectionFactoryImpl as default pool since
327
// it seems simple and reliable passing all our tests.
328
Class JavaDoc defaultConnectionFactoryImpl = DBCPDatabaseConnectionFactoryImpl.class;
329
330                // Find out if we are running under a j2ee server. If yes, redefine
331
// default variable defaultConnectionFactoryImpl to use
332
// j2ee database connection factory implementation.
333
if (J2EEUtils.getJ2EEServerType() != J2EEUtils.J2EE_SERVER_NO)
334                {
335                   defaultConnectionFactoryImpl = J2EEDatabaseConnectionFactoryImpl.class;
336                }
337                
338                connectionFactory = (DatabaseConnectionFactory)ClassFactory.getInstance(
339                            ).createInstance(DatabaseConnectionFactory.class,
340                                             defaultConnectionFactoryImpl);
341                if ((connectionFactory instanceof DatabaseConnectionFactoryImpl)
342                   && (transactionFactory instanceof DatabaseTransactionFactoryImpl))
343                {
344                   // Connect these two together so that the database connections
345
// can be properly managed by transaction factory
346
((DatabaseConnectionFactoryImpl)connectionFactory).setTransactionFactory(
347                      (DatabaseTransactionFactoryImpl)transactionFactory);
348                }
349                
350                setInstance(connectionFactory);
351             }
352          }
353       }
354       
355       return s_defaultInstance;
356    }
357    
358    /**
359     * Set default database connection factory instance. This instance will be
360     * returned by getInstance method until it is changed.
361     *
362     * @param dcfDefaultConnectionFactory - new default database
363     * connection factory instance
364     * @see #getInstance
365     */

366    public static void setInstance(
367       DatabaseConnectionFactory dcfDefaultConnectionFactory
368    )
369    {
370       if (GlobalConstants.ERROR_CHECKING)
371       {
372          assert dcfDefaultConnectionFactory != null
373                 : "Default database connection factory instance cannot be null";
374       }
375       
376       synchronized (DBCF_IMPL_LOCK)
377       {
378          s_defaultInstance = dcfDefaultConnectionFactory;
379          s_logger.fine("Default database connection factory is "
380                        + s_defaultInstance.getClass().getName());
381       }
382    }
383
384    // Connection factory methods ///////////////////////////////////////////////
385
// These methods ensure that the database connection factory is integrated
386
// with database transaction factory so that the transaction factory can
387
// properly manage connections created by this connection factory
388

389
390   /**
391    * {@inheritDoc}
392    */

393    public final Connection JavaDoc requestConnection(
394       boolean bAutoCommit
395    ) throws OSSDatabaseAccessException
396    {
397       Connection JavaDoc con;
398       
399       if (m_transactionFactory == null)
400       {
401          // This is not prefered situation, the connection which will be returned
402
// will not be managed by transaction factory
403
s_logger.finest("Requesting connection without transaction factory.");
404          con = requestNonTransactionalConnection(bAutoCommit);
405       }
406       else
407       {
408          // Let the transactional factory return transactional connection
409
// by allowing it to call back us to get non transactional connection
410
con = m_transactionFactory.requestTransactionalConnection(bAutoCommit,
411                                        null, null, null, this);
412       }
413       
414       return con;
415    }
416    
417    /**
418     * {@inheritDoc}
419     */

420    public final Connection JavaDoc requestConnection(
421       boolean bAutoCommit,
422       String JavaDoc strUser,
423       String JavaDoc strPassword
424    ) throws OSSDatabaseAccessException
425    {
426       Connection JavaDoc con;
427       
428       if (m_transactionFactory == null)
429       {
430          // This is not prefered situation, the connection which will be returned
431
// will not be managed by transaction factory
432
s_logger.finest("Requesting connection without transaction factory.");
433          con = requestNonTransactionalConnection(bAutoCommit, strUser, strPassword);
434       }
435       else
436       {
437          // Let the transactional factory return transactional connection
438
// by allowing it to call back us to get non transactional connection
439
con = m_transactionFactory.requestTransactionalConnection(bAutoCommit,
440                                        null, strUser, strPassword, this);
441       }
442       
443       return con;
444    }
445       
446    /**
447     * {@inheritDoc}
448     */

449    public final Connection JavaDoc requestConnection(
450       boolean bAutoCommit,
451       String JavaDoc strDataSourceName
452    ) throws OSSDatabaseAccessException
453    {
454       Connection JavaDoc con;
455       
456       if (m_transactionFactory == null)
457       {
458          // This is not prefered situation, the connection which will be returned
459
// will not be managed by transaction factory
460
s_logger.finest("Requesting connection without transaction factory.");
461          con = requestNonTransactionalConnection(bAutoCommit, strDataSourceName);
462       }
463       else
464       {
465          // Let the transactional factory return transactional connection
466
// by allowing it to call back us to get non transactional connection
467
con = m_transactionFactory.requestTransactionalConnection(bAutoCommit,
468                                        strDataSourceName, null, null, this);
469       }
470       
471       return con;
472    }
473    
474    /**
475     * {@inheritDoc}
476     */

477    public final Connection JavaDoc requestConnection(
478       boolean bAutoCommit,
479       String JavaDoc strDataSourceName,
480       String JavaDoc strUser,
481       String JavaDoc strPassword
482    ) throws OSSDatabaseAccessException
483    {
484       Connection JavaDoc con;
485       
486       if (m_transactionFactory == null)
487       {
488          // This is not prefered situation, the connection which will be returned
489
// will not be managed by transaction factory
490
s_logger.finest("Requesting connection without transaction factory.");
491          con = requestNonTransactionalConnection(bAutoCommit, strDataSourceName,
492                                                  strUser, strPassword);
493       }
494       else
495       {
496          // Let the transactional factory return transactional connection
497
// by allowing it to call back us to get non transactional connection
498
con = m_transactionFactory.requestTransactionalConnection(bAutoCommit,
499                                        strDataSourceName, strUser, strPassword,
500                                        this);
501       }
502       
503       return con;
504    }
505
506    /**
507     * {@inheritDoc}
508     */

509    public final void returnConnection(
510       Connection JavaDoc cntDBConnection
511    )
512    {
513       if (m_transactionFactory == null)
514       {
515          // This is not prefered situation, the connection which will be returned
516
// will not be managed by transaction factory
517
s_logger.finest("Returning connection without transaction factory.");
518          returnNonTransactionalConnection(cntDBConnection);
519       }
520       else
521       {
522          // Let the transactional factory decide if the connection should be
523
// returned by allowing it to call us back to return any non transactional
524
// connection
525
m_transactionFactory.returnTransactionalConnection(cntDBConnection, this);
526       }
527    }
528
529    // Configuration methods ////////////////////////////////////////////////////
530

531    /**
532     * Set the transaction factory for this connection factory. This can be done
533     * only if the transaction factory is not set yet (e.g. using constructor).
534     *
535     * @param transactionFactory - the transaction factory to set.
536     */

537    public void setTransactionFactory(
538       DatabaseTransactionFactoryImpl transactionFactory
539    )
540    {
541       if (GlobalConstants.ERROR_CHECKING)
542       {
543          assert m_transactionFactory == null
544                 : "Transaction factory can be set only if it is not set.";
545       }
546       
547       m_transactionFactory = transactionFactory;
548    }
549    
550    /**
551     * {@inheritDoc}
552     */

553    public String JavaDoc getDatabaseDriver(
554    )
555    {
556       return m_strDatabaseDriver;
557    }
558
559    /**
560     * {@inheritDoc}
561     */

562    public void setDatabaseDriver(
563       String JavaDoc strDatabaseDriver
564    )
565    {
566       if (GlobalConstants.ERROR_CHECKING)
567       {
568          // Since we don't know who everybody is using this, for now it can be set
569
// only once
570
assert m_strDatabaseDriver == null
571                 : "Database driver cannot be changed once set";
572       }
573       
574       m_strDatabaseDriver = strDatabaseDriver;
575    }
576
577    /**
578     * {@inheritDoc}
579     */

580    public String JavaDoc getDatabasePassword(
581    )
582    {
583       return m_strDatabasePassword;
584    }
585
586    /**
587     * {@inheritDoc}
588     */

589    public void setDatabasePassword(
590       String JavaDoc strDatabasePassword
591    )
592    {
593       if (GlobalConstants.ERROR_CHECKING)
594       {
595          // Since we don't know who everybody is using this, for now it can be set
596
// only once
597
assert m_strDatabasePassword == null
598                 : "Database password cannot be changed once set";
599       }
600       
601       m_strDatabasePassword = strDatabasePassword;
602    }
603
604    /**
605     * {@inheritDoc}
606     */

607    public String JavaDoc getDatabaseURL(
608    )
609    {
610       return m_strDatabaseURL;
611    }
612
613    /**
614     * {@inheritDoc}
615     */

616    public void setDatabaseURL(
617       String JavaDoc strDatabaseURL
618    )
619    {
620       if (GlobalConstants.ERROR_CHECKING)
621       {
622          // Since we don't know who everybody is using this, for now it can be set
623
// only once
624
assert m_strDatabaseURL == null
625                 : "Database URL cannot be changed once set";
626       }
627       
628       m_strDatabaseURL = strDatabaseURL;
629    }
630
631    /**
632     * {@inheritDoc}
633     */

634    public String JavaDoc getDatabaseUser(
635    )
636    {
637       return m_strDatabaseUser;
638    }
639
640    /**
641     * {@inheritDoc}
642     */

643    public void setDatabaseUser(
644       String JavaDoc strDatabaseUser
645    )
646    {
647       if (GlobalConstants.ERROR_CHECKING)
648       {
649          // Since we don't know who everybody is using this, for now it can be set
650
// only once
651
assert m_strDatabaseUser == null
652                 : "Database user cannot be changed once set";
653       }
654       
655       m_strDatabaseUser = strDatabaseUser;
656    }
657    
658    /**
659     * {@inheritDoc}
660     */

661    public String JavaDoc getDatabaseAdminUser(
662    )
663    {
664       return m_strDatabaseAdminUser;
665    }
666
667    /**
668     * {@inheritDoc}
669     */

670    public void setDatabaseAdminUser(
671       String JavaDoc strDatabaseUser
672    )
673    {
674       if (GlobalConstants.ERROR_CHECKING)
675       {
676          // Since we don't know who everybody is using this, for now it can be set
677
// only once
678
assert m_strDatabaseAdminUser == null
679                 : "Database admin user cannot be changed once set";
680       }
681       
682       m_strDatabaseAdminUser = strDatabaseUser;
683    }
684
685    /**
686     * {@inheritDoc}
687     */

688    public String JavaDoc getDatabaseAdminPassword(
689    )
690    {
691       return m_strDatabaseAdminPassword;
692    }
693
694    /**
695     * {@inheritDoc}
696     */

697    public void setDatabaseAdminPassword(
698       String JavaDoc strDatabasePassword
699    )
700    {
701       if (GlobalConstants.ERROR_CHECKING)
702       {
703          // Since we don't know who everybody is using this, for now it can be set
704
// only once
705
assert m_strDatabaseAdminPassword == null
706                 : "Database admin password cannot be changed once set";
707       }
708              
709       m_strDatabaseAdminPassword = strDatabasePassword;
710    }
711
712    /**
713     * {@inheritDoc}
714     */

715    public boolean getUseAdminDataSource(
716    )
717    {
718       return m_bUseAdminDataSource;
719    }
720    
721    /**
722     * {@inheritDoc}
723     */

724    public void setUseAdminDataSource(
725       boolean bUseAdminDataSource
726    )
727    {
728       m_bUseAdminDataSource = bUseAdminDataSource;
729    }
730    
731    /**
732     * {@inheritDoc}
733     */

734    public void loadDefaultDatabaseProperties(
735    ) throws OSSConfigException,
736             OSSDatabaseAccessException
737    {
738       Properties JavaDoc prpSettings;
739       String JavaDoc strDatabaseDriver;
740       String JavaDoc strDatabaseURL;
741       String JavaDoc strDatabaseUser;
742       String JavaDoc strDatabasePassword;
743       String JavaDoc strDatabaseAdminUser;
744       String JavaDoc strDatabaseAdminPassword;
745       boolean bUseAdminDataSource;
746
747       prpSettings = Config.getInstance().getPropertiesSafely();
748
749       strDatabaseDriver = Config.getStringProperty(prpSettings,
750                                                    DATABASE_DRIVER,
751                                                    "JDBC driver class name");
752       strDatabaseURL = Config.getStringProperty(prpSettings,
753                                                 DATABASE_URL,
754                                                 "Database URL");
755       strDatabaseUser = Config.getStringProperty(prpSettings,
756                                                  DATABASE_USER,
757                                                  "User name of database user");
758       // Password can have 0 length
759
strDatabasePassword = Config.getStringProperty(prpSettings,
760                                                 DATABASE_PASSWORD,
761                                                 "Password of database user",
762                                                 true);
763       strDatabaseAdminUser = Config.getStringProperty(
764                                        prpSettings,
765                                        DATABASE_ADMIN_USER,
766                                        "User name of administrator database user");
767       // Password can have 0 length
768
strDatabaseAdminPassword = Config.getStringProperty(prpSettings,
769                                            DATABASE_ADMIN_PASSWORD,
770                                            "Password of administrator database user",
771                                            true);
772       bUseAdminDataSource = Config.getBooleanProperty(
773                                       prpSettings,
774                                       DATABASE_USE_ADMIN_DATAROURCE,
775                                       DATABASE_USE_ADMIN_DATAROURCE_DEFAULT,
776                                       "Flag specifying if to use separate"
777                                       + " administrator data source");
778
779       // Try load database driver and establish connection to the database
780
initializeDriver(strDatabaseDriver);
781       
782       // Everything worked, now set the default values
783
setDatabaseDriver(strDatabaseDriver);
784       setDatabaseURL(strDatabaseURL);
785       setDatabaseUser(strDatabaseUser);
786       setDatabasePassword(strDatabasePassword);
787       setDatabaseAdminUser(strDatabaseAdminUser);
788       setDatabaseAdminPassword(strDatabaseAdminPassword);
789       setUseAdminDataSource(bUseAdminDataSource);
790    }
791    
792    /**
793     * Get number for connections which are currently requested and were not
794     * returned.
795     *
796     * @return int - how many connections were currently requested from pool
797     * and were not returned yet.
798     */

799    public int getTotalRequestedConnectionCount(
800    )
801    {
802       return m_iRequestedConnectionCount;
803    }
804   
805    /**
806     * Get real driver name which is used to connect to database. This can be
807     * wrapped for example in a spy driver.
808     *
809     * @return String - real JDBC driver name.
810     */

811    public String JavaDoc getRealDatabaseDriver(
812    )
813    {
814       return m_strRealDatabaseDriver;
815    }
816
817    // Helper methods ///////////////////////////////////////////////////////////
818

819    /**
820     * Initialize specified database driver.
821     *
822     * @param strDatabaseDriver - class name of JDBC driver
823     * @throws OSSConfigException - problem accessing or locating the config file.
824     * @throws OSSDatabaseAccessException - error initializing the driver
825     */

826    protected void initializeDriver(
827       String JavaDoc strDatabaseDriver
828    ) throws OSSConfigException,
829             OSSDatabaseAccessException
830    {
831       // Try load database driver and establish connection to the database
832
try
833       {
834          Class.forName(strDatabaseDriver).newInstance();
835       }
836       catch (ClassNotFoundException JavaDoc cnfExc)
837       {
838           // A call to Class.forName() forces us to consider this exception :-)...
839
throw new OSSDatabaseAccessException("Cannot load JDBC driver "
840                                              + strDatabaseDriver,
841                                              cnfExc);
842       }
843       catch (IllegalAccessException JavaDoc iaeExc)
844       {
845           // A call to Class.forName() forces us to consider this exception :-)...
846
throw new OSSDatabaseAccessException("Cannot access JDBC driver "
847                                              + strDatabaseDriver,
848                                              iaeExc);
849       }
850       catch (InstantiationException JavaDoc ieExc)
851       {
852           // A call to Class.forName() forces us to consider this exception :-)...
853
throw new OSSDatabaseAccessException("Cannot instantiate JDBC driver "
854                                              + strDatabaseDriver,
855                                              ieExc);
856       }
857       
858       // The driver is initialized correctly, now see if this is the real driver
859
if (strDatabaseDriver.indexOf(SPY_DRIVER_IDENTIFICATION) != -1)
860       {
861          // We are using SPY driver, so lookup the real driver
862
Config spyConfig = new Config(SPY_CONFIG_FILE_NAME);
863          
864          m_strRealDatabaseDriver = Config.getStringProperty(spyConfig,
865                                                             SPY_REALDRIVER,
866                                                             "Real JDBC driver class name");
867       }
868       else
869       {
870          m_strRealDatabaseDriver = strDatabaseDriver;
871       }
872    }
873    
874    /**
875     * Initialize connection to the default state so it can be used to work with
876     * the database. The most common setup is that we will set the autocommit
877     * by default to true when transaction is not in progress and to false if
878     * there is a pending transaction. This is mainly because if selects are
879     * executed without transaction and transaction isolation is set to for
880     * example serializable, it can come to a deadlock since the select may
881     * block table when different connection tries to modify it.
882     *
883     * @param bAutoCommit - The desired autocommit state of the connection. If
884     * this connection is invoked in global (JTA) transaction
885     * then the autocommit is false regardless of what
886     * value is specified here. Use true here if the client
887     * only reads the data and false if the client also
888     * modifies the data.
889     * Use DatabaseTransactionFactory.commitTransaction
890     * to commit the transaction.
891     * @param cntDBConnection - valid connection to the database
892     * @throws SQLException - problem initializing the connection
893     */

894    protected void initializeConnection(
895       Connection JavaDoc cntDBConnection,
896       boolean bAutoCommit
897    ) throws SQLException JavaDoc
898    {
899       try
900       {
901          if ((m_transactionFactory != null)
902             && (m_transactionFactory.isTransactionInProgress()))
903          {
904             // If we are in transaction disable autocommit.
905
if ((m_transactionFactory != null)
906                && (m_transactionFactory.isTransactionMonitored()))
907             {
908                s_logger.finest("Setting autocommit to false. Requested autocommit"
909                                + bAutoCommit + " and transaction is in progress.");
910             }
911             cntDBConnection.setAutoCommit(false);
912          }
913          else
914          {
915             // If we are not in transaction set the autocommit to the desired state
916
if ((m_transactionFactory != null)
917                 && (m_transactionFactory.isTransactionMonitored()))
918             {
919                s_logger.finest("Setting autocommit to requested autocommit "
920                                + bAutoCommit + " since no transaction is in progress.");
921             }
922             cntDBConnection.setAutoCommit(bAutoCommit);
923          }
924       }
925       catch (SystemException JavaDoc sExc)
926       {
927          throw new SQLException JavaDoc("Error while getting transaction status.");
928       }
929       catch (OSSException ossExc)
930       {
931          throw new SQLException JavaDoc("Error while getting transaction status.");
932       }
933
934    }
935
936    /**
937     * This method is a delegation method for now final
938     * org.opensubsystems.core.persist.db.DatabaseConnectionFactory#requestConnection()
939     * to get connection which is not tied to the transactional manager.
940     *
941     * This method is protected so that only classes from this package can access it.
942     *
943     * @param bAutoCommit - The desired autocommit state of the connection. If
944     * this connection is invoked in global (JTA) transaction
945     * then the autocommit is false regardless of what
946     * value is specified here. Use true here if the client
947     * only reads the data and false if the client also
948     * modifies the data.
949     * Use DatabaseTransactionFactory.commitTransaction
950     * to commit the transaction.
951     * @return Connection - connection to a database, never null
952     * @see #returnConnection
953     * @throws OSSDatabaseAccessException - if connection cannot be established
954     */

955    protected abstract Connection JavaDoc requestNonTransactionalConnection(
956       boolean bAutoCommit
957    ) throws OSSDatabaseAccessException;
958    
959    /**
960     * This method is a delegation method for now final
961     * org.opensubsystems.core.persist.db.DatabaseConnectionFactory
962     * #requestConnection(String, String)
963     * to get connection which is not tied to the transactional manager.
964     *
965     * This method is protected so that only classes from this package can access it.
966     *
967     * @param bAutoCommit - The desired autocommit state of the connection. If
968     * this connection is invoked in global (JTA) transaction
969     * then the autocommit is false regardless of what
970     * value is specified here. Use true here if the client
971     * only reads the data and false if the client also
972     * modifies the data.
973     * Use DatabaseTransactionFactory.commitTransaction
974     * to commit the transaction.
975     * @param strUser - user name to connect to the database
976     * @param strPassword - password to the database
977     * @return Connection - connection to a database, never null
978     * @see #returnConnection
979     * @throws OSSDatabaseAccessException - if connection cannot be established
980     */

981    protected abstract Connection JavaDoc requestNonTransactionalConnection(
982       boolean bAutoCommit,
983       String JavaDoc strUser,
984       String JavaDoc strPassword
985    ) throws OSSDatabaseAccessException;
986
987    /**
988     * This method is a delegation method for now final
989     * org.opensubsystems.core.persist.db.DatabaseConnectionFactory
990     * #requestConnection(String)
991     * to get connection which is not tied to the transactional manager.
992     *
993     * This method is protected so that only classes from this package can access it.
994     *
995     * @param bAutoCommit - The desired autocommit state of the connection. If
996     * this connection is invoked in global (JTA) transaction
997     * then the autocommit is false regardless of what
998     * value is specified here. Use true here if the client
999     * only reads the data and false if the client also
1000    * modifies the data.
1001    * Use DatabaseTransactionFactory.commitTransaction
1002    * to commit the transaction.
1003    * @param strDataSourceName - data source which will be used to get connections
1004    * @return Connection - connection to a database, never null
1005    * @see #returnConnection
1006    * @throws OSSDatabaseAccessException - if connection cannot be established
1007    */

1008   protected abstract Connection JavaDoc requestNonTransactionalConnection(
1009      boolean bAutoCommit,
1010      String JavaDoc strDataSourceName
1011   ) throws OSSDatabaseAccessException;
1012
1013   /**
1014    * This method is a delegation method for now final
1015    * org.opensubsystems.core.persist.db.DatabaseConnectionFactory
1016    * #requestConnection(String, String, String)
1017    * to get connection which is not tied to the transactional manager.
1018    *
1019    * This method is protected so that only classes from this package can access it.
1020    *
1021    * @param bAutoCommit - The desired autocommit state of the connection. If
1022    * this connection is invoked in global (JTA) transaction
1023    * then the autocommit is false regardless of what
1024    * value is specified here. Use true here if the client
1025    * only reads the data and false if the client also
1026    * modifies the data.
1027    * Use DatabaseTransactionFactory.commitTransaction
1028    * to commit the transaction.
1029    * @param strDataSourceName - data source which will be used to get connections
1030    * @param strUser - user name to connect to the database
1031    * @param strPassword - password to the database
1032    * @return Connection - connection to a database, never null
1033    * @see #returnConnection
1034    * @throws OSSDatabaseAccessException - if connection cannot be established
1035    */

1036   protected abstract Connection JavaDoc requestNonTransactionalConnection(
1037      boolean bAutoCommit,
1038      String JavaDoc strDataSourceName,
1039      String JavaDoc strUser,
1040      String JavaDoc strPassword
1041   ) throws OSSDatabaseAccessException;
1042
1043   /**
1044    * This method is a delegation method for now final
1045    * org.opensubsystems.core.persist.db.DatabaseConnectionFactory
1046    * #returnConnection(java.sql.Connection)
1047    * to return connection which is not tied to the transactional manager.
1048    *
1049    * This method is protected so that only classes from this package can access it.
1050    *
1051    * @param cntDBConnection - connection to return, can be null
1052    */

1053   public abstract void returnNonTransactionalConnection(
1054      Connection JavaDoc cntDBConnection
1055   );
1056}
1057
Popular Tags