%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 500332 2007-01-26 20:30:34Z tfischer $ |
|
59 | */ |
|
60 | 4 | public class TorqueInstance |
61 | { |
|
62 | /** Logging */ |
|
63 | 44 | private static Log log = LogFactory.getLog(TorqueInstance.class); |
64 | ||
65 | 136 | /** 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 | 30 | private String defaultDBName = null; |
70 | ||
71 | 68 | /** |
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 | 30 | private Map databases = Collections.synchronizedMap(new HashMap()); |
77 | ||
78 | 68 | /** 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 | 30 | private boolean isInit = false; |
86 | ||
87 | 68 | /** |
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 | 30 | private boolean defaultDsfIsReference = false; |
94 | ||
95 | 68 | /** |
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 | 30 | private Map mapBuilderCache = null; |
102 | ||
103 | 68 | /** |
104 | * Creates a new instance with default configuration. |
|
105 | * |
|
106 | * @see #resetConfiguration() |
|
107 | */ |
|
108 | 5 | public TorqueInstance() |
109 | 25 | { |
110 | 30 | resetConfiguration(); |
111 | 98 | } |
112 | 68 | |
113 | 68 | /** |
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 | 24 | log.debug("initialize()"); |
123 | ||
124 | 92 | if (isInit) |
125 | { |
|
126 | 68 | log.debug("Multiple initializations of Torque attempted"); |
127 | 0 | return; |
128 | } |
|
129 | ||
130 | 24 | if (conf == null || conf.isEmpty()) |
131 | { |
|
132 | 68 | 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 | 24 | Configuration subConf = conf.subset(Torque.TORQUE_KEY); |
144 | 24 | if (subConf == null || subConf.isEmpty()) |
145 | 68 | { |
146 | 68 | 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 | 24 | setConfiguration(subConf); |
153 | ||
154 | 92 | initDefaultDbName(conf); |
155 | 24 | initAdapters(conf); |
156 | 92 | initDataSourceFactories(conf); |
157 | 68 | |
158 | 68 | // setup manager mappings |
159 | 24 | initManagerMappings(conf); |
160 | 68 | |
161 | 24 | isInit = true; |
162 | ||
163 | 17 | // re-build any MapBuilders that may have gone lost during serialization |
164 | 45 | synchronized (mapBuilderCache) |
165 | { |
|
166 | 97 | for (Iterator i = mapBuilderCache.entrySet().iterator(); i.hasNext();) |
167 | { |
|
168 | 6 | Map.Entry entry = (Map.Entry)i.next(); |
169 | 68 | |
170 | 6 | if (null == entry.getValue()) |
171 | 68 | { |
172 | 68 | 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 | 5 | } |
188 | 68 | } |
189 | 5 | } |
190 | 20 | } |
191 | 24 | } |
192 | ||
193 | 68 | |
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 | 68 | { |
206 | // Determine default database name. |
|
207 | 28 | defaultDBName = |
208 | 8 | conf.getString( |
209 | 4 | Torque.DATABASE_KEY |
210 | + "." |
|
211 | + Torque.DEFAULT_KEY); |
|
212 | 24 | 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 | 68 | + " not set"; |
221 | 0 | log.error(error); |
222 | 68 | throw new TorqueException(error); |
223 | 68 | } |
224 | 24 | } |
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 | 68 | throws TorqueException |
238 | { |
|
239 | 228 | log.debug("initAdapters(" + conf + ")"); |
240 | 204 | |
241 | 24 | Configuration c = conf.subset(Torque.DATABASE_KEY); |
242 | 24 | if (c == null || c.isEmpty()) |
243 | 68 | { |
244 | 68 | String error = "Invalid configuration : " |
245 | + "No keys starting with " |
|
246 | + Torque.TORQUE_KEY |
|
247 | + "." |
|
248 | 68 | + Torque.DATABASE_KEY |
249 | + " found in configuration"; |
|
250 | 0 | log.error(error); |
251 | 68 | throw new TorqueException(error); |
252 | } |
|
253 | 68 | |
254 | 68 | try |
255 | { |
|
256 | 40 | for (Iterator it = c.getKeys(); it.hasNext();) |
257 | 68 | { |
258 | 72 | String key = (String) it.next(); |
259 | 72 | if (key.endsWith(DB.ADAPTER_KEY) |
260 | 76 | || key.endsWith(DB.DRIVER_KEY)) |
261 | 68 | { |
262 | 24 | String adapter = c.getString(key); |
263 | 24 | String handle = key.substring(0, key.indexOf('.')); |
264 | ||
265 | DB db; |
|
266 | ||
267 | 24 | db = DBFactory.create(adapter); |
268 | ||
269 | // Not supported, try manually defined adapter class |
|
270 | 92 | if (db == null) |
271 | 68 | { |
272 | 296 | String adapterClassName = c.getString(key + "." + adapter + ".className", null); |
273 | 228 | db = DBFactory.create(adapter, adapterClassName); |
274 | } |
|
275 | 204 | |
276 | 24 | Database database = getOrCreateDatabase(handle); |
277 | ||
278 | // register the adapter for this name |
|
279 | 24 | database.setAdapter(db); |
280 | 232 | log.debug("Adding " + adapter + " -> " |
281 | 4 | + 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 | 24 | getDatabaseMap(handle); |
290 | 24 | for (int i = 0; |
291 | 100 | i < IDGeneratorFactory.ID_GENERATOR_METHODS.length; |
292 | 140 | i++) |
293 | { |
|
294 | 84 | database.addIdGenerator( |
295 | 80 | IDGeneratorFactory.ID_GENERATOR_METHODS[i], |
296 | 12 | IDGeneratorFactory.create(db, handle)); |
297 | 68 | } |
298 | } |
|
299 | 60 | } |
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 | 20 | } |
312 | ||
313 | 68 | // check that at least the default database has got an adapter. |
314 | 24 | Database defaultDatabase |
315 | 4 | = (Database) databases.get(Torque.getDefaultDB()); |
316 | 24 | if (defaultDatabase == null |
317 | 4 | || 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 | 68 | throw new TorqueException(error); |
331 | } |
|
332 | 92 | } |
333 | 68 | |
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 | 68 | throws TorqueException |
348 | { |
|
349 | 92 | log.debug("initDataSourceFactories(" + conf + ")"); |
350 | 68 | |
351 | 24 | Configuration c = conf.subset(DataSourceFactory.DSFACTORY_KEY); |
352 | 92 | if (c == null || c.isEmpty()) |
353 | 68 | { |
354 | 68 | String error = "Invalid configuration: " |
355 | + "No keys starting with " |
|
356 | 68 | + Torque.TORQUE_KEY |
357 | 68 | + "." |
358 | + DataSourceFactory.DSFACTORY_KEY |
|
359 | 68 | + " found in configuration"; |
360 | 0 | log.error(error); |
361 | 68 | throw new TorqueException(error); |
362 | 68 | } |
363 | ||
364 | 68 | try |
365 | { |
|
366 | 32 | for (Iterator it = c.getKeys(); it.hasNext();) |
367 | { |
|
368 | 24 | String key = (String) it.next(); |
369 | 24 | if (key.endsWith(DataSourceFactory.FACTORY_KEY)) |
370 | { |
|
371 | 24 | String classname = c.getString(key); |
372 | 24 | String handle = key.substring(0, key.indexOf('.')); |
373 | 28 | log.debug("handle: " + handle |
374 | 4 | + " DataSourceFactory: " + classname); |
375 | 92 | Class dsfClass = Class.forName(classname); |
376 | 24 | DataSourceFactory dsf = |
377 | 72 | (DataSourceFactory) dsfClass.newInstance(); |
378 | 24 | dsf.initialize(c.subset(handle)); |
379 | 68 | |
380 | 24 | Database database = getOrCreateDatabase(handle); |
381 | 24 | database.setDataSourceFactory(dsf); |
382 | } |
|
383 | 20 | } |
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 | 20 | } |
395 | ||
396 | 24 | Database defaultDatabase |
397 | 4 | = (Database) databases.get(defaultDBName); |
398 | 24 | if (defaultDatabase == null |
399 | 4 | || 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 | 68 | log.error(error); |
412 | 0 | throw new TorqueException(error); |
413 | 68 | } |
414 | ||
415 | // As there might be a default database configured |
|
416 | 68 | // 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 | 68 | // not, then add a dummy entry for the "default" |
420 | // |
|
421 | 68 | // 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 | 68 | // |
426 | // in your Torque.properties |
|
427 | // |
|
428 | ||
429 | { |
|
430 | 24 | Database databaseInfoForKeyDefault |
431 | 4 | = getOrCreateDatabase(DEFAULT_NAME); |
432 | 24 | if ((!defaultDBName.equals(DEFAULT_NAME)) |
433 | 4 | && databaseInfoForKeyDefault.getDataSourceFactory() == null) |
434 | { |
|
435 | 28 | log.debug("Adding the DatasourceFactory from database " |
436 | 4 | + defaultDBName |
437 | 55 | + " onto database " + DEFAULT_NAME); |
438 | 28 | databaseInfoForKeyDefault.setDataSourceFactory( |
439 | 4 | defaultDatabase.getDataSourceFactory()); |
440 | 75 | this.defaultDsfIsReference = true; |
441 | } |
|
442 | } |
|
443 | 51 | |
444 | 75 | } |
445 | ||
446 | /** |
|
447 | * Initialization of Torque with a properties file. |
|
448 | * |
|
449 | 51 | * @param configFile The absolute path to the configuration file. |
450 | 51 | * @throws TorqueException Any exceptions caught during processing will be |
451 | * rethrown wrapped into a TorqueException. |
|
452 | */ |
|
453 | public void init(String configFile) |
|
454 | throws TorqueException |
|
455 | { |
|
456 | 18 | log.debug("init(" + configFile + ")"); |
457 | try |
|
458 | { |
|
459 | 18 | Configuration configuration |
460 | 3 | = new PropertiesConfiguration(configFile); |
461 | ||
462 | 86 | log.debug("Config Object is " + configuration); |
463 | 86 | init(configuration); |
464 | 68 | } |
465 | 68 | catch (ConfigurationException e) |
466 | { |
|
467 | 0 | throw new TorqueException(e); |
468 | 15 | } |
469 | 18 | } |
470 | ||
471 | /** |
|
472 | * Initialization of Torque with a Configuration object. |
|
473 | * |
|
474 | * @param conf The Torque configuration. |
|
475 | * @throws TorqueException Any exceptions caught during processing will be |
|
476 | * rethrown wrapped into a TorqueException. |
|
477 | */ |
|
478 | public synchronized void init(Configuration conf) |
|
479 | throws TorqueException |
|
480 | { |
|
481 | 24 | log.debug("init(" + conf + ")"); |
482 | 24 | setConfiguration(conf); |
483 | 24 | initialize(); |
484 | 24 | } |
485 | ||
486 | ||
487 | /** |
|
488 | * Creates a mapping between classes and their manager classes. |
|
489 | * |
|
490 | * The mapping is built according to settings present in |
|
491 | * properties file. The entries should have the |
|
492 | * following form: |
|
493 | 68 | * |
494 | 68 | * <pre> |
495 | * torque.managed_class.com.mycompany.Myclass.manager= \ |
|
496 | 68 | * com.mycompany.MyManagerImpl |
497 | * services.managed_class.com.mycompany.Myotherclass.manager= \ |
|
498 | 340 | * com.mycompany.MyOtherManagerImpl |
499 | * </pre> |
|
500 | 340 | * |
501 | * <br> |
|
502 | * |
|
503 | * Generic ServiceBroker provides no Services. |
|
504 | * |
|
505 | * @param conf the Configuration representing the properties file |
|
506 | * @throws TorqueException Any exceptions caught during processing will be |
|
507 | * rethrown wrapped into a TorqueException. |
|
508 | */ |
|
509 | protected void initManagerMappings(Configuration conf) |
|
510 | throws TorqueException |
|
511 | { |
|
512 | 24 | int pref = Torque.MANAGER_PREFIX.length(); |
513 | 24 | int suff = Torque.MANAGER_SUFFIX.length(); |
514 | ||
515 | 48 | for (Iterator it = conf.getKeys(); it.hasNext();) |
516 | { |
|
517 | 120 | String key = (String) it.next(); |
518 | ||
519 | 120 | if (key.startsWith(Torque.MANAGER_PREFIX) |
520 | && key.endsWith(Torque.MANAGER_SUFFIX)) |
|
521 | { |
|
522 | 0 | String managedClassKey = key.substring(pref, |
523 | key.length() - suff); |
|
524 | 0 | if (!managers.containsKey(managedClassKey)) |
525 | 340 | { |
526 | 68 | String managerClass = conf.getString(key); |
527 | 0 | log.info("Added Manager for Class: " + managedClassKey |
528 | + " -> " + managerClass); |
|
529 | try |
|
530 | { |
|
531 | 0 | initManager(managedClassKey, managerClass); |
532 | } |
|
533 | 0 | catch (TorqueException e) |
534 | { |
|
535 | // the exception thrown here seems to disappear. |
|
536 | // At least when initialized by Turbine, should find |
|
537 | // out why, but for now make sure it is noticed. |
|
538 | 0 | log.error("", e); |
539 | 0 | e.printStackTrace(); |
540 | 0 | throw e; |
541 | 0 | } |
542 | } |
|
543 | } |
|
544 | 100 | } |
545 | 24 | } |
546 | ||
547 | /** |
|
548 | * Initialize a manager |
|
549 | * |
|
550 | * @param name name of the manager |
|
551 | * @param className name of the manager class |
|
552 | * @throws TorqueException Any exceptions caught during processing will be |
|
553 | * rethrown wrapped into a TorqueException. |
|
554 | */ |
|
555 | private synchronized void initManager(String name, String className) |
|
556 | throws TorqueException |
|
557 | { |
|
558 | 0 | AbstractBaseManager manager = (AbstractBaseManager) managers.get(name); |
559 | ||
560 | 0 | if (manager == null) |
561 | { |
|
562 | 0 | if (className != null && className.length() != 0) |
563 | { |
|
564 | try |
|
565 | { |
|
566 | 0 | manager = (AbstractBaseManager) |
567 | Class.forName(className).newInstance(); |
|
568 | 1360 | managers.put(name, manager); |
569 | } |
|
570 | 0 | catch (Exception e) |
571 | { |
|
572 | 0 | throw new TorqueException("Could not instantiate " |
573 | + "manager associated with class: " |
|
574 | + name, e); |
|
575 | 0 | } |
576 | } |
|
577 | } |
|
578 | 0 | } |
579 | ||
580 | 136 | /** |
581 | 136 | * Determine whether Torque has already been initialized. |
582 | 136 | * |
583 | * @return true if Torque is already initialized |
|
584 | */ |
|
585 | public boolean isInit() |
|
586 | { |
|
587 | 486 | return isInit; |
588 | } |
|
589 | ||
590 | /** |
|
591 | 204 | * Sets the configuration for Torque and all dependencies. |
592 | 204 | * The prefix <code>TORQUE_KEY</code> needs to be removed from the |
593 | * configuration keys for the provided configuration. |
|
594 | * |
|
595 | * @param conf the Configuration. |
|
596 | */ |
|
597 | public void setConfiguration(Configuration conf) |
|
598 | { |
|
599 | 48 | log.debug("setConfiguration(" + conf + ")"); |
600 | 48 | this.conf = conf; |
601 | 48 | } |
602 | ||
603 | /** |
|
604 | * Get the configuration for this component. |
|
605 | * |
|
606 | * @return the Configuration |
|
607 | */ |
|
608 | public Configuration getConfiguration() |
|
609 | { |
|
610 | 72 | log.debug("getConfiguration() = " + conf); |
611 | 72 | return conf; |
612 | } |
|
613 | ||
614 | /** |
|
615 | * This method returns a Manager for the given name. |
|
616 | * |
|
617 | * @param name name of the manager |
|
618 | * @return a Manager |
|
619 | */ |
|
620 | public AbstractBaseManager getManager(String name) |
|
621 | { |
|
622 | 0 | AbstractBaseManager m = (AbstractBaseManager) managers.get(name); |
623 | 0 | if (m == null) |
624 | { |
|
625 | 0 | log.error("No configured manager for key " + name + "."); |
626 | } |
|
627 | 0 | return m; |
628 | } |
|
629 | ||
630 | /** |
|
631 | * This methods returns either the Manager from the configuration file, |
|
632 | * or the default one provided by the generated code. |
|
633 | * |
|
634 | * @param name name of the manager |
|
635 | * @param defaultClassName the class to use if name has not been configured |
|
636 | * @return a Manager |
|
637 | */ |
|
638 | public AbstractBaseManager getManager(String name, |
|
639 | String defaultClassName) |
|
640 | { |
|
641 | 0 | AbstractBaseManager m = (AbstractBaseManager) managers.get(name); |
642 | 0 | if (m == null) |
643 | { |
|
644 | 0 | log.debug("Added late Manager mapping for Class: " |
645 | + name + " -> " + defaultClassName); |
|
646 | ||
647 | try |
|
648 | { |
|
649 | 0 | initManager(name, defaultClassName); |
650 | } |
|
651 | 0 | catch (TorqueException e) |
652 | { |
|
653 | 0 | log.error(e.getMessage(), e); |
654 | 0 | } |
655 | ||
656 | // Try again now that the default manager should be in the map |
|
657 | 0 | m = (AbstractBaseManager) managers.get(name); |
658 | 34 | } |
659 | ||
660 | 34 | return m; |
661 | } |
|
662 | 68 | |
663 | 68 | /** |
664 | 68 | * Shuts down the service. |
665 | * |
|
666 | * This method halts the IDBroker's daemon thread in all of |
|
667 | * the DatabaseMap's. It also closes all SharedPoolDataSourceFactories |
|
668 | 68 | * and PerUserPoolDataSourceFactories initialized by Torque. |
669 | 34 | * @exception TorqueException if a DataSourceFactory could not be closed |
670 | * cleanly. Only the first exception is rethrown, any following |
|
671 | * exceptions are logged but ignored. |
|
672 | 34 | */ |
673 | 34 | public synchronized void shutdown() |
674 | throws TorqueException |
|
675 | 34 | { |
676 | // stop the idbrokers |
|
677 | 82 | synchronized (databases) |
678 | { |
|
679 | 86 | for (Iterator it = databases.values().iterator(); it.hasNext();) |
680 | { |
|
681 | 92 | Database database = (Database) it.next(); |
682 | 24 | IDBroker idBroker = database.getIDBroker(); |
683 | 24 | if (idBroker != null) |
684 | { |
|
685 | 0 | idBroker.stop(); |
686 | } |
|
687 | 54 | } |
688 | 44 | } |
689 | ||
690 | // shut down the data source factories |
|
691 | 12 | TorqueException exception = null; |
692 | 14 | synchronized (databases) |
693 | 34 | { |
694 | 16 | for (Iterator it = databases.keySet().iterator(); it.hasNext();) |
695 | 34 | { |
696 | 24 | Object databaseKey = it.next(); |
697 | 17 | |
698 | 24 | Database database |
699 | 4 | = (Database) databases.get(databaseKey); |
700 | 24 | if (DEFAULT_NAME.equals(databaseKey) && defaultDsfIsReference) |
701 | 17 | { |
702 | // the DataSourceFactory of the database with the name |
|
703 | 17 | // DEFAULT_NAME is just a reference to aynother entry. |
704 | // Do not close because this leads to closing |
|
705 | // the same DataSourceFactory twice. |
|
706 | 29 | database.setDataSourceFactory(null); |
707 | 12 | break; |
708 | 17 | } |
709 | ||
710 | 17 | try |
711 | 34 | { |
712 | 46 | DataSourceFactory dataSourceFactory |
713 | 36 | = database.getDataSourceFactory(); |
714 | 12 | if (dataSourceFactory != null) |
715 | 17 | { |
716 | 6 | dataSourceFactory.close(); |
717 | 17 | database.setDataSourceFactory(null); |
718 | 17 | } |
719 | } |
|
720 | 6 | catch (TorqueException e) |
721 | { |
|
722 | 7 | log.error("Error while closing the DataSourceFactory " |
723 | 1 | + databaseKey, |
724 | 1 | e); |
725 | 6 | if (exception == null) |
726 | 85 | { |
727 | 91 | exception = e; |
728 | 85 | } |
729 | 90 | } |
730 | 10 | } |
731 | 10 | } |
732 | 12 | if (exception != null) |
733 | { |
|
734 | 6 | throw exception; |
735 | } |
|
736 | 6 | resetConfiguration(); |
737 | 6 | } |
738 | ||
739 | /** |
|
740 | * Resets some internal configuration variables to |
|
741 | * their defaults. |
|
742 | */ |
|
743 | private void resetConfiguration() |
|
744 | { |
|
745 | 36 | mapBuilderCache = Collections.synchronizedMap(new HashMap()); |
746 | 36 | managers = new HashMap(); |
747 | 36 | isInit = false; |
748 | 36 | } |
749 | ||
750 | /** |
|
751 | * Returns the default database map information. |
|
752 | * |
|
753 | * @return A DatabaseMap. |
|
754 | * @throws TorqueException Any exceptions caught during processing will be |
|
755 | * rethrown wrapped into a TorqueException. |
|
756 | */ |
|
757 | 391 | public DatabaseMap getDatabaseMap() |
758 | throws TorqueException |
|
759 | { |
|
760 | 0 | return getDatabaseMap(getDefaultDB()); |
761 | } |
|
762 | 391 | |
763 | 391 | /** |
764 | * Returns the database map information. Name relates to the name |
|
765 | * of the connection pool to associate with the map. |
|
766 | * |
|
767 | * @param name The name of the database corresponding to the |
|
768 | * <code>DatabaseMap</code> to retrieve. |
|
769 | * @return The named <code>DatabaseMap</code>. |
|
770 | * @throws TorqueException Any exceptions caught during processing will be |
|
771 | * rethrown wrapped into a TorqueException. |
|
772 | */ |
|
773 | 17 | public DatabaseMap getDatabaseMap(String name) |
774 | 17 | throws TorqueException |
775 | { |
|
776 | 138 | if (name == null) |
777 | { |
|
778 | 0 | throw new TorqueException ("DatabaseMap name was null!"); |
779 | } |
|
780 | ||
781 | 138 | Database database = getOrCreateDatabase(name); |
782 | 138 | return database.getDatabaseMap(); |
783 | } |
|
784 | ||
785 | /** |
|
786 | * Get the registered MapBuilders |
|
787 | * |
|
788 | * @return the MapBuilder cache |
|
789 | * |
|
790 | */ |
|
791 | public Map getMapBuilders() |
|
792 | { |
|
793 | 0 | return mapBuilderCache; |
794 | } |
|
795 | ||
796 | /** |
|
797 | * Register a MapBuilder |
|
798 | * |
|
799 | * @param className the MapBuilder |
|
800 | */ |
|
801 | public void registerMapBuilder(String className) |
|
802 | { |
|
803 | 6 | mapBuilderCache.put(className, null); |
804 | 6 | } |
805 | ||
806 | /** |
|
807 | * Register a MapBuilder |
|
808 | * |
|
809 | * @param builder the instance of the MapBuilder |
|
810 | * |
|
811 | */ |
|
812 | public void registerMapBuilder(MapBuilder builder) |
|
813 | { |
|
814 | 0 | mapBuilderCache.put(builder.getClass().getName(), builder); |
815 | 0 | } |
816 | ||
817 | /** |
|
818 | * Get a MapBuilder |
|
819 | * |
|
820 | * @param className of the MapBuilder |
|
821 | * @return A MapBuilder, not null |
|
822 | * @throws TorqueException if the Map Builder cannot be instantiated |
|
823 | * |
|
824 | */ |
|
825 | public MapBuilder getMapBuilder(String className) |
|
826 | 34 | throws TorqueException |
827 | { |
|
828 | 34 | try |
829 | 34 | { |
830 | 6 | MapBuilder mb = (MapBuilder)mapBuilderCache.get(className); |
831 | 34 | |
832 | 6 | if (mb == null) |
833 | { |
|
834 | 40 | mb = (MapBuilder) Class.forName(className).newInstance(); |
835 | // Cache the MapBuilder before it is built. |
|
836 | 6 | mapBuilderCache.put(className, mb); |
837 | } |
|
838 | ||
839 | 6 | if (mb.isBuilt()) |
840 | { |
|
841 | 34 | return mb; |
842 | } |
|
843 | ||
844 | try |
|
845 | { |
|
846 | 6 | mb.doBuild(); |
847 | } |
|
848 | 0 | catch (Exception e) |
849 | { |
|
850 | // remove the MapBuilder from the cache if it can't be built correctly |
|
851 | 0 | mapBuilderCache.remove(className); |
852 | 0 | throw e; |
853 | 5 | } |
854 | ||
855 | 6 | return mb; |
856 | } |
|
857 | 0 | catch (Exception e) |
858 | { |
|
859 | 0 | log.error("getMapBuilder failed trying to instantiate: " |
860 | + className, e); |
|
861 | 0 | throw new TorqueException(e); |
862 | } |
|
863 | } |
|
864 | ||
865 | /** |
|
866 | * This method returns a Connection from the default pool. |
|
867 | * |
|
868 | * @return The requested connection, never null. |
|
869 | * @throws TorqueException Any exceptions caught during processing will be |
|
870 | * rethrown wrapped into a TorqueException. |
|
871 | */ |
|
872 | public Connection getConnection() |
|
873 | throws TorqueException |
|
874 | { |
|
875 | 0 | return getConnection(getDefaultDB()); |
876 | } |
|
877 | ||
878 | /** |
|
879 | * Returns a database connection to the database with the key |
|
880 | * <code>name</code>. |
|
881 | * @param name The database name. |
|
882 | 663 | * @return a database connection, never null. |
883 | 663 | * @throws TorqueException If no DataSourceFactory is configured for the |
884 | * named database, the connection information is wrong, or the |
|
885 | * connection cannot be returned for any other reason. |
|
886 | */ |
|
887 | 663 | public Connection getConnection(String name) |
888 | throws TorqueException |
|
889 | { |
|
890 | 0 | if (!Torque.isInit()) |
891 | { |
|
892 | 0 | throw new TorqueException("Torque is not initialized"); |
893 | } |
|
894 | try |
|
895 | { |
|
896 | 0 | return getDatabase(name) |
897 | .getDataSourceFactory() |
|
898 | .getDataSource() |
|
899 | 765 | .getConnection(); |
900 | } |
|
901 | 0 | catch (SQLException se) |
902 | { |
|
903 | 0 | throw new TorqueException(se); |
904 | } |
|
905 | } |
|
906 | ||
907 | /** |
|
908 | * Returns the DataSourceFactory for the database with the name |
|
909 | * <code>name</code>. |
|
910 | * |
|
911 | * @param name The name of the database to get the DSF for. |
|
912 | * @return A DataSourceFactory object, never null. |
|
913 | * @throws TorqueException if Torque is not initiliaized, or |
|
914 | * no DatasourceFactory is configured for the given name. |
|
915 | */ |
|
916 | public DataSourceFactory getDataSourceFactory(String name) |
|
917 | throws TorqueException |
|
918 | { |
|
919 | 12 | Database database = getDatabase(name); |
920 | ||
921 | 12 | DataSourceFactory dsf = null; |
922 | 12 | if (database != null) |
923 | { |
|
924 | 12 | dsf = database.getDataSourceFactory(); |
925 | } |
|
926 | ||
927 | 12 | if (dsf == null) |
928 | { |
|
929 | 0 | throw new TorqueException( |
930 | "There was no DataSourceFactory " |
|
931 | + "configured for the connection " + name); |
|
932 | } |
|
933 | ||
934 | 12 | return dsf; |
935 | } |
|
936 | ||
937 | /** |
|
938 | * This method returns a Connection using the given parameters. |
|
939 | * You should only use this method if you need user based access to the |
|
940 | * database! |
|
941 | * |
|
942 | * @param name The database name. |
|
943 | * @param username The name of the database user. |
|
944 | * @param password The password of the database user. |
|
945 | * @return A Connection. |
|
946 | * @throws TorqueException Any exceptions caught during processing will be |
|
947 | 527 | * rethrown wrapped into a TorqueException. |
948 | 527 | */ |
949 | public Connection getConnection(String name, String username, |
|
950 | String password) |
|
951 | throws TorqueException |
|
952 | 527 | { |
953 | 0 | if (!Torque.isInit()) |
954 | { |
|
955 | 0 | throw new TorqueException("Torque is not initialized"); |
956 | } |
|
957 | try |
|
958 | { |
|
959 | 0 | return getDataSourceFactory(name) |
960 | .getDataSource().getConnection(username, password); |
|
961 | } |
|
962 | 0 | catch (SQLException se) |
963 | { |
|
964 | 0 | throw new TorqueException(se); |
965 | 1292 | } |
966 | } |
|
967 | ||
968 | /** |
|
969 | 1292 | * Returns the database adapter for a specific database. |
970 | * |
|
971 | * @param name the name of the database to get the adapter for. |
|
972 | * @return The corresponding database adapter, or null if no database |
|
973 | * adapter is defined for the given database. |
|
974 | * @throws TorqueException Any exceptions caught during processing will be |
|
975 | * rethrown wrapped into a TorqueException. |
|
976 | */ |
|
977 | public DB getDB(String name) throws TorqueException |
|
978 | { |
|
979 | 234 | Database database = getDatabase(name); |
980 | 234 | if (database == null) |
981 | { |
|
982 | 0 | return null; |
983 | } |
|
984 | 234 | return database.getAdapter(); |
985 | } |
|
986 | 34 | |
987 | /////////////////////////////////////////////////////////////////////////// |
|
988 | 17 | |
989 | /** |
|
990 | 17 | * Returns the name of the default database. |
991 | * |
|
992 | * @return name of the default DB, or null if Torque is not initialized yet |
|
993 | */ |
|
994 | public String getDefaultDB() |
|
995 | { |
|
996 | 270 | return defaultDBName; |
997 | } |
|
998 | ||
999 | /** |
|
1000 | * Closes a connection. |
|
1001 | * |
|
1002 | * @param con A Connection to close. |
|
1003 | */ |
|
1004 | 595 | public void closeConnection(Connection con) |
1005 | { |
|
1006 | 595 | if (con != null) |
1007 | 595 | { |
1008 | try |
|
1009 | 136 | { |
1010 | 136 | con.close(); |
1011 | } |
|
1012 | 595 | catch (SQLException e) |
1013 | { |
|
1014 | 0 | log.error("Error occured while closing connection.", e); |
1015 | 0 | } |
1016 | } |
|
1017 | 0 | } |
1018 | ||
1019 | /** |
|
1020 | * Sets the current schema for a database connection |
|
1021 | * |
|
1022 | * @param name The database name. |
|
1023 | * @param schema The current schema name. |
|
1024 | * @throws TorqueException Any exceptions caught during processing will be |
|
1025 | * rethrown wrapped into a TorqueException. |
|
1026 | */ |
|
1027 | public void setSchema(String name, String schema) |
|
1028 | throws TorqueException |
|
1029 | { |
|
1030 | 0 | getOrCreateDatabase(name).setSchema(schema); |
1031 | 0 | } |
1032 | ||
1033 | /** |
|
1034 | * This method returns the current schema for a database connection |
|
1035 | * |
|
1036 | * @param name The database name. |
|
1037 | * @return The current schema name. Null means, no schema has been set. |
|
1038 | * @throws TorqueException Any exceptions caught during processing will be |
|
1039 | * rethrown wrapped into a TorqueException. |
|
1040 | */ |
|
1041 | public String getSchema(String name) |
|
1042 | throws TorqueException |
|
1043 | { |
|
1044 | 186 | Database database = getDatabase(name); |
1045 | 186 | if (database == null) |
1046 | { |
|
1047 | 0 | return null; |
1048 | } |
|
1049 | 186 | return database.getSchema(); |
1050 | } |
|
1051 | ||
1052 | /** |
|
1053 | * Returns the database for the key <code>databaseName</code>. |
|
1054 | * |
|
1055 | * @param databaseName the key to get the database for. |
|
1056 | * @return the database for the specified key, or null if the database |
|
1057 | * does not exist. |
|
1058 | * @throws TorqueException if Torque is not yet initialized. |
|
1059 | */ |
|
1060 | public Database getDatabase(String databaseName) throws TorqueException |
|
1061 | { |
|
1062 | 456 | if (!isInit()) |
1063 | { |
|
1064 | 0 | throw new TorqueException("Torque is not initialized."); |
1065 | } |
|
1066 | 456 | return (Database) databases.get(databaseName); |
1067 | } |
|
1068 | ||
1069 | /** |
|
1070 | * Returns a Map containing all Databases registered to Torque. |
|
1071 | * The key of the Map is the name of the database, and the value is the |
|
1072 | * database instance. <br/> |
|
1073 | * Note that in the very special case where a new database which |
|
1074 | * is not configured in Torque's configuration gets known to Torque |
|
1075 | * at a later time, the returned map may change, and there is no way to |
|
1076 | * protect you against this. |
|
1077 | * |
|
1078 | * @return a Map containing all Databases known to Torque, never null. |
|
1079 | * @throws TorqueException if Torque is not yet initialized. |
|
1080 | */ |
|
1081 | public Map getDatabases() throws TorqueException |
|
1082 | { |
|
1083 | 12 | if (!isInit()) |
1084 | { |
|
1085 | 6 | throw new TorqueException("Torque is not initialized."); |
1086 | } |
|
1087 | 6 | return Collections.unmodifiableMap(databases); |
1088 | } |
|
1089 | ||
1090 | /** |
|
1091 | * Returns the database for the key <code>databaseName</code>. |
|
1092 | * If no database is associated to the specified key, |
|
1093 | * a new database is created, mapped to the specified key, and returned. |
|
1094 | * |
|
1095 | * @param databaseName the key to get the database for. |
|
1096 | * @return the database associated with specified key, or the newly created |
|
1097 | * database, never null. |
|
1098 | */ |
|
1099 | public Database getOrCreateDatabase(String databaseName) |
|
1100 | { |
|
1101 | 210 | synchronized (databases) |
1102 | { |
|
1103 | 210 | Database result = (Database) databases.get(databaseName); |
1104 | 210 | if (result == null) |
1105 | { |
|
1106 | 48 | result = new Database(databaseName); |
1107 | 48 | databases.put(databaseName, result); |
1108 | } |
|
1109 | 210 | return result; |
1110 | 0 | } |
1111 | } |
|
1112 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |