KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > com > lutris > appserver > server > sql > StandardDatabaseManager


1  
2
3 /*
4  * Enhydra Java Application Server Project
5  *
6  * The contents of this file are subject to the Enhydra Public License
7  * Version 1.1 (the "License"); you may not use this file except in
8  * compliance with the License. You may obtain a copy of the License on
9  * the Enhydra web site ( http://www.enhydra.org/ ).
10  *
11  * Software distributed under the License is distributed on an "AS IS"
12  * basis, WITHOUT WARRANTY OF ANY KIND, either express or implied. See
13  * the License for the specific terms governing rights and limitations
14  * under the License.
15  *
16  * The Initial Developer of the Enhydra Application Server is Lutris
17  * Technologies, Inc. The Enhydra Application Server and portions created
18  * by Lutris Technologies, Inc. are Copyright Lutris Technologies, Inc.
19  * All Rights Reserved.
20  *
21  * Contributor(s):
22  *
23  * $Id: StandardDatabaseManager.java,v 1.9 2005/05/26 08:08:10 predrag Exp $
24  */

25 package com.lutris.appserver.server.sql;
26
27 import java.io.FileInputStream JavaDoc;
28 import java.io.InputStream JavaDoc;
29 import java.sql.SQLException JavaDoc;
30 import java.lang.reflect.Method JavaDoc;
31 import java.net.URL JavaDoc;
32 import java.util.Date JavaDoc;
33 import java.util.Enumeration JavaDoc;
34 import java.util.Hashtable JavaDoc;
35 import org.enhydra.dods.Common;
36 import org.enhydra.dods.CommonConstants;
37 import org.enhydra.dods.DODS;
38 import org.enhydra.dods.cache.CacheConstants;
39 import org.enhydra.dods.cache.Wrapper;
40 import com.lutris.appserver.server.sql.standard.StandardLogicalDatabase;
41 import com.lutris.appserver.server.sql.standard.DriverSpecificConstants;
42 import com.lutris.classloader.MultiClassLoader;
43 import com.lutris.util.Config;
44 import com.lutris.util.ConfigException;
45 import com.lutris.util.ConfigFile;
46 import org.enhydra.util.ConfigFileInterface;
47 import com.lutris.util.KeywordValueException;
48 import com.lutris.dods.builder.generator.query.QueryBuilder;
49 import com.lutris.logging.Logger;
50
51 import java.io.File JavaDoc;
52
53 import javax.xml.parsers.DocumentBuilder JavaDoc;
54 import javax.xml.parsers.DocumentBuilderFactory JavaDoc;
55
56 import org.w3c.dom.Document JavaDoc;
57 import org.w3c.dom.Element JavaDoc;
58 import org.w3c.dom.NodeList JavaDoc;
59
60
61 /**
62  * The standard database manager implementation. A database manager
63  * manages logical databases. It provides a single object from which
64  * database connections, object ids (OIDs), transactions and queries
65  * can be obtained. The configuration file specifies what logical
66  * database to create.
67  * <P>
68  * The configuration data is specified as follows:
69  * <UL>
70  * <LI> <B><CODE>DatabaseManager.Databases</CODE></B> -
71  * A list of logical SQL database names.
72  * <LI> <B><CODE>DatabaseManager.DefaultDatabase</CODE></B> -
73  * The default logical database used by this application. Optional,
74  * if not specified, then the first entry in
75  * "DatabaseManager.Databases" is used.
76  * <LI> <B><CODE>DatabaseManager.Debug</CODE></B> -
77  * Specify true to enable Query and Transaction logging, false to
78  * disable it. Optional, false if not specified.
79  * </UL>
80  * For each logical database, there is a set of entry names in the form
81  * <B><CODE>DatabaseManager.DB.<I>dbname</I></CODE></B>.
82  * Where <CODE><I>dbname</I></CODE> is one of the listed logical databases.
83  * <P>
84  * <B><CODE>DatabaseManager.DB.<I>dbname</I>.ClassType</CODE></B> -
85  * This is an optional field which specifies the class of the logical
86  * database implementation or a symbolic name if one on the standard types
87  * are selected. This is recommended because although JDBC abstracts the
88  * data access, the functionality of each database is slightly different
89  * and this parameter allows for optimised usage. The following are
90  * standard types:
91  * <UL>
92  * <LI> <I>Oracle</I> - For optimized Oracle 7/8 usage.
93  * <LI> <I>Informix</I> - For optimized Informix usage.
94  * <LI> <I>Sybase</I> - For optimized Sybase usage.
95  * <LI> <I>Msql</I> - For optimized Microsoft MSQL usage.
96  * <LI> <I>Standard</I> - For all other JDBC databases. <B>(Default)</B>
97  * <LI> <I>class</I> - For vendor supplied database classes.
98  * </UL>
99  * <P>
100  * Note that since a single SQL user is used to access the database by
101  * the entire application, connections maybe kept open, thus saving this
102  * overhead on each request. Connections are opened as desired until
103  * the maximum configured is reached.
104  * <P>
105  * If a thread needs to process a transaction, it requests a connection.
106  * If none are available, then a new connection is created up to the
107  * configured maximum. A thread is queued waiting for a connection to be
108  * returned if a new connection can't be created.
109  * <P>
110  * Note also that multiple logical names may map to the same actual
111  * database, making it easy to migrate databases if necessary and to
112  * provide access through multiple users.
113  *
114  * @version $Revision: 1.9 $
115  * @since LBS1.8
116  * @author Paul Morgan
117  * @author Kyle Clark
118  */

119 public class StandardDatabaseManager implements DatabaseManager, CacheConstants, DriverSpecificConstants {
120
121     /**
122      * Table of named logical databases.
123      */

124     private Hashtable JavaDoc logicalDatabases = new Hashtable JavaDoc();
125
126     /**
127      * Default logical database.
128      */

129     private LogicalDatabase defaultLogicalDatabase = null;
130
131     /**
132      * Controls debugging for Transactions and Queries.
133      */

134     protected boolean debug = false;
135     protected String JavaDoc defaultDB = null;
136     protected Config config = null;
137     
138     protected String JavaDoc confDir = null;
139     
140     private String JavaDoc appName = CacheConstants.DEFAULT_APP_NAME;
141     
142     private DatabaseManagerConfiguration dbmConf = new DatabaseManagerConfiguration();
143     
144     private Config mainConfig = null;
145     
146     
147
148     
149     /**
150      * Creates a new <code>DatabaseManager</code> object and configures
151      * the logical databases defined in the config file.
152      *
153      * @param config
154      * The configuration data for logical databases.
155      * @exception ConfigException
156      * If there is an error in the configuration file.
157      * @exception DatabaseManagerException
158      * If a logical database name is specified twice in the configuration file.
159      * @exception SQLException
160      * If a SQL error occurs.
161      */

162     public StandardDatabaseManager(Config config)
163         throws ConfigException, DatabaseManagerException, SQLException JavaDoc {
164             
165         this.config = config;
166         String JavaDoc[] databases = config.getStrings("Databases");
167
168         if (databases == null) {
169             return;
170         }
171             
172         try {
173             confDir = config.getString("ConfigurationDir", null);
174         } catch (KeywordValueException except) {
175             confDir = null;
176         }
177         try {
178             appName = config.getString(PARAMNAME_APP_NAME, DEFAULT_APP_NAME);
179         } catch (KeywordValueException except) {
180             appName = DEFAULT_APP_NAME;
181         }
182         Common.setConfigDir(confDir);
183  
184         try {
185             Config userConfig = (Config) config.getSection("DB.User");
186             if (userConfig != null) {
187                 String JavaDoc value;
188                 if ((value = userConfig.getString("userWildcard")) != null) {
189                     dbmConf.setUserConfigWildcard(value);
190                 }
191                 if ((value = userConfig.getString("userSingleWildcard")) != null) {
192                     dbmConf.setUserConfigSingleWildcard(value);
193                 }
194                 if ((value = userConfig.getString("userSingleWildcardEscape"))
195                         != null) {
196                     dbmConf.setUserConfigSingleWildcardEscape(value);
197                 }
198                 if ((value = userConfig.getString("userWildcardEscape")) != null) {
199                     dbmConf.setUserConfigWildcardEscape(value);
200                 }
201             }
202         } catch (Exception JavaDoc except) {}
203
204  
205         Config defaultsConfig;
206
207         try {
208             defaultsConfig = (Config) config.getSection("defaults");
209         } catch (KeywordValueException except) {
210             throw new ConfigException("No DatabaseManager.defaults defined in config file.");
211         }
212         
213         if (defaultsConfig != null) {
214             dbmConf.setAllReadOnly(defaultsConfig.getBoolean(PARAMNAME_ALL_READ_ONLY,
215                     CacheConstants.DEFAULT_All_READONLY));
216             dbmConf.setLazyLoading(defaultsConfig.getBoolean(PARAMNAME_LAZY_LOADING,
217                     false));
218             dbmConf.setCaseSensitive(defaultsConfig.getBoolean(PARAMNAME_CASE_SENSITIVE,
219                     DEFAULT_CASE_SENSITIVE));
220             dbmConf.setMaxExecuteTime(defaultsConfig.getInt(PARAMNAME_MAX_EXECUTE_TIME,
221                     0));
222             dbmConf.setTransactionCheck(defaultsConfig.getBoolean(PARAMNAME_TRANSACTION_CHECK,
223                     false));
224             dbmConf.setDeleteCheckVersion(defaultsConfig.getBoolean(PARAMNAME_DELETE_CHECK_VERSION,
225                     false));
226             dbmConf.setAutoSave(defaultsConfig.getBoolean(PARAMNAME_AUTO_SAVE,
227                     false));
228             dbmConf.setAutoSaveCreateVirgin(defaultsConfig.getBoolean(PARAMNAME_AUTO_SAVE_CREATE_VIRGIN,
229                     false));
230             dbmConf.setAutoWrite(defaultsConfig.getBoolean(PARAMNAME_AUTO_WRITE,
231                     false));
232             dbmConf.setTransactionCaches(defaultsConfig.getBoolean(PARAMNAME_TRANSACTION_CACHES,
233                     false));
234             dbmConf.setDeadlockWaitTime(defaultsConfig.getInt(PARAMNAME_DEADLOCK_READ_TIME,
235                     0));
236             dbmConf.setDeadlockRetryCount(defaultsConfig.getInt(PARAMNAME_DEADLOCK_RETRY_NUMBER,
237                     0));
238             QueryBuilder.setDefaultQueryTimeout(config.getInt(PARAMNAME_QUERY_TIMEOUT,
239                     0));
240             dbmConf.setQueryTimeout(defaultsConfig.getInt(PARAMNAME_QUERY_TIMEOUT,
241                     0));
242             dbmConf.setSelectOids(defaultsConfig.getBoolean(PARAMNAME_SELECT_OIDS,
243                     false));
244             dbmConf.setIncrementVersions(defaultsConfig.getBoolean(PARAMNAME_INCREMENT_VERSIONS,
245                     true));
246             QueryBuilder.setDefaultFetchSize(config.getInt(PARAMNAME_DEFAULT_FETCH_SIZE,
247                     -1));
248             dbmConf.setDefaultFetchSize(defaultsConfig.getInt(PARAMNAME_DEFAULT_FETCH_SIZE,
249                     -1));
250             dbmConf.setDBTransactionFactoryName(defaultsConfig.getString(CommonConstants.TRANSACTION_FACTORY,
251                     null));
252             dbmConf.setConnectionAllocatorName(defaultsConfig.getString(CommonConstants.CONNECTION_ALLOCATOR,
253                     null));
254             dbmConf.setDBConnectionFactoryName(defaultsConfig.getString(CommonConstants.CONNECTION_FACTORY,
255                     null));
256             dbmConf.setQueryCacheImplClass(defaultsConfig.getString(CommonConstants.QUERY_CACAHE_IMPL_CLASS,
257                     null));
258             dbmConf.setFullCacheCountLimit(defaultsConfig.getInt(CacheConstants.FULL_CACHE_COUNT_LIMIT,
259                     CacheConstants.DEFAULT_FULL_CACHE_COUNT_LIMIT));
260             dbmConf.setCaseInsensitiveDatabase(defaultsConfig.getBoolean(CommonConstants.CASE_INSENSITIVE_DATABASE,
261                     CommonConstants.DEFAULT_CASE_INSENSITIVE_DATABASE));
262             dbmConf.setXaDefaultTimeout(defaultsConfig.getInt(CommonConstants.XA_DEFAULT_TIMEOUT
263                     ,CommonConstants.DEFAULT_XA_DEFAULT_TIMEOUT));
264             dbmConf.setXaTransactonManagerLookupName(defaultsConfig.getString(CommonConstants.XA_TM_LOOKUP_NAME
265                     ,CommonConstants.DEFAULT_XA_TM_LOOKUP_NAME));
266             dbmConf.setXaUsageCase(defaultsConfig.getInt(CommonConstants.XA_USAGE_CASE
267                     ,CommonConstants.DEFAULT_XA_USAGE_CASE));
268             dbmConf.setXaWrappedTransImplFactory(defaultsConfig.getString(CommonConstants.XA_WRAPPED_TRANS_IMPL_FACTORY
269                     ,CommonConstants.DEFAULT_XA_WRAPPED_TRANS_IMPL_FACTORY));
270             dbmConf.setXaUserTransactonLookupName(defaultsConfig.getString(CommonConstants.XA_USER_TRANSACTION_LOOKUP_NAME
271                     ,CommonConstants.DEFAULT_XA_USER_TRANSACTION_LOOKUP_NAME));
272             dbmConf.setXaJtaSupport(defaultsConfig.getString(CommonConstants.XA_JTA_SUPPORT
273                     ,CommonConstants.DEFAULT_XA_JTA_SUPPORT));
274             try {
275                 dbmConf.setUseCursorName(defaultsConfig.getBoolean(PARAMNAME_USE_CURSOR_NAME));
276             } catch (ConfigException e) {
277                 dbmConf.setUseCursorName(null);
278             }
279             dbmConf.setInitCachesResultSetType(defaultsConfig.getString(CommonConstants.INIT_CACHES_RESULT_SET_TYPE,
280                     null));
281             dbmConf.setInitCachesResultSetConcurrency(defaultsConfig.getString(CommonConstants.INIT_CACHES_RESULT_SET_CONCURRENCY,
282                     null));
283             dbmConf.setSqlBatch(defaultsConfig.getBoolean(CommonConstants.SQL_BATCH,
284                     CommonConstants.DEFAULT_SQL_BATCH));
285             try {
286                 dbmConf.setQueryTimeLimit(new Integer JavaDoc(defaultsConfig.getInt(CommonConstants.QUERY_TIME_LIMIT)));
287             } catch (ConfigException e) {
288                 dbmConf.setQueryTimeLimit(null);
289             }
290         }
291         try {
292             defaultsConfig = (Config) config.getSection("defaults.cache");
293         } catch (KeywordValueException except) {
294             throw new ConfigException("No DatabaseManager.defaults defined in config file.");
295         }
296         
297         if (defaultsConfig != null) {
298             dbmConf.setReserveFactor(defaultsConfig.getDouble(PARAMNAME_RESERVE_FACTOR,
299                     CacheConstants.DEFAULT_RESERVE_FACTOR));
300             dbmConf.setCachePercentage(defaultsConfig.getDouble(PARAMNAME_CACHE_PERCENTAGE,
301                     CacheConstants.DEFAULT_CACHE_PERCENTAGE));
302             dbmConf.setMaxCacheSize(defaultsConfig.getInt(PARAMNAME_MAX_CACHE_SIZE,
303                     CacheConstants.DEFAULT_MAX_CACHE_SIZE));
304             dbmConf.setMaxSimpleCacheSize(defaultsConfig.getInt(PARAMNAME_MAX_SIMPLE_CACHE_SIZE,
305                     CacheConstants.DEFAULT_MAX_SIMPLE_QUERY_CACHE_SIZE));
306             dbmConf.setMaxComplexCacheSize(defaultsConfig.getInt(PARAMNAME_MAX_COMPLEX_CACHE_SIZE,
307                     CacheConstants.DEFAULT_MAX_COMPLEX_QUERY_CACHE_SIZE));
308             dbmConf.setMaxMultiJoinCacheSize(defaultsConfig.getInt(PARAMNAME_MAX_MULTI_JOIN_CACHE_SIZE,
309                     CacheConstants.DEFAULT_MAX_MULTI_JOIN_QUERY_CACHE_SIZE));
310             dbmConf.setInitAllCaches(defaultsConfig.getBoolean(PARAMNAME_INITIAL_ALL_CACHES,
311                     CacheConstants.DEFAULT_INITIAL_ALL_CACHES));
312             dbmConf.setInitialCacheFetchSize(defaultsConfig.getInt(CacheConstants.PARAMNAME_INITIAL_CACHE_FETCH_SIZE,
313                     CacheConstants.DEFAULT_INITIAL_CACHE_FETCH_SIZE));
314             dbmConf.setInitialDSCacheSize(defaultsConfig.getInt(CacheConstants.PARAMNAME_INITIAL_DS_CACHE_SIZE,
315                     CacheConstants.DEFAULT_INITIAL_DS_CACHE_SIZE));
316             dbmConf.setDodsCacheFactory(defaultsConfig.getString(CacheConstants.PARAMNAME_DODS_CACHE_FACTORY
317                             ,CacheConstants.DEFAULT_DODS_CACHE_FACTORY));
318         }
319         
320         isDODSConfigured = null != System.getProperty("DODS_HOME", null)
321                 || null != config.getString("ConfigurationDir", null);
322 // mustConfigureDODS = config.getBoolean("DoFullInit", false);
323
mustConfigureDODS = false;
324
325         /**
326          * Configure each logical database.
327          */

328         Config dbConfig;
329
330         for (int idx = 0; idx < databases.length; idx++) {
331             String JavaDoc dbName = databases[idx];
332
333             try {
334                 dbConfig = (Config) config.getSection("DB." + dbName);
335             } catch (KeywordValueException except) {
336                 throw new ConfigException("No DatabaseManager.DB." + dbName
337                         + " defined in config file.");
338             }
339             
340             if (logicalDatabases.get(dbName) != null) {
341                 throw new DatabaseManagerException("duplicate logical database name: \""
342                         + dbName + "\"");
343             }
344             
345             LogicalDatabase logicalDatabase = loadLogicalDatabase(dbName,dbConfig);
346
347             logicalDatabases.put(dbName, logicalDatabase);
348         }
349
350         /**
351          * Set default database if supplied.
352          */

353         defaultDB = config.getString("DefaultDatabase", databases[0]);
354         setDefaultDatabase(defaultDB);
355
356         /**
357          * Set debug logging of Queries and Transactions.
358          */

359         boolean debugLogging = config.getBoolean("Debug", false);
360
361         setDebugLogging(debugLogging);
362         Wrapper.getInstance().setTimeout(config.getLong("MainCacheLockTimeout",
363                 100));
364
365         /**
366          * Set the oid and version column names in CoreDO.
367          * Note that these could be configured for each logical
368          * database but this would require some complex extensions
369          * to DBQuery and DBTransaction in order to ensure that
370          * the correct values were always being used without
371          * creating race conditions.
372          * This means that the limitation is currently that all
373          * databases accessed by your application must use the
374          * same column names.
375          */

376         String JavaDoc oidColumnName = config.getString("ObjectIdColumnName", null);
377
378         if (oidColumnName != null) {
379             CoreDO.set_OIdColumnName(oidColumnName);
380         }
381         String JavaDoc versionColumnName = config.getString("VersionColumnName", null);
382
383         if (versionColumnName != null) {
384             CoreDO.set_versionColumnName(versionColumnName);
385         }
386      
387         if(mainConfig == null) {
388          ConfigFileInterface mainConfigFile = null;
389             if(config!=null)
390                mainConfigFile = config.getConfigFile();
391             if(mainConfigFile!=null)
392                mainConfig = mainConfigFile.getConfig();
393         }
394     }
395
396
397
398
399     public void initChaches(ClassLoader JavaDoc clsLoader) {
400             try{
401                 initAllDodsCaches(this.config, clsLoader);
402         }catch(Exception JavaDoc e){
403                 DODS.getLogChannel().write(Logger.DEBUG,"Unable to load caches at startup");
404             }
405     }
406
407
408
409     
410     /**
411      * Creates new <code>StandardDatabaseManager</code> instance.
412      *
413      * @param confURL Additional path to folder or *.jar file with configuration file. If null use DODS classpath
414      *
415      * @param confFile Name of conf file relativ to *.jar file or to specifide folder (from confURL/DODS claspath).
416      *
417      * @return new <code>StandardDatabaseManager</code> instance.
418      *
419      */

420     public static DatabaseManager newInstance(URL JavaDoc confURL, String JavaDoc confFile)
421         throws ConfigException, DatabaseManagerException, SQLException JavaDoc {
422         try {
423             InputStream JavaDoc configIS = Common.getConfFileFromURL(confURL, confFile);
424             ConfigFile configFile = new ConfigFile(configIS);
425             Config config = configFile.getConfig();
426             configIS.close();
427             Config dbConfig = new Config(config.getSection("DatabaseManager"),configFile);
428             return new StandardDatabaseManager(dbConfig);
429         } catch (Exception JavaDoc e) {
430             throw new ConfigException(e);
431         }
432     }
433         
434
435     
436     /**
437      * Creates new <code>StandardDatabaseManager</code> instance.
438      *
439      * @param fileName full path name of the application configuration file.
440      *
441      * @return new <code>StandardDatabaseManager</code> instance.
442      *
443      */

444     public static DatabaseManager newInstance(String JavaDoc fileName)
445         throws ConfigException, DatabaseManagerException, SQLException JavaDoc {
446         try {
447             Config config = null;
448             ConfigFile configFile = null;
449             if(fileName!=null) {
450                 try {
451                     File inputFile = new File(fileName);
452                     if(inputFile!=null && inputFile.isFile()) {
453                         configFile = new ConfigFile(inputFile);
454                         config = configFile.getConfig();
455                     }
456                 } catch (Exception JavaDoc e) {
457                     System.out.println("Error during configuration file reading: '"+fileName+"'");
458                 }
459             }
460             if (config==null){
461                 InputStream JavaDoc configIS=Common.getConfFileFromURL(null,null);
462                 configFile = new ConfigFile(configIS);
463                 config = configFile.getConfig();
464                 configIS.close();
465             }
466             if (config==null){
467                 throw new Exception JavaDoc("Can't create configuration object from file:'"+fileName+"'");
468             }
469             Config dbConfig = new Config(config.getSection("DatabaseManager"),configFile);
470             return new StandardDatabaseManager(dbConfig);
471         } catch (Exception JavaDoc e) {
472             throw new ConfigException(e);
473         }
474     }
475         
476     /**
477      * Return main configuration class
478      *
479      * @return
480      * main configuration class.
481      */

482     public Config getConfig() {
483         return config;
484     }
485
486     /**
487      * Return main application configuration class
488      *
489      * @return
490      * main application configuration class.
491      */

492
493     public Config getParentConfig() {
494      
495             return mainConfig;
496     }
497
498
499
500     boolean isDODSConfigured = false;
501     boolean mustConfigureDODS = false;
502
503     /**
504      * Actually load the specified logical database. This method provides
505      * an easy way to override the default behavour.
506      *
507      * @return
508      * The logical database.
509      * @exception DatabaseManagerException
510      * if an error occurs creating the logical database.
511      */

512     public LogicalDatabase loadLogicalDatabase(String JavaDoc dbName, Config dbConfig)
513         throws DatabaseManagerException {
514         LogicalDatabase lDB = null;
515
516         try {
517             if (mustConfigureDODS && !isDODSConfigured) {
518                 throw new DatabaseManagerException("DODS is not configured properly.");
519             }
520             if (isDODSConfigured) {
521                 String JavaDoc dbClassName = dbConfig.getString("ClassType", "Standard");
522                 String JavaDoc classPath = Common.getDodsConfProperty("ClassPath",
523                         dbClassName);
524                 String JavaDoc className = Common.getDodsConfProperty("ClassName",
525                         dbClassName);
526
527                 if (classPath != null && className != null) {
528                     MultiClassLoader loader = new MultiClassLoader(null);
529
530                     loader.setClassPath(classPath);
531                     Class JavaDoc dbClass = loader.loadClass(className);
532
533                     lDB = (LogicalDatabase) dbClass.newInstance();
534                     lDB.init(dbName, dbConfig);
535                 }
536             }
537             if (lDB == null) {
538                 lDB = new StandardLogicalDatabase(dbName, dbConfig, dbmConf);
539             }
540         } catch (Exception JavaDoc except) {
541             throw new DatabaseManagerException("Could not create logical database "
542                     + dbName,
543                     except);
544         }
545         return lDB;
546     }
547
548     /**
549      * Return default database name (given in config file)
550      * @return
551      * default database name
552      */

553     public String JavaDoc getDefaultDB() {
554         return defaultDB;
555     }
556
557     /**
558      * Allocate a connection to a thread. The connection should be returned
559      * to the allocator by calling its
560      * <a HREF=com.lutris.appserver.server.sql.DBConnection#release>
561      * release()</a> function. A thread will wait if
562      * no connections are available.
563      * Interupted exceptions are converted to
564      * errors.
565      * N.B. Can't be synchronized, as connection allocator
566      * <CODE>allocate</CODE> may wait.
567      *
568      * @param dbName
569      * Logical name of the database to allocate a connection to.
570      * @return
571      * The allocated connection object.
572      * @exception DatabaseManagerException
573      * If a nonexistent logical database name is supplied.
574      * @exception SQLException
575      * If a SQL error occures.
576      */

577     public DBConnection allocateConnection(String JavaDoc dbName)
578         throws DatabaseManagerException, SQLException JavaDoc {
579         LogicalDatabase logicalDatabase = findLogicalDatabase(dbName);
580
581         return logicalDatabase.allocateConnection();
582     }
583
584     /**
585      * Allocate a connection to a thread. The connection should be returned
586      * to the allocator by calling its
587      * <a HREF=com.lutris.appserver.server.sql.DBConnection#release>
588      * release()</a> function. A thread will wait if
589      * no connections are available.
590      * Interupted exceptions are converted to
591      * errors. The connection is allocated from the default logical
592      * database.
593      *
594      * @return
595      * The allocated connection object.
596      * @exception DatabaseManagerException
597      * If no default logical database has been set.
598      * @exception SQLException
599      * If a SQL error occurs.
600      * @see
601      * #setDefaultDatabase
602      */

603     public DBConnection allocateConnection()
604         throws DatabaseManagerException, SQLException JavaDoc {
605         if (defaultLogicalDatabase == null) {
606             throw new DatabaseManagerException("Default logical database "
607                     + "has not been specified.");
608         }
609         return defaultLogicalDatabase.allocateConnection();
610     }
611
612     /**
613      * Allocate an object id from the specified logical database.
614      *
615      * @param dbName
616      * Logical name of the database from which to obtain an object id.
617      * @return The allocated unique OID
618      * @exception DatabaseManagerException
619      * If a nonexistent logical database name is supplied.
620      * @exception ObjectIdException
621      * If a problem (e.g. SQL error) occured in obtaining the OID.
622      */

623     public ObjectId allocateObjectId(String JavaDoc dbName)
624         throws DatabaseManagerException, ObjectIdException {
625         LogicalDatabase logicalDatabase = findLogicalDatabase(dbName);
626
627         return logicalDatabase.allocateObjectId();
628     }
629
630     /**
631      * Allocate an object id from the specified logical database.
632      *
633      * @return The allocated connection object.
634      * @exception DatabaseManagerException
635      * If a nonexistent default logical database has been set.
636      * @exception ObjectIdException
637      * If a problem (e.g. SQL error) occured in obtaining the OID.
638      * @see
639      * #setDefaultDatabase
640      */

641     public ObjectId allocateObjectId()
642         throws DatabaseManagerException, ObjectIdException {
643         if (defaultLogicalDatabase == null) {
644             throw new DatabaseManagerException("Default logical database "
645                     + "has not been specified.");
646         }
647         return defaultLogicalDatabase.allocateObjectId();
648     }
649
650     /**
651      * Check does oid belong to Object id's range [minOId, currentOId]
652      *
653      * @param dbName
654      * Logical name of the database from which to check an object id.
655      * @param oid
656      * oid which will be checked.
657      * @exception DatabaseManagerException
658      * If a nonexistent logical database name is supplied.
659      * @exception ObjectIdException
660      * If a oid does't belong to range.
661      */

662     public void checkOId(String JavaDoc dbName, ObjectId oid)
663         throws DatabaseManagerException, ObjectIdException {
664         LogicalDatabase logicalDatabase = findLogicalDatabase(dbName);
665
666         logicalDatabase.checkOId(oid);
667     }
668
669     /**
670      * Check does oid belong to Object id's range [minOId, currentOId] for default database
671      *
672      * @param oid
673      * oid which will be checked.
674      * @exception DatabaseManagerException
675      * If a nonexistent default logical database has been set.
676      * @exception ObjectIdException
677      * If a oid does't belong to range.
678      */

679     public void checkOId(ObjectId oid)
680         throws DatabaseManagerException, ObjectIdException {
681         if (defaultLogicalDatabase == null) {
682             throw new DatabaseManagerException("Default logical database "
683                     + "has not been specified.");
684         }
685         defaultLogicalDatabase.checkOId(oid);
686     }
687
688     /**
689      * Create a transaction object for the specified logical database.
690      *
691      * @param dbName
692      * Logical name of the database from which to obtain a transaction.
693      * @return The transaction
694      * @exception DatabaseManagerException
695      * If a nonexistent or invalid logical database name is supplied.
696      * @exception SQLException
697      * If a problem occured creating the transaction.
698      */

699     public DBTransaction createTransaction(String JavaDoc dbName)
700         throws DatabaseManagerException, SQLException JavaDoc {
701         DBTransaction ret;
702
703         if (dbName == null) {
704             return createTransaction();
705         }
706         LogicalDatabase logicalDatabase = findLogicalDatabase(dbName);
707
708         ret = logicalDatabase.createTransaction();
709         ret.setDatabaseName(dbName);
710         return ret;
711     }
712
713     /**
714      * Create a transaction object for the default logical database.
715      *
716      * @return The transaction
717      * @exception DatabaseManagerException
718      * If a nonexistent default logical database has been set.
719      * @exception SQLException
720      * If a problem occured creating the transaction.
721      * @see
722      * #setDefaultDatabase
723      */

724     public DBTransaction createTransaction()
725         throws DatabaseManagerException, SQLException JavaDoc {
726         DBTransaction ret;
727
728         if (defaultLogicalDatabase == null) {
729             throw new DatabaseManagerException("Default logical database "
730                     + "has not been specified.");
731         }
732         ret = defaultLogicalDatabase.createTransaction();
733         ret.setDatabaseName(defaultDB);
734         return ret;
735     }
736
737     /**
738      * Create a query object for the specified logical database.
739      *
740      * @param dbName
741      * Logical name of the database from which to obtain a query.
742      * @return The query
743      * @exception DatabaseManagerException
744      * If a nonexistent or invalid logical database name is supplied.
745      * @exception SQLException
746      * If a problem occured creating the query.
747      */

748     public DBQuery createQuery(String JavaDoc dbName)
749         throws DatabaseManagerException, SQLException JavaDoc {
750         LogicalDatabase logicalDatabase = findLogicalDatabase(dbName);
751
752         return logicalDatabase.createQuery();
753     }
754
755     /**
756      * Create a query object for the default logical database.
757      *
758      * @return The query
759      * @exception DatabaseManagerException
760      * If a nonexistent default logical database has been set.
761      * @exception SQLException
762      * If a problem occured creating the query.
763      * @see
764      * #setDefaultDatabase
765      */

766     public DBQuery createQuery()
767         throws DatabaseManagerException, SQLException JavaDoc {
768         if (defaultLogicalDatabase == null) {
769             throw new DatabaseManagerException("Default logical database "
770                     + "has not been specified.");
771         }
772         return defaultLogicalDatabase.createQuery();
773     }
774
775     /**
776      * Return a loical database type for the specified logical database.
777      *
778      * @param dbName
779      * Logical name of the database from which to obtain a query.
780      * @return loical database type
781      * @exception DatabaseManagerException
782      * If a nonexistent or invalid logical database name is supplied.
783      * @exception SQLException
784      * If a problem occured creating the query.
785      */

786     public String JavaDoc logicalDatabaseType(String JavaDoc dbName)
787         throws DatabaseManagerException, SQLException JavaDoc {
788         LogicalDatabase logicalDatabase = null;
789
790         if (dbName != null) {
791             logicalDatabase = findLogicalDatabase(dbName);
792             return logicalDatabase.getType();
793         } else {
794             return logicalDatabaseType();
795         }
796     }
797
798     /**
799      * Return a loical database type for the default logical database.
800      *
801      * @return loical database type
802      * @exception DatabaseManagerException
803      * If a nonexistent default logical database has been set.
804      * @exception SQLException
805      * If a problem occured creating the query.
806      * @see
807      * #setDefaultDatabase
808      */

809     public String JavaDoc logicalDatabaseType()
810         throws DatabaseManagerException, SQLException JavaDoc {
811         if (defaultLogicalDatabase == null) {
812             throw new DatabaseManagerException("Default logical database "
813                     + "has not been specified.");
814         }
815         return defaultLogicalDatabase.getType();
816     }
817  
818     /**
819      * Find the named logical database in hash table.
820      *
821      * @param dbName Logical name of the database to locate.
822      * @exception DatabaseManagerException If a nonexistant logical database
823      * name is supplied.
824      */

825     public LogicalDatabase findLogicalDatabase(String JavaDoc dbName)
826         throws DatabaseManagerException {
827         LogicalDatabase logicalDatabase = (LogicalDatabase) logicalDatabases.get(dbName);
828
829         if (logicalDatabase == null) {
830             throw new DatabaseManagerException
831                     ("unknown logical database name: \"" + dbName + "\"");
832         }
833         return logicalDatabase;
834     }
835
836     /**
837      * Set the default logical database. This should only be called
838      * after the logical database
839      * (<A HREF=com.lutris.appserver.server.sql.LogicalDatabase></A>
840      * has been established.
841      *
842      * @param dbName The default logical database.
843      * @exception DatabaseManagerException
844      * if the logical database name is invalid or not found.
845      */

846     public void setDefaultDatabase(String JavaDoc dbName)
847         throws DatabaseManagerException {
848         defaultLogicalDatabase = findLogicalDatabase(dbName);
849     }
850
851     /**
852      * Shutdown the database manager. All logical databases will be
853      * shutdown and all connections closed.
854      */

855     public void shutdown() {
856         for (Enumeration JavaDoc keys = logicalDatabases.keys();
857                 keys.hasMoreElements();) {
858             LogicalDatabase logicalDatabase = (LogicalDatabase)
859                     logicalDatabases.get((String JavaDoc) keys.nextElement());
860
861             logicalDatabase.shutdown();
862         }
863     }
864
865     // ====================================================================
866
// The following are primarily for management purposes...
867
// ====================================================================
868
/**
869      * Returns the list of managed logical databases.
870      *
871      * @return List of logical database names.
872      */

873     public String JavaDoc[] getLogicalDatabaseNames() {
874         String JavaDoc[] names = new String JavaDoc[logicalDatabases.size()];
875         int idx = 0;
876         Enumeration JavaDoc keys = logicalDatabases.keys();
877
878         while (keys.hasMoreElements()) {
879             names[idx++] = (String JavaDoc) keys.nextElement();
880         }
881         return names;
882     }
883
884     /**
885      * Returns a description of the logical database type.
886      *
887      * @param dbName
888      * The logical database name.
889      * @return
890      * A text description of the logical database type.
891      * @exception DatabaseManagerException
892      * If a nonexistent logical database name is supplied.
893      */

894     public String JavaDoc getType(String JavaDoc dbName)
895         throws DatabaseManagerException {
896         LogicalDatabase logicalDatabase = findLogicalDatabase(dbName);
897
898         return logicalDatabase.getType();
899     }
900
901     /**
902      * Gets the number of requests made to the database since startup time.
903      *
904      * @param dbName The name of the logical database.
905      * @exception DatabaseManagerException
906      * If a nonexistent logical database name is supplied.
907      * @return The number of database requests since the server started.
908      */

909     public long getRequestCount(String JavaDoc dbName)
910         throws DatabaseManagerException {
911         LogicalDatabase logicalDatabase = findLogicalDatabase(dbName);
912
913         return logicalDatabase.getRequestCount();
914     }
915
916     /**
917      * Gets the number of currently active connections.
918      *
919      * @param dbName The name of the logical database.
920      * @exception DatabaseManagerException
921      * If a nonexistent logical database name is supplied.
922      * @return The number of currently active connections.
923      */

924     public int getActiveConnectionCount(String JavaDoc dbName)
925         throws DatabaseManagerException {
926         LogicalDatabase logicalDatabase = findLogicalDatabase(dbName);
927
928         return logicalDatabase.getActiveConnectionCount();
929     }
930
931     /**
932      * Gets the maximum number of concurent connections that existed
933      * at any time since this object was created, or
934      * <CODE>resetMaxConnectionCount()</CODE> was called.
935      * This is a historical highwater mark.
936      * If you do not implement this feature, return -1.
937      *
938      * @param dbName The name of the logical database.
939      * @exception DatabaseManagerException
940      * If a nonexistent logical database name is supplied.
941      * @return The highwater mark for number of connections, or -1.
942      */

943     public int getMaxConnectionCount(String JavaDoc dbName)
944         throws DatabaseManagerException {
945         LogicalDatabase logicalDatabase = findLogicalDatabase(dbName);
946
947         return logicalDatabase.getMaxConnectionCount();
948     }
949
950     /**
951      * Gets the time when the maximum refered to by
952      * <CODE>maxConnectionCount()</CODE> occured.
953      *
954      * @param dbName The name of the logical database.
955      * @exception DatabaseManagerException
956      * If a nonexistent logical database name is supplied.
957      * @return The Date of when the maximum number of connections occured.
958      */

959     public Date JavaDoc getMaxConnectionCountDate(String JavaDoc dbName)
960         throws DatabaseManagerException {
961         LogicalDatabase logicalDatabase = findLogicalDatabase(dbName);
962
963         return logicalDatabase.getMaxConnectionCountDate();
964     }
965
966     /**
967      * Reset the maximum connection count. See
968      * <CODE>maxConnectionCount()</CODE>. The highwater mark should be
969      * reset to the current number of connections.
970      *
971      * @param dbName The name of the logical database.
972      * @exception DatabaseManagerException
973      * If a nonexistent logical database name is supplied.
974      */

975     public void resetMaxConnectionCount(String JavaDoc dbName)
976         throws DatabaseManagerException {
977         LogicalDatabase logicalDatabase = findLogicalDatabase(dbName);
978
979         logicalDatabase.resetMaxConnectionCount();
980         return;
981     }
982
983     /**
984      * Turn debugging on or off.
985      *
986      * @param condition on of off.
987      */

988     public void setDebugLogging(boolean condition) {
989         debug = condition;
990     }
991
992     /**
993      * Return allReadOnly parameter (given in config file)
994      * @return
995      * allReadOnly parameter
996      */

997     public boolean getAllReadOnly() {
998         return dbmConf.isAllReadOnly();
999     }
1000   
1001    /**
1002     * Return AppName parameter (given in config file)
1003     * @return
1004     * AppName parameter
1005     */

1006    public String JavaDoc getAppName() {
1007        return appName;
1008    }
1009
1010    public DatabaseManagerConfiguration getDatabaseManagerConfiguration() {
1011        return dbmConf;
1012    }
1013     
1014    
1015    /**
1016     * Init chaches for specified Database
1017     * @param dbConfig Database section of app. configuration file.
1018     * @param fileName File (path) with list of data layer classes.
1019     */

1020    private void initDatabaseCaches(Config dbConfig,String JavaDoc fileName, ClassLoader JavaDoc cls){
1021        String JavaDoc tablesXmlFile=null;
1022        try {
1023            tablesXmlFile = dbConfig.getString("ClassList",fileName);
1024        } catch (ConfigException e) {}
1025        InputStream JavaDoc tablesList = null;
1026        if (tablesXmlFile!=null){
1027            tablesList = getTablesXML(tablesXmlFile,cls);
1028        }else{
1029            tablesList = getTablesXML((String JavaDoc)null,cls);
1030        }
1031        if(tablesList!=null){
1032            initCaches(tablesList, cls);
1033        }
1034    }
1035    
1036    /**
1037     * Init chaches for all Databases specified in DatabaseManager section of application conf file.
1038     * @param config DatabaseManager section of app configuration file.
1039     * @param cls application classLoader
1040     */

1041    public void initAllDodsCaches(Config config, ClassLoader JavaDoc cls){
1042        Config dbConfig = null;
1043        String JavaDoc[] databases = null;
1044        String JavaDoc tablesXmlFile = null;
1045        try {
1046            databases = config.getStrings("Databases");
1047            tablesXmlFile = config.getString("ClassList",(String JavaDoc)null);
1048        } catch (ConfigException e) {
1049            DODS.getLogChannel().write(Logger.DEBUG,"Unable to init caches: Error reading application configuation file");
1050        }
1051        if(databases!=null){
1052            for (int idx = 0; idx < databases.length; idx++) {
1053                String JavaDoc dbName = databases[idx];
1054                try {
1055                    dbConfig = (Config) config.getSection("DB." + dbName);
1056                    initDatabaseCaches(dbConfig,tablesXmlFile, cls);
1057                } catch (Exception JavaDoc except) {
1058                    DODS.getLogChannel().write(Logger.DEBUG,"Unable to init caches for database: "+dbName);
1059                }
1060            }
1061        }
1062    }
1063
1064    /**
1065     * Read xml file with list of classes in data layer.
1066     * @param fileName Path of xml file with data layer class list
1067     * @return InputStream with xml file.
1068     */

1069    private InputStream JavaDoc getTablesXML(String JavaDoc fileName, ClassLoader JavaDoc cls){
1070        InputStream JavaDoc res=null;
1071        if(fileName!=null){
1072            try{
1073                File tablesFile = new File(fileName);
1074                if (tablesFile.isFile()) {
1075                    res= new FileInputStream JavaDoc(fileName);
1076                }
1077            }catch(Exception JavaDoc e){
1078                DODS.getLogChannel().write(Logger.DEBUG,"Unable to read table names from file: "+fileName);
1079            }
1080        }else{
1081            try{
1082// res = this.getClass().getClassLoader().getResourceAsStream("org/enhydra/dods/DODSClassList.xml");
1083
res = cls.getResourceAsStream("org/enhydra/dods/DODSClassList.xml");
1084            }catch(Exception JavaDoc e){
1085                DODS.getLogChannel().write(Logger.DEBUG,"Unable to read table names from resources: org.enhydra.dods.DODSClassList.xml");
1086            }
1087        }
1088        return res;
1089    }
1090    
1091    /**
1092     * Initialize caches for all data layer classes specified in tablesList (xml file)
1093     * @param tablesList InputStream of XML file with data layer class names.
1094     */

1095    private void initCaches(InputStream JavaDoc tablesList, ClassLoader JavaDoc cls){
1096        Document JavaDoc doc = null;
1097        try {
1098            DocumentBuilderFactory JavaDoc factory = DocumentBuilderFactory.newInstance();
1099            DocumentBuilder JavaDoc builder = factory.newDocumentBuilder();
1100            doc = builder.parse(tablesList);
1101        } catch (Exception JavaDoc e) {
1102            DODS.getLogChannel().write(Logger.DEBUG,"Unable to parse xml file with cache initialisation tables list.");
1103        }
1104        if(doc!=null){
1105            NodeList JavaDoc classNodes = doc.getElementsByTagName("CLASS");
1106            for (int i = 0; i < classNodes.getLength(); i++) {
1107                String JavaDoc className = ((Element JavaDoc)classNodes.item(i)).getAttribute("name");
1108                try {
1109                    Class JavaDoc ce = cls.loadClass(className);
1110                    Method JavaDoc mth = ce.getMethod("getCacheDodsTableName",new Class JavaDoc[] {});
1111                    mth.invoke(null, new Object JavaDoc[]{});
1112                } catch (Exception JavaDoc e1) {
1113                    e1.printStackTrace();
1114                    DODS.getLogChannel().write(Logger.DEBUG,"Unable to invoke caches for class: "+className);
1115                }
1116            }
1117        }
1118    }
1119    
1120}
1121
Popular Tags