%line | %branch | |||||||||
---|---|---|---|---|---|---|---|---|---|---|
org.apache.torque.TorqueInstance |
|
|
1 | package org.apache.torque; |
|
2 | ||
3 | /* |
|
4 | * Copyright 2001-2005 The Apache Software Foundation. |
|
5 | * |
|
6 | * Licensed under the Apache License, Version 2.0 (the "License") |
|
7 | * you may not use this file except in compliance with the License. |
|
8 | * You may obtain a copy of the License at |
|
9 | * |
|
10 | * http://www.apache.org/licenses/LICENSE-2.0 |
|
11 | * |
|
12 | * Unless required by applicable law or agreed to in writing, software |
|
13 | * distributed under the License is distributed on an "AS IS" BASIS, |
|
14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. |
|
15 | * See the License for the specific language governing permissions and |
|
16 | * limitations under the License. |
|
17 | */ |
|
18 | ||
19 | import java.sql.Connection; |
|
20 | import java.sql.SQLException; |
|
21 | import java.util.ArrayList; |
|
22 | import java.util.Collections; |
|
23 | import java.util.HashMap; |
|
24 | import java.util.Iterator; |
|
25 | import java.util.List; |
|
26 | import java.util.Map; |
|
27 | ||
28 | import org.apache.commons.configuration.Configuration; |
|
29 | import org.apache.commons.configuration.ConfigurationException; |
|
30 | import org.apache.commons.configuration.PropertiesConfiguration; |
|
31 | import org.apache.commons.lang.StringUtils; |
|
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.AbstractDataSourceFactory; |
|
37 | import org.apache.torque.dsfactory.DataSourceFactory; |
|
38 | import org.apache.torque.manager.AbstractBaseManager; |
|
39 | import org.apache.torque.map.DatabaseMap; |
|
40 | import org.apache.torque.map.TableMap; |
|
41 | import org.apache.torque.oid.IDBroker; |
|
42 | import org.apache.torque.oid.IDGeneratorFactory; |
|
43 | import org.apache.torque.util.BasePeer; |
|
44 | ||
45 | /** |
|
46 | * The core of Torque's implementation. Both the classic {@link |
|
47 | * org.apache.torque.Torque} static wrapper and the {@link |
|
48 | * org.apache.torque.avalon.TorqueComponent} <a |
|
49 | * href="http://avalon.apache.org/">Avalon</a> implementation leverage |
|
50 | * this class. |
|
51 | * |
|
52 | * @author <a href="mailto:dlr@finemaltcoding.com">Daniel Rall</a> |
|
53 | * @author <a href="mailto:magnus@handtolvur.is">Magn�s ��r Torfason</a> |
|
54 | * @author <a href="mailto:jvanzyl@apache.org">Jason van Zyl</a> |
|
55 | * @author <a href="mailto:Rafal.Krzewski@e-point.pl">Rafal Krzewski</a> |
|
56 | * @author <a href="mailto:mpoeschl@marmot.at">Martin Poeschl</a> |
|
57 | * @author <a href="mailto:hps@intermeta.de">Henning P. Schmiedehausen</a> |
|
58 | * @author <a href="mailto:kschrader@karmalab.org">Kurt Schrader</a> |
|
59 | * @version $Id: TorqueInstance.java 326694 2005-10-19 20:36:03Z tfischer $ |
|
60 | */ |
|
61 | public class TorqueInstance |
|
62 | { |
|
63 | /** Logging */ |
|
64 | 4 | private static Log log = LogFactory.getLog(TorqueInstance.class); |
65 | ||
66 | /** A constant for <code>default</code>. */ |
|
67 | private static final String DEFAULT_NAME = "default"; |
|
68 | ||
69 | /** The db name that is specified as the default in the property file */ |
|
70 | 2 | private String defaultDBName = null; |
71 | ||
72 | /** The global cache of database maps */ |
|
73 | private Map dbMaps; |
|
74 | ||
75 | /** The cache of DataSourceFactory's */ |
|
76 | private Map dsFactoryMap; |
|
77 | ||
78 | /** The cache of DB adapter keys */ |
|
79 | private Map adapterMap; |
|
80 | ||
81 | /** A repository of Manager instances. */ |
|
82 | private Map managers; |
|
83 | ||
84 | /** Torque-specific configuration. */ |
|
85 | private Configuration conf; |
|
86 | ||
87 | /** flag to set to true once this class has been initialized */ |
|
88 | 2 | private boolean isInit = false; |
89 | ||
90 | /** |
|
91 | * a flag which indicates whether the DataSourceFactory with the key |
|
92 | * <code>DEFAULT</code> is a reference to another |
|
93 | * DataSourceFactory. This is important to know when closing the |
|
94 | * DataSourceFactories on shutdown(); |
|
95 | */ |
|
96 | 2 | private boolean defaultDSFIsReference = false; |
97 | ||
98 | /** |
|
99 | * Store mapbuilder classnames for peers that have been referenced prior |
|
100 | * to Torque being initialized. This can happen if torque om/peer objects |
|
101 | * are serialized then unserialized prior to Torque being reinitialized. |
|
102 | * This condition exists in a normal catalina restart. |
|
103 | */ |
|
104 | 2 | private List mapBuilders = null; |
105 | ||
106 | /** |
|
107 | * Creates a new instance with default configuration. |
|
108 | * |
|
109 | * @see #resetConfiguration() |
|
110 | */ |
|
111 | public TorqueInstance() |
|
112 | 2 | { |
113 | 2 | resetConfiguration(); |
114 | 2 | } |
115 | ||
116 | /** |
|
117 | * Initializes this instance of Torque. |
|
118 | * |
|
119 | * @see org.apache.stratum.lifecycle.Initializable |
|
120 | * @throws TorqueException Any exceptions caught during processing will be |
|
121 | * rethrown wrapped into a TorqueException. |
|
122 | */ |
|
123 | private synchronized void initialize() throws TorqueException |
|
124 | { |
|
125 | 2 | log.debug("initialize()"); |
126 | ||
127 | 2 | if (isInit) |
128 | { |
|
129 | 0 | log.debug("Multiple initializations of Torque attempted"); |
130 | 0 | return; |
131 | } |
|
132 | ||
133 | 2 | if (conf == null || conf.isEmpty()) |
134 | { |
|
135 | 0 | throw new TorqueException("Torque cannot be initialized without " |
136 | + "a valid configuration. Please check the log files " |
|
137 | + "for further details."); |
|
138 | } |
|
139 | ||
140 | // Now that we have dealt with processing the log4j properties |
|
141 | // that may be contained in the configuration we will make the |
|
142 | // configuration consist only of the remain torque specific |
|
143 | // properties that are contained in the configuration. First |
|
144 | // look for properties that are in the "torque" namespace. |
|
145 | ||
146 | 2 | Configuration subConf = conf.subset(Torque.TORQUE_KEY); |
147 | 2 | if (subConf == null || subConf.isEmpty()) |
148 | { |
|
149 | 0 | String error = ("Invalid configuration. No keys starting with " |
150 | + Torque.TORQUE_KEY |
|
151 | + " found in configuration"); |
|
152 | 0 | log.error(error); |
153 | 0 | throw new TorqueException(error); |
154 | } |
|
155 | 2 | setConfiguration(subConf); |
156 | ||
157 | 2 | initDefaultDbName(conf); |
158 | 2 | initAdapters(conf); |
159 | 2 | initDataSourceFactories(conf); |
160 | ||
161 | 2 | dbMaps = new HashMap(); |
162 | 2 | for (Iterator i = mapBuilders.iterator(); i.hasNext();) |
163 | { |
|
164 | //this will add any maps in this builder to the proper database map |
|
165 | 0 | BasePeer.getMapBuilder((String) i.next()); |
166 | } |
|
167 | // any further mapBuilders will be called/built on demand |
|
168 | 2 | mapBuilders = null; |
169 | ||
170 | // setup manager mappings |
|
171 | 2 | initManagerMappings(conf); |
172 | ||
173 | 2 | isInit = true; |
174 | 2 | } |
175 | ||
176 | ||
177 | /** |
|
178 | * initializes the name of the default database |
|
179 | * @param conf the configuration representing the torque section |
|
180 | * of the properties file |
|
181 | * @throws TorqueException if the appropriate key is not set |
|
182 | */ |
|
183 | private final void initDefaultDbName(Configuration conf) |
|
184 | throws TorqueException |
|
185 | { |
|
186 | // Determine default database name. |
|
187 | 2 | defaultDBName = |
188 | conf.getString( |
|
189 | Torque.DATABASE_KEY |
|
190 | + "." |
|
191 | + Torque.DEFAULT_KEY); |
|
192 | 2 | if (defaultDBName == null) |
193 | { |
|
194 | 0 | String error = "Invalid configuration: Key " |
195 | + Torque.TORQUE_KEY |
|
196 | + "." |
|
197 | + Torque.DATABASE_KEY |
|
198 | + "." |
|
199 | + Torque.DEFAULT_KEY |
|
200 | + " not set"; |
|
201 | 0 | log.error(error); |
202 | 0 | throw new TorqueException(error); |
203 | } |
|
204 | 2 | } |
205 | ||
206 | /** |
|
207 | * |
|
208 | * @param conf the Configuration representing the torque section of the |
|
209 | * properties file |
|
210 | * @throws TorqueException Any exceptions caught during processing will be |
|
211 | * rethrown wrapped into a TorqueException. |
|
212 | */ |
|
213 | private final void initAdapters(Configuration conf) |
|
214 | throws TorqueException |
|
215 | { |
|
216 | 2 | log.debug("initAdapters(" + conf + ")"); |
217 | 2 | adapterMap = new HashMap(); |
218 | ||
219 | 2 | Configuration c = conf.subset(Torque.DATABASE_KEY); |
220 | 2 | if (c == null || c.isEmpty()) |
221 | { |
|
222 | 0 | String error = "Invalid configuration : " |
223 | + "No keys starting with " |
|
224 | + Torque.TORQUE_KEY |
|
225 | + "." |
|
226 | + Torque.DATABASE_KEY |
|
227 | + " found in configuration"; |
|
228 | 0 | log.error(error); |
229 | 0 | throw new TorqueException(error); |
230 | } |
|
231 | ||
232 | try |
|
233 | { |
|
234 | 2 | for (Iterator it = c.getKeys(); it.hasNext(); ) |
235 | { |
|
236 | 4 | String key = (String) it.next(); |
237 | 4 | if (key.endsWith(DB.ADAPTER_KEY)) |
238 | { |
|
239 | 2 | String adapter = c.getString(key); |
240 | 2 | String handle = key.substring(0, key.indexOf('.')); |
241 | 2 | DB db = DBFactory.create(adapter); |
242 | // register the adapter for this name |
|
243 | 2 | adapterMap.put(handle, db); |
244 | 2 | log.debug("Adding " + adapter + " -> " + handle + " as Adapter"); |
245 | } |
|
246 | } |
|
247 | } |
|
248 | 0 | catch (Exception e) |
249 | { |
|
250 | 0 | log.error("Error reading configuration seeking database " |
251 | + "adapters", e); |
|
252 | 0 | throw new TorqueException(e); |
253 | 2 | } |
254 | ||
255 | 2 | if (adapterMap.get(Torque.getDefaultDB()) == null) |
256 | { |
|
257 | 0 | String error = "Invalid configuration : " |
258 | + "No adapter definition found for default DB " |
|
259 | + "An adapter must be defined under " |
|
260 | + Torque.TORQUE_KEY |
|
261 | + "." |
|
262 | + Torque.DATABASE_KEY |
|
263 | + "." |
|
264 | + Torque.getDefaultDB() |
|
265 | + "." |
|
266 | + DB.ADAPTER_KEY; |
|
267 | 0 | log.error(error); |
268 | 0 | throw new TorqueException(error); |
269 | } |
|
270 | 2 | } |
271 | ||
272 | /** |
|
273 | * |
|
274 | * @param conf the Configuration representing the properties file |
|
275 | * @throws TorqueException Any exceptions caught during processing will be |
|
276 | * rethrown wrapped into a TorqueException. |
|
277 | */ |
|
278 | private void initDataSourceFactories(Configuration conf) |
|
279 | throws TorqueException |
|
280 | { |
|
281 | 2 | log.debug("initDataSourceFactories(" + conf + ")"); |
282 | 2 | dsFactoryMap = new HashMap(); |
283 | ||
284 | 2 | Configuration c = conf.subset(DataSourceFactory.DSFACTORY_KEY); |
285 | 2 | if (c == null || c.isEmpty()) |
286 | { |
|
287 | 0 | String error = "Invalid configuration: " |
288 | + "No keys starting with " |
|
289 | + Torque.TORQUE_KEY |
|
290 | + "." |
|
291 | + DataSourceFactory.DSFACTORY_KEY |
|
292 | + " found in configuration"; |
|
293 | 0 | log.error(error); |
294 | 0 | throw new TorqueException(error); |
295 | } |
|
296 | ||
297 | try |
|
298 | { |
|
299 | 2 | for (Iterator it = c.getKeys(); it.hasNext();) |
300 | { |
|
301 | 2 | String key = (String) it.next(); |
302 | 2 | if (key.endsWith(DataSourceFactory.FACTORY_KEY)) |
303 | { |
|
304 | 2 | String classname = c.getString(key); |
305 | 2 | String handle = key.substring(0, key.indexOf('.')); |
306 | 2 | log.debug("handle: " + handle |
307 | + " DataSourceFactory: " + classname); |
|
308 | 2 | Class dsfClass = Class.forName(classname); |
309 | 2 | DataSourceFactory dsf = |
310 | (DataSourceFactory) dsfClass.newInstance(); |
|
311 | 2 | dsf.initialize(c.subset(handle)); |
312 | 2 | dsFactoryMap.put(handle, dsf); |
313 | } |
|
314 | } |
|
315 | } |
|
316 | 0 | catch (Exception e) |
317 | { |
|
318 | 0 | log.error("Error reading adapter configuration", e); |
319 | 0 | throw new TorqueException(e); |
320 | 2 | } |
321 | ||
322 | 2 | if (dsFactoryMap.get(Torque.getDefaultDB()) == null) |
323 | { |
|
324 | 0 | String error = "Invalid configuration : " |
325 | + "No DataSourceFactory definition for default DB found. " |
|
326 | + "A DataSourceFactory must be defined under the key" |
|
327 | + Torque.TORQUE_KEY |
|
328 | + "." |
|
329 | + DataSourceFactory.DSFACTORY_KEY |
|
330 | + "." |
|
331 | + Torque.getDefaultDB() |
|
332 | + "." |
|
333 | + DataSourceFactory.FACTORY_KEY; |
|
334 | 0 | log.error(error); |
335 | 0 | throw new TorqueException(error); |
336 | } |
|
337 | ||
338 | // As there might be a default database configured |
|
339 | // to map "default" onto an existing datasource, we |
|
340 | // must check, whether there _is_ really an entry for |
|
341 | // the "default" in the dsFactoryMap or not. If it is |
|
342 | // not, then add a dummy entry for the "default" |
|
343 | // |
|
344 | // Without this, you can't actually access the "default" |
|
345 | // data-source, even if you have an entry like |
|
346 | // |
|
347 | // database.default = bookstore |
|
348 | // |
|
349 | // in your Torque.properties |
|
350 | // |
|
351 | 2 | String defaultDB = getDefaultDB(); |
352 | ||
353 | 2 | if (dsFactoryMap.get(DEFAULT_NAME) == null |
354 | && !defaultDB.equals(DEFAULT_NAME)) |
|
355 | { |
|
356 | 2 | log.debug("Adding a dummy entry for " |
357 | + DEFAULT_NAME + ", mapped onto " + defaultDB); |
|
358 | 2 | dsFactoryMap.put(DEFAULT_NAME, dsFactoryMap.get(defaultDB)); |
359 | 2 | this.defaultDSFIsReference = true; |
360 | } |
|
361 | 2 | } |
362 | ||
363 | /** |
|
364 | * Initialization of Torque with a properties file. |
|
365 | * |
|
366 | * @param configFile The absolute path to the configuration file. |
|
367 | * @throws TorqueException Any exceptions caught during processing will be |
|
368 | * rethrown wrapped into a TorqueException. |
|
369 | */ |
|
370 | public void init(String configFile) |
|
371 | throws TorqueException |
|
372 | { |
|
373 | 2 | log.debug("init(" + configFile + ")"); |
374 | try |
|
375 | { |
|
376 | 2 | Configuration conf = new PropertiesConfiguration(configFile); |
377 | ||
378 | 2 | log.debug("Config Object is " + conf); |
379 | 2 | init(conf); |
380 | } |
|
381 | 0 | catch (ConfigurationException e) |
382 | { |
|
383 | 0 | throw new TorqueException(e); |
384 | 2 | } |
385 | 2 | } |
386 | ||
387 | /** |
|
388 | * Initialization of Torque with a properties file. |
|
389 | * |
|
390 | * @param conf The Torque configuration. |
|
391 | * @throws TorqueException Any exceptions caught during processing will be |
|
392 | * rethrown wrapped into a TorqueException. |
|
393 | */ |
|
394 | public void init(Configuration conf) |
|
395 | throws TorqueException |
|
396 | { |
|
397 | 2 | log.debug("init(" + conf + ")"); |
398 | 2 | setConfiguration(conf); |
399 | 2 | initialize(); |
400 | 2 | } |
401 | ||
402 | ||
403 | /** |
|
404 | * Creates a mapping between classes and their manager classes. |
|
405 | * |
|
406 | * The mapping is built according to settings present in |
|
407 | * properties file. The entries should have the |
|
408 | * following form: |
|
409 | * |
|
410 | * <pre> |
|
411 | * torque.managed_class.com.mycompany.Myclass.manager= \ |
|
412 | * com.mycompany.MyManagerImpl |
|
413 | * services.managed_class.com.mycompany.Myotherclass.manager= \ |
|
414 | * com.mycompany.MyOtherManagerImpl |
|
415 | * </pre> |
|
416 | * |
|
417 | * <br> |
|
418 | * |
|
419 | * Generic ServiceBroker provides no Services. |
|
420 | * |
|
421 | * @param conf the Configuration representing the properties file |
|
422 | * @throws TorqueException Any exceptions caught during processing will be |
|
423 | * rethrown wrapped into a TorqueException. |
|
424 | */ |
|
425 | protected void initManagerMappings(Configuration conf) |
|
426 | throws TorqueException |
|
427 | { |
|
428 | 2 | int pref = Torque.MANAGER_PREFIX.length(); |
429 | 2 | int suff = Torque.MANAGER_SUFFIX.length(); |
430 | ||
431 | 2 | for (Iterator it = conf.getKeys(); it.hasNext();) |
432 | { |
|
433 | 8 | String key = (String) it.next(); |
434 | ||
435 | 8 | if (key.startsWith(Torque.MANAGER_PREFIX) |
436 | && key.endsWith(Torque.MANAGER_SUFFIX)) |
|
437 | { |
|
438 | 0 | String managedClassKey = key.substring(pref, |
439 | key.length() - suff); |
|
440 | 0 | if (!managers.containsKey(managedClassKey)) |
441 | { |
|
442 | 0 | String managerClass = conf.getString(key); |
443 | 0 | log.info("Added Manager for Class: " + managedClassKey |
444 | + " -> " + managerClass); |
|
445 | try |
|
446 | { |
|
447 | 0 | initManager(managedClassKey, managerClass); |
448 | } |
|
449 | 0 | catch (TorqueException e) |
450 | { |
|
451 | // the exception thrown here seems to disappear. |
|
452 | // At least when initialized by Turbine, should find |
|
453 | // out why, but for now make sure it is noticed. |
|
454 | 0 | log.error("", e); |
455 | 0 | e.printStackTrace(); |
456 | 0 | throw e; |
457 | 8 | } |
458 | } |
|
459 | } |
|
460 | } |
|
461 | 2 | } |
462 | ||
463 | /** |
|
464 | * Initialize a manager |
|
465 | * |
|
466 | * @param name name of the manager |
|
467 | * @param className name of the manager class |
|
468 | * @throws TorqueException Any exceptions caught during processing will be |
|
469 | * rethrown wrapped into a TorqueException. |
|
470 | */ |
|
471 | private synchronized void initManager(String name, String className) |
|
472 | throws TorqueException |
|
473 | { |
|
474 | 0 | AbstractBaseManager manager = (AbstractBaseManager) managers.get(name); |
475 | ||
476 | 0 | if (manager == null) |
477 | { |
|
478 | 0 | if (className != null && className.length() != 0) |
479 | { |
|
480 | try |
|
481 | { |
|
482 | 0 | manager = (AbstractBaseManager) |
483 | Class.forName(className).newInstance(); |
|
484 | 0 | managers.put(name, manager); |
485 | } |
|
486 | 0 | catch (Exception e) |
487 | { |
|
488 | 0 | throw new TorqueException("Could not instantiate " |
489 | + "manager associated with class: " |
|
490 | + name, e); |
|
491 | 0 | } |
492 | } |
|
493 | } |
|
494 | 0 | } |
495 | ||
496 | /** |
|
497 | * Determine whether Torque has already been initialized. |
|
498 | * |
|
499 | * @return true if Torque is already initialized |
|
500 | */ |
|
501 | public boolean isInit() |
|
502 | { |
|
503 | 21 | return isInit; |
504 | } |
|
505 | ||
506 | /** |
|
507 | * Sets the configuration for Torque and all dependencies. |
|
508 | * |
|
509 | * @param conf the Configuration |
|
510 | */ |
|
511 | public void setConfiguration(Configuration conf) |
|
512 | { |
|
513 | 4 | log.debug("setConfiguration(" + conf + ")"); |
514 | 4 | this.conf = conf; |
515 | 4 | } |
516 | ||
517 | /** |
|
518 | * Get the configuration for this component. |
|
519 | * |
|
520 | * @return the Configuration |
|
521 | */ |
|
522 | public Configuration getConfiguration() |
|
523 | { |
|
524 | 7 | log.debug("getConfiguration() = " + conf); |
525 | 7 | return conf; |
526 | } |
|
527 | ||
528 | /** |
|
529 | * This method returns a Manager for the given name. |
|
530 | * |
|
531 | * @param name name of the manager |
|
532 | * @return a Manager |
|
533 | */ |
|
534 | public AbstractBaseManager getManager(String name) |
|
535 | { |
|
536 | 0 | AbstractBaseManager m = (AbstractBaseManager) managers.get(name); |
537 | 0 | if (m == null) |
538 | { |
|
539 | 0 | log.error("No configured manager for key " + name + "."); |
540 | } |
|
541 | 0 | return m; |
542 | } |
|
543 | ||
544 | /** |
|
545 | * This methods returns either the Manager from the configuration file, |
|
546 | * or the default one provided by the generated code. |
|
547 | * |
|
548 | * @param name name of the manager |
|
549 | * @param defaultClassName the class to use if name has not been configured |
|
550 | * @return a Manager |
|
551 | */ |
|
552 | public AbstractBaseManager getManager(String name, |
|
553 | String defaultClassName) |
|
554 | { |
|
555 | 0 | AbstractBaseManager m = (AbstractBaseManager) managers.get(name); |
556 | 0 | if (m == null) |
557 | { |
|
558 | 0 | log.debug("Added late Manager mapping for Class: " |
559 | + name + " -> " + defaultClassName); |
|
560 | ||
561 | try |
|
562 | { |
|
563 | 0 | initManager(name, defaultClassName); |
564 | } |
|
565 | 0 | catch (TorqueException e) |
566 | { |
|
567 | 0 | log.error(e.getMessage(), e); |
568 | 0 | } |
569 | ||
570 | // Try again now that the default manager should be in the map |
|
571 | 0 | m = (AbstractBaseManager) managers.get(name); |
572 | } |
|
573 | ||
574 | 0 | return m; |
575 | } |
|
576 | ||
577 | /** |
|
578 | * Shuts down the service. |
|
579 | * |
|
580 | * This method halts the IDBroker's daemon thread in all of |
|
581 | * the DatabaseMap's. It also closes all SharedPoolDataSourceFactories |
|
582 | * and PerUserPoolDataSourceFactories initialized by Torque. |
|
583 | * @exception TorqueException if a DataSourceFactory could not be closed |
|
584 | * cleanly. Only the first exception is rethrown, any following |
|
585 | * exceptions are logged but ignored. |
|
586 | */ |
|
587 | public synchronized void shutdown() |
|
588 | throws TorqueException |
|
589 | { |
|
590 | 0 | if (dbMaps != null) |
591 | { |
|
592 | 0 | for (Iterator it = dbMaps.values().iterator(); it.hasNext();) |
593 | { |
|
594 | 0 | DatabaseMap map = (DatabaseMap) it.next(); |
595 | 0 | IDBroker idBroker = map.getIDBroker(); |
596 | 0 | if (idBroker != null) |
597 | { |
|
598 | 0 | idBroker.stop(); |
599 | } |
|
600 | } |
|
601 | } |
|
602 | 0 | TorqueException exception = null; |
603 | 0 | for (Iterator it = dsFactoryMap.keySet().iterator(); it.hasNext();) |
604 | { |
|
605 | 0 | Object dsfKey = it.next(); |
606 | ||
607 | 0 | if (DEFAULT_NAME.equals(dsfKey) && defaultDSFIsReference) |
608 | { |
|
609 | // the entry with the key DEFAULT_NAME |
|
610 | // is just a reference to aynother entry. Do not close because |
|
611 | // this leads to closing the same DataSourceFactory twice. |
|
612 | 0 | it.remove(); |
613 | 0 | break; |
614 | } |
|
615 | ||
616 | 0 | DataSourceFactory dsf |
617 | = (DataSourceFactory) dsFactoryMap.get(dsfKey); |
|
618 | try |
|
619 | { |
|
620 | 0 | dsf.close(); |
621 | 0 | it.remove(); |
622 | } |
|
623 | 0 | catch (TorqueException e) |
624 | { |
|
625 | 0 | log.error("Error while closing the DataSourceFactory " |
626 | + dsfKey, |
|
627 | e); |
|
628 | 0 | if (exception == null) |
629 | { |
|
630 | 0 | exception = e; |
631 | } |
|
632 | 0 | } |
633 | } |
|
634 | 0 | if (exception != null) |
635 | { |
|
636 | 0 | throw exception; |
637 | } |
|
638 | 0 | resetConfiguration(); |
639 | 0 | } |
640 | ||
641 | /** |
|
642 | * Resets some internal configuration variables to |
|
643 | * their defaults. |
|
644 | */ |
|
645 | private void resetConfiguration() |
|
646 | { |
|
647 | 2 | mapBuilders = Collections.synchronizedList(new ArrayList()); |
648 | 2 | managers = new HashMap(); |
649 | 2 | isInit = false; |
650 | 2 | } |
651 | ||
652 | /** |
|
653 | * Returns the default database map information. |
|
654 | * |
|
655 | * @return A DatabaseMap. |
|
656 | * @throws TorqueException Any exceptions caught during processing will be |
|
657 | * rethrown wrapped into a TorqueException. |
|
658 | */ |
|
659 | public DatabaseMap getDatabaseMap() |
|
660 | throws TorqueException |
|
661 | { |
|
662 | 0 | return getDatabaseMap(getDefaultDB()); |
663 | } |
|
664 | ||
665 | /** |
|
666 | * Returns the database map information. Name relates to the name |
|
667 | * of the connection pool to associate with the map. |
|
668 | * |
|
669 | * @param name The name of the database corresponding to the |
|
670 | * <code>DatabaseMap</code> to retrieve. |
|
671 | * @return The named <code>DatabaseMap</code>. |
|
672 | * @throws TorqueException Any exceptions caught during processing will be |
|
673 | * rethrown wrapped into a TorqueException. |
|
674 | */ |
|
675 | public DatabaseMap getDatabaseMap(String name) |
|
676 | throws TorqueException |
|
677 | { |
|
678 | 13 | if (name == null) |
679 | { |
|
680 | 0 | throw new TorqueException ("DatabaseMap name was null!"); |
681 | } |
|
682 | ||
683 | 13 | if (dbMaps == null) |
684 | { |
|
685 | 0 | throw new TorqueException("Torque was not initialized properly."); |
686 | } |
|
687 | ||
688 | 13 | synchronized (dbMaps) |
689 | { |
|
690 | 13 | DatabaseMap map = (DatabaseMap) dbMaps.get(name); |
691 | 13 | if (map == null) |
692 | { |
|
693 | // Still not there. Create and add. |
|
694 | 1 | map = initDatabaseMap(name); |
695 | } |
|
696 | 13 | return map; |
697 | 0 | } |
698 | } |
|
699 | ||
700 | /** |
|
701 | * Creates and initializes the mape for the named database. |
|
702 | * Assumes that <code>dbMaps</code> member is sync'd. |
|
703 | * |
|
704 | * @param name The name of the database to map. |
|
705 | * @return The desired map. |
|
706 | * @throws TorqueException Any exceptions caught during processing will be |
|
707 | * rethrown wrapped into a TorqueException. |
|
708 | */ |
|
709 | private final DatabaseMap initDatabaseMap(String name) |
|
710 | throws TorqueException |
|
711 | { |
|
712 | 1 | DatabaseMap map = new DatabaseMap(name); |
713 | ||
714 | // Add info about IDBroker's table. |
|
715 | 1 | setupIdTable(map); |
716 | ||
717 | // Setup other ID generators for this map. |
|
718 | try |
|
719 | { |
|
720 | 1 | String key = getDatabaseProperty(name, "adapter"); |
721 | 1 | if (StringUtils.isEmpty(key)) |
722 | { |
|
723 | 0 | key = getDatabaseProperty(name, "driver"); |
724 | } |
|
725 | 1 | DB db = DBFactory.create(key); |
726 | 1 | for (int i = 0; i < IDGeneratorFactory.ID_GENERATOR_METHODS.length; |
727 | 3 | i++) |
728 | { |
|
729 | 3 | map.addIdGenerator(IDGeneratorFactory.ID_GENERATOR_METHODS[i], |
730 | IDGeneratorFactory.create(db, name)); |
|
731 | } |
|
732 | } |
|
733 | 0 | catch (java.lang.InstantiationException e) |
734 | { |
|
735 | 0 | throw new TorqueException(e); |
736 | 1 | } |
737 | ||
738 | // Avoid possible ConcurrentModificationException by |
|
739 | // constructing a copy of dbMaps. |
|
740 | 1 | Map newMaps = new HashMap(dbMaps); |
741 | 1 | newMaps.put(name, map); |
742 | 1 | dbMaps = newMaps; |
743 | ||
744 | 1 | return map; |
745 | } |
|
746 | ||
747 | /** |
|
748 | * Register a MapBuilder |
|
749 | * |
|
750 | * @param className the MapBuilder |
|
751 | */ |
|
752 | public void registerMapBuilder(String className) |
|
753 | { |
|
754 | 0 | mapBuilders.add(className); |
755 | 0 | } |
756 | ||
757 | /** |
|
758 | * Returns the specified property of the given database, or the empty |
|
759 | * string if no value is set for the property. |
|
760 | * |
|
761 | * @param db The name of the database whose property to get. |
|
762 | * @param prop The name of the property to get. |
|
763 | * @return The property's value. |
|
764 | */ |
|
765 | private String getDatabaseProperty(String db, String prop) |
|
766 | { |
|
767 | 1 | return conf.getString(new StringBuffer("database.") |
768 | .append(db) |
|
769 | .append('.') |
|
770 | .append(prop) |
|
771 | .toString(), ""); |
|
772 | } |
|
773 | ||
774 | /** |
|
775 | * Setup IDBroker's table information within given database map. |
|
776 | * |
|
777 | * This method should be called on all new database map to ensure that |
|
778 | * IDBroker functionality is available in all databases used by the |
|
779 | * application. |
|
780 | * |
|
781 | * @param map the DataBaseMap to setup. |
|
782 | */ |
|
783 | private final void setupIdTable(DatabaseMap map) |
|
784 | { |
|
785 | 1 | map.setIdTable("ID_TABLE"); |
786 | 1 | TableMap tMap = map.getIdTable(); |
787 | 1 | tMap.addPrimaryKey("ID_TABLE_ID", new Integer(0)); |
788 | 1 | tMap.addColumn("TABLE_NAME", ""); |
789 | 1 | tMap.addColumn("NEXT_ID", new Integer(0)); |
790 | 1 | tMap.addColumn("QUANTITY", new Integer(0)); |
791 | 1 | } |
792 | ||
793 | /** |
|
794 | * This method returns a Connection from the default pool. |
|
795 | * |
|
796 | * @return The requested connection. |
|
797 | * @throws TorqueException Any exceptions caught during processing will be |
|
798 | * rethrown wrapped into a TorqueException. |
|
799 | */ |
|
800 | public Connection getConnection() |
|
801 | throws TorqueException |
|
802 | { |
|
803 | 0 | return getConnection(getDefaultDB()); |
804 | } |
|
805 | ||
806 | /** |
|
807 | * |
|
808 | * @param name The database name. |
|
809 | * @return a database connection |
|
810 | * @throws TorqueException Any exceptions caught during processing will be |
|
811 | * rethrown wrapped into a TorqueException. |
|
812 | */ |
|
813 | public Connection getConnection(String name) |
|
814 | throws TorqueException |
|
815 | { |
|
816 | 1 | Connection con = null; |
817 | 1 | DataSourceFactory dsf = null; |
818 | ||
819 | try |
|
820 | { |
|
821 | 1 | return getDataSourceFactory(name).getDataSource().getConnection(); |
822 | } |
|
823 | 1 | catch(SQLException se) |
824 | { |
|
825 | 1 | throw new TorqueException(se); |
826 | } |
|
827 | } |
|
828 | ||
829 | /** |
|
830 | * Returns a DataSourceFactory |
|
831 | * |
|
832 | * @param name Name of the DSF to get |
|
833 | * @return A DataSourceFactory object |
|
834 | */ |
|
835 | protected DataSourceFactory getDataSourceFactory(String name) |
|
836 | throws TorqueException |
|
837 | { |
|
838 | 21 | if (!isInit()) |
839 | { |
|
840 | 0 | throw new TorqueException("Torque is not initialized."); |
841 | } |
|
842 | ||
843 | 21 | DataSourceFactory dsf = null; |
844 | ||
845 | try |
|
846 | { |
|
847 | 21 | dsf = (DataSourceFactory) dsFactoryMap.get(name); |
848 | } |
|
849 | 0 | catch (Exception e) |
850 | { |
|
851 | 0 | throw new TorqueException(e); |
852 | 21 | } |
853 | ||
854 | 21 | if (dsf == null) |
855 | { |
|
856 | 0 | throw new NullPointerException( |
857 | "There was no DataSourceFactory " |
|
858 | + "configured for the connection " + name); |
|
859 | } |
|
860 | ||
861 | 21 | return dsf; |
862 | } |
|
863 | ||
864 | /** |
|
865 | * This method returns a Connecton using the given parameters. |
|
866 | * You should only use this method if you need user based access to the |
|
867 | * database! |
|
868 | * |
|
869 | * @param name The database name. |
|
870 | * @param username The name of the database user. |
|
871 | * @param password The password of the database user. |
|
872 | * @return A Connection. |
|
873 | * @throws TorqueException Any exceptions caught during processing will be |
|
874 | * rethrown wrapped into a TorqueException. |
|
875 | */ |
|
876 | public Connection getConnection(String name, String username, |
|
877 | String password) |
|
878 | throws TorqueException |
|
879 | { |
|
880 | try |
|
881 | { |
|
882 | 0 | return getDataSourceFactory(name).getDataSource().getConnection(username, password); |
883 | } |
|
884 | 0 | catch(SQLException se) |
885 | { |
|
886 | 0 | throw new TorqueException(se); |
887 | } |
|
888 | } |
|
889 | ||
890 | /** |
|
891 | * Returns database adapter for a specific connection pool. |
|
892 | * |
|
893 | * @param name A pool name. |
|
894 | * @return The corresponding database adapter. |
|
895 | * @throws TorqueException Any exceptions caught during processing will be |
|
896 | * rethrown wrapped into a TorqueException. |
|
897 | */ |
|
898 | public DB getDB(String name) throws TorqueException |
|
899 | { |
|
900 | 46 | return (DB) adapterMap.get(name); |
901 | } |
|
902 | ||
903 | /////////////////////////////////////////////////////////////////////////// |
|
904 | ||
905 | /** |
|
906 | * Returns the name of the default database. |
|
907 | * |
|
908 | * @return name of the default DB, or null if Torque is not initialized yet |
|
909 | */ |
|
910 | public String getDefaultDB() |
|
911 | { |
|
912 | 32 | return defaultDBName; |
913 | } |
|
914 | ||
915 | /** |
|
916 | * Closes a connection. |
|
917 | * |
|
918 | * @param con A Connection to close. |
|
919 | */ |
|
920 | public void closeConnection(Connection con) |
|
921 | { |
|
922 | 0 | if (con != null) |
923 | { |
|
924 | try |
|
925 | { |
|
926 | 0 | con.close(); |
927 | } |
|
928 | 0 | catch (SQLException e) |
929 | { |
|
930 | 0 | log.error("Error occured while closing connection.", e); |
931 | 0 | } |
932 | } |
|
933 | 0 | } |
934 | ||
935 | /** |
|
936 | * Sets the current schema for a database connection |
|
937 | * |
|
938 | * @param name The database name. |
|
939 | * @param schema The current schema name |
|
940 | * @throws TorqueException Any exceptions caught during processing will be |
|
941 | * rethrown wrapped into a TorqueException. |
|
942 | */ |
|
943 | public void setSchema(String name, String schema) |
|
944 | throws TorqueException |
|
945 | { |
|
946 | 0 | getDataSourceFactory(name).setSchema(schema); |
947 | 0 | } |
948 | ||
949 | /** |
|
950 | * This method returns the current schema for a database connection |
|
951 | * |
|
952 | * @param name The database name. |
|
953 | * @return The current schema name. Null means, no schema has been set. |
|
954 | * @throws TorqueException Any exceptions caught during processing will be |
|
955 | * rethrown wrapped into a TorqueException. |
|
956 | */ |
|
957 | public String getSchema(String name) |
|
958 | throws TorqueException |
|
959 | { |
|
960 | 19 | return getDataSourceFactory(name).getSchema(); |
961 | } |
|
962 | ||
963 | } |
This report is generated by jcoverage, Maven and Maven JCoverage Plugin. |