KickJava   Java API By Example, From Geeks To Geeks.

Java > Open Source Codes > org > apache > cayenne > jpa > conf > EntityMapLoader


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.jpa.conf;
21
22 import java.io.IOException JavaDoc;
23 import java.net.URL JavaDoc;
24 import java.util.Enumeration JavaDoc;
25 import java.util.HashSet JavaDoc;
26 import java.util.Map JavaDoc;
27 import java.util.Set JavaDoc;
28
29 import javax.persistence.spi.PersistenceUnitInfo;
30
31 import org.apache.cayenne.jpa.JpaProviderException;
32 import org.apache.cayenne.jpa.map.JpaClassDescriptor;
33 import org.apache.cayenne.jpa.map.JpaEntityMap;
34
35 /**
36  * Loads JPA mapping information from all sources per JPA specification.
37  * <h3>Specification Documentation, Chapter 6.2.1.6</h3>
38  * <p>
39  * The set of managed persistence classes that are managed by a persistence unit is
40  * defined by using one or more of the following:
41  * <ul>
42  * <li>One or more object/relational mapping XML files
43  * <li>One or more jar files that will be searched for classes
44  * <li>An explicit list of the classes
45  * <li>The annotated managed persistence classes contained in the root of the persistence
46  * unit (unless the exclude-unlisted-classes element is specified) [Java SE doesn't have
47  * to support that].
48  * </ul>
49  * <p>
50  * The result is undefined if multiple mapping files (including any orm.xml file)
51  * referenced within a single persistence unit contain overlapping mapping information for
52  * any given class.
53  * </p>
54  * <p>
55  * The resulting set of entities managed by the persistence unit [and contained in the
56  * returned entity map] is the union of these sources, with the mapping metadata
57  * annotations (or annotation defaults) for any given class being overridden by the XML
58  * mapping information file if there are both annotations as well as XML mappings for that
59  * class. The minimum portable level of overriding is at the level of the persistent field
60  * or property.
61  * </p>
62  *
63  * @author Andrus Adamchik
64  */

65 public class EntityMapLoader {
66
67     static final String JavaDoc DESCRIPTOR_LOCATION = "META-INF/orm.xml";
68
69     protected EntityMapLoaderContext context;
70     protected Map JavaDoc<String JavaDoc, JpaClassDescriptor> descriptors;
71
72     /**
73      * Creates an EntityMapLoader for the persistence unit, merging entity information
74      * from all locations supported by the JPA specification.
75      */

76     public EntityMapLoader(PersistenceUnitInfo persistenceUnit) {
77         loadEntityMap(persistenceUnit);
78     }
79
80     /**
81      * Returns an entity map with entity
82      */

83     public JpaEntityMap getEntityMap() {
84         return context.getEntityMap();
85     }
86
87     /**
88      * Loads a combined entity map including managed class descriptors from all supported
89      * locations.
90      */

91     protected void loadEntityMap(PersistenceUnitInfo persistenceUnit)
92             throws JpaProviderException {
93
94         this.context = new EntityMapLoaderContext(persistenceUnit);
95
96         try {
97             loadFromAnnotations(persistenceUnit);
98             updateFromXML(persistenceUnit);
99             updateFromDefaults();
100         }
101         catch (JpaProviderException e) {
102             throw e;
103         }
104         catch (Exception JavaDoc e) {
105             throw new JpaProviderException("Error loading ORM descriptors", e);
106         }
107     }
108
109     /**
110      * Updates missing values with spec-compilant defaults.
111      */

112     protected void updateFromDefaults() {
113         new EntityMapDefaultsProcessor().applyDefaults(context);
114     }
115
116     /**
117      * Updates mapping with data loaded from XML. JPA specification gives some leeway in
118      * processing conflicting mapping files. Cayenne provider strategy is "last mapping
119      * file overrides all".
120      * <h3>Specification Documentation, Chapter 6.2.1.6</h3>
121      * <p>
122      * An <em>orm.xml</em> file may be specified in the META-INF directory in the root
123      * of the persistence unit or in the META-INF directory of any jar file referenced by
124      * the persistence.xml. Alternatively, or in addition, other mapping files maybe
125      * referenced by the mapping-file elements of the persistence-unit element, and may be
126      * present anywhere on the classpath. An orm.xml file or other mapping file is loaded
127      * as a resource by the persistence provider.
128      */

129     protected void updateFromXML(PersistenceUnitInfo unit) throws IOException JavaDoc {
130
131         EntityMapMergeProcessor merger = new EntityMapMergeProcessor(context);
132
133         Set JavaDoc loadedLocations = new HashSet JavaDoc();
134         EntityMapXMLLoader loader = new EntityMapXMLLoader(
135                 context.getTempClassLoader(),
136                 false);
137
138         // 1. load from the standard file called orm.xml
139
loadedLocations.add(DESCRIPTOR_LOCATION);
140         Enumeration JavaDoc<URL JavaDoc> standardDescriptors = context.getTempClassLoader().getResources(
141                 DESCRIPTOR_LOCATION);
142
143         while (standardDescriptors.hasMoreElements()) {
144             JpaEntityMap map = loader.getEntityMap(standardDescriptors.nextElement());
145             merger.mergeOverride(map);
146         }
147
148         // 2. load from orm.xml within the jars
149
// TODO: andrus, 4/20/2006 - load from the jar files
150

151         // 3. load from explicitly specified descriptors
152
for (String JavaDoc descriptor : unit.getMappingFileNames()) {
153
154             // avoid loading duplicates, such as META-INF/orm.xml that is also explicitly
155
// mentioned in the unit...
156
if (loadedLocations.add(descriptor)) {
157
158                 Enumeration JavaDoc<URL JavaDoc> mappedDescriptors = context
159                         .getTempClassLoader()
160                         .getResources(descriptor);
161                 while (mappedDescriptors.hasMoreElements()) {
162                     JpaEntityMap map = loader.getEntityMap(mappedDescriptors
163                             .nextElement());
164                     merger.mergeOverride(map);
165                 }
166             }
167         }
168     }
169
170     /**
171      * Loads JpaEntityMap based on metadata annotations of persistent classes.
172      */

173     protected void loadFromAnnotations(PersistenceUnitInfo persistenceUnit) {
174
175         if (!persistenceUnit.getManagedClassNames().isEmpty()) {
176
177             // must use Unit class loader to prevent loading an un-enahnced class in the
178
// app ClassLoader.
179
ClassLoader JavaDoc loader = context.getTempClassLoader();
180             EntityMapAnnotationLoader annotationLoader = new EntityMapAnnotationLoader(
181                     context);
182
183             for (String JavaDoc className : persistenceUnit.getManagedClassNames()) {
184
185                 Class JavaDoc managedClass;
186                 try {
187                     managedClass = Class.forName(className, true, loader);
188                 }
189                 catch (ClassNotFoundException JavaDoc e) {
190                     throw new JpaProviderException("Class not found: " + className, e);
191                 }
192
193                 annotationLoader.loadClassMapping(managedClass);
194             }
195         }
196     }
197
198     public EntityMapLoaderContext getContext() {
199         return context;
200     }
201 }
202
Popular Tags