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.HashSet;
27 import java.util.Iterator;
28 import java.util.Map;
29 import java.util.Set;
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.lang.StringUtils;
35 import org.apache.commons.logging.Log;
36 import org.apache.commons.logging.LogFactory;
37 import org.apache.torque.adapter.Adapter;
38 import org.apache.torque.adapter.AdapterFactory;
39 import org.apache.torque.adapter.IDMethod;
40 import org.apache.torque.dsfactory.DataSourceFactory;
41 import org.apache.torque.manager.AbstractBaseManager;
42 import org.apache.torque.map.DatabaseMap;
43 import org.apache.torque.oid.IDBroker;
44 import org.apache.torque.oid.IDGeneratorFactory;
45 import org.apache.torque.om.Persistent;
46 import org.apache.torque.util.Transaction;
47 import org.apache.torque.util.TransactionManager;
48 import org.apache.torque.util.TransactionManagerImpl;
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67 public class TorqueInstance
68 {
69
70 private static Log log = LogFactory.getLog(TorqueInstance.class);
71
72
73 private static final String DEFAULT_NAME = "default";
74
75
76 private String defaultDBName = null;
77
78
79
80
81
82
83 private final Map<String, Database> databases
84 = Collections.synchronizedMap(new HashMap<String, Database>());
85
86
87 private Map<String, AbstractBaseManager<?>> managers;
88
89
90 private final Set<IDBroker> idBrokers = new HashSet<IDBroker>();
91
92
93 private Configuration conf;
94
95
96 private boolean isInit = false;
97
98
99
100
101
102
103
104 private boolean defaultDsfIsReference = false;
105
106
107
108
109
110
111 public TorqueInstance()
112 {
113 resetConfiguration();
114 }
115
116
117
118
119
120
121
122 private synchronized void initialize() throws TorqueException
123 {
124 log.debug("initialize()");
125
126 if (isInit)
127 {
128 throw new TorqueException(
129 "Multiple initializations of Torque attempted");
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 initTransactionManager(conf);
140 initDefaultDbName(conf);
141 initDataSourceFactories(conf);
142 initSchemata(conf);
143 initAdapters(conf);
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159 {
160 Database defaultDatabase = databases.get(defaultDBName);
161 Database databaseInfoForKeyDefault
162 = getOrCreateDatabase(DEFAULT_NAME);
163 if ((!defaultDBName.equals(DEFAULT_NAME))
164 && databaseInfoForKeyDefault.getDataSourceFactory() == null)
165 {
166 log.debug("Adding the DatasourceFactory and DatabaseAdapter "
167 + "from database "
168 + defaultDBName
169 + " onto database " + DEFAULT_NAME);
170 databaseInfoForKeyDefault.setDataSourceFactory(
171 defaultDatabase.getDataSourceFactory());
172 databaseInfoForKeyDefault.setAdapter(
173 defaultDatabase.getAdapter());
174
175 this.defaultDsfIsReference = true;
176 }
177 }
178
179
180 initManagerMappings(conf);
181 startIdBrokers();
182
183 isInit = true;
184 }
185
186
187
188
189
190
191
192
193
194
195
196 private void initTransactionManager(Configuration conf)
197 throws TorqueException
198 {
199 log.debug("initTransactionManager(" + conf + ")");
200
201 String transactionManagerClassName =
202 conf.getString(Torque.TRANSACTION_MANAGER_KEY);
203 TransactionManager transactionManager;
204 if (StringUtils.isEmpty(transactionManagerClassName))
205 {
206 if (log.isTraceEnabled())
207 {
208 log.trace("Configuration key " + Torque.TORQUE_KEY + "."
209 + Torque.TRANSACTION_MANAGER_KEY
210 + " not set, using default transaction manager "
211 + TransactionManagerImpl.class.getName());
212 }
213 transactionManager = new TransactionManagerImpl();
214 }
215 else
216 {
217 try
218 {
219 Class<?> transactionManagerClass
220 = Class.forName(transactionManagerClassName);
221 transactionManager = (TransactionManager)
222 transactionManagerClass.newInstance();
223 if (log.isTraceEnabled())
224 {
225 log.trace("Using transaction manager "
226 + transactionManager.getClass().getName());
227 }
228 }
229 catch (Exception e)
230 {
231 log.error("Error handling transaction manager configuration",
232 e);
233 throw new TorqueException(e);
234 }
235 }
236 Transaction.setTransactionManager(transactionManager);
237 }
238
239
240
241
242
243
244
245
246
247
248
249
250 private void initDefaultDbName(Configuration conf)
251 throws TorqueException
252 {
253 log.debug("initDefaultDbName(" + conf + ")");
254
255
256 defaultDBName =
257 conf.getString(
258 Torque.DATABASE_KEY
259 + "."
260 + Torque.DEFAULT_KEY);
261 if (defaultDBName == null)
262 {
263 String error = "Invalid configuration: Key "
264 + Torque.TORQUE_KEY
265 + "."
266 + Torque.DATABASE_KEY
267 + "."
268 + Torque.DEFAULT_KEY
269 + " not set";
270 log.error(error);
271 throw new TorqueException(error);
272 }
273 }
274
275
276
277
278
279
280
281
282
283
284
285
286 private void initAdapters(Configuration conf)
287 throws TorqueException
288 {
289 log.debug("initAdapters(" + conf + ")");
290
291 Configuration c = conf.subset(Torque.DATABASE_KEY);
292 if (c == null || c.isEmpty())
293 {
294 String error = "Invalid configuration : "
295 + "No keys starting with "
296 + Torque.TORQUE_KEY
297 + "."
298 + Torque.DATABASE_KEY
299 + " found in configuration";
300 log.error(error);
301 throw new TorqueException(error);
302 }
303
304 try
305 {
306 for (Iterator<?> it = c.getKeys(); it.hasNext();)
307 {
308 String key = (String) it.next();
309 if (key.endsWith(Adapter.ADAPTER_KEY)
310 || key.endsWith(Adapter.DRIVER_KEY))
311 {
312 String adapterKey = c.getString(key);
313 String handle = key.substring(0, key.indexOf('.'));
314
315 Database database = getOrCreateDatabase(handle);
316 Adapter adapter = null;
317
318 if (StringUtils.equals(
319 Adapter.AUTODETECT_ADAPTER,
320 adapterKey))
321 {
322 Connection con = null;
323 try
324 {
325 con = database.getDataSourceFactory()
326 .getDataSource().getConnection();
327 adapter = AdapterFactory.autoDetectAdapter(con);
328 }
329 catch (SQLException e)
330 {
331 log.error(
332 "Could not get product information from JDBC",
333 e);
334 }
335 finally
336 {
337 closeConnection(con);
338 }
339 }
340 else
341 {
342 adapter = AdapterFactory.create(adapterKey);
343 }
344
345
346 if (adapter == null)
347 {
348 String adapterClassName = c.getString(
349 key + "." + adapterKey + ".className", null);
350 adapter = AdapterFactory.create(
351 adapterKey,
352 adapterClassName);
353 }
354
355
356 database.setAdapter(adapter);
357 log.debug("Adding " + adapterKey + " -> "
358 + handle + " as Adapter");
359
360
361 for (IDMethod idMethod
362 : IDGeneratorFactory.ID_GENERATOR_METHODS)
363 {
364 database.addIdGenerator(
365 idMethod,
366 IDGeneratorFactory.create(adapter, handle));
367 }
368 }
369 }
370 }
371 catch (InstantiationException e)
372 {
373 log.error("Error creating a database adapter instance", e);
374 throw new TorqueException(e);
375 }
376
377
378 Database defaultDatabase
379 = databases.get(getDefaultDB());
380 if (defaultDatabase == null
381 || defaultDatabase.getAdapter() == null)
382 {
383 String error = "Invalid configuration : "
384 + "No adapter definition found for default DB "
385 + "An adapter must be defined under "
386 + Torque.TORQUE_KEY
387 + "."
388 + Torque.DATABASE_KEY
389 + "."
390 + getDefaultDB()
391 + "."
392 + Adapter.ADAPTER_KEY;
393 log.error(error);
394 throw new TorqueException(error);
395 }
396 }
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412 private void initDataSourceFactories(Configuration conf)
413 throws TorqueException
414 {
415 log.debug("initDataSourceFactories(" + conf + ")");
416
417 Configuration c = conf.subset(DataSourceFactory.DSFACTORY_KEY);
418 if (c == null || c.isEmpty())
419 {
420 String error = "Invalid configuration: "
421 + "No keys starting with "
422 + Torque.TORQUE_KEY
423 + "."
424 + DataSourceFactory.DSFACTORY_KEY
425 + " found in configuration";
426 log.error(error);
427 throw new TorqueException(error);
428 }
429
430
431 try
432 {
433 for (Iterator<?> it = c.getKeys(); it.hasNext();)
434 {
435 String key = (String) it.next();
436 if (key.endsWith(DataSourceFactory.FACTORY_KEY))
437 {
438 String classname = c.getString(key);
439 String handle = key.substring(0, key.indexOf('.'));
440 log.debug("handle: " + handle
441 + " DataSourceFactory: " + classname);
442 Class<?> dsfClass = Class.forName(classname);
443 DataSourceFactory dsf =
444 (DataSourceFactory) dsfClass.newInstance();
445 Configuration subConf = c.subset(handle);
446 dsf.initialize(subConf);
447
448 Database database = getOrCreateDatabase(handle);
449 database.setDataSourceFactory(dsf);
450
451
452
453 String schema = subConf.getString(Torque.SCHEMA_KEY, null);
454 if (!StringUtils.isEmpty(schema))
455 {
456 log.warn("Defining the schema in the dsfactory "
457 + "is deprecated, please configure it "
458 + "via the config key "
459 + "torque.database.${databasename}.schema");
460 }
461 database.setSchema(schema);
462 }
463 }
464 }
465 catch (RuntimeException e)
466 {
467 log.error("Error reading DataSourceFactory configuration", e);
468 throw new TorqueRuntimeException(e);
469 }
470 catch (Exception e)
471 {
472 log.error("Error reading DataSourceFactory configuration", e);
473 throw new TorqueException(e);
474 }
475
476 Database defaultDatabase
477 = databases.get(defaultDBName);
478 if (defaultDatabase == null
479 || defaultDatabase.getDataSourceFactory() == null)
480 {
481 String error = "Invalid configuration : "
482 + "No DataSourceFactory definition for default DB found. "
483 + "A DataSourceFactory must be defined under the key"
484 + Torque.TORQUE_KEY
485 + "."
486 + DataSourceFactory.DSFACTORY_KEY
487 + "."
488 + defaultDBName
489 + "."
490 + DataSourceFactory.FACTORY_KEY;
491 log.error(error);
492 throw new TorqueException(error);
493 }
494 }
495
496
497
498
499
500
501
502
503
504
505 private void initSchemata(Configuration conf)
506 throws TorqueException
507 {
508 log.debug("initSchemata(" + conf + ")");
509
510
511 Configuration c = conf.subset(Torque.DATABASE_KEY);
512 if (c == null || c.isEmpty())
513 {
514 String error = "Invalid configuration: "
515 + "No keys starting with "
516 + Torque.TORQUE_KEY
517 + "."
518 + Torque.DATABASE_KEY
519 + " found in configuration";
520 log.error(error);
521 throw new TorqueException(error);
522 }
523 try
524 {
525 for (Iterator<?> it = c.getKeys(); it.hasNext();)
526 {
527 String key = (String) it.next();
528 int indexOfDot = key.indexOf('.');
529 if (indexOfDot == -1)
530 {
531 continue;
532 }
533 String handle = key.substring(0, indexOfDot);
534
535 log.debug("database handle: " + handle);
536 Configuration subConf = c.subset(handle);
537
538 Database database = getOrCreateDatabase(handle);
539
540 String schema = subConf.getString(Torque.SCHEMA_KEY, null);
541
542
543 if (StringUtils.isEmpty(schema))
544 {
545 schema = database.getSchema();
546 }
547 if (StringUtils.isEmpty(schema))
548 {
549 schema = conf.getString(
550 Torque.DEFAULT_SCHEMA_KEY,
551 null);
552 }
553 database.setSchema(schema);
554 }
555 }
556 catch (RuntimeException e)
557 {
558 log.error("Error reading DataSourceFactory configuration", e);
559 throw new TorqueRuntimeException(e);
560 }
561 catch (Exception e)
562 {
563 log.error("Error reading DataSourceFactory configuration", e);
564 throw new TorqueException(e);
565 }
566
567 }
568
569
570
571
572
573
574
575
576
577 public void init(String configFile)
578 throws TorqueException
579 {
580 log.debug("init(" + configFile + ")");
581 try
582 {
583 Configuration configuration
584 = new PropertiesConfiguration(configFile);
585
586 log.debug("Config Object is " + configuration);
587 init(configuration);
588 }
589 catch (ConfigurationException e)
590 {
591 throw new TorqueException(e);
592 }
593 }
594
595
596
597
598
599
600
601
602
603 public synchronized void init(Configuration conf)
604 throws TorqueException
605 {
606 log.debug("init(" + conf + ")");
607 setConfiguration(conf);
608 initialize();
609 }
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634 protected synchronized void initManagerMappings(Configuration conf)
635 throws TorqueException
636 {
637 int pref = Torque.MANAGER_PREFIX.length();
638 int suff = Torque.MANAGER_SUFFIX.length();
639
640 for (Iterator<?> it = conf.getKeys(); it.hasNext();)
641 {
642 String key = (String) it.next();
643
644 if (key.startsWith(Torque.MANAGER_PREFIX)
645 && key.endsWith(Torque.MANAGER_SUFFIX))
646 {
647 String managedClassKey = key.substring(pref,
648 key.length() - suff);
649 if (!managers.containsKey(managedClassKey))
650 {
651 String managerClass = conf.getString(key);
652 log.info("Added Manager for Class: " + managedClassKey
653 + " -> " + managerClass);
654 try
655 {
656 initManager(managedClassKey, managerClass);
657 }
658 catch (TorqueException e)
659 {
660
661
662
663 log.error("", e);
664 e.printStackTrace();
665 throw e;
666 }
667 }
668 }
669 }
670 }
671
672
673
674
675
676
677
678
679
680 private synchronized void initManager(String name, String className)
681 throws TorqueException
682 {
683 AbstractBaseManager<?> manager = managers.get(name);
684
685 if (manager == null)
686 {
687 if (className != null && className.length() != 0)
688 {
689 try
690 {
691 manager = (AbstractBaseManager<?>)
692 Class.forName(className).newInstance();
693 managers.put(name, manager);
694 }
695 catch (Exception e)
696 {
697 throw new TorqueException("Could not instantiate "
698 + "manager associated with class: "
699 + name, e);
700 }
701 }
702 }
703 }
704
705
706
707
708 private void startIdBrokers()
709 {
710 for (IDBroker idBroker : idBrokers)
711 {
712 idBroker.start();
713 }
714 }
715
716
717
718
719
720
721 public boolean isInit()
722 {
723 return isInit;
724 }
725
726
727
728
729
730
731
732
733
734
735
736 public void setConfiguration(Configuration conf)
737 throws TorqueException
738 {
739 log.debug("setConfiguration(" + conf + ")");
740
741 Configuration subConf = conf.subset(Torque.TORQUE_KEY);
742 if (subConf == null || subConf.isEmpty())
743 {
744 String error = ("Invalid configuration. No keys starting with "
745 + Torque.TORQUE_KEY
746 + " found in configuration");
747 log.error(error);
748 throw new TorqueException(error);
749 }
750 this.conf = subConf;
751 }
752
753
754
755
756
757
758 public Configuration getConfiguration()
759 {
760 log.debug("getConfiguration() = " + conf);
761 return conf;
762 }
763
764
765
766
767
768
769
770 public <T extends AbstractBaseManager<? extends Persistent>> T getManager(String name)
771 {
772 @SuppressWarnings("unchecked")
773 T m = (T) managers.get(name);
774 if (m == null)
775 {
776 log.error("No configured manager for key " + name + ".");
777 }
778 return m;
779 }
780
781
782
783
784
785
786
787
788
789
790 @SuppressWarnings("unchecked")
791 public <T extends AbstractBaseManager<? extends Persistent>> T getManager(String name,
792 String defaultClassName)
793 {
794 T m = (T) managers.get(name);
795 if (m == null)
796 {
797 log.debug("Added late Manager mapping for Class: "
798 + name + " -> " + defaultClassName);
799
800 try
801 {
802 initManager(name, defaultClassName);
803 }
804 catch (TorqueException e)
805 {
806 log.error(e.getMessage(), e);
807 }
808
809
810 m = (T) managers.get(name);
811 }
812
813 return m;
814 }
815
816
817
818
819
820
821
822
823
824
825
826
827 public synchronized void shutdown()
828 throws TorqueException
829 {
830 for (IDBroker idBroker : idBrokers)
831 {
832 idBroker.stop();
833
834
835 }
836
837
838 for (Iterator<Map.Entry<String, AbstractBaseManager<?>>> it
839 = managers.entrySet().iterator(); it.hasNext();)
840 {
841 Map.Entry<String, AbstractBaseManager<?>> mentry
842 = it.next();
843
844 AbstractBaseManager<?> manager = mentry.getValue();
845 manager.dispose();
846 it.remove();
847 }
848
849
850 TorqueException exception = null;
851 synchronized (databases)
852 {
853 for (Map.Entry<String, Database> databaseMapEntry
854 : databases.entrySet())
855 {
856 Object databaseKey = databaseMapEntry.getKey();
857 Database database = databaseMapEntry.getValue();
858 if (DEFAULT_NAME.equals(databaseKey) && defaultDsfIsReference)
859 {
860
861
862
863
864 database.setDataSourceFactory(null);
865 continue;
866 }
867
868 try
869 {
870 DataSourceFactory dataSourceFactory
871 = database.getDataSourceFactory();
872 if (dataSourceFactory != null)
873 {
874 dataSourceFactory.close();
875 database.setDataSourceFactory(null);
876 }
877 }
878 catch (TorqueException e)
879 {
880 log.error("Error while closing the DataSourceFactory "
881 + databaseKey,
882 e);
883 if (exception == null)
884 {
885 exception = e;
886 }
887 }
888 }
889 }
890 if (exception != null)
891 {
892 throw exception;
893 }
894 resetConfiguration();
895 }
896
897
898
899
900 private void resetConfiguration()
901 {
902 managers = new HashMap<String, AbstractBaseManager<?>>();
903 isInit = false;
904 }
905
906
907
908
909
910
911
912
913 public DatabaseMap getDatabaseMap()
914 throws TorqueException
915 {
916 String name = getDefaultDB();
917 if (name == null)
918 {
919 throw new TorqueException("Torque is not initialized");
920 }
921 return getDatabaseMap(getDefaultDB());
922 }
923
924
925
926
927
928
929
930
931
932
933
934
935 public DatabaseMap getDatabaseMap(String name)
936 throws TorqueException
937 {
938 if (name == null)
939 {
940 if (!Torque.isInit())
941 {
942 throw new TorqueException("Torque is not initialized");
943 }
944 name = getDefaultDB();
945 }
946 Database database = getOrCreateDatabase(name);
947 return database.getDatabaseMap();
948 }
949
950
951
952
953
954
955
956
957
958
959 public void registerIDBroker(IDBroker idBroker)
960 {
961 idBrokers.add(idBroker);
962 if (isInit())
963 {
964 idBroker.start();
965 }
966 }
967
968
969
970
971
972
973
974
975
976 public Connection getConnection()
977 throws TorqueException
978 {
979 return getConnection(getDefaultDB());
980 }
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995 public Connection getConnection(String name)
996 throws TorqueException
997 {
998 if (!isInit())
999 {
1000 throw new TorqueException("Torque is not initialized");
1001 }
1002 try
1003 {
1004 return getDatabase(name)
1005 .getDataSourceFactory()
1006 .getDataSource()
1007 .getConnection();
1008 }
1009 catch (SQLException se)
1010 {
1011 throw new TorqueException(se);
1012 }
1013 }
1014
1015
1016
1017
1018
1019
1020
1021
1022
1023
1024
1025
1026 public DataSourceFactory getDataSourceFactory(String name)
1027 throws TorqueException
1028 {
1029 if (!isInit())
1030 {
1031 throw new TorqueException("Torque is not initialized");
1032 }
1033
1034 Database database = getDatabase(name);
1035
1036 DataSourceFactory dsf = null;
1037 if (database != null)
1038 {
1039 dsf = database.getDataSourceFactory();
1040 }
1041
1042 if (dsf == null)
1043 {
1044 throw new TorqueException(
1045 "There was no DataSourceFactory "
1046 + "configured for the connection " + name);
1047 }
1048
1049 return dsf;
1050 }
1051
1052
1053
1054
1055
1056
1057
1058
1059
1060
1061
1062
1063
1064
1065
1066 public Connection getConnection(String name, String username,
1067 String password)
1068 throws TorqueException
1069 {
1070 if (!isInit())
1071 {
1072 throw new TorqueException("Torque is not initialized");
1073 }
1074 try
1075 {
1076 return getDataSourceFactory(name)
1077 .getDataSource().getConnection(username, password);
1078 }
1079 catch (SQLException se)
1080 {
1081 throw new TorqueException(se);
1082 }
1083 }
1084
1085
1086
1087
1088
1089
1090
1091
1092
1093
1094
1095
1096
1097
1098 @Deprecated
1099 public Adapter getDB(String name) throws TorqueException
1100 {
1101 if (!isInit())
1102 {
1103 throw new TorqueException("Torque is not initialized");
1104 }
1105 Database database = getDatabase(name);
1106 if (database == null)
1107 {
1108 return null;
1109 }
1110 return database.getAdapter();
1111 }
1112
1113
1114
1115
1116
1117
1118
1119
1120
1121
1122
1123 public Adapter getAdapter(String name) throws TorqueException
1124 {
1125 if (!isInit())
1126 {
1127 throw new TorqueException("Torque is not initialized");
1128 }
1129 Database database = getDatabase(name);
1130 if (database == null)
1131 {
1132 return null;
1133 }
1134 return database.getAdapter();
1135 }
1136
1137
1138
1139
1140
1141
1142
1143
1144 public String getDefaultDB()
1145 {
1146 return defaultDBName;
1147 }
1148
1149
1150
1151
1152
1153
1154 public void closeConnection(Connection con)
1155 {
1156 if (con != null)
1157 {
1158 try
1159 {
1160 con.close();
1161 }
1162 catch (SQLException e)
1163 {
1164 log.error("Error occured while closing connection.", e);
1165 }
1166 }
1167 }
1168
1169
1170
1171
1172
1173
1174
1175
1176
1177 public void setSchema(String name, String schema)
1178 {
1179 getOrCreateDatabase(name).setSchema(schema);
1180 }
1181
1182
1183
1184
1185
1186
1187
1188
1189
1190
1191
1192 public String getSchema(String name)
1193 throws TorqueException
1194 {
1195 if (!isInit())
1196 {
1197 throw new TorqueException("Torque is not initialized");
1198 }
1199 Database database = getDatabase(name);
1200 if (database == null)
1201 {
1202 return null;
1203 }
1204 return database.getSchema();
1205 }
1206
1207
1208
1209
1210
1211
1212
1213
1214
1215
1216
1217
1218 public Database getDatabase(String databaseName) throws TorqueException
1219 {
1220 if (!isInit())
1221 {
1222 throw new TorqueException("Torque is not initialized.");
1223 }
1224 if (databaseName == null)
1225 {
1226 databaseName = getDefaultDB();
1227 }
1228 return databases.get(databaseName);
1229 }
1230
1231
1232
1233
1234
1235
1236
1237
1238
1239
1240
1241
1242
1243
1244 public Map<String, Database> getDatabases() throws TorqueException
1245 {
1246 if (!isInit())
1247 {
1248 throw new TorqueException("Torque is not initialized.");
1249 }
1250 return Collections.unmodifiableMap(databases);
1251 }
1252
1253
1254
1255
1256
1257
1258
1259
1260
1261
1262
1263
1264
1265 public Database getOrCreateDatabase(String databaseName)
1266 {
1267 if (databaseName == null)
1268 {
1269 throw new NullPointerException("databaseName is null");
1270 }
1271 synchronized (databases)
1272 {
1273 Database result = databases.get(databaseName);
1274 if (result == null)
1275 {
1276 result = new Database(databaseName);
1277 databases.put(databaseName, result);
1278 }
1279 return result;
1280 }
1281 }
1282 }