View Javadoc

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