%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.torque.TorqueInstance |
|
|
1 | package org.apache.torque; |
|
2 | ||
3 | /* |
|
4 | * Licensed to the Apache Software Foundation (ASF) under one |
|
5 | * or more contributor license agreements. See the NOTICE file |
|
6 | * distributed with this work for additional information |
|
7 | * regarding copyright ownership. The ASF licenses this file |
|
8 | * to you under the Apache License, Version 2.0 (the |
|
9 | * "License"); you may not use this file except in compliance |
|
10 | * with the License. You may obtain a copy of the License at |
|
11 | * |
|
12 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
13 | * |
|
14 | * Unless required by applicable law or agreed to in writing, |
|
15 | * software distributed under the License is distributed on an |
|
16 | * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY |
|
17 | * KIND, either express or implied. See the License for the |
|
18 | * specific language governing permissions and limitations |
|
19 | * under the License. |
|
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 | 60 | 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 | 36 | 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 | 36 | 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 | 36 | 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 | 36 | 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 | 36 | private Map mapBuilderCache = null; |
102 | ||
103 | /** |
|
104 | * Creates a new instance with default configuration. |
|
105 | * |
|
106 | * @see #resetConfiguration() |
|
107 | */ |
|
108 | public TorqueInstance() |
|
109 | 36 | { |
110 | 36 | resetConfiguration(); |
111 | 36 | } |
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 | 30 | log.debug("initialize()"); |
123 | ||
124 | 30 | if (isInit) |
125 | { |
|
126 | 0 | log.debug("Multiple initializations of Torque attempted"); |
127 | 0 | return; |
128 | } |
|
129 | ||
130 | 30 | if (conf == null || conf.isEmpty()) |
131 | { |
|
132 | 0 | throw new TorqueException("Torque cannot be initialized without " |
133 | + "a valid configuration. Please check the log files " |
|
134 | + "for further details."); |
|
135 | } |
|
136 | ||
137 | // Now that we have dealt with processing the log4j properties |
|
138 | // that may be contained in the configuration we will make the |
|
139 | // configuration consist only of the remain torque specific |
|
140 | // properties that are contained in the configuration. First |
|
141 | // look for properties that are in the "torque" namespace. |
|
142 | ||
143 | 30 | Configuration subConf = conf.subset(Torque.TORQUE_KEY); |
144 | 30 | if (subConf == null || subConf.isEmpty()) |
145 | { |
|
146 | 0 | String error = ("Invalid configuration. No keys starting with " |
147 | + Torque.TORQUE_KEY |
|
148 | + " found in configuration"); |
|
149 | 0 | log.error(error); |
150 | 0 | throw new TorqueException(error); |
151 | } |
|
152 | 30 | setConfiguration(subConf); |
153 | ||
154 | 30 | initDefaultDbName(conf); |
155 | 30 | initAdapters(conf); |
156 | 30 | initDataSourceFactories(conf); |
157 | ||
158 | // setup manager mappings |
|
159 | 30 | initManagerMappings(conf); |
160 | ||
161 | 30 | isInit = true; |
162 | ||
163 | // re-build any MapBuilders that may have gone lost during serialization |
|
164 | 30 | synchronized (mapBuilderCache) |
165 | { |
|
166 | 30 | for (Iterator i = mapBuilderCache.entrySet().iterator(); i.hasNext();) |
167 | { |
|
168 | 6 | Map.Entry entry = (Map.Entry)i.next(); |
169 | ||
170 | 6 | if (null == entry.getValue()) |
171 | { |
|
172 | try |
|
173 | { |
|
174 | // create and build the MapBuilder |
|
175 | 6 | MapBuilder builder = (MapBuilder) Class.forName((String) entry.getKey()).newInstance(); |
176 | ||
177 | 6 | if (!builder.isBuilt()) |
178 | { |
|
179 | 6 | builder.doBuild(); |
180 | } |
|
181 | ||
182 | 6 | entry.setValue(builder); |
183 | } |
|
184 | 0 | catch (Exception e) |
185 | { |
|
186 | 0 | throw new TorqueException(e); |
187 | 9 | } |
188 | } |
|
189 | 3 | } |
190 | 30 | } |
191 | 30 | } |
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 | // Determine default database name. |
|
207 | 30 | defaultDBName = |
208 | conf.getString( |
|
209 | Torque.DATABASE_KEY |
|
210 | + "." |
|
211 | + Torque.DEFAULT_KEY); |
|
212 | 30 | if (defaultDBName == null) |
213 | { |
|
214 | 0 | String error = "Invalid configuration: Key " |
215 | + Torque.TORQUE_KEY |
|
216 | + "." |
|
217 | + Torque.DATABASE_KEY |
|
218 | + "." |
|
219 | + Torque.DEFAULT_KEY |
|
220 | + " not set"; |
|
221 | 0 | log.error(error); |
222 | 0 | throw new TorqueException(error); |
223 | } |
|
224 | 30 | } |
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 | 30 | log.debug("initAdapters(" + conf + ")"); |
240 | ||
241 | 30 | Configuration c = conf.subset(Torque.DATABASE_KEY); |
242 | 30 | if (c == null || c.isEmpty()) |
243 | { |
|
244 | 0 | String error = "Invalid configuration : " |
245 | + "No keys starting with " |
|
246 | + Torque.TORQUE_KEY |
|
247 | + "." |
|
248 | + Torque.DATABASE_KEY |
|
249 | + " found in configuration"; |
|
250 | 0 | log.error(error); |
251 | 0 | throw new TorqueException(error); |
252 | } |
|
253 | ||
254 | try |
|
255 | { |
|
256 | 30 | for (Iterator it = c.getKeys(); it.hasNext();) |
257 | { |
|
258 | 90 | String key = (String) it.next(); |
259 | 90 | if (key.endsWith(DB.ADAPTER_KEY) |
260 | || key.endsWith(DB.DRIVER_KEY)) |
|
261 | { |
|
262 | 30 | String adapter = c.getString(key); |
263 | 30 | String handle = key.substring(0, key.indexOf('.')); |
264 | ||
265 | DB db; |
|
266 | ||
267 | 30 | db = DBFactory.create(adapter); |
268 | ||
269 | // Not supported, try manually defined adapter class |
|
270 | 30 | if (db == null) |
271 | { |
|
272 | 30 | String adapterClassName = c.getString(key + "." + adapter + ".className", null); |
273 | 30 | db = DBFactory.create(adapter, adapterClassName); |
274 | } |
|
275 | ||
276 | 30 | Database database = getOrCreateDatabase(handle); |
277 | ||
278 | // register the adapter for this name |
|
279 | 30 | database.setAdapter(db); |
280 | 30 | log.debug("Adding " + adapter + " -> " |
281 | + handle + " as Adapter"); |
|
282 | ||
283 | // add Id generators |
|
284 | ||
285 | // first make sure that the dtabaseMap exists for the name |
|
286 | // as the idGenerators are still stored in the database map |
|
287 | // TODO: change when the idGenerators are stored in the |
|
288 | // database |
|
289 | 30 | getDatabaseMap(handle); |
290 | 30 | for (int i = 0; |
291 | 120 | i < IDGeneratorFactory.ID_GENERATOR_METHODS.length; |
292 | 90 | i++) |
293 | { |
|
294 | 90 | database.addIdGenerator( |
295 | IDGeneratorFactory.ID_GENERATOR_METHODS[i], |
|
296 | IDGeneratorFactory.create(db, handle)); |
|
297 | } |
|
298 | } |
|
299 | 45 | } |
300 | } |
|
301 | 0 | catch (InstantiationException e) |
302 | { |
|
303 | 0 | log.error("Error creating a database adapter instance", e); |
304 | 0 | throw new TorqueException(e); |
305 | } |
|
306 | 0 | catch (TorqueException e) |
307 | { |
|
308 | 0 | log.error("Error reading configuration seeking database " |
309 | + "adapters", e); |
|
310 | 0 | throw new TorqueException(e); |
311 | 30 | } |
312 | ||
313 | // check that at least the default database has got an adapter. |
|
314 | 30 | Database defaultDatabase |
315 | = (Database) databases.get(Torque.getDefaultDB()); |
|
316 | 30 | if (defaultDatabase == null |
317 | || defaultDatabase.getAdapter() == null) |
|
318 | { |
|
319 | 0 | 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 | 0 | log.error(error); |
330 | 0 | throw new TorqueException(error); |
331 | } |
|
332 | 30 | } |
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 | 30 | log.debug("initDataSourceFactories(" + conf + ")"); |
350 | ||
351 | 30 | Configuration c = conf.subset(DataSourceFactory.DSFACTORY_KEY); |
352 | 30 | if (c == null || c.isEmpty()) |
353 | { |
|
354 | 0 | String error = "Invalid configuration: " |
355 | + "No keys starting with " |
|
356 | + Torque.TORQUE_KEY |
|
357 | + "." |
|
358 | + DataSourceFactory.DSFACTORY_KEY |
|
359 | + " found in configuration"; |
|
360 | 0 | log.error(error); |
361 | 0 | throw new TorqueException(error); |
362 | } |
|
363 | ||
364 | try |
|
365 | { |
|
366 | 30 | for (Iterator it = c.getKeys(); it.hasNext();) |
367 | { |
|
368 | 30 | String key = (String) it.next(); |
369 | 30 | if (key.endsWith(DataSourceFactory.FACTORY_KEY)) |
370 | { |
|
371 | 30 | String classname = c.getString(key); |
372 | 30 | String handle = key.substring(0, key.indexOf('.')); |
373 | 30 | log.debug("handle: " + handle |
374 | + " DataSourceFactory: " + classname); |
|
375 | 30 | Class dsfClass = Class.forName(classname); |
376 | 30 | DataSourceFactory dsf = |
377 | (DataSourceFactory) dsfClass.newInstance(); |
|
378 | 30 | dsf.initialize(c.subset(handle)); |
379 | ||
380 | 30 | Database database = getOrCreateDatabase(handle); |
381 | 30 | database.setDataSourceFactory(dsf); |
382 | } |
|
383 | 15 | } |
384 | } |
|
385 | 0 | catch (RuntimeException e) |
386 | { |
|
387 | 0 | log.error("Runtime Error reading adapter configuration", e); |
388 | 0 | throw new TorqueRuntimeException(e); |
389 | } |
|
390 | 0 | catch (Exception e) |
391 | { |
|
392 | 0 | log.error("Error reading adapter configuration", e); |
393 | 0 | throw new TorqueException(e); |
394 | 30 | } |
395 | ||
396 | 30 | Database defaultDatabase |
397 | = (Database) databases.get(defaultDBName); |
|
398 | 30 | if (defaultDatabase == null |
399 | || defaultDatabase.getDataSourceFactory() == null) |
|
400 | { |
|
401 | 0 | 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 | 0 | log.error(error); |
412 | 0 | throw new TorqueException(error); |
413 | } |
|
414 | ||
415 | // As there might be a default database configured |
|
416 | // to map "default" onto an existing datasource, we |
|
417 | // must check, whether there _is_ really an entry for |
|
418 | // the "default" in the dsFactoryMap or not. If it is |
|
419 | // not, then add a dummy entry for the "default" |
|
420 | // |
|
421 | // Without this, you can't actually access the "default" |
|
422 | // data-source, even if you have an entry like |
|
423 | // |
|
424 | // database.default = bookstore |
|
425 | // |
|
426 | // in your Torque.properties |
|
427 | // |
|
428 | ||
429 | { |
|
430 | 30 | Database databaseInfoForKeyDefault |
431 | = getOrCreateDatabase(DEFAULT_NAME); |
|
432 | 30 | if ((!defaultDBName.equals(DEFAULT_NAME)) |
433 | && databaseInfoForKeyDefault.getDataSourceFactory() == null) |
|
434 | { |
|
435 | 30 | log.debug("Adding the DatasourceFactory and DatabaseAdapter from database " |
436 | + defaultDBName |
|
437 | + " onto database " + DEFAULT_NAME); |
|
438 | 30 | databaseInfoForKeyDefault.setDataSourceFactory( |
439 | defaultDatabase.getDataSourceFactory()); |
|
440 | 30 | databaseInfoForKeyDefault.setAdapter( |
441 | defaultDatabase.getAdapter()); |
|
442 | ||
443 | 30 | this.defaultDsfIsReference = true; |
444 | } |
|
445 | } |
|
446 | ||
447 | 30 | } |
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 | 24 | log.debug("init(" + configFile + ")"); |
460 | try |
|
461 | { |
|
462 | 24 | Configuration configuration |
463 | = new PropertiesConfiguration(configFile); |
|
464 | ||
465 | 24 | log.debug("Config Object is " + configuration); |
466 | 24 | init(configuration); |
467 | } |
|
468 | 0 | catch (ConfigurationException e) |
469 | { |
|
470 | 0 | throw new TorqueException(e); |
471 | 24 | } |
472 | 24 | } |
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 | 30 | log.debug("init(" + conf + ")"); |
485 | 30 | setConfiguration(conf); |
486 | 30 | initialize(); |
487 | 30 | } |
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 | 30 | int pref = Torque.MANAGER_PREFIX.length(); |
516 | 30 | int suff = Torque.MANAGER_SUFFIX.length(); |
517 | ||
518 | 30 | for (Iterator it = conf.getKeys(); it.hasNext();) |
519 | { |
|
520 | 150 | String key = (String) it.next(); |
521 | ||
522 | 150 | if (key.startsWith(Torque.MANAGER_PREFIX) |
523 | && key.endsWith(Torque.MANAGER_SUFFIX)) |
|
524 | { |
|
525 | 0 | String managedClassKey = key.substring(pref, |
526 | key.length() - suff); |
|
527 | 0 | if (!managers.containsKey(managedClassKey)) |
528 | { |
|
529 | 0 | String managerClass = conf.getString(key); |
530 | 0 | log.info("Added Manager for Class: " + managedClassKey |
531 | + " -> " + managerClass); |
|
532 | try |
|
533 | { |
|
534 | 0 | initManager(managedClassKey, managerClass); |
535 | } |
|
536 | 0 | catch (TorqueException e) |
537 | { |
|
538 | // the exception thrown here seems to disappear. |
|
539 | // At least when initialized by Turbine, should find |
|
540 | // out why, but for now make sure it is noticed. |
|
541 | 0 | log.error("", e); |
542 | 0 | e.printStackTrace(); |
543 | 0 | throw e; |
544 | 75 | } |
545 | } |
|
546 | } |
|
547 | 75 | } |
548 | 30 | } |
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 | 0 | AbstractBaseManager manager = (AbstractBaseManager) managers.get(name); |
562 | ||
563 | 0 | if (manager == null) |
564 | { |
|
565 | 0 | if (className != null && className.length() != 0) |
566 | { |
|
567 | try |
|
568 | { |
|
569 | 0 | manager = (AbstractBaseManager) |
570 | Class.forName(className).newInstance(); |
|
571 | 0 | managers.put(name, manager); |
572 | } |
|
573 | 0 | catch (Exception e) |
574 | { |
|
575 | 0 | throw new TorqueException("Could not instantiate " |
576 | + "manager associated with class: " |
|
577 | + name, e); |
|
578 | 0 | } |
579 | } |
|
580 | } |
|
581 | 0 | } |
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 | 522 | 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 | 60 | log.debug("setConfiguration(" + conf + ")"); |
603 | 60 | this.conf = conf; |
604 | 60 | } |
605 | ||
606 | /** |
|
607 | * Get the configuration for this component. |
|
608 | * |
|
609 | * @return the Configuration |
|
610 | */ |
|
611 | public Configuration getConfiguration() |
|
612 | { |
|
613 | 90 | log.debug("getConfiguration() = " + conf); |
614 | 90 | 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 | 0 | AbstractBaseManager m = (AbstractBaseManager) managers.get(name); |
626 | 0 | if (m == null) |
627 | { |
|
628 | 0 | log.error("No configured manager for key " + name + "."); |
629 | } |
|
630 | 0 | 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 | 0 | AbstractBaseManager m = (AbstractBaseManager) managers.get(name); |
645 | 0 | if (m == null) |
646 | { |
|
647 | 0 | log.debug("Added late Manager mapping for Class: " |
648 | + name + " -> " + defaultClassName); |
|
649 | ||
650 | try |
|
651 | { |
|
652 | 0 | initManager(name, defaultClassName); |
653 | } |
|
654 | 0 | catch (TorqueException e) |
655 | { |
|
656 | 0 | log.error(e.getMessage(), e); |
657 | 0 | } |
658 | ||
659 | // Try again now that the default manager should be in the map |
|
660 | 0 | m = (AbstractBaseManager) managers.get(name); |
661 | } |
|
662 | ||
663 | 0 | 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 | // stop the idbrokers |
|
680 | 12 | synchronized (databases) |
681 | { |
|
682 | 12 | for (Iterator it = databases.values().iterator(); it.hasNext();) |
683 | { |
|
684 | 24 | Database database = (Database) it.next(); |
685 | 24 | IDBroker idBroker = database.getIDBroker(); |
686 | 24 | if (idBroker != null) |
687 | { |
|
688 | 0 | idBroker.stop(); |
689 | } |
|
690 | 12 | } |
691 | 12 | } |
692 | ||
693 | // shut down the cache managers |
|
694 | 12 | synchronized (managers) |
695 | { |
|
696 | 12 | for (Iterator it = managers.entrySet().iterator(); it.hasNext();) |
697 | { |
|
698 | 0 | Map.Entry mentry = (Map.Entry)it.next(); |
699 | ||
700 | 0 | AbstractBaseManager manager = (AbstractBaseManager)mentry.getValue(); |
701 | 0 | manager.dispose(); |
702 | 0 | it.remove(); |
703 | } |
|
704 | 12 | } |
705 | ||
706 | // shut down the data source factories |
|
707 | 12 | TorqueException exception = null; |
708 | 12 | synchronized (databases) |
709 | { |
|
710 | 12 | for (Iterator it = databases.keySet().iterator(); it.hasNext();) |
711 | { |
|
712 | 24 | Object databaseKey = it.next(); |
713 | ||
714 | 24 | Database database |
715 | = (Database) databases.get(databaseKey); |
|
716 | 24 | if (DEFAULT_NAME.equals(databaseKey) && defaultDsfIsReference) |
717 | { |
|
718 | // the DataSourceFactory of the database with the name |
|
719 | // DEFAULT_NAME is just a reference to aynother entry. |
|
720 | // Do not close because this leads to closing |
|
721 | // the same DataSourceFactory twice. |
|
722 | 12 | database.setDataSourceFactory(null); |
723 | 12 | break; |
724 | } |
|
725 | ||
726 | try |
|
727 | { |
|
728 | 12 | DataSourceFactory dataSourceFactory |
729 | = database.getDataSourceFactory(); |
|
730 | 12 | if (dataSourceFactory != null) |
731 | { |
|
732 | 6 | dataSourceFactory.close(); |
733 | 6 | database.setDataSourceFactory(null); |
734 | } |
|
735 | } |
|
736 | 0 | catch (TorqueException e) |
737 | { |
|
738 | 0 | log.error("Error while closing the DataSourceFactory " |
739 | + databaseKey, |
|
740 | e); |
|
741 | 0 | if (exception == null) |
742 | { |
|
743 | 0 | exception = e; |
744 | } |
|
745 | 18 | } |
746 | 6 | } |
747 | 12 | } |
748 | 12 | if (exception != null) |
749 | { |
|
750 | 0 | throw exception; |
751 | } |
|
752 | 12 | resetConfiguration(); |
753 | 12 | } |
754 | ||
755 | /** |
|
756 | * Resets some internal configuration variables to |
|
757 | * their defaults. |
|
758 | */ |
|
759 | private void resetConfiguration() |
|
760 | { |
|
761 | 48 | mapBuilderCache = Collections.synchronizedMap(new HashMap()); |
762 | 48 | managers = new HashMap(); |
763 | 48 | isInit = false; |
764 | 48 | } |
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 | 0 | 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 | 156 | if (name == null) |
793 | { |
|
794 | 0 | throw new TorqueException ("DatabaseMap name was null!"); |
795 | } |
|
796 | ||
797 | 156 | Database database = getOrCreateDatabase(name); |
798 | 156 | 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 | 6 | return mapBuilderCache; |
810 | } |
|
811 | ||
812 | /** |
|
813 | * Register a MapBuilder |
|
814 | * |
|
815 | * @param className the MapBuilder |
|
816 | */ |
|
817 | public void registerMapBuilder(String className) |
|
818 | { |
|
819 | 6 | mapBuilderCache.put(className, null); |
820 | 6 | } |
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 | 0 | mapBuilderCache.put(builder.getClass().getName(), builder); |
831 | 0 | } |
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 | 6 | MapBuilder mb = (MapBuilder)mapBuilderCache.get(className); |
847 | ||
848 | 6 | if (mb == null) |
849 | { |
|
850 | 6 | mb = (MapBuilder) Class.forName(className).newInstance(); |
851 | // Cache the MapBuilder before it is built. |
|
852 | 6 | mapBuilderCache.put(className, mb); |
853 | } |
|
854 | ||
855 | 6 | if (mb.isBuilt()) |
856 | { |
|
857 | 0 | return mb; |
858 | } |
|
859 | ||
860 | try |
|
861 | { |
|
862 | 6 | mb.doBuild(); |
863 | } |
|
864 | 0 | catch (Exception e) |
865 | { |
|
866 | // remove the MapBuilder from the cache if it can't be built correctly |
|
867 | 0 | mapBuilderCache.remove(className); |
868 | 0 | throw e; |
869 | 6 | } |
870 | ||
871 | 6 | return mb; |
872 | } |
|
873 | 0 | catch (Exception e) |
874 | { |
|
875 | 0 | log.error("getMapBuilder failed trying to instantiate: " |
876 | + className, e); |
|
877 | 0 | 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 | 0 | 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 | 0 | if (!Torque.isInit()) |
907 | { |
|
908 | 0 | throw new TorqueException("Torque is not initialized"); |
909 | } |
|
910 | try |
|
911 | { |
|
912 | 0 | return getDatabase(name) |
913 | .getDataSourceFactory() |
|
914 | .getDataSource() |
|
915 | .getConnection(); |
|
916 | } |
|
917 | 0 | catch (SQLException se) |
918 | { |
|
919 | 0 | 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 | 12 | Database database = getDatabase(name); |
936 | ||
937 | 12 | DataSourceFactory dsf = null; |
938 | 12 | if (database != null) |
939 | { |
|
940 | 12 | dsf = database.getDataSourceFactory(); |
941 | } |
|
942 | ||
943 | 12 | if (dsf == null) |
944 | { |
|
945 | 0 | throw new TorqueException( |
946 | "There was no DataSourceFactory " |
|
947 | + "configured for the connection " + name); |
|
948 | } |
|
949 | ||
950 | 12 | 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 | 0 | if (!Torque.isInit()) |
970 | { |
|
971 | 0 | throw new TorqueException("Torque is not initialized"); |
972 | } |
|
973 | try |
|
974 | { |
|
975 | 0 | return getDataSourceFactory(name) |
976 | .getDataSource().getConnection(username, password); |
|
977 | } |
|
978 | 0 | catch (SQLException se) |
979 | { |
|
980 | 0 | 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 | 264 | Database database = getDatabase(name); |
996 | 264 | if (database == null) |
997 | { |
|
998 | 0 | return null; |
999 | } |
|
1000 | 264 | 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 | 294 | 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 | 0 | if (con != null) |
1023 | { |
|
1024 | try |
|
1025 | { |
|
1026 | 0 | con.close(); |
1027 | } |
|
1028 | 0 | catch (SQLException e) |
1029 | { |
|
1030 | 0 | log.error("Error occured while closing connection.", e); |
1031 | 0 | } |
1032 | } |
|
1033 | 0 | } |
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 | 0 | getOrCreateDatabase(name).setSchema(schema); |
1047 | 0 | } |
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 | 198 | Database database = getDatabase(name); |
1061 | 198 | if (database == null) |
1062 | { |
|
1063 | 0 | return null; |
1064 | } |
|
1065 | 198 | 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 | 498 | if (!isInit()) |
1079 | { |
|
1080 | 0 | throw new TorqueException("Torque is not initialized."); |
1081 | } |
|
1082 | 498 | 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 | 12 | if (!isInit()) |
1100 | { |
|
1101 | 6 | throw new TorqueException("Torque is not initialized."); |
1102 | } |
|
1103 | 6 | 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 | 246 | synchronized (databases) |
1118 | { |
|
1119 | 246 | Database result = (Database) databases.get(databaseName); |
1120 | 246 | if (result == null) |
1121 | { |
|
1122 | 60 | result = new Database(databaseName); |
1123 | 60 | databases.put(databaseName, result); |
1124 | } |
|
1125 | 246 | return result; |
1126 | 0 | } |
1127 | } |
|
1128 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |