KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > oracle > toplink > essentials > internal > ejb > cmp3 > metadata > MetadataProcessor


1 /*
2  * The contents of this file are subject to the terms
3  * of the Common Development and Distribution License
4  * (the "License"). You may not use this file except
5  * in compliance with the License.
6  *
7  * You can obtain a copy of the license at
8  * glassfish/bootstrap/legal/CDDLv1.0.txt or
9  * https://glassfish.dev.java.net/public/CDDLv1.0.html.
10  * See the License for the specific language governing
11  * permissions and limitations under the License.
12  *
13  * When distributing Covered Code, include this CDDL
14  * HEADER in each file and include the License file at
15  * glassfish/bootstrap/legal/CDDLv1.0.txt. If applicable,
16  * add the following below this CDDL HEADER, with the
17  * fields enclosed by brackets "[]" replaced with your
18  * own identifying information: Portions Copyright [yyyy]
19  * [name of copyright owner]
20  */

21 package oracle.toplink.essentials.internal.ejb.cmp3.metadata;
22
23 import java.io.InputStream JavaDoc;
24 import java.io.IOException JavaDoc;
25
26 import java.util.Collection JavaDoc;
27 import java.util.HashSet JavaDoc;
28 import java.util.Iterator JavaDoc;
29 import java.util.Set JavaDoc;
30
31 import javax.persistence.spi.PersistenceUnitInfo;
32
33 import oracle.toplink.essentials.ejb.cmp3.persistence.PersistenceUnitProcessor;
34 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.ClassAccessor;
35 import oracle.toplink.essentials.internal.ejb.cmp3.metadata.accessors.objects.MetadataClass;
36
37 import oracle.toplink.essentials.internal.ejb.cmp3.xml.accessors.XMLClassAccessor;
38
39 import oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLConstants;
40 import oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLHelper;
41 import oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLLogger;
42 import oracle.toplink.essentials.internal.ejb.cmp3.xml.XMLValidator;
43
44 import oracle.toplink.essentials.internal.sessions.AbstractSession;
45
46 import org.w3c.dom.Node JavaDoc;
47 import org.w3c.dom.NodeList JavaDoc;
48
49 /**
50  * The object/relational metadata processor for the EJB3.0 specification.
51  *
52  * @author Guy Pelletier
53  * @since TopLink EJB 3.0 Reference Implementation
54  */

55 public class MetadataProcessor {
56     protected ClassLoader JavaDoc m_loader;
57     protected MetadataLogger m_logger;
58     protected MetadataProject m_project;
59     protected MetadataValidator m_validator;
60     
61     /**
62      * INTERNAL:
63      * Called from EntityManagerSetupImpl. The 'real' EJB 3.0 processing
64      * that includes XML and annotations.
65      */

66     public MetadataProcessor(AbstractSession session, ClassLoader JavaDoc loader, boolean enableLazyForOneToOne) {
67         m_loader = loader;
68         m_project = new MetadataProject(session, enableLazyForOneToOne);
69     }
70     
71     /**
72      * INTERNAL:
73      * Called from RelationshipWeaverTestSuite. Use this constructor to avoid
74      * XML processing.
75      */

76     public MetadataProcessor(AbstractSession session, ClassLoader JavaDoc loader, Collection JavaDoc<Class JavaDoc> entities, boolean enableLazyForOneToOne) {
77         m_loader = loader;
78         m_project = new MetadataProject(session, enableLazyForOneToOne);
79         
80         for (Class JavaDoc entity : entities) {
81             m_project.addDescriptor(new MetadataDescriptor(entity));
82         }
83     }
84     
85     /**
86      * INTERNAL:
87      * Method to place EntityListener's on the descriptors from the given
88      * session. This call is made from the EntityManagerSetup deploy call.
89      */

90     public void addEntityListeners() {
91         for (MetadataDescriptor descriptor: m_project.getDescriptors()) {
92             // Process all descriptors that are in our project.
93
ClassAccessor accessor = descriptor.getClassAccessor();
94             
95             // The class loader has changed, update the class stored for
96
// our class accessor and its list of mapped superclasses.
97
accessor.setAnnotatedElement(descriptor.getJavaClass());
98             accessor.clearMappedSuperclasses();
99             
100             accessor.processListeners(m_loader);
101         }
102     }
103     
104     /**
105      * INTERNAL:
106      * Method to place NamedQueries and NamedNativeQueries on the given session.
107      * This call is made from the EntityManagerSetup deploy call.
108      */

109     public void addNamedQueries() {
110         m_project.processNamedQueries(m_validator);
111         m_project.processNamedNativeQueries(m_loader);
112     }
113     
114     /**
115      * INTERNAL:
116      * Return a set of class names for each entity, embeddable found in the xml
117      * descriptor instance document.
118      */

119     public static Set JavaDoc<String JavaDoc> buildClassSet(InputStream JavaDoc xmlDocumentInputStream, String JavaDoc fileName, ClassLoader JavaDoc loader) {
120         XMLHelper helper = new XMLHelper(xmlDocumentInputStream, fileName, loader);
121         
122         // Process the package node.
123
String JavaDoc defaultPkg = helper.getNodeValue(new String JavaDoc[] {XMLConstants.ENTITY_MAPPINGS, XMLConstants.PACKAGE, XMLConstants.TEXT});
124
125         // Handle entities only. Mapped superclasses and embeddables are
126
// discovered and processed separately.
127
HashSet JavaDoc<String JavaDoc> classSet = new HashSet JavaDoc<String JavaDoc>();
128         classSet.addAll(buildClassSetForNodeList(helper, XMLConstants.ENTITY, defaultPkg));
129
130         return classSet;
131     }
132     
133     /**
134      * INTERNAL:
135      * The class name of each node in the node list will be added to the
136      * provided collection.
137      */

138     protected static Set JavaDoc<String JavaDoc> buildClassSetForNodeList(XMLHelper helper, String JavaDoc xPath, String JavaDoc defaultPkg) {
139         HashSet JavaDoc<String JavaDoc> classNames = new HashSet JavaDoc<String JavaDoc>();
140         NodeList JavaDoc nodes = helper.getNodes(XMLConstants.ENTITY_MAPPINGS, xPath);
141         int nodeCount = nodes.getLength();
142         
143         for (int i = 0; i < nodeCount; i++) {
144             // Process the required class attribute node.
145
classNames.add(XMLHelper.getFullyQualifiedClassName(helper.getNode(nodes.item(i), XMLConstants.ATT_CLASS).getNodeValue(), defaultPkg));
146         }
147         
148         return classNames;
149     }
150     
151     /**
152      * INTERNAL:
153      * Return the logger used by the processor.
154      */

155     public MetadataLogger getLogger() {
156         return m_logger;
157     }
158     
159     /**
160      * INTERNAL:
161      */

162      public MetadataProject getProject() {
163          return m_project;
164      }
165     
166     /**
167      * INTERNAL:
168      * Return the validator used by the processor.
169      */

170     public MetadataValidator getValidator() {
171         return m_validator;
172     }
173     
174     /**
175      * INTERNAL:
176      * Called from RelationshipWeaverTestSuite which uses only annotations
177      * and no XML.
178      */

179     public AbstractSession processAnnotations() {
180         // Set the correct contextual validator and logger.
181
m_validator = new MetadataValidator();
182         m_logger = new MetadataLogger(m_project.getSession());
183
184         // take a copy of the collection to avoid concurrent modification exception
185
// that would result when embeddables are added lazily.
186
for (MetadataDescriptor descriptor:
187                 m_project.getDescriptors().toArray(new MetadataDescriptor[]{})) {
188             // Process all descriptors that are in our project.
189
ClassAccessor accessor = descriptor.getClassAccessor();
190                 
191             // If there is no accessor on this descriptor then it has not been
192
// processed yet. Create one and process it.
193
if (accessor == null) {
194                 accessor = new ClassAccessor(new MetadataClass(descriptor.getJavaClass()), this, descriptor);
195                 descriptor.setClassAccessor(accessor);
196                 accessor.process();
197             }
198         }
199         
200         // Process the project and anything that was deferred like
201
// sequencing and relationship mappings. Return the session and we
202
// are done.
203
return m_project.process();
204     }
205     
206     /**
207      * INTERNAL:
208      * Process persistence unit metadata and defaults, and apply them to each
209      * entity in the collection. Any conflicts in elements defined in multiple
210      * documents will cause an exception to be thrown. The first instance
211      * encountered wins, i.e. any conflicts between PU metadata definitions in
212      * multiple instance documents will cause an exception to be thrown. The
213      * one exception to this rule is default listeners: all default listeners
214      * found will be added to a list in the order that they are read from the
215      * instance document(s).
216      */

217      public void processPersistenceUnitMetadata(AbstractSession session, PersistenceUnitInfo persistenceUnitInfo, Collection JavaDoc<String JavaDoc> mappingFileNames, Collection JavaDoc<Class JavaDoc> entities) {
218         if (! mappingFileNames.isEmpty()) {
219             // For each orm xml instance document, process persistence unit
220
// metadata/defaults and mapped superclasses.
221
Iterator JavaDoc<String JavaDoc> fileNames = mappingFileNames.iterator();
222
223             Iterator JavaDoc<String JavaDoc> mappingFileNamesIt = mappingFileNames.iterator();
224             while (mappingFileNamesIt.hasNext()){
225                 String JavaDoc fileName = mappingFileNamesIt.next();
226                 InputStream JavaDoc inputStream = null;
227                 m_logger = new XMLLogger(session);
228                 try {
229                     inputStream = PersistenceUnitProcessor.createInputStreamForFileInPersistenceUnit(fileName, persistenceUnitInfo, m_loader);
230                     
231                     if (inputStream == null){
232                         getLogger().logWarningMessage(XMLLogger.COULD_NOT_FIND_ORM_XML_FILE, fileName);
233                         continue;
234                     }
235                     // Initialize a helper for navigating the instance document.
236
XMLHelper helper = new XMLHelper(inputStream, fileNames.next(), m_loader);
237                 
238                     // Store all mapped-superclasses.
239
NodeList JavaDoc nodes = helper.getNodes(XMLConstants.ENTITY_MAPPINGS, XMLConstants.MAPPED_SUPERCLASS);
240         
241                     for (int i = 0; i < nodes.getLength(); i++) {
242                         Node JavaDoc node = nodes.item(i);
243                         Class JavaDoc cls = helper.getNodeValue(nodes.item(i), XMLConstants.ATT_CLASS, void.class);
244                         m_project.addMappedSuperclass(cls, node, helper);
245                     }
246                     
247                     // Store all embeddable classes.
248
nodes = helper.getNodes(XMLConstants.ENTITY_MAPPINGS, XMLConstants.EMBEDDABLE);
249
250                     for (int i = 0; i < nodes.getLength(); i++) {
251                         Node JavaDoc node = nodes.item(i);
252                         Class JavaDoc cls = helper.getNodeValue(nodes.item(i), XMLConstants.ATT_CLASS, void.class);
253                         m_project.addEmbeddable(cls, node, helper);
254                     }
255
256                     // Look for a persistence-unit-metadata node.
257
Node JavaDoc persistenceUnitMetadataNode = helper.getNode(new String JavaDoc[] {XMLConstants.ENTITY_MAPPINGS, XMLConstants.PU_METADATA});
258                 
259                     if (persistenceUnitMetadataNode != null) {
260                         MetadataPersistenceUnit persistenceUnit = new MetadataPersistenceUnit();
261                         
262                         // Process the xml-mapping-metadata-complete tag.
263
persistenceUnit.setIsMetadataComplete(helper.getNode(persistenceUnitMetadataNode, XMLConstants.METADATA_COMPLETE) != null);
264
265                         // process persistence unit defaults
266
Node JavaDoc persistenceUnitDefaultsNode = helper.getNode(persistenceUnitMetadataNode, XMLConstants.PU_DEFAULTS);
267                         
268                         if (persistenceUnitDefaultsNode != null) {
269                             // Process the persistence unit access.
270
persistenceUnit.setAccess(helper.getNodeTextValue(persistenceUnitDefaultsNode, XMLConstants.ACCESS));
271                     
272                             // Process the persitence unit schema.
273
persistenceUnit.setSchema(helper.getNodeTextValue(persistenceUnitDefaultsNode, XMLConstants.SCHEMA));
274                     
275                             // Process the persistence unit catalog.
276
persistenceUnit.setCatalog(helper.getNodeTextValue(persistenceUnitDefaultsNode, XMLConstants.CATALOG));
277                     
278                             // Process the persistence unit cascade-persist.
279
persistenceUnit.setIsCascadePersist(helper.getNode(persistenceUnitDefaultsNode, XMLConstants.CASCADE_PERSIST) != null);
280                     
281                             // Process the default entity-listeners. No conflict
282
// checking will be done, that is, any and all
283
// default listeners will be added to the project.
284
NodeList JavaDoc listenerNodes = helper.getNodes(persistenceUnitDefaultsNode, XMLConstants.ENTITY_LISTENERS, XMLConstants.ENTITY_LISTENER);
285                             if (listenerNodes != null) {
286                                 m_project.addDefaultListeners(listenerNodes, helper);
287                             }
288                         }
289                         
290                         // Add the metadata persistence unit to the project if
291
// there is no conflicting metadata (from other
292
// persistence unit metadata)
293
MetadataPersistenceUnit existingPersistenceUnit = m_project.getPersistenceUnit();
294                         if (existingPersistenceUnit != null) {
295                             if (! existingPersistenceUnit.equals(persistenceUnit)) {
296                                 (new XMLValidator()).throwPersistenceUnitMetadataConflict(existingPersistenceUnit.getConflict());
297                             }
298                         } else {
299                             m_project.setPersistenceUnit(persistenceUnit);
300                         }
301                     }
302                 } catch (IOException JavaDoc exception){
303                     getLogger().logWarningMessage(XMLLogger.ERROR_LOADING_ORM_XML_FILE, fileName, exception);
304                 } catch (RuntimeException JavaDoc re) {
305                     throw re;
306                 } finally {
307                     if (inputStream != null){
308                         try{
309                             inputStream.close();
310                         } catch (IOException JavaDoc exc){};
311                     }
312                 }
313
314             }
315         }
316         
317         // Add a metadata descriptor to the project for every entity class.
318
// Any persistence unit metadata/defaults will be applied
319
if (! entities.isEmpty()) {
320             for (Class JavaDoc entity : entities) {
321                 m_project.addDescriptor(new MetadataDescriptor(entity));
322             }
323         }
324     }
325     
326     /**
327      * INTERNAL:
328      * Process the xml and fill in the project. Process the entity-mappings
329      * information then process the entities.
330      */

331     public void processXML(InputStream JavaDoc xmlDocumentStream, String JavaDoc fileName) {
332         if (m_project.hasDescriptors()) {
333              // Initialize the correct contextual objects.
334
m_validator = new XMLValidator();
335             m_logger = new XMLLogger(m_project.getSession());
336             XMLHelper helper = new XMLHelper(xmlDocumentStream, fileName, m_loader);
337         
338             // Process the entity mappings ... this is a crude way of doing
339
// things ... but hey ... the clock is ticking ...
340
MetadataDescriptor desc = m_project.getDescriptors().iterator().next();
341             XMLClassAccessor dummyAccessor = new XMLClassAccessor(new MetadataClass(desc.getJavaClass()), null, helper, this, desc);
342             dummyAccessor.processEntityMappings();
343         
344             // Process the entity nodes for this xml document.
345
NodeList JavaDoc entityNodes = helper.getNodes(XMLConstants.ENTITY_MAPPINGS, XMLConstants.ENTITY);
346
347             if (entityNodes != null) {
348                 for (int i = 0; i < entityNodes.getLength(); i++) {
349                     Node JavaDoc entityNode = entityNodes.item(i);
350                     Class JavaDoc entityClass = helper.getClassForNode(entityNode);
351                     MetadataDescriptor descriptor = m_project.getDescriptor(entityClass);
352
353                     // Process all descriptors that are in our project.
354
ClassAccessor accessor = descriptor.getClassAccessor();
355                 
356                     // If there is no accessor on this descriptor then it has not
357
// been processed yet. Create one and process it.
358
if (accessor == null) {
359                         accessor = new XMLClassAccessor(new MetadataClass(descriptor.getJavaClass()), entityNode, helper, this, descriptor);
360                         descriptor.setClassAccessor(accessor);
361                         accessor.process();
362                     }
363                 }
364             }
365         } else {
366             // WIP - log a warning that we have no entities to process ...
367
}
368     }
369     
370     /**
371      * INTERNAL:
372      * Use this method to set the correct class loader that should be used
373      * during processing.
374      */

375     public void setClassLoader(ClassLoader JavaDoc loader) {
376         m_loader = loader;
377     }
378 }
379
Popular Tags