1 package org.apache.torque;
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22 import java.sql.Connection;
23 import java.sql.SQLException;
24 import java.util.Collections;
25 import java.util.HashMap;
26 import java.util.Iterator;
27 import java.util.Map;
28
29 import org.apache.commons.configuration.Configuration;
30 import org.apache.commons.configuration.ConfigurationException;
31 import org.apache.commons.configuration.PropertiesConfiguration;
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.DataSourceFactory;
37 import org.apache.torque.manager.AbstractBaseManager;
38 import org.apache.torque.map.DatabaseMap;
39 import org.apache.torque.map.MapBuilder;
40 import org.apache.torque.oid.IDBroker;
41 import org.apache.torque.oid.IDGeneratorFactory;
42
43 /***
44 * The core of Torque's implementation. Both the classic {@link
45 * org.apache.torque.Torque} static wrapper and the {@link
46 * org.apache.torque.avalon.TorqueComponent} <a
47 * href="http://avalon.apache.org/">Avalon</a> implementation leverage
48 * this class.
49 *
50 * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a>
51 * @author <a href="mailto:magnus@handtolvur.is">Magn?s ??r Torfason</a>
52 * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a>
53 * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a>
54 * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a>
55 * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a>
56 * @author <a href="mailto:kschrader@karmalab.org">Kurt Schrader</a>
57 * @author <a href="mailto:tv@apache.org">Thomas Vandahl</a>
58 * @version $Id: TorqueInstance.java 571790 2007-09-01 12:40:44Z tv $
59 */
60 public class TorqueInstance
61 {
62 /*** Logging */
63 private static Log log = LogFactory.getLog(TorqueInstance.class);
64
65 /*** A constant for <code>default</code>. */
66 private static final String DEFAULT_NAME = "default";
67
68 /*** The db name that is specified as the default in the property file */
69 private String defaultDBName = null;
70
71 /***
72 * The Map which contains all known databases. All iterations over the map
73 * and other operations where the databaase map needs to stay
74 * in a defined state must be synchronized to this map.
75 */
76 private Map databases = Collections.synchronizedMap(new HashMap());
77
78 /*** A repository of Manager instances. */
79 private Map managers;
80
81 /*** Torque-specific configuration. */
82 private Configuration conf;
83
84 /*** flag to set to true once this class has been initialized */
85 private boolean isInit = false;
86
87 /***
88 * a flag which indicates whether the DataSourceFactory in the database
89 * named <code>DEFAULT</code> is a reference to another
90 * DataSourceFactory. This is important to know when closing the
91 * DataSourceFactories on shutdown();
92 */
93 private boolean defaultDsfIsReference = false;
94
95 /***
96 * Store mapbuilder classnames for peers that have been referenced prior
97 * to Torque being initialized. This can happen if torque om/peer objects
98 * are serialized then unserialized prior to Torque being reinitialized.
99 * This condition exists in a normal catalina restart.
100 */
101 private Map mapBuilderCache = null;
102
103 /***
104 * Creates a new instance with default configuration.
105 *
106 * @see #resetConfiguration()
107 */
108 public TorqueInstance()
109 {
110 resetConfiguration();
111 }
112
113 /***
114 * Initializes this instance of Torque.
115 *
116 * @see org.apache.stratum.lifecycle.Initializable
117 * @throws TorqueException Any exceptions caught during processing will be
118 * rethrown wrapped into a TorqueException.
119 */
120 private synchronized void initialize() throws TorqueException
121 {
122 log.debug("initialize()");
123
124 if (isInit)
125 {
126 log.debug("Multiple initializations of Torque attempted");
127 return;
128 }
129
130 if (conf == null || conf.isEmpty())
131 {
132 throw new TorqueException("Torque cannot be initialized without "
133 + "a valid configuration. Please check the log files "
134 + "for further details.");
135 }
136
137
138
139
140
141
142
143 Configuration subConf = conf.subset(Torque.TORQUE_KEY);
144 if (subConf == null || subConf.isEmpty())
145 {
146 String error = ("Invalid configuration. No keys starting with "
147 + Torque.TORQUE_KEY
148 + " found in configuration");
149 log.error(error);
150 throw new TorqueException(error);
151 }
152 setConfiguration(subConf);
153
154 initDefaultDbName(conf);
155 initAdapters(conf);
156 initDataSourceFactories(conf);
157
158
159 initManagerMappings(conf);
160
161 isInit = true;
162
163
164 synchronized (mapBuilderCache)
165 {
166 for (Iterator i = mapBuilderCache.entrySet().iterator(); i.hasNext();)
167 {
168 Map.Entry entry = (Map.Entry)i.next();
169
170 if (null == entry.getValue())
171 {
172 try
173 {
174
175 MapBuilder builder = (MapBuilder) Class.forName((String) entry.getKey()).newInstance();
176
177 if (!builder.isBuilt())
178 {
179 builder.doBuild();
180 }
181
182 entry.setValue(builder);
183 }
184 catch (Exception e)
185 {
186 throw new TorqueException(e);
187 }
188 }
189 }
190 }
191 }
192
193
194 /***
195 * Initializes the name of the default database and
196 * associates the database with the name <code>DEFAULT_NAME</code>
197 * to the default database.
198 *
199 * @param conf the configuration representing the torque section.
200 * of the properties file.
201 * @throws TorqueException if the appropriate key is not set.
202 */
203 private void initDefaultDbName(Configuration conf)
204 throws TorqueException
205 {
206
207 defaultDBName =
208 conf.getString(
209 Torque.DATABASE_KEY
210 + "."
211 + Torque.DEFAULT_KEY);
212 if (defaultDBName == null)
213 {
214 String error = "Invalid configuration: Key "
215 + Torque.TORQUE_KEY
216 + "."
217 + Torque.DATABASE_KEY
218 + "."
219 + Torque.DEFAULT_KEY
220 + " not set";
221 log.error(error);
222 throw new TorqueException(error);
223 }
224 }
225
226 /***
227 * Reads the adapter settings from the configuration and
228 * assigns the appropriate database adapters and Id Generators
229 * to the databases.
230 *
231 * @param conf the Configuration representing the torque section of the
232 * properties file
233 * @throws TorqueException Any exceptions caught during processing will be
234 * rethrown wrapped into a TorqueException.
235 */
236 private void initAdapters(Configuration conf)
237 throws TorqueException
238 {
239 log.debug("initAdapters(" + conf + ")");
240
241 Configuration c = conf.subset(Torque.DATABASE_KEY);
242 if (c == null || c.isEmpty())
243 {
244 String error = "Invalid configuration : "
245 + "No keys starting with "
246 + Torque.TORQUE_KEY
247 + "."
248 + Torque.DATABASE_KEY
249 + " found in configuration";
250 log.error(error);
251 throw new TorqueException(error);
252 }
253
254 try
255 {
256 for (Iterator it = c.getKeys(); it.hasNext();)
257 {
258 String key = (String) it.next();
259 if (key.endsWith(DB.ADAPTER_KEY)
260 || key.endsWith(DB.DRIVER_KEY))
261 {
262 String adapter = c.getString(key);
263 String handle = key.substring(0, key.indexOf('.'));
264
265 DB db;
266
267 db = DBFactory.create(adapter);
268
269
270 if (db == null)
271 {
272 String adapterClassName = c.getString(key + "." + adapter + ".className", null);
273 db = DBFactory.create(adapter, adapterClassName);
274 }
275
276 Database database = getOrCreateDatabase(handle);
277
278
279 database.setAdapter(db);
280 log.debug("Adding " + adapter + " -> "
281 + handle + " as Adapter");
282
283
284
285
286
287
288
289 getDatabaseMap(handle);
290 for (int i = 0;
291 i < IDGeneratorFactory.ID_GENERATOR_METHODS.length;
292 i++)
293 {
294 database.addIdGenerator(
295 IDGeneratorFactory.ID_GENERATOR_METHODS[i],
296 IDGeneratorFactory.create(db, handle));
297 }
298 }
299 }
300 }
301 catch (InstantiationException e)
302 {
303 log.error("Error creating a database adapter instance", e);
304 throw new TorqueException(e);
305 }
306 catch (TorqueException e)
307 {
308 log.error("Error reading configuration seeking database "
309 + "adapters", e);
310 throw new TorqueException(e);
311 }
312
313
314 Database defaultDatabase
315 = (Database) databases.get(Torque.getDefaultDB());
316 if (defaultDatabase == null
317 || defaultDatabase.getAdapter() == null)
318 {
319 String error = "Invalid configuration : "
320 + "No adapter definition found for default DB "
321 + "An adapter must be defined under "
322 + Torque.TORQUE_KEY
323 + "."
324 + Torque.DATABASE_KEY
325 + "."
326 + Torque.getDefaultDB()
327 + "."
328 + DB.ADAPTER_KEY;
329 log.error(error);
330 throw new TorqueException(error);
331 }
332 }
333
334 /***
335 * Reads the settings for the DataSourceFactories from the configuration
336 * and creates and/or cinfigures the DataSourceFactories for the databases.
337 * If no DataSorceFactory is assigned to the database with the name
338 * <code>DEFAULT_NAME</code>, a reference to the DataSourceFactory
339 * of the default daztabase is made from the database with the name
340 * <code>DEFAULT_NAME</code>.
341 *
342 * @param conf the Configuration representing the properties file
343 * @throws TorqueException Any exceptions caught during processing will be
344 * rethrown wrapped into a TorqueException.
345 */
346 private void initDataSourceFactories(Configuration conf)
347 throws TorqueException
348 {
349 log.debug("initDataSourceFactories(" + conf + ")");
350
351 Configuration c = conf.subset(DataSourceFactory.DSFACTORY_KEY);
352 if (c == null || c.isEmpty())
353 {
354 String error = "Invalid configuration: "
355 + "No keys starting with "
356 + Torque.TORQUE_KEY
357 + "."
358 + DataSourceFactory.DSFACTORY_KEY
359 + " found in configuration";
360 log.error(error);
361 throw new TorqueException(error);
362 }
363
364 try
365 {
366 for (Iterator it = c.getKeys(); it.hasNext();)
367 {
368 String key = (String) it.next();
369 if (key.endsWith(DataSourceFactory.FACTORY_KEY))
370 {
371 String classname = c.getString(key);
372 String handle = key.substring(0, key.indexOf('.'));
373 log.debug("handle: " + handle
374 + " DataSourceFactory: " + classname);
375 Class dsfClass = Class.forName(classname);
376 DataSourceFactory dsf =
377 (DataSourceFactory) dsfClass.newInstance();
378 dsf.initialize(c.subset(handle));
379
380 Database database = getOrCreateDatabase(handle);
381 database.setDataSourceFactory(dsf);
382 }
383 }
384 }
385 catch (RuntimeException e)
386 {
387 log.error("Runtime Error reading adapter configuration", e);
388 throw new TorqueRuntimeException(e);
389 }
390 catch (Exception e)
391 {
392 log.error("Error reading adapter configuration", e);
393 throw new TorqueException(e);
394 }
395
396 Database defaultDatabase
397 = (Database) databases.get(defaultDBName);
398 if (defaultDatabase == null
399 || defaultDatabase.getDataSourceFactory() == null)
400 {
401 String error = "Invalid configuration : "
402 + "No DataSourceFactory definition for default DB found. "
403 + "A DataSourceFactory must be defined under the key"
404 + Torque.TORQUE_KEY
405 + "."
406 + DataSourceFactory.DSFACTORY_KEY
407 + "."
408 + defaultDBName
409 + "."
410 + DataSourceFactory.FACTORY_KEY;
411 log.error(error);
412 throw new TorqueException(error);
413 }
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429 {
430 Database databaseInfoForKeyDefault
431 = getOrCreateDatabase(DEFAULT_NAME);
432 if ((!defaultDBName.equals(DEFAULT_NAME))
433 && databaseInfoForKeyDefault.getDataSourceFactory() == null)
434 {
435 log.debug("Adding the DatasourceFactory and DatabaseAdapter from database "
436 + defaultDBName
437 + " onto database " + DEFAULT_NAME);
438 databaseInfoForKeyDefault.setDataSourceFactory(
439 defaultDatabase.getDataSourceFactory());
440 databaseInfoForKeyDefault.setAdapter(
441 defaultDatabase.getAdapter());
442
443 this.defaultDsfIsReference = true;
444 }
445 }
446
447 }
448
449 /***
450 * Initialization of Torque with a properties file.
451 *
452 * @param configFile The absolute path to the configuration file.
453 * @throws TorqueException Any exceptions caught during processing will be
454 * rethrown wrapped into a TorqueException.
455 */
456 public void init(String configFile)
457 throws TorqueException
458 {
459 log.debug("init(" + configFile + ")");
460 try
461 {
462 Configuration configuration
463 = new PropertiesConfiguration(configFile);
464
465 log.debug("Config Object is " + configuration);
466 init(configuration);
467 }
468 catch (ConfigurationException e)
469 {
470 throw new TorqueException(e);
471 }
472 }
473
474 /***
475 * Initialization of Torque with a Configuration object.
476 *
477 * @param conf The Torque configuration.
478 * @throws TorqueException Any exceptions caught during processing will be
479 * rethrown wrapped into a TorqueException.
480 */
481 public synchronized void init(Configuration conf)
482 throws TorqueException
483 {
484 log.debug("init(" + conf + ")");
485 setConfiguration(conf);
486 initialize();
487 }
488
489
490 /***
491 * Creates a mapping between classes and their manager classes.
492 *
493 * The mapping is built according to settings present in
494 * properties file. The entries should have the
495 * following form:
496 *
497 * <pre>
498 * torque.managed_class.com.mycompany.Myclass.manager= \
499 * com.mycompany.MyManagerImpl
500 * services.managed_class.com.mycompany.Myotherclass.manager= \
501 * com.mycompany.MyOtherManagerImpl
502 * </pre>
503 *
504 * <br>
505 *
506 * Generic ServiceBroker provides no Services.
507 *
508 * @param conf the Configuration representing the properties file
509 * @throws TorqueException Any exceptions caught during processing will be
510 * rethrown wrapped into a TorqueException.
511 */
512 protected void initManagerMappings(Configuration conf)
513 throws TorqueException
514 {
515 int pref = Torque.MANAGER_PREFIX.length();
516 int suff = Torque.MANAGER_SUFFIX.length();
517
518 for (Iterator it = conf.getKeys(); it.hasNext();)
519 {
520 String key = (String) it.next();
521
522 if (key.startsWith(Torque.MANAGER_PREFIX)
523 && key.endsWith(Torque.MANAGER_SUFFIX))
524 {
525 String managedClassKey = key.substring(pref,
526 key.length() - suff);
527 if (!managers.containsKey(managedClassKey))
528 {
529 String managerClass = conf.getString(key);
530 log.info("Added Manager for Class: " + managedClassKey
531 + " -> " + managerClass);
532 try
533 {
534 initManager(managedClassKey, managerClass);
535 }
536 catch (TorqueException e)
537 {
538
539
540
541 log.error("", e);
542 e.printStackTrace();
543 throw e;
544 }
545 }
546 }
547 }
548 }
549
550 /***
551 * Initialize a manager
552 *
553 * @param name name of the manager
554 * @param className name of the manager class
555 * @throws TorqueException Any exceptions caught during processing will be
556 * rethrown wrapped into a TorqueException.
557 */
558 private synchronized void initManager(String name, String className)
559 throws TorqueException
560 {
561 AbstractBaseManager manager = (AbstractBaseManager) managers.get(name);
562
563 if (manager == null)
564 {
565 if (className != null && className.length() != 0)
566 {
567 try
568 {
569 manager = (AbstractBaseManager)
570 Class.forName(className).newInstance();
571 managers.put(name, manager);
572 }
573 catch (Exception e)
574 {
575 throw new TorqueException("Could not instantiate "
576 + "manager associated with class: "
577 + name, e);
578 }
579 }
580 }
581 }
582
583 /***
584 * Determine whether Torque has already been initialized.
585 *
586 * @return true if Torque is already initialized
587 */
588 public boolean isInit()
589 {
590 return isInit;
591 }
592
593 /***
594 * Sets the configuration for Torque and all dependencies.
595 * The prefix <code>TORQUE_KEY</code> needs to be removed from the
596 * configuration keys for the provided configuration.
597 *
598 * @param conf the Configuration.
599 */
600 public void setConfiguration(Configuration conf)
601 {
602 log.debug("setConfiguration(" + conf + ")");
603 this.conf = conf;
604 }
605
606 /***
607 * Get the configuration for this component.
608 *
609 * @return the Configuration
610 */
611 public Configuration getConfiguration()
612 {
613 log.debug("getConfiguration() = " + conf);
614 return conf;
615 }
616
617 /***
618 * This method returns a Manager for the given name.
619 *
620 * @param name name of the manager
621 * @return a Manager
622 */
623 public AbstractBaseManager getManager(String name)
624 {
625 AbstractBaseManager m = (AbstractBaseManager) managers.get(name);
626 if (m == null)
627 {
628 log.error("No configured manager for key " + name + ".");
629 }
630 return m;
631 }
632
633 /***
634 * This methods returns either the Manager from the configuration file,
635 * or the default one provided by the generated code.
636 *
637 * @param name name of the manager
638 * @param defaultClassName the class to use if name has not been configured
639 * @return a Manager
640 */
641 public AbstractBaseManager getManager(String name,
642 String defaultClassName)
643 {
644 AbstractBaseManager m = (AbstractBaseManager) managers.get(name);
645 if (m == null)
646 {
647 log.debug("Added late Manager mapping for Class: "
648 + name + " -> " + defaultClassName);
649
650 try
651 {
652 initManager(name, defaultClassName);
653 }
654 catch (TorqueException e)
655 {
656 log.error(e.getMessage(), e);
657 }
658
659
660 m = (AbstractBaseManager) managers.get(name);
661 }
662
663 return m;
664 }
665
666 /***
667 * Shuts down the service.
668 *
669 * This method halts the IDBroker's daemon thread in all of
670 * the DatabaseMap's. It also closes all SharedPoolDataSourceFactories
671 * and PerUserPoolDataSourceFactories initialized by Torque.
672 * @exception TorqueException if a DataSourceFactory could not be closed
673 * cleanly. Only the first exception is rethrown, any following
674 * exceptions are logged but ignored.
675 */
676 public synchronized void shutdown()
677 throws TorqueException
678 {
679
680 synchronized (databases)
681 {
682 for (Iterator it = databases.values().iterator(); it.hasNext();)
683 {
684 Database database = (Database) it.next();
685 IDBroker idBroker = database.getIDBroker();
686 if (idBroker != null)
687 {
688 idBroker.stop();
689 }
690 }
691 }
692
693
694 synchronized (managers)
695 {
696 for (Iterator it = managers.entrySet().iterator(); it.hasNext();)
697 {
698 Map.Entry mentry = (Map.Entry)it.next();
699
700 AbstractBaseManager manager = (AbstractBaseManager)mentry.getValue();
701 manager.dispose();
702 it.remove();
703 }
704 }
705
706
707 TorqueException exception = null;
708 synchronized (databases)
709 {
710 for (Iterator it = databases.keySet().iterator(); it.hasNext();)
711 {
712 Object databaseKey = it.next();
713
714 Database database
715 = (Database) databases.get(databaseKey);
716 if (DEFAULT_NAME.equals(databaseKey) && defaultDsfIsReference)
717 {
718
719
720
721
722 database.setDataSourceFactory(null);
723 break;
724 }
725
726 try
727 {
728 DataSourceFactory dataSourceFactory
729 = database.getDataSourceFactory();
730 if (dataSourceFactory != null)
731 {
732 dataSourceFactory.close();
733 database.setDataSourceFactory(null);
734 }
735 }
736 catch (TorqueException e)
737 {
738 log.error("Error while closing the DataSourceFactory "
739 + databaseKey,
740 e);
741 if (exception == null)
742 {
743 exception = e;
744 }
745 }
746 }
747 }
748 if (exception != null)
749 {
750 throw exception;
751 }
752 resetConfiguration();
753 }
754
755 /***
756 * Resets some internal configuration variables to
757 * their defaults.
758 */
759 private void resetConfiguration()
760 {
761 mapBuilderCache = Collections.synchronizedMap(new HashMap());
762 managers = new HashMap();
763 isInit = false;
764 }
765
766 /***
767 * Returns the default database map information.
768 *
769 * @return A DatabaseMap.
770 * @throws TorqueException Any exceptions caught during processing will be
771 * rethrown wrapped into a TorqueException.
772 */
773 public DatabaseMap getDatabaseMap()
774 throws TorqueException
775 {
776 return getDatabaseMap(getDefaultDB());
777 }
778
779 /***
780 * Returns the database map information. Name relates to the name
781 * of the connection pool to associate with the map.
782 *
783 * @param name The name of the database corresponding to the
784 * <code>DatabaseMap</code> to retrieve.
785 * @return The named <code>DatabaseMap</code>.
786 * @throws TorqueException Any exceptions caught during processing will be
787 * rethrown wrapped into a TorqueException.
788 */
789 public DatabaseMap getDatabaseMap(String name)
790 throws TorqueException
791 {
792 if (name == null)
793 {
794 throw new TorqueException ("DatabaseMap name was null!");
795 }
796
797 Database database = getOrCreateDatabase(name);
798 return database.getDatabaseMap();
799 }
800
801 /***
802 * Get the registered MapBuilders
803 *
804 * @return the MapBuilder cache
805 *
806 */
807 public Map getMapBuilders()
808 {
809 return mapBuilderCache;
810 }
811
812 /***
813 * Register a MapBuilder
814 *
815 * @param className the MapBuilder
816 */
817 public void registerMapBuilder(String className)
818 {
819 mapBuilderCache.put(className, null);
820 }
821
822 /***
823 * Register a MapBuilder
824 *
825 * @param builder the instance of the MapBuilder
826 *
827 */
828 public void registerMapBuilder(MapBuilder builder)
829 {
830 mapBuilderCache.put(builder.getClass().getName(), builder);
831 }
832
833 /***
834 * Get a MapBuilder
835 *
836 * @param className of the MapBuilder
837 * @return A MapBuilder, not null
838 * @throws TorqueException if the Map Builder cannot be instantiated
839 *
840 */
841 public MapBuilder getMapBuilder(String className)
842 throws TorqueException
843 {
844 try
845 {
846 MapBuilder mb = (MapBuilder)mapBuilderCache.get(className);
847
848 if (mb == null)
849 {
850 mb = (MapBuilder) Class.forName(className).newInstance();
851
852 mapBuilderCache.put(className, mb);
853 }
854
855 if (mb.isBuilt())
856 {
857 return mb;
858 }
859
860 try
861 {
862 mb.doBuild();
863 }
864 catch (Exception e)
865 {
866
867 mapBuilderCache.remove(className);
868 throw e;
869 }
870
871 return mb;
872 }
873 catch (Exception e)
874 {
875 log.error("getMapBuilder failed trying to instantiate: "
876 + className, e);
877 throw new TorqueException(e);
878 }
879 }
880
881 /***
882 * This method returns a Connection from the default pool.
883 *
884 * @return The requested connection, never null.
885 * @throws TorqueException Any exceptions caught during processing will be
886 * rethrown wrapped into a TorqueException.
887 */
888 public Connection getConnection()
889 throws TorqueException
890 {
891 return getConnection(getDefaultDB());
892 }
893
894 /***
895 * Returns a database connection to the database with the key
896 * <code>name</code>.
897 * @param name The database name.
898 * @return a database connection, never null.
899 * @throws TorqueException If no DataSourceFactory is configured for the
900 * named database, the connection information is wrong, or the
901 * connection cannot be returned for any other reason.
902 */
903 public Connection getConnection(String name)
904 throws TorqueException
905 {
906 if (!Torque.isInit())
907 {
908 throw new TorqueException("Torque is not initialized");
909 }
910 try
911 {
912 return getDatabase(name)
913 .getDataSourceFactory()
914 .getDataSource()
915 .getConnection();
916 }
917 catch (SQLException se)
918 {
919 throw new TorqueException(se);
920 }
921 }
922
923 /***
924 * Returns the DataSourceFactory for the database with the name
925 * <code>name</code>.
926 *
927 * @param name The name of the database to get the DSF for.
928 * @return A DataSourceFactory object, never null.
929 * @throws TorqueException if Torque is not initiliaized, or
930 * no DatasourceFactory is configured for the given name.
931 */
932 public DataSourceFactory getDataSourceFactory(String name)
933 throws TorqueException
934 {
935 Database database = getDatabase(name);
936
937 DataSourceFactory dsf = null;
938 if (database != null)
939 {
940 dsf = database.getDataSourceFactory();
941 }
942
943 if (dsf == null)
944 {
945 throw new TorqueException(
946 "There was no DataSourceFactory "
947 + "configured for the connection " + name);
948 }
949
950 return dsf;
951 }
952
953 /***
954 * This method returns a Connection using the given parameters.
955 * You should only use this method if you need user based access to the
956 * database!
957 *
958 * @param name The database name.
959 * @param username The name of the database user.
960 * @param password The password of the database user.
961 * @return A Connection.
962 * @throws TorqueException Any exceptions caught during processing will be
963 * rethrown wrapped into a TorqueException.
964 */
965 public Connection getConnection(String name, String username,
966 String password)
967 throws TorqueException
968 {
969 if (!Torque.isInit())
970 {
971 throw new TorqueException("Torque is not initialized");
972 }
973 try
974 {
975 return getDataSourceFactory(name)
976 .getDataSource().getConnection(username, password);
977 }
978 catch (SQLException se)
979 {
980 throw new TorqueException(se);
981 }
982 }
983
984 /***
985 * Returns the database adapter for a specific database.
986 *
987 * @param name the name of the database to get the adapter for.
988 * @return The corresponding database adapter, or null if no database
989 * adapter is defined for the given database.
990 * @throws TorqueException Any exceptions caught during processing will be
991 * rethrown wrapped into a TorqueException.
992 */
993 public DB getDB(String name) throws TorqueException
994 {
995 Database database = getDatabase(name);
996 if (database == null)
997 {
998 return null;
999 }
1000 return database.getAdapter();
1001 }
1002
1003
1004
1005 /***
1006 * Returns the name of the default database.
1007 *
1008 * @return name of the default DB, or null if Torque is not initialized yet
1009 */
1010 public String getDefaultDB()
1011 {
1012 return defaultDBName;
1013 }
1014
1015 /***
1016 * Closes a connection.
1017 *
1018 * @param con A Connection to close.
1019 */
1020 public void closeConnection(Connection con)
1021 {
1022 if (con != null)
1023 {
1024 try
1025 {
1026 con.close();
1027 }
1028 catch (SQLException e)
1029 {
1030 log.error("Error occured while closing connection.", e);
1031 }
1032 }
1033 }
1034
1035 /***
1036 * Sets the current schema for a database connection
1037 *
1038 * @param name The database name.
1039 * @param schema The current schema name.
1040 * @throws TorqueException Any exceptions caught during processing will be
1041 * rethrown wrapped into a TorqueException.
1042 */
1043 public void setSchema(String name, String schema)
1044 throws TorqueException
1045 {
1046 getOrCreateDatabase(name).setSchema(schema);
1047 }
1048
1049 /***
1050 * This method returns the current schema for a database connection
1051 *
1052 * @param name The database name.
1053 * @return The current schema name. Null means, no schema has been set.
1054 * @throws TorqueException Any exceptions caught during processing will be
1055 * rethrown wrapped into a TorqueException.
1056 */
1057 public String getSchema(String name)
1058 throws TorqueException
1059 {
1060 Database database = getDatabase(name);
1061 if (database == null)
1062 {
1063 return null;
1064 }
1065 return database.getSchema();
1066 }
1067
1068 /***
1069 * Returns the database for the key <code>databaseName</code>.
1070 *
1071 * @param databaseName the key to get the database for.
1072 * @return the database for the specified key, or null if the database
1073 * does not exist.
1074 * @throws TorqueException if Torque is not yet initialized.
1075 */
1076 public Database getDatabase(String databaseName) throws TorqueException
1077 {
1078 if (!isInit())
1079 {
1080 throw new TorqueException("Torque is not initialized.");
1081 }
1082 return (Database) databases.get(databaseName);
1083 }
1084
1085 /***
1086 * Returns a Map containing all Databases registered to Torque.
1087 * The key of the Map is the name of the database, and the value is the
1088 * database instance. <br/>
1089 * Note that in the very special case where a new database which
1090 * is not configured in Torque's configuration gets known to Torque
1091 * at a later time, the returned map may change, and there is no way to
1092 * protect you against this.
1093 *
1094 * @return a Map containing all Databases known to Torque, never null.
1095 * @throws TorqueException if Torque is not yet initialized.
1096 */
1097 public Map getDatabases() throws TorqueException
1098 {
1099 if (!isInit())
1100 {
1101 throw new TorqueException("Torque is not initialized.");
1102 }
1103 return Collections.unmodifiableMap(databases);
1104 }
1105
1106 /***
1107 * Returns the database for the key <code>databaseName</code>.
1108 * If no database is associated to the specified key,
1109 * a new database is created, mapped to the specified key, and returned.
1110 *
1111 * @param databaseName the key to get the database for.
1112 * @return the database associated with specified key, or the newly created
1113 * database, never null.
1114 */
1115 public Database getOrCreateDatabase(String databaseName)
1116 {
1117 synchronized (databases)
1118 {
1119 Database result = (Database) databases.get(databaseName);
1120 if (result == null)
1121 {
1122 result = new Database(databaseName);
1123 databases.put(databaseName, result);
1124 }
1125 return result;
1126 }
1127 }
1128 }