View Javadoc

1   package org.apache.torque;
2   
3   /* ====================================================================
4    * The Apache Software License, Version 1.1
5    *
6    * Copyright (c) 2001-2003 The Apache Software Foundation.  All rights
7    * reserved.
8    *
9    * Redistribution and use in source and binary forms, with or without
10   * modification, are permitted provided that the following conditions
11   * are met:
12   *
13   * 1. Redistributions of source code must retain the above copyright
14   *    notice, this list of conditions and the following disclaimer.
15   *
16   * 2. Redistributions in binary form must reproduce the above copyright
17   *    notice, this list of conditions and the following disclaimer in
18   *    the documentation and/or other materials provided with the
19   *    distribution.
20   *
21   * 3. The end-user documentation included with the redistribution,
22   *    if any, must include the following acknowledgment:
23   *       "This product includes software developed by the
24   *        Apache Software Foundation (http://www.apache.org/)."
25   *    Alternately, this acknowledgment may appear in the software itself,
26   *    if and wherever such third-party acknowledgments normally appear.
27   *
28   * 4. The names "Apache" and "Apache Software Foundation" and
29   *    "Apache Turbine" must not be used to endorse or promote products
30   *    derived from this software without prior written permission. For
31   *    written permission, please contact apache@apache.org.
32   *
33   * 5. Products derived from this software may not be called "Apache",
34   *    "Apache Turbine", nor may "Apache" appear in their name, without
35   *    prior written permission of the Apache Software Foundation.
36   *
37   * THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESSED OR IMPLIED
38   * WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
39   * OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
40   * DISCLAIMED.  IN NO EVENT SHALL THE APACHE SOFTWARE FOUNDATION OR
41   * ITS CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL,
42   * SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT
43   * LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF
44   * USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND
45   * ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
46   * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
47   * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
48   * SUCH DAMAGE.
49   * ====================================================================
50   *
51   * This software consists of voluntary contributions made by many
52   * individuals on behalf of the Apache Software Foundation.  For more
53   * information on the Apache Software Foundation, please see
54   * <http://www.apache.org/>.
55   */
56  
57  import java.io.IOException;
58  import java.sql.Connection;
59  import java.sql.SQLException;
60  import java.util.ArrayList;
61  import java.util.Collections;
62  import java.util.HashMap;
63  import java.util.Iterator;
64  import java.util.List;
65  import java.util.Map;
66  
67  import org.apache.commons.configuration.Configuration;
68  import org.apache.commons.configuration.PropertiesConfiguration;
69  
70  import org.apache.commons.logging.Log;
71  import org.apache.commons.logging.LogFactory;
72  
73  import org.apache.torque.adapter.DB;
74  import org.apache.torque.adapter.DBFactory;
75  import org.apache.torque.dsfactory.DataSourceFactory;
76  import org.apache.torque.manager.AbstractBaseManager;
77  import org.apache.torque.map.DatabaseMap;
78  import org.apache.torque.map.TableMap;
79  import org.apache.torque.oid.IDBroker;
80  import org.apache.torque.oid.IDGeneratorFactory;
81  import org.apache.torque.util.BasePeer;
82  
83  /***
84   * The core of Torque's implementation.  Both the classic {@link
85   * org.apache.torque.Torque} static wrapper and the {@link
86   * org.apache.torque.avalon.TorqueComponent} <a
87   * href="http://avalon.apache.org/">Avalon</a> implementation leverage
88   * this class.
89   *
90   * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
91   * @author <a href="mailto:magnus@handtolvur.is">Magn?s ??r Torfason</a>
92   * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
93   * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
94   * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
95   * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
96   * @author <a href="mailto:kschrader@karmalab.org">Kurt Schrader</a>
97   * @version $Id: TorqueInstance.java,v 1.5 2003/08/05 18:09:35 mpoeschl Exp $
98   */
99  public class TorqueInstance
100 {
101     /*** Logging */
102     private static Log log = LogFactory.getLog(TorqueInstance.class);
103 
104     /*** A constant for <code>default</code>. */
105     private static final String DEFAULT_NAME = "default";
106 
107     /*** The db name that is specified as the default in the property file */
108     private String defaultDBName;
109 
110     /*** The global cache of database maps */
111     private Map dbMaps;
112 
113     /*** The cache of DataSourceFactory's */
114     private Map dsFactoryMap;
115 
116     /*** The cache of DB adapter keys */
117     private Map adapterMap;
118 
119     /*** A repository of Manager instances. */
120     private Map managers;
121 
122     /*** Torque-specific configuration. */
123     private Configuration conf;
124 
125     /*** flag to set to true once this class has been initialized */
126     private boolean isInit = false;
127 
128     /***
129      * Store mapbuilder classnames for peers that have been referenced prior
130      * to Torque being initialized.  This can happen if torque om/peer objects
131      * are serialized then unserialized prior to Torque being reinitialized.
132      * This condition exists in a normal catalina restart.
133      */
134     private List mapBuilders = null;
135 
136     /***
137      * Creates a new instance with default configuration.
138      *
139      * @see #resetConfiguration()
140      */
141     public TorqueInstance()
142     {
143         resetConfiguration();
144     }
145 
146     /***
147      * Initializes this instance of Torque.
148      *
149      * @see org.apache.stratum.lifecycle.Initializable
150      * @throws TorqueException Any exceptions caught during processing will be
151      *         rethrown wrapped into a TorqueException.
152      */
153     private synchronized void initialize() throws TorqueException
154     {
155         log.debug("initialize()");
156 
157         if (isInit)
158         {
159             log.debug("Multiple initializations of Torque attempted");
160             return;
161         }
162 
163         if (conf == null)
164         {
165             throw new TorqueException("Torque cannot be initialized without "
166                     + "a valid configuration. Please check the log files "
167                     + "for further details.");
168         }
169 
170         // Now that we have dealt with processing the log4j properties
171         // that may be contained in the configuration we will make the
172         // configuration consist only of the remain torque specific
173         // properties that are contained in the configuration. First
174         // look for properties that are in the "torque" namespace.
175 
176         Configuration subConf = conf.subset("torque");
177 
178         if (!subConf.isEmpty())
179         {
180             setConfiguration(subConf);
181         }
182 
183         dbMaps = new HashMap();
184         initAdapters(conf);
185         initDataSourceFactories(conf);
186 
187         for (Iterator i = mapBuilders.iterator(); i.hasNext();)
188         {
189             //this will add any maps in this builder to the proper database map
190             BasePeer.getMapBuilder((String) i.next());
191         }
192         // any further mapBuilders will be called/built on demand
193         mapBuilders = null;
194 
195         // setup manager mappings
196         initManagerMappings(conf);
197 
198         isInit = true;
199     }
200 
201     /***
202      *
203      * @param conf the Configuration representing the properties file
204      * @throws TorqueException Any exceptions caught during processing will be
205      *         rethrown wrapped into a TorqueException.
206      */
207     private final void initAdapters(Configuration conf)
208             throws TorqueException
209     {
210         log.debug("initAdapters(" + conf + ")");
211         adapterMap = new HashMap();
212         Configuration c = conf.subset("database");
213 
214         if (c != null)
215         {
216             boolean foundAdapters = false;
217 
218             try
219             {
220                 for (Iterator it = c.getKeys(); it.hasNext(); )
221                 {
222                     String key = (String) it.next();
223                     if (key.endsWith("adapter"))
224                     {
225                         String adapter = c.getString(key);
226                         String handle = key.substring(0, key.indexOf('.'));
227                         DB db = DBFactory.create(adapter);
228                         // register the adapter for this name
229                         adapterMap.put(handle, db);
230                         log.debug("Adding " + adapter + " -> " + handle + " as Adapter");
231                         foundAdapters = true;
232                     }
233                 }
234                 if (!foundAdapters)
235                 {
236                     log.warn("Databases defined but no adapter "
237                              + "configurations found!");
238                 }
239             }
240             catch (Exception e)
241             {
242                 log.error("Error reading configuration seeking database "
243                           + "adapters", e);
244                 throw new TorqueException(e);
245             }
246         }
247         else
248         {
249             log.warn("No Database definitions found!");
250         }
251 
252     }
253 
254     /***
255      *
256      * @param conf the Configuration representing the properties file
257      * @throws TorqueException Any exceptions caught during processing will be
258      *         rethrown wrapped into a TorqueException.
259      */
260     private void initDataSourceFactories(Configuration conf)
261             throws TorqueException
262     {
263         log.debug("initDataSourceFactories(" + conf + ")");
264         dsFactoryMap = new HashMap();
265         Configuration c = conf.subset("dsfactory");
266         if (c != null)
267         {
268             boolean foundFactories = false;
269 
270             try
271             {
272                 for (Iterator it = c.getKeys(); it.hasNext();)
273                 {
274                     String key = (String) it.next();
275                     if (key.endsWith("factory"))
276                     {
277                         String classname = c.getString(key);
278                         String handle = key.substring(0, key.indexOf('.'));
279                         log.debug("handle: " + handle
280                                 + " DataSourceFactory: " + classname);
281                         Class dsfClass = Class.forName(classname);
282                         DataSourceFactory dsf =
283                                 (DataSourceFactory) dsfClass.newInstance();
284                         dsf.initialize(c.subset(handle));
285                         dsFactoryMap.put(handle, dsf);
286                         foundFactories = true;
287                     }
288                 }
289                 if (!foundFactories)
290                 {
291                     log.warn("Data Sources configured but no factories found!");
292                 }
293             }
294             catch (Exception e)
295             {
296                 log.error("Error reading adapter configuration", e);
297                 throw new TorqueException(e);
298             }
299         }
300 
301         // As there might be a default database configured
302         // to map "default" onto an existing datasource, we
303         // must check, whether there _is_ really an entry for
304         // the "default" in the dsFactoryMap or not. If it is
305         // not, then add a dummy entry for the "default"
306         //
307         // Without this, you can't actually access the "default"
308         // data-source, even if you have an entry like
309         //
310         // database.default = bookstore
311         //
312         // in your Torque.properties
313         //
314         String defaultDB = getDefaultDB();
315 
316         if (dsFactoryMap.get(DEFAULT_NAME) == null
317                 && !defaultDB.equals(DEFAULT_NAME))
318         {
319             log.debug("Adding a dummy entry for "
320                     + DEFAULT_NAME + ", mapped onto " + defaultDB);
321             dsFactoryMap.put(DEFAULT_NAME, dsFactoryMap.get(defaultDB));
322         }
323     }
324 
325     /***
326      * Initialization of Torque with a properties file.
327      *
328      * @param configFile The absolute path to the configuration file.
329      * @throws TorqueException Any exceptions caught during processing will be
330      *         rethrown wrapped into a TorqueException.
331      */
332     public void init(String configFile)
333             throws TorqueException
334     {
335         log.debug("init(" + configFile + ")");
336         try
337         {
338             Configuration conf = (Configuration)
339                     new PropertiesConfiguration(configFile);
340 
341             log.debug("Config Object is " + conf);
342             init(conf);
343         }
344         catch (IOException e)
345         {
346             throw new TorqueException(e);
347         }
348     }
349 
350     /***
351      * Initialization of Torque with a properties file.
352      *
353      * @param conf The Torque configuration.
354      * @throws TorqueException Any exceptions caught during processing will be
355      *         rethrown wrapped into a TorqueException.
356      */
357     public void init(Configuration conf)
358             throws TorqueException
359     {
360         log.debug("init(" + conf + ")");
361         setConfiguration(conf);
362         initialize();
363     }
364 
365 
366     /***
367      * Creates a mapping between classes and their manager classes.
368      *
369      * The mapping is built according to settings present in
370      * properties file.  The entries should have the
371      * following form:
372      *
373      * <pre>
374      * torque.managed_class.com.mycompany.Myclass.manager= \
375      *          com.mycompany.MyManagerImpl
376      * services.managed_class.com.mycompany.Myotherclass.manager= \
377      *          com.mycompany.MyOtherManagerImpl
378      * </pre>
379      *
380      * <br>
381      *
382      * Generic ServiceBroker provides no Services.
383      *
384      * @param conf the Configuration representing the properties file
385      * @throws TorqueException Any exceptions caught during processing will be
386      *         rethrown wrapped into a TorqueException.
387      */
388     protected void initManagerMappings(Configuration conf)
389             throws TorqueException
390     {
391         int pref = Torque.MANAGER_PREFIX.length();
392         int suff = Torque.MANAGER_SUFFIX.length();
393 
394         for (Iterator it = conf.getKeys(); it.hasNext();)
395         {
396             String key = (String) it.next();
397 
398             if (key.startsWith(Torque.MANAGER_PREFIX)
399                     && key.endsWith(Torque.MANAGER_SUFFIX))
400             {
401                 String managedClassKey = key.substring(pref,
402                         key.length() - suff);
403                 if (!managers.containsKey(managedClassKey))
404                 {
405                     String managerClass = conf.getString(key);
406                     log.info("Added Manager for Class: " + managedClassKey
407                             + " -> " + managerClass);
408                     try
409                     {
410                         initManager(managedClassKey, managerClass);
411                     }
412                     catch (TorqueException e)
413                     {
414                         // the exception thrown here seems to disappear.
415                         // At least when initialized by Turbine, should find
416                         // out why, but for now make sure it is noticed.
417                         log.error("", e);
418                         e.printStackTrace();
419                         throw e;
420                     }
421                 }
422             }
423         }
424     }
425 
426     /***
427      * Initialize a manager
428      *
429      * @param name name of the manager
430      * @param className name of the manager class
431      * @throws TorqueException Any exceptions caught during processing will be
432      *         rethrown wrapped into a TorqueException.
433      */
434     private synchronized void initManager(String name, String className)
435             throws TorqueException
436     {
437         AbstractBaseManager manager = (AbstractBaseManager) managers.get(name);
438 
439         if (manager == null)
440         {
441             if (className != null && className.length() != 0)
442             {
443                 try
444                 {
445                     manager = (AbstractBaseManager)
446                             Class.forName(className).newInstance();
447                     managers.put(name, manager);
448                 }
449                 catch (Exception e)
450                 {
451                     throw new TorqueException("Could not instantiate "
452                             + "manager associated with class: "
453                             + name, e);
454                 }
455             }
456         }
457     }
458 
459     /***
460      * Determine whether Torque has already been initialized.
461      *
462      * @return true if Torque is already initialized
463      */
464     public boolean isInit()
465     {
466         return isInit;
467     }
468 
469     /***
470      * Sets the configuration for Torque and all dependencies.
471      *
472      * @param conf the Configuration
473      */
474     public void setConfiguration(Configuration conf)
475     {
476         log.debug("setConfiguration(" + conf + ")");
477         this.conf = conf;
478     }
479 
480     /***
481      * Get the configuration for this component.
482      *
483      * @return the Configuration
484      */
485     public Configuration getConfiguration()
486     {
487         log.debug("getConfiguration() = " + conf);
488         return conf;
489     }
490 
491     /***
492      * This method returns a Manager for the given name.
493      *
494      * @param name name of the manager
495      * @return a Manager
496      */
497     public AbstractBaseManager getManager(String name)
498     {
499         AbstractBaseManager m = (AbstractBaseManager) managers.get(name);
500         if (m == null)
501         {
502             log.error("No configured manager for key " + name + ".");
503         }
504         return m;
505     }
506 
507     /***
508      * This methods returns either the Manager from the configuration file,
509      * or the default one provided by the generated code.
510      *
511      * @param name name of the manager
512      * @param defaultClassName the class to use if name has not been configured
513      * @return a Manager
514      */
515     public AbstractBaseManager getManager(String name,
516             String defaultClassName)
517     {
518         AbstractBaseManager m = (AbstractBaseManager) managers.get(name);
519         if (m == null)
520         {
521             log.debug("Added late Manager mapping for Class: "
522                     + name + " -> " + defaultClassName);
523 
524             try
525             {
526                 initManager(name, defaultClassName);
527             }
528             catch (TorqueException e)
529             {
530                 log.error(e.getMessage(), e);
531             }
532 
533             // Try again now that the default manager should be in the map
534             m = (AbstractBaseManager) managers.get(name);
535         }
536 
537         return m;
538     }
539 
540     /***
541      * Shuts down the service.
542      *
543      * This method halts the IDBroker's daemon thread in all of
544      * the DatabaseMap's.
545      */
546     public synchronized void shutdown()
547     {
548         if (dbMaps != null)
549         {
550             for (Iterator it = dbMaps.values().iterator(); it.hasNext();)
551             {
552                 DatabaseMap map = (DatabaseMap) it.next();
553                 IDBroker idBroker = map.getIDBroker();
554                 if (idBroker != null)
555                 {
556                     idBroker.stop();
557                 }
558             }
559         }
560         resetConfiguration();
561     }
562 
563     /***
564      * Resets some internal configuration variables to
565      * their defaults.
566      */
567     private void resetConfiguration()
568     {
569         mapBuilders = Collections.synchronizedList(new ArrayList());
570         managers = new HashMap();
571         isInit = false;
572     }
573 
574     /***
575      * Returns the default database map information.
576      *
577      * @return A DatabaseMap.
578      * @throws TorqueException Any exceptions caught during processing will be
579      *         rethrown wrapped into a TorqueException.
580      */
581     public DatabaseMap getDatabaseMap()
582             throws TorqueException
583     {
584         return getDatabaseMap(getDefaultDB());
585     }
586 
587     /***
588      * Returns the database map information. Name relates to the name
589      * of the connection pool to associate with the map.
590      *
591      * @param name The name of the database corresponding to the
592      *        <code>DatabaseMap</code> to retrieve.
593      * @return The named <code>DatabaseMap</code>.
594      * @throws TorqueException Any exceptions caught during processing will be
595      *         rethrown wrapped into a TorqueException.
596      */
597     public DatabaseMap getDatabaseMap(String name)
598             throws TorqueException
599     {
600         if (name == null)
601         {
602             throw new TorqueException ("DatabaseMap name was null!");
603         }
604 
605         if (dbMaps == null)
606         {
607             throw new TorqueException("Torque was not initialized properly.");
608         }
609 
610         synchronized (dbMaps)
611         {
612             DatabaseMap map = (DatabaseMap) dbMaps.get(name);
613             if (map == null)
614             {
615                 // Still not there.  Create and add.
616                 map = initDatabaseMap(name);
617             }
618             return map;
619         }
620     }
621 
622     /***
623      * Creates and initializes the mape for the named database.
624      * Assumes that <code>dbMaps</code> member is sync'd.
625      *
626      * @param name The name of the database to map.
627      * @return The desired map.
628      * @throws TorqueException Any exceptions caught during processing will be
629      *         rethrown wrapped into a TorqueException.
630      */
631     private final DatabaseMap initDatabaseMap(String name)
632             throws TorqueException
633     {
634         DatabaseMap map = new DatabaseMap(name);
635 
636         // Add info about IDBroker's table.
637         setupIdTable(map);
638 
639         // Setup other ID generators for this map.
640         try
641         {
642             String key = getDatabaseProperty(name, "driver");
643             if (key == null || key.length() == 0)
644             {
645                 key = getDatabaseProperty(name, "adapter");
646             }
647             DB db = DBFactory.create(key);
648             for (int i = 0; i < IDGeneratorFactory.ID_GENERATOR_METHODS.length;
649                  i++)
650             {
651                 map.addIdGenerator(IDGeneratorFactory.ID_GENERATOR_METHODS[i],
652                         IDGeneratorFactory.create(db));
653             }
654         }
655         catch (java.lang.InstantiationException e)
656         {
657             throw new TorqueException(e);
658         }
659 
660         // Avoid possible ConcurrentModificationException by
661         // constructing a copy of dbMaps.
662         Map newMaps = new HashMap(dbMaps);
663         newMaps.put(name, map);
664         dbMaps = newMaps;
665 
666         return map;
667     }
668 
669     /***
670      * Register a MapBuilder
671      *
672      * @param className the MapBuilder
673      */
674     public void registerMapBuilder(String className)
675     {
676         mapBuilders.add(className);
677     }
678 
679     /***
680      * Returns the specified property of the given database, or the empty
681      * string if no value is set for the property.
682      *
683      * @param db   The name of the database whose property to get.
684      * @param prop The name of the property to get.
685      * @return     The property's value.
686      */
687     private String getDatabaseProperty(String db, String prop)
688     {
689         return conf.getString(new StringBuffer("database.")
690                 .append(db)
691                 .append('.')
692                 .append(prop)
693                 .toString(), "");
694     }
695 
696     /***
697      * Setup IDBroker's table information within given database map.
698      *
699      * This method should be called on all new database map to ensure that
700      * IDBroker functionality is available in all databases used by the
701      * application.
702      *
703      * @param map the DataBaseMap to setup.
704      */
705     private final void setupIdTable(DatabaseMap map)
706     {
707         map.setIdTable("ID_TABLE");
708         TableMap tMap = map.getIdTable();
709         tMap.addPrimaryKey("ID_TABLE_ID", new Integer(0));
710         tMap.addColumn("TABLE_NAME", "");
711         tMap.addColumn("NEXT_ID", new Integer(0));
712         tMap.addColumn("QUANTITY", new Integer(0));
713     }
714 
715     /***
716      * This method returns a Connection from the default pool.
717      *
718      * @return The requested connection.
719      * @throws TorqueException Any exceptions caught during processing will be
720      *         rethrown wrapped into a TorqueException.
721      */
722     public Connection getConnection()
723             throws TorqueException
724     {
725         return getConnection(getDefaultDB());
726     }
727 
728     /***
729      *
730      * @param name The database name.
731      * @return a database connection
732      * @throws TorqueException Any exceptions caught during processing will be
733      *         rethrown wrapped into a TorqueException.
734      */
735     public Connection getConnection(String name)
736             throws TorqueException
737     {
738         Connection con = null;
739         DataSourceFactory dsf = null;
740         try
741         {
742             dsf = (DataSourceFactory) dsFactoryMap.get(name);
743             con = dsf.getDataSource().getConnection();
744         }
745         catch (Exception e)
746         {
747             if (dsf == null && e instanceof NullPointerException)
748             {
749                 throw new NullPointerException(
750                         "There was no DataSourceFactory "
751                         + "configured for the connection " + name);
752             }
753             else
754             {
755                 throw new TorqueException(e);
756             }
757         }
758         return con;
759     }
760 
761     /***
762      * This method returns a Connecton using the given parameters.
763      * You should only use this method if you need user based access to the
764      * database!
765      *
766      * @param name The database name.
767      * @param username The name of the database user.
768      * @param password The password of the database user.
769      * @return A Connection.
770      * @throws TorqueException Any exceptions caught during processing will be
771      *         rethrown wrapped into a TorqueException.
772      */
773     public Connection getConnection(String name, String username,
774             String password)
775             throws TorqueException
776     {
777         Connection con = null;
778         DataSourceFactory dsf = null;
779         try
780         {
781             dsf = (DataSourceFactory) dsFactoryMap.get(name);
782             con = dsf.getDataSource().getConnection(username, password);
783         }
784         catch (Exception e)
785         {
786             if (dsf == null && e instanceof NullPointerException)
787             {
788                 throw new NullPointerException(
789                         "There was no DataSourceFactory "
790                         + "configured for the connection " + name);
791             }
792             else
793             {
794                 throw new TorqueException(e);
795             }
796         }
797         return con;
798     }
799 
800     /***
801      * Returns database adapter for a specific connection pool.
802      *
803      * @param name A pool name.
804      * @return The corresponding database adapter.
805      * @throws TorqueException Any exceptions caught during processing will be
806      *         rethrown wrapped into a TorqueException.
807      */
808     public DB getDB(String name) throws TorqueException
809     {
810         return (DB) adapterMap.get(name);
811     }
812 
813     ///////////////////////////////////////////////////////////////////////////
814 
815     /***
816      * Returns the name of the default database.
817      *
818      * @return name of the default DB
819      */
820     public String getDefaultDB()
821     {
822         if (conf == null)
823         {
824             return DEFAULT_NAME;
825         }
826         else if (defaultDBName == null)
827         {
828             // Determine default database name.
829             defaultDBName =
830                     conf.getString(Torque.DATABASE_DEFAULT, 
831                             DEFAULT_NAME).trim();
832         }
833 
834         return defaultDBName;
835     }
836 
837     /***
838      * Closes a connection.
839      *
840      * @param con A Connection to close.
841      */
842     public void closeConnection(Connection con)
843     {
844         if (con != null)
845         {
846             try
847             {
848                 con.close();
849             }
850             catch (SQLException e)
851             {
852                 log.error("Error occured while closing connection.", e);
853             }
854         }
855     }
856 }