KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > jboss > ejb > plugins > cmp > jdbc > metadata > JDBCApplicationMetaData


1 /*
2 * JBoss, Home of Professional Open Source
3 * Copyright 2005, JBoss Inc., and individual contributors as indicated
4 * by the @authors tag. See the copyright.txt in the distribution for a
5 * full listing of individual contributors.
6 *
7 * This is free software; you can redistribute it and/or modify it
8 * under the terms of the GNU Lesser General Public License as
9 * published by the Free Software Foundation; either version 2.1 of
10 * the License, or (at your option) any later version.
11 *
12 * This software is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this software; if not, write to the Free
19 * Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA
20 * 02110-1301 USA, or see the FSF site: http://www.fsf.org.
21 */

22 package org.jboss.ejb.plugins.cmp.jdbc.metadata;
23
24 import java.util.ArrayList JavaDoc;
25 import java.util.Collection JavaDoc;
26 import java.util.Collections JavaDoc;
27 import java.util.HashMap JavaDoc;
28 import java.util.HashSet JavaDoc;
29 import java.util.Iterator JavaDoc;
30 import java.util.Map JavaDoc;
31
32 import org.w3c.dom.Element JavaDoc;
33
34 import org.jboss.deployment.DeploymentException;
35 import org.jboss.metadata.ApplicationMetaData;
36 import org.jboss.metadata.BeanMetaData;
37 import org.jboss.metadata.EntityMetaData;
38 import org.jboss.metadata.MetaData;
39 import org.jboss.metadata.RelationMetaData;
40
41 import org.jboss.ejb.plugins.cmp.jdbc.SQLUtil;
42
43 /**
44  * This immutable class contains information about the application
45  *
46  * @author <a HREF="mailto:dain@daingroup.com">Dain Sundstrom</a>
47  * @author <a HREF="sebastien.alborini@m4x.org">Sebastien Alborini</a>
48  * @author <a HREF="alex@jboss.org">Alexey Loubyansky</a>
49  * @version $Revision: 37459 $
50  */

51 public final class JDBCApplicationMetaData
52 {
53    private final static Class JavaDoc JDBC_PM = org.jboss.ejb.plugins.cmp.jdbc.JDBCStoreManager.class;
54
55    /**
56     * The class loader for this application. The class loader is used to
57     * load all classes used by this application.
58     */

59    private final ClassLoader JavaDoc classLoader;
60
61    /**
62     * Application metadata loaded from the ejb-jar.xml file
63     */

64    private final ApplicationMetaData applicationMetaData;
65
66    /**
67     * Map with user defined type mapping, e.g. enum mappings
68     */

69    private final Map JavaDoc userTypeMappings;
70
71    /**
72     * Map of the type mappings by name.
73     */

74    private final Map JavaDoc typeMappings = new HashMap JavaDoc();
75
76    /**
77     * Map of the entities managed by jbosscmp-jdbc by bean name.
78     */

79    private final Map JavaDoc entities = new HashMap JavaDoc();
80
81    /**
82     * Collection of relations in this application.
83     */

84    private final Collection JavaDoc relationships = new HashSet JavaDoc();
85
86    /**
87     * Map of the collection relationship roles for each entity by entity object.
88     */

89    private final Map JavaDoc entityRoles = new HashMap JavaDoc();
90
91    /**
92     * Map of the dependent value classes by java class type.
93     */

94    private final Map JavaDoc valueClasses = new HashMap JavaDoc();
95
96    /**
97     * Map from abstract schema name to entity name
98     */

99    private final Map JavaDoc entitiesByAbstractSchemaName = new HashMap JavaDoc();
100
101    /**
102     * Map from entity interface(s) java type to entity name
103     */

104    private final Map JavaDoc entitiesByInterface = new HashMap JavaDoc();
105
106    /**
107     * Map of the entity commands by name.
108     */

109    private final Map JavaDoc entityCommands = new HashMap JavaDoc();
110
111    /**
112     * Constructs jdbc application meta data with the data from the
113     * applicationMetaData.
114     *
115     * @param applicationMetaData the application data loaded from
116     * the ejb-jar.xml file
117     * @param classLoader the ClassLoader used to load the classes
118     * of the application
119     * @throws DeploymentException if an problem occures while loading
120     * the classes or if data in the ejb-jar.xml is inconsistent
121     * with data from jbosscmp-jdbc.xml file
122     */

123    public JDBCApplicationMetaData(ApplicationMetaData applicationMetaData, ClassLoader JavaDoc classLoader)
124       throws DeploymentException
125    {
126       // the classloader is the same for all the beans in the application
127
this.classLoader = classLoader;
128       this.applicationMetaData = applicationMetaData;
129
130       // create metadata for all jbosscmp-jdbc-managed cmp entities
131
// we do that here in case there is no jbosscmp-jdbc.xml
132
Iterator JavaDoc beans = applicationMetaData.getEnterpriseBeans();
133       while(beans.hasNext())
134       {
135          BeanMetaData bean = (BeanMetaData)beans.next();
136
137          // only take entities
138
if(bean.isEntity())
139          {
140             EntityMetaData entity = (EntityMetaData)bean;
141
142             // only take jbosscmp-jdbc-managed CMP entities
143
Class JavaDoc pm;
144             try
145             {
146                pm = classLoader.loadClass(entity.getContainerConfiguration().getPersistenceManager());
147             }
148             catch (ClassNotFoundException JavaDoc e)
149             {
150                throw new DeploymentException("Unable to load persistence manager", e);
151             }
152             if(entity.isCMP() &&
153                (JDBC_PM.isAssignableFrom(pm) || pm.getName().equals("org.jboss.ejb.plugins.cmp.jdbc2.JDBCStoreManager2")))
154             {
155                JDBCEntityMetaData jdbcEntity = new JDBCEntityMetaData(this, entity);
156
157                entities.put(entity.getEjbName(), jdbcEntity);
158
159                String JavaDoc schemaName = jdbcEntity.getAbstractSchemaName();
160                if(schemaName != null)
161                {
162                   entitiesByAbstractSchemaName.put(schemaName, jdbcEntity);
163                }
164
165                Class JavaDoc remote = jdbcEntity.getRemoteClass();
166                if(remote != null)
167                {
168                   entitiesByInterface.put(remote, jdbcEntity);
169                }
170
171                Class JavaDoc local = jdbcEntity.getLocalClass();
172                if(local != null)
173                {
174                   entitiesByInterface.put(local, jdbcEntity);
175                }
176
177                // initialized the entity roles collection
178
entityRoles.put(entity.getEjbName(), new HashSet JavaDoc());
179             }
180          }
181       }
182
183       // relationships
184
Iterator JavaDoc iterator = applicationMetaData.getRelationships();
185       while(iterator.hasNext())
186       {
187          RelationMetaData relation = (RelationMetaData)iterator.next();
188
189          // Relationship metadata
190
JDBCRelationMetaData jdbcRelation =
191             new JDBCRelationMetaData(this, relation);
192          relationships.add(jdbcRelation);
193
194          // Left relationship-role metadata
195
JDBCRelationshipRoleMetaData left =
196             jdbcRelation.getLeftRelationshipRole();
197          Collection JavaDoc leftEntityRoles =
198             (Collection JavaDoc)entityRoles.get(left.getEntity().getName());
199          leftEntityRoles.add(left);
200
201          // Right relationship-role metadata
202
JDBCRelationshipRoleMetaData right =
203             jdbcRelation.getRightRelationshipRole();
204          Collection JavaDoc rightEntityRoles =
205             (Collection JavaDoc)entityRoles.get(right.getEntity().getName());
206          rightEntityRoles.add(right);
207       }
208
209       userTypeMappings = Collections.EMPTY_MAP;
210    }
211
212    /**
213     * Constructs application meta data with the data contained in the
214     * jboss-cmp xml element from a jbosscmp-jdbc xml file. Optional values
215     * of the xml element that are not present are loaded from the
216     * defalutValues parameter.
217     *
218     * @param element the xml Element which contains the metadata about
219     * this application
220     * @param defaultValues the JDBCApplicationMetaData which contains
221     * the values
222     * for optional elements of the element
223     * @throws DeploymentException if the xml element is not semantically correct
224     */

225    public JDBCApplicationMetaData(Element JavaDoc element, JDBCApplicationMetaData defaultValues)
226       throws DeploymentException
227    {
228       // importXml will be called at least once: with standardjbosscmp-jdbc.xml
229
// it may be called a second time with user-provided jbosscmp-jdbc.xml
230
// we must ensure to set all defaults values in the first call
231

232       classLoader = defaultValues.classLoader;
233       applicationMetaData = defaultValues.applicationMetaData;
234
235       Element JavaDoc userTypeMaps = MetaData.getOptionalChild(element, "user-type-mappings");
236       if(userTypeMaps != null)
237       {
238          userTypeMappings = new HashMap JavaDoc();
239          Iterator JavaDoc iter = MetaData.getChildrenByTagName(userTypeMaps, "user-type-mapping");
240          while(iter.hasNext())
241          {
242             Element JavaDoc userTypeMappingEl = (Element JavaDoc)iter.next();
243             JDBCUserTypeMappingMetaData userTypeMapping = new JDBCUserTypeMappingMetaData(userTypeMappingEl);
244             userTypeMappings.put(userTypeMapping.getJavaType(), userTypeMapping);
245          }
246       }
247       else
248          userTypeMappings = defaultValues.getUserTypeMappings();
249
250       // type-mappings: (optional, always set in standardjbosscmp-jdbc.xml)
251
typeMappings.putAll(defaultValues.typeMappings);
252       Element JavaDoc typeMaps = MetaData.getOptionalChild(element, "type-mappings");
253       if(typeMaps != null)
254       {
255          for(Iterator JavaDoc i = MetaData.getChildrenByTagName(typeMaps, "type-mapping"); i.hasNext();)
256          {
257             Element JavaDoc typeMappingElement = (Element JavaDoc)i.next();
258             JDBCTypeMappingMetaData typeMapping =
259                new JDBCTypeMappingMetaData(typeMappingElement);
260             typeMappings.put(typeMapping.getName(), typeMapping);
261          }
262       }
263
264       // dependent-value-objects
265
valueClasses.putAll(defaultValues.valueClasses);
266       Element JavaDoc valueClassesElement =
267          MetaData.getOptionalChild(element, "dependent-value-classes");
268       if(valueClassesElement != null)
269       {
270          for(Iterator JavaDoc i = MetaData.getChildrenByTagName(
271             valueClassesElement, "dependent-value-class");
272              i.hasNext();)
273          {
274
275             Element JavaDoc valueClassElement = (Element JavaDoc)i.next();
276             JDBCValueClassMetaData valueClass =
277                new JDBCValueClassMetaData(valueClassElement, classLoader);
278             valueClasses.put(valueClass.getJavaType(), valueClass);
279          }
280       }
281
282       // entity-commands: (optional, always set in standardjbosscmp-jdbc.xml)
283
entityCommands.putAll(defaultValues.entityCommands);
284       Element JavaDoc entityCommandMaps = MetaData.getOptionalChild(
285          element, "entity-commands");
286       if(entityCommandMaps != null)
287       {
288          for(Iterator JavaDoc i =
289             MetaData.getChildrenByTagName(entityCommandMaps, "entity-command");
290              i.hasNext();)
291          {
292
293             Element JavaDoc entityCommandElement = (Element JavaDoc)i.next();
294             JDBCEntityCommandMetaData entityCommand =
295                new JDBCEntityCommandMetaData(entityCommandElement);
296             entityCommands.put(entityCommand.getCommandName(), entityCommand);
297          }
298       }
299       
300       // reserved words: (optional, always set in standardjbosscmp-jdbc.xml)
301
// list of reserved words that should be escaped in table names
302
Element JavaDoc rWords = MetaData.getOptionalChild(element,"reserved-words");
303       if (rWords!=null)
304       {
305         for (Iterator JavaDoc i = MetaData.getChildrenByTagName(rWords,"word"); i.hasNext() ; )
306         {
307                 Element JavaDoc rWord = (Element JavaDoc)i.next();
308                 SQLUtil.addToRwords(MetaData.getElementContent(rWord));
309         }
310       }
311
312       // defaults: apply defaults for entities (optional, always
313
// set in standardjbosscmp-jdbc.xml)
314
entities.putAll(defaultValues.entities);
315       entitiesByAbstractSchemaName.putAll(
316          defaultValues.entitiesByAbstractSchemaName);
317       entitiesByInterface.putAll(defaultValues.entitiesByInterface);
318       Element JavaDoc defaults = MetaData.getOptionalChild(element, "defaults");
319       if(defaults != null)
320       {
321          ArrayList JavaDoc values = new ArrayList JavaDoc(entities.values());
322          for(Iterator JavaDoc i = values.iterator(); i.hasNext();)
323          {
324             JDBCEntityMetaData entityMetaData = (JDBCEntityMetaData)i.next();
325
326             // create the new metadata with the defaults applied
327
entityMetaData =
328                new JDBCEntityMetaData(this, defaults, entityMetaData);
329
330             // replace the old meta data with the new
331
entities.put(entityMetaData.getName(), entityMetaData);
332
333             String JavaDoc schemaName = entityMetaData.getAbstractSchemaName();
334             if(schemaName != null)
335             {
336                entitiesByAbstractSchemaName.put(schemaName, entityMetaData);
337             }
338
339             Class JavaDoc remote = entityMetaData.getRemoteClass();
340             if(remote != null)
341             {
342                entitiesByInterface.put(remote, entityMetaData);
343             }
344
345             Class JavaDoc local = entityMetaData.getLocalClass();
346             if(local != null)
347             {
348                entitiesByInterface.put(local, entityMetaData);
349             }
350          }
351       }
352
353       // enterprise-beans: apply entity specific configuration
354
// (only in jbosscmp-jdbc.xml)
355
Element JavaDoc enterpriseBeans =
356          MetaData.getOptionalChild(element, "enterprise-beans");
357       if(enterpriseBeans != null)
358       {
359          for(Iterator JavaDoc i =
360             MetaData.getChildrenByTagName(enterpriseBeans, "entity");
361              i.hasNext();)
362          {
363
364             Element JavaDoc beanElement = (Element JavaDoc)i.next();
365
366             // get entity by name, if not found, it is a config error
367
String JavaDoc ejbName =
368                MetaData.getUniqueChildContent(beanElement, "ejb-name");
369             JDBCEntityMetaData entityMetaData = getBeanByEjbName(ejbName);
370
371             if(entityMetaData == null)
372             {
373                throw new DeploymentException("Configuration found in " +
374                   "jbosscmp-jdbc.xml for entity " + ejbName + " but bean " +
375                   "is not a jbosscmp-jdbc-managed cmp entity in " +
376                   "ejb-jar.xml");
377             }
378             entityMetaData =
379                new JDBCEntityMetaData(this, beanElement, entityMetaData);
380             entities.put(entityMetaData.getName(), entityMetaData);
381
382             String JavaDoc schemaName = entityMetaData.getAbstractSchemaName();
383             if(schemaName != null)
384             {
385                entitiesByAbstractSchemaName.put(schemaName, entityMetaData);
386             }
387
388             Class JavaDoc remote = entityMetaData.getRemoteClass();
389             if(remote != null)
390             {
391                entitiesByInterface.put(remote, entityMetaData);
392             }
393
394             Class JavaDoc local = entityMetaData.getLocalClass();
395             if(local != null)
396             {
397                entitiesByInterface.put(local, entityMetaData);
398             }
399          }
400       }
401
402       // defaults: apply defaults for relationships (optional, always
403
// set in standardjbosscmp-jdbc.xml)
404
if(defaults == null)
405       {
406          // no defaults just copy over the existing relationships and roles
407
relationships.addAll(defaultValues.relationships);
408          entityRoles.putAll(defaultValues.entityRoles);
409       }
410       else
411       {
412
413          // create a new empty role collection for each entity
414
for(Iterator JavaDoc i = entities.values().iterator(); i.hasNext();)
415          {
416             JDBCEntityMetaData entity = (JDBCEntityMetaData)i.next();
417             entityRoles.put(entity.getName(), new HashSet JavaDoc());
418          }
419
420          // for each relationship, apply defaults and store
421
for(Iterator JavaDoc i = defaultValues.relationships.iterator();
422              i.hasNext();)
423          {
424
425             JDBCRelationMetaData relationMetaData =
426                (JDBCRelationMetaData)i.next();
427
428             // create the new metadata with the defaults applied
429
relationMetaData =
430                new JDBCRelationMetaData(this, defaults, relationMetaData);
431
432             // replace the old metadata with the new
433
relationships.add(relationMetaData);
434
435             // store new left role
436
JDBCRelationshipRoleMetaData left =
437                relationMetaData.getLeftRelationshipRole();
438             Collection JavaDoc leftEntityRoles =
439                (Collection JavaDoc)entityRoles.get(left.getEntity().getName());
440             leftEntityRoles.add(left);
441
442             // store new right role
443
JDBCRelationshipRoleMetaData right =
444                relationMetaData.getRightRelationshipRole();
445             Collection JavaDoc rightEntityRoles =
446                (Collection JavaDoc)entityRoles.get(right.getEntity().getName());
447             rightEntityRoles.add(right);
448          }
449       }
450
451       // relationships: apply entity specific configuration
452
// (only in jbosscmp-jdbc.xml)
453
Element JavaDoc relationshipsElement =
454          MetaData.getOptionalChild(element, "relationships");
455       if(relationshipsElement != null)
456       {
457
458          // create a map of the relations by name (if it has a name)
459
Map JavaDoc relationByName = new HashMap JavaDoc();
460          for(Iterator JavaDoc i = relationships.iterator(); i.hasNext();)
461          {
462             JDBCRelationMetaData relation = (JDBCRelationMetaData)i.next();
463             if(relation.getRelationName() != null)
464             {
465                relationByName.put(relation.getRelationName(), relation);
466             }
467          }
468
469
470          for(Iterator JavaDoc i = MetaData.getChildrenByTagName(relationshipsElement, "ejb-relation"); i.hasNext();)
471          {
472             Element JavaDoc relationElement = (Element JavaDoc)i.next();
473
474             // get relation by name, if not found, it is a config error
475
String JavaDoc relationName = MetaData.getUniqueChildContent(relationElement, "ejb-relation-name");
476             JDBCRelationMetaData oldRelation = (JDBCRelationMetaData)relationByName.get(relationName);
477
478             if(oldRelation == null)
479             {
480                throw new DeploymentException("Configuration found in " +
481                   "jbosscmp-jdbc.xml for relation " + relationName +
482                   " but relation is not a jbosscmp-jdbc-managed relation " +
483                   "in ejb-jar.xml");
484             }
485             // create new metadata with relation specific config applied
486
JDBCRelationMetaData newRelation =
487                new JDBCRelationMetaData(this, relationElement, oldRelation);
488
489             // replace the old metadata with the new
490
relationships.remove(oldRelation);
491             relationships.add(newRelation);
492
493             // replace the old left role with the new
494
JDBCRelationshipRoleMetaData newLeft =
495                newRelation.getLeftRelationshipRole();
496             Collection JavaDoc leftEntityRoles =
497                (Collection JavaDoc)entityRoles.get(newLeft.getEntity().getName());
498             leftEntityRoles.remove(oldRelation.getLeftRelationshipRole());
499             leftEntityRoles.add(newLeft);
500
501             // replace the old right role with the new
502
JDBCRelationshipRoleMetaData newRight =
503                newRelation.getRightRelationshipRole();
504             Collection JavaDoc rightEntityRoles =
505                (Collection JavaDoc)entityRoles.get(newRight.getEntity().getName());
506             rightEntityRoles.remove(oldRelation.getRightRelationshipRole());
507             rightEntityRoles.add(newRight);
508          }
509       }
510
511    }
512
513    /**
514     * Gets the type mapping with the specified name
515     * @param name the name for the type mapping
516     * @return the matching type mapping or null if not found
517     */

518    public JDBCTypeMappingMetaData getTypeMappingByName(String JavaDoc name)
519    {
520       return (JDBCTypeMappingMetaData)typeMappings.get(name);
521    }
522
523    /**
524     * Gets the relationship roles for the entity with the specified name.
525     * @param entityName the name of the entity whos roles are returned
526     * @return an unmodifiable collection of JDBCRelationshipRoles
527     * of the specified entity
528     */

529    public Collection JavaDoc getRolesForEntity(String JavaDoc entityName)
530    {
531       Collection JavaDoc roles = (Collection JavaDoc)entityRoles.get(entityName);
532       return Collections.unmodifiableCollection(roles);
533    }
534
535    /**
536     * Gets dependent value classes that are directly managed by the container.
537     * @returns an unmodifiable collection of JDBCValueClassMetaData
538     */

539    public Collection JavaDoc getValueClasses()
540    {
541       return Collections.unmodifiableCollection(valueClasses.values());
542    }
543
544    /**
545     * Gets the classloader for this application which is used to load
546     * all classes.
547     * @return the ClassLoader for the application
548     */

549    public ClassLoader JavaDoc getClassLoader()
550    {
551       return classLoader;
552    }
553
554    /**
555     * Gets the metadata for an entity bean by name.
556     * @param name the name of the entity meta data to return
557     * @return the entity meta data for the specified name
558     */

559    public JDBCEntityMetaData getBeanByEjbName(String JavaDoc name)
560    {
561       return (JDBCEntityMetaData)entities.get(name);
562    }
563
564    /**
565     * Gets the entity command with the specified name
566     * @param name the name for the entity-command
567     * @return the matching entity command or null if not found
568     */

569    public JDBCEntityCommandMetaData getEntityCommandByName(String JavaDoc name)
570    {
571       return (JDBCEntityCommandMetaData)entityCommands.get(name);
572    }
573
574    public Map JavaDoc getUserTypeMappings()
575    {
576       return Collections.unmodifiableMap(userTypeMappings);
577    }
578 }
579
Popular Tags