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