KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > conf > RuntimeLoadDelegate


1 /*****************************************************************
2  * Licensed to the Apache Software Foundation (ASF) under one
3  * or more contributor license agreements. See the NOTICE file
4  * distributed with this work for additional information
5  * regarding copyright ownership. The ASF licenses this file
6  * to you under the Apache License, Version 2.0 (the
7  * "License"); you may not use this file except in compliance
8  * with the License. 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,
13  * software distributed under the License is distributed on an
14  * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
15  * KIND, either express or implied. See the License for the
16  * specific language governing permissions and limitations
17  * under the License.
18  ****************************************************************/

19
20 package org.apache.cayenne.conf;
21
22 import java.io.InputStream JavaDoc;
23 import java.util.HashMap JavaDoc;
24 import java.util.Iterator JavaDoc;
25 import java.util.Map JavaDoc;
26
27 import javax.sql.DataSource JavaDoc;
28
29 import org.apache.cayenne.ConfigurationException;
30 import org.apache.cayenne.access.DataDomain;
31 import org.apache.cayenne.access.DataNode;
32 import org.apache.cayenne.dba.AutoAdapter;
33 import org.apache.cayenne.dba.DbAdapter;
34 import org.apache.cayenne.map.DataMap;
35 import org.apache.cayenne.map.MapLoader;
36 import org.apache.commons.logging.Log;
37 import org.apache.commons.logging.LogFactory;
38 import org.xml.sax.InputSource JavaDoc;
39
40 /**
41  * Implementation of ConfigLoaderDelegate that creates Cayenne access objects stack.
42  *
43  * @author Andrus Adamchik
44  */

45 public class RuntimeLoadDelegate implements ConfigLoaderDelegate {
46
47     private static final Log logger = LogFactory.getLog(RuntimeLoadDelegate.class);
48
49     // TODO: andrus, 7/17/2006 - these variables, and project upgrade logic should be
50
// refactored out of the MapLoader. In fact we should either modify raw XML during the
51
// upgrade, or implement some consistent upgrade API across variou loaders
52
final static String JavaDoc _1_2_PACKAGE_PREFIX = "org.objectstyle.cayenne.";
53     final static String JavaDoc _2_0_PACKAGE_PREFIX = "org.apache.cayenne.";
54
55     protected Map JavaDoc domains = new HashMap JavaDoc();
56     protected Map JavaDoc views = new HashMap JavaDoc();
57     protected ConfigStatus status;
58     protected Configuration config;
59     protected long startTime;
60     protected MapLoader mapLoader;
61
62     public RuntimeLoadDelegate(Configuration config, ConfigStatus status) {
63
64         this.config = config;
65
66         if (status == null) {
67             status = new ConfigStatus();
68         }
69
70         this.status = status;
71     }
72
73     protected DataDomain findDomain(String JavaDoc name) throws FindException {
74         DataDomain domain = (DataDomain) domains.get(name);
75         if (domain == null) {
76             throw new FindException("Can't find DataDomain: " + name);
77         }
78
79         return domain;
80     }
81
82     protected DataMap findMap(String JavaDoc domainName, String JavaDoc mapName) throws FindException {
83         DataDomain domain = findDomain(domainName);
84         DataMap map = domain.getMap(mapName);
85         if (map == null) {
86             throw new FindException("Can't find DataMap: " + mapName);
87         }
88
89         return map;
90     }
91
92     protected DataNode findNode(String JavaDoc domainName, String JavaDoc nodeName) throws FindException {
93         DataDomain domain = findDomain(domainName);
94         DataNode node = domain.getNode(nodeName);
95         if (node == null) {
96             throw new FindException("Can't find DataNode: " + nodeName);
97         }
98
99         return node;
100     }
101
102     public boolean loadError(Throwable JavaDoc th) {
103         logger.info("Parser Exception.", th);
104         status.getOtherFailures().add(th.getMessage());
105         return false;
106     }
107
108     /**
109      * @since 1.1
110      */

111     public void shouldLoadProjectVersion(String JavaDoc version) {
112         config.setProjectVersion(version);
113     }
114
115     /**
116      * @since 1.1
117      */

118     public void shouldRegisterDataView(String JavaDoc name, String JavaDoc location) {
119         views.put(name, location);
120     }
121
122     public void shouldLoadDataDomainProperties(String JavaDoc domainName, Map JavaDoc properties) {
123         if (properties == null || properties.isEmpty()) {
124             return;
125         }
126
127         DataDomain domain = null;
128         try {
129             domain = findDomain(domainName);
130         }
131         catch (FindException ex) {
132             logger.info("Error: Domain is not loaded: " + domainName);
133             throw new ConfigurationException("Domain is not loaded: " + domainName);
134         }
135
136         domain.initWithProperties(properties);
137     }
138
139     public void shouldLoadDataDomain(String JavaDoc domainName) {
140         if (domainName == null) {
141             logger.info("Error: unnamed <domain>.");
142             throw new ConfigurationException("Domain 'name' attribute must be not null.");
143         }
144
145         logger.info("loaded domain: " + domainName);
146         domains.put(domainName, new DataDomain(domainName));
147     }
148
149     public void shouldLoadDataMaps(String JavaDoc domainName, Map JavaDoc locations) {
150         if (locations.size() == 0) {
151             return;
152         }
153
154         DataDomain domain = null;
155         try {
156             domain = findDomain(domainName);
157         }
158         catch (FindException ex) {
159             logger.info("Error: Domain is not loaded: " + domainName);
160             throw new ConfigurationException("Domain is not loaded: " + domainName);
161         }
162
163         // load DataMaps tree
164
Iterator JavaDoc it = locations.keySet().iterator();
165         while (it.hasNext()) {
166             String JavaDoc name = (String JavaDoc) it.next();
167             DataMap map = domain.getMap(name);
168             if (map != null) {
169                 continue;
170             }
171
172             loadDataMap(domain, name, locations);
173         }
174     }
175
176     protected MapLoader getMapLoader() {
177         // it is worth caching the map loader, as it precompiles some XML operations
178
// starting from release 3.0
179
if (mapLoader == null) {
180             mapLoader = new MapLoader();
181         }
182
183         return mapLoader;
184     }
185
186     /**
187      * Returns DataMap for the name and location information. If a DataMap is already
188      * loaded within a given domain, such loaded map is returned, otherwise the map is
189      * loaded and linked with the DataDomain.
190      */

191     protected DataMap loadDataMap(DataDomain domain, String JavaDoc mapName, Map JavaDoc locations) {
192
193         if (mapName == null) {
194             throw new ConfigurationException("Error: <map> without 'name'.");
195         }
196
197         String JavaDoc location = (String JavaDoc) locations.get(mapName);
198
199         if (location == null) {
200             throw new ConfigurationException("Error: map '"
201                     + mapName
202                     + "' without 'location'.");
203         }
204
205         // load DataMap
206
InputStream JavaDoc mapIn = config.getMapConfiguration(location);
207         if (mapIn == null) {
208             logger.info("Warning: map location not found.");
209             getStatus().addFailedMap(mapName, location, "map location not found");
210             return null;
211         }
212
213         try {
214             DataMap map = getMapLoader().loadDataMap(new InputSource JavaDoc(mapIn));
215
216             logger.info("loaded <map name='"
217                     + mapName
218                     + "' location='"
219                     + location
220                     + "'>.");
221
222             map.setName(mapName);
223             map.setLocation(location);
224
225             domain.addMap(map);
226             return map;
227         }
228         catch (Exception JavaDoc dmex) {
229             logger.info("Warning: map loading failed.", dmex);
230             getStatus().addFailedMap(
231                     mapName,
232                     location,
233                     "map loading failed - " + dmex.getMessage());
234             return null;
235         }
236     }
237
238     /**
239      * Creates a new DataNode. Subclasses may override this method to provide a custom
240      * node class.
241      *
242      * @since 1.
243      */

244     protected DataNode createDataNode(String JavaDoc nodeName) {
245         return new DataNode(nodeName);
246     }
247
248     public void shouldLoadDataNode(
249             String JavaDoc domainName,
250             String JavaDoc nodeName,
251             String JavaDoc dataSource,
252             String JavaDoc adapter,
253             String JavaDoc factory) {
254
255         logger.info("loading <node name='"
256                 + nodeName
257                 + "' datasource='"
258                 + dataSource
259                 + "' factory='"
260                 + factory
261                 + "'>.");
262
263         if (nodeName == null) {
264             throw new ConfigurationException("Error: <node> without 'name'.");
265         }
266
267         factory = convertClassNameFromV1_2(factory);
268         adapter = convertClassNameFromV1_2(adapter);
269
270         if (dataSource == null) {
271             logger.info("Warning: <node> '" + nodeName + "' has no 'datasource'.");
272         }
273
274         if (factory == null) {
275             if (config.getDataSourceFactory() != null) {
276                 logger.info("Warning: <node> '" + nodeName + "' without 'factory'.");
277             }
278             else {
279                 throw new ConfigurationException("Error: <node> '"
280                         + nodeName
281                         + "' without 'factory'.");
282             }
283         }
284
285         DataNode node = createDataNode(nodeName);
286
287         node.setDataSourceFactory(factory);
288         node.setDataSourceLocation(dataSource);
289
290         // load DataSource
291
try {
292             // use DomainHelper factory if it exists, if not - use factory specified
293
// in configuration data
294
DataSourceFactory confFactory = config.getDataSourceFactory();
295             DataSourceFactory localFactory = (confFactory != null)
296                     ? confFactory
297                     : (DataSourceFactory) Class.forName(factory).newInstance();
298
299             logger.info("using factory: " + localFactory.getClass().getName());
300
301             localFactory.initializeWithParentConfiguration(config);
302             DataSource JavaDoc ds = localFactory.getDataSource(dataSource);
303             if (ds != null) {
304                 logger.info("loaded datasource.");
305                 node.setDataSource(ds);
306             }
307             else {
308                 logger.info("Warning: null datasource.");
309                 getStatus().getFailedDataSources().put(nodeName, dataSource);
310             }
311         }
312         catch (Exception JavaDoc ex) {
313             logger.info("Error: DataSource load failed", ex);
314             getStatus().addFailedDataSource(
315                     nodeName,
316                     dataSource,
317                     "DataSource load failed - " + ex.getMessage());
318         }
319
320         initAdapter(node, adapter);
321
322         try {
323             findDomain(domainName).addNode(node);
324         }
325         catch (FindException ex) {
326             logger.info("Error: can't load node, unknown domain: " + domainName);
327             getStatus().addFailedDataSource(
328                     nodeName,
329                     nodeName,
330                     "can't load node, unknown domain: " + domainName);
331         }
332     }
333
334     /**
335      * @since 2.0
336      */

337     String JavaDoc convertClassNameFromV1_2(String JavaDoc name) {
338         if (name == null) {
339             return null;
340         }
341
342         // upgrade from v. <= 1.2
343
if (name.startsWith(_1_2_PACKAGE_PREFIX)) {
344             return _2_0_PACKAGE_PREFIX + name.substring(_1_2_PACKAGE_PREFIX.length());
345         }
346
347         return name;
348     }
349
350     /**
351      * Intializes DataNode adapter.
352      *
353      * @since 1.2
354      */

355     protected void initAdapter(DataNode node, String JavaDoc adapterName) {
356
357         if (adapterName != null) {
358             try {
359                 ClassLoader JavaDoc cl = Thread.currentThread().getContextClassLoader();
360                 Class JavaDoc dbAdapterClass = Class.forName(adapterName, true, cl);
361                 node.setAdapter((DbAdapter) dbAdapterClass.newInstance());
362                 return;
363             }
364             catch (Exception JavaDoc ex) {
365                 logger.info("instantiating adapter failed", ex);
366                 getStatus().addFailedAdapter(
367                         node.getName(),
368                         adapterName,
369                         "instantiating adapter failed - " + ex.getMessage());
370             }
371         }
372
373         logger.info("no adapter set, using automatic adapter.");
374         node.setAdapter(new AutoAdapter(new NodeDataSource(node)));
375     }
376
377     public void shouldLinkDataMap(String JavaDoc domainName, String JavaDoc nodeName, String JavaDoc mapName) {
378
379         if (mapName == null) {
380             logger.info("<map-ref> has no 'name'.");
381             throw new ConfigurationException("<map-ref> has no 'name'.");
382         }
383
384         logger.info("loaded map-ref: " + mapName + ".");
385         DataMap map = null;
386         DataNode node = null;
387
388         try {
389             map = findMap(domainName, mapName);
390         }
391         catch (FindException ex) {
392             logger.info("Error: unknown map: " + mapName);
393             getStatus().addFailedMapRefs(mapName, "unknown map: " + mapName);
394             return;
395         }
396
397         try {
398             node = findNode(domainName, nodeName);
399         }
400         catch (FindException ex) {
401             logger.info("Error: unknown node: " + nodeName);
402             getStatus().addFailedMapRefs(mapName, "unknown node: " + nodeName);
403             return;
404         }
405
406         node.addDataMap(map);
407     }
408
409     /**
410      * Returns the domains.
411      *
412      * @return List
413      */

414     public Map JavaDoc getDomains() {
415         return domains;
416     }
417
418     /**
419      * Returns the status.
420      *
421      * @return ConfigStatus
422      */

423     public ConfigStatus getStatus() {
424         return status;
425     }
426
427     /**
428      * Returns the config.
429      *
430      * @return Configuration
431      */

432     public Configuration getConfig() {
433         return config;
434     }
435
436     /**
437      * Sets the config.
438      *
439      * @param config The config to set
440      */

441     public void setConfig(Configuration config) {
442         this.config = config;
443     }
444
445     /**
446      * @see org.apache.cayenne.conf.ConfigLoaderDelegate#finishedLoading()
447      */

448     public void finishedLoading() {
449         // check for failures
450
if (status.hasFailures()) {
451             if (!config.isIgnoringLoadFailures()) {
452                 StringBuffer JavaDoc msg = new StringBuffer JavaDoc(128);
453                 msg.append("Load failures. Main configuration class: ");
454                 msg.append(config.getClass().getName());
455                 msg.append(", details: ");
456                 msg.append(status.describeFailures());
457                 throw new ConfigurationException(msg.toString());
458             }
459         }
460
461         // update configuration object
462
Iterator JavaDoc it = getDomains().values().iterator();
463         while (it.hasNext()) {
464             config.addDomain((DataDomain) it.next());
465         }
466
467         config.setDataViewLocations(views);
468
469         logger.info("finished configuration loading in "
470                 + (System.currentTimeMillis() - startTime)
471                 + " ms.");
472     }
473
474     /**
475      * @see org.apache.cayenne.conf.ConfigLoaderDelegate#startedLoading()
476      */

477     public void startedLoading() {
478         startTime = System.currentTimeMillis();
479         logger.info("started configuration loading.");
480     }
481
482     /**
483      * Thrown when loaded data does not contain certain expected objects.
484      */

485     class FindException extends Exception JavaDoc {
486
487         /**
488          * Constructor for FindException.
489          *
490          * @param msg
491          */

492         public FindException(String JavaDoc msg) {
493             super(msg);
494         }
495     }
496 }
497
Popular Tags