001: /**
002: * Licensed to the Apache Software Foundation (ASF) under one or more
003: * contributor license agreements. See the NOTICE file distributed with
004: * this work for additional information regarding copyright ownership.
005: * The ASF licenses this file to You under the Apache License, Version 2.0
006: * (the "License"); you may not use this file except in compliance with
007: * the License. You may obtain a copy of the License at
008: *
009: * http://www.apache.org/licenses/LICENSE-2.0
010: *
011: * Unless required by applicable law or agreed to in writing, software
012: * distributed under the License is distributed on an "AS IS" BASIS,
013: * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
014: * See the License for the specific language governing permissions and
015: * limitations under the License.
016: */package org.apache.openejb.config;
017:
018: import java.io.ByteArrayInputStream;
019: import java.net.URL;
020: import java.util.List;
021: import java.util.Map;
022: import java.util.TreeMap;
023: import java.util.Set;
024: import java.util.TreeSet;
025: import javax.xml.bind.JAXBElement;
026:
027: import org.apache.openejb.jee.jpa.Attributes;
028: import org.apache.openejb.jee.jpa.Basic;
029: import org.apache.openejb.jee.jpa.Column;
030: import org.apache.openejb.jee.jpa.Entity;
031: import org.apache.openejb.jee.jpa.EntityMappings;
032: import org.apache.openejb.jee.jpa.Field;
033: import org.apache.openejb.jee.jpa.GeneratedValue;
034: import org.apache.openejb.jee.jpa.GenerationType;
035: import org.apache.openejb.jee.jpa.Id;
036: import org.apache.openejb.jee.jpa.JoinColumn;
037: import org.apache.openejb.jee.jpa.JoinTable;
038: import org.apache.openejb.jee.jpa.NamedQuery;
039: import org.apache.openejb.jee.jpa.OneToMany;
040: import org.apache.openejb.jee.jpa.OneToOne;
041: import org.apache.openejb.jee.jpa.RelationField;
042: import org.apache.openejb.jee.jpa.Table;
043: import org.apache.openejb.jee.jpa.AttributeOverride;
044: import org.apache.openejb.jee.oejb2.EjbRelationType;
045: import org.apache.openejb.jee.oejb2.EjbRelationshipRoleType;
046: import org.apache.openejb.jee.oejb2.EntityBeanType;
047: import org.apache.openejb.jee.oejb2.JaxbOpenejbJar2;
048: import org.apache.openejb.jee.oejb2.OpenejbJarType;
049: import org.apache.openejb.jee.oejb2.QueryType;
050: import org.apache.openejb.jee.oejb2.MessageDrivenBeanType;
051: import org.apache.openejb.jee.oejb2.ActivationConfigType;
052: import org.apache.openejb.jee.oejb2.ActivationConfigPropertyType;
053: import org.apache.openejb.jee.oejb2.EjbRefType;
054: import org.apache.openejb.jee.oejb2.PatternType;
055: import org.apache.openejb.jee.oejb2.EjbLocalRefType;
056: import org.apache.openejb.jee.oejb2.Jndi;
057: import org.apache.openejb.jee.oejb3.OpenejbJar;
058: import org.apache.openejb.jee.oejb3.EjbDeployment;
059: import org.apache.openejb.jee.oejb3.EjbLink;
060: import org.apache.openejb.jee.EjbJar;
061: import org.apache.openejb.jee.MessageDrivenBean;
062: import org.apache.openejb.jee.EnterpriseBean;
063: import org.apache.openejb.jee.ActivationConfigProperty;
064: import org.apache.openejb.jee.ActivationConfig;
065: import org.apache.openejb.jee.EjbRef;
066:
067: public class OpenEjb2Conversion implements DynamicDeployer {
068: public AppModule deploy(AppModule appModule) {
069: for (EjbModule ejbModule : appModule.getEjbModules()) {
070: Object altDD = getOpenejbJarType(ejbModule);
071: if (altDD instanceof OpenejbJarType) {
072: convertEjbRefs(ejbModule.getEjbJar(), ejbModule
073: .getOpenejbJar(), (OpenejbJarType) altDD);
074: convertMdbConfigs(ejbModule.getEjbJar(),
075: (OpenejbJarType) altDD);
076: mergeEntityMappings(ejbModule.getModuleId(), appModule
077: .getCmpMappings(), ejbModule.getOpenejbJar(),
078: (OpenejbJarType) altDD);
079: }
080: }
081: return appModule;
082: }
083:
084: private OpenejbJarType getOpenejbJarType(EjbModule ejbModule) {
085: Object altDD = ejbModule.getAltDDs().get("openejb-jar.xml");
086: if (altDD instanceof String) {
087: try {
088: altDD = JaxbOpenejbJar2.unmarshal(OpenejbJarType.class,
089: new ByteArrayInputStream(((String) altDD)
090: .getBytes()), false);
091: } catch (Exception e) {
092: // todo warn about not being able to parse sun descriptor
093: }
094: }
095: if (altDD instanceof URL) {
096: try {
097: altDD = JaxbOpenejbJar2.unmarshal(OpenejbJarType.class,
098: ((URL) altDD).openStream(), false);
099: } catch (Exception e) {
100: // todo warn about not being able to parse sun descriptor
101: }
102: }
103: if (altDD instanceof JAXBElement) {
104: altDD = ((JAXBElement) altDD).getValue();
105: }
106: if (altDD instanceof OpenejbJarType) {
107: return (OpenejbJarType) altDD;
108: }
109: return null;
110: }
111:
112: public void convertEjbRefs(EjbJar ejbJar, OpenejbJar openejbJar,
113: OpenejbJarType openejbJarType) {
114: Map<String, EnterpriseBean> ejbs = ejbJar
115: .getEnterpriseBeansByEjbName();
116: Map<String, EjbDeployment> deployments = openejbJar
117: .getDeploymentsByEjbName();
118:
119: for (org.apache.openejb.jee.oejb2.EnterpriseBean enterpriseBean : openejbJarType
120: .getEnterpriseBeans()) {
121: EnterpriseBean ejb = ejbs.get(enterpriseBean.getEjbName());
122: if (ejb == null) {
123: // todo warn no such ejb in the ejb-jar.xml
124: continue;
125: }
126: Map<String, EjbRef> ejbRefs = ejb.getEjbRefMap();
127:
128: EjbDeployment deployment = deployments.get(enterpriseBean
129: .getEjbName());
130: if (deployment == null) {
131: // todo warn no such ejb in the ejb-jar.xml
132: continue;
133: }
134:
135: for (String name : enterpriseBean.getLocalJndiName()) {
136: deployment.getJndi().add(
137: new org.apache.openejb.jee.oejb3.Jndi(name,
138: "LocalHome"));
139: }
140:
141: for (String name : enterpriseBean.getJndiName()) {
142: deployment.getJndi().add(
143: new org.apache.openejb.jee.oejb3.Jndi(name,
144: "RemoteHome"));
145: }
146:
147: for (Jndi jndi : enterpriseBean.getJndi()) {
148: deployment.getJndi().add(
149: new org.apache.openejb.jee.oejb3.Jndi(jndi
150: .getName(), jndi.getInterface()));
151: }
152:
153: Set<String> ejbLinks = new TreeSet<String>();
154: for (EjbLink ejbLink : deployment.getEjbLink()) {
155: ejbLinks.add(ejbLink.getEjbRefName());
156: }
157:
158: for (EjbRefType refType : enterpriseBean.getEjbRef()) {
159: String refName = refType.getRefName();
160: if (ejbLinks.contains(refName)) {
161: // don't overwrite refs that have been already set
162: continue;
163: }
164:
165: String nsCorbaloc = refType.getNsCorbaloc();
166: if (nsCorbaloc != null) {
167: EjbRef ref = ejbRefs.get(refName);
168: if (ref != null) {
169: ref.setMappedName("jndi:" + nsCorbaloc);
170: }
171: } else if (refType.getEjbLink() != null) {
172: EjbRef ref = ejbRefs.get(refName);
173: if (ref != null) {
174: ref.setEjbLink(refType.getEjbLink());
175: }
176: } else {
177: PatternType pattern = refType.getPattern();
178: addEjbLink(deployment, refName, pattern);
179: }
180: }
181:
182: for (EjbLocalRefType refType : enterpriseBean
183: .getEjbLocalRef()) {
184: String refName = refType.getRefName();
185: if (ejbLinks.contains(refName)) {
186: // don't overwrite refs that have been already set
187: continue;
188: }
189:
190: if (refType.getEjbLink() != null) {
191: EjbRef ref = ejbRefs.get(refName);
192: if (ref != null) {
193: ref.setEjbLink(refType.getEjbLink());
194: }
195: } else {
196: PatternType pattern = refType.getPattern();
197: addEjbLink(deployment, refName, pattern);
198: }
199: }
200: }
201: }
202:
203: private void addEjbLink(EjbDeployment deployment, String refName,
204: PatternType pattern) {
205: String module = pattern.getModule();
206: if (module == null) {
207: module = pattern.getArtifactId();
208: }
209: String ejbName = pattern.getName();
210: String deploymentId = module + "/" + ejbName;
211: EjbLink ejbLink = new EjbLink(refName, deploymentId);
212: deployment.getEjbLink().add(ejbLink);
213: }
214:
215: public void convertMdbConfigs(EjbJar ejbJar,
216: OpenejbJarType openejbJarType) {
217: Map<String, MessageDrivenBean> mdbs = new TreeMap<String, MessageDrivenBean>();
218: for (EnterpriseBean enterpriseBean : ejbJar
219: .getEnterpriseBeans()) {
220: if (!(enterpriseBean instanceof MessageDrivenBean)) {
221: continue;
222: }
223: mdbs.put(enterpriseBean.getEjbName(),
224: (MessageDrivenBean) enterpriseBean);
225: }
226: for (org.apache.openejb.jee.oejb2.EnterpriseBean enterpriseBean : openejbJarType
227: .getEnterpriseBeans()) {
228: if (!(enterpriseBean instanceof MessageDrivenBeanType)) {
229: continue;
230: }
231: MessageDrivenBeanType bean = (MessageDrivenBeanType) enterpriseBean;
232: MessageDrivenBean mdb = mdbs.get(bean.getEjbName());
233: if (mdb == null) {
234: // todo warn no such ejb in the ejb-jar.xml
235: continue;
236: }
237: ActivationConfigType activationConfigType = bean
238: .getActivationConfig();
239: if (activationConfigType != null) {
240: ActivationConfig activationConfig = mdb
241: .getActivationConfig();
242: if (activationConfig == null) {
243: activationConfig = new ActivationConfig();
244: mdb.setActivationConfig(activationConfig);
245: }
246: for (ActivationConfigPropertyType propertyType : activationConfigType
247: .getActivationConfigProperty()) {
248: ActivationConfigProperty property = new ActivationConfigProperty(
249: propertyType
250: .getActivationConfigPropertyName(),
251: propertyType
252: .getActivationConfigPropertyValue());
253: activationConfig.getActivationConfigProperty().add(
254: property);
255: }
256: }
257: }
258: }
259:
260: public void mergeEntityMappings(String moduleId,
261: EntityMappings entityMappings, OpenejbJar openejbJar,
262: OpenejbJarType openejbJarType) {
263: Map<String, EntityData> entities = new TreeMap<String, EntityData>();
264: if (entityMappings != null) {
265: for (Entity entity : entityMappings.getEntity()) {
266: entities.put(entity.getDescription(), new EntityData(
267: entity));
268: }
269: }
270: for (org.apache.openejb.jee.oejb2.EnterpriseBean enterpriseBean : openejbJarType
271: .getEnterpriseBeans()) {
272: if (!(enterpriseBean instanceof EntityBeanType)) {
273: continue;
274: }
275: EntityBeanType bean = (EntityBeanType) enterpriseBean;
276: EntityData entityData = entities.get(moduleId + "#"
277: + bean.getEjbName());
278: if (entityData == null) {
279: // todo warn no such ejb in the ejb-jar.xml
280: continue;
281: }
282:
283: Table table = new Table();
284: table.setName(bean.getTableName());
285: entityData.entity.setTable(table);
286:
287: for (EntityBeanType.CmpFieldMapping cmpFieldMapping : bean
288: .getCmpFieldMapping()) {
289: String cmpFieldName = cmpFieldMapping.getCmpFieldName();
290: Field field = entityData.fields.get(cmpFieldName);
291: if (field == null) {
292: // todo warn no such cmp-field in the ejb-jar.xml
293: continue;
294: }
295: Column column = new Column();
296: column.setName(cmpFieldMapping.getTableColumn());
297: field.setColumn(column);
298: }
299:
300: if (bean.getKeyGenerator() != null) {
301: // todo support complex primary keys
302: Attributes attributes = entityData.entity
303: .getAttributes();
304: if (attributes != null
305: && attributes.getId().size() == 1) {
306: Id id = attributes.getId().get(0);
307:
308: // todo detect specific generation strategy
309: id.setGeneratedValue(new GeneratedValue(
310: GenerationType.IDENTITY));
311: }
312: }
313:
314: for (QueryType query : bean.getQuery()) {
315: NamedQuery namedQuery = new NamedQuery();
316: QueryType.QueryMethod queryMethod = query
317: .getQueryMethod();
318:
319: // todo deployment id could change in one of the later conversions... use entity name instead, but we need to save it off
320: StringBuilder name = new StringBuilder();
321: name.append(entityData.entity.getName()).append(".")
322: .append(queryMethod.getMethodName());
323: if (queryMethod.getMethodParams() != null
324: && !queryMethod.getMethodParams()
325: .getMethodParam().isEmpty()) {
326: name.append('(');
327: boolean first = true;
328: for (String methodParam : queryMethod
329: .getMethodParams().getMethodParam()) {
330: if (!first)
331: name.append(",");
332: name.append(methodParam);
333: first = false;
334: }
335: name.append(')');
336: }
337: namedQuery.setName(name.toString());
338:
339: namedQuery.setQuery(query.getEjbQl());
340: entityData.entity.getNamedQuery().add(namedQuery);
341: }
342: }
343:
344: for (EjbRelationType relation : openejbJarType.getEjbRelation()) {
345: List<EjbRelationshipRoleType> roles = relation
346: .getEjbRelationshipRole();
347: if (roles.isEmpty()) {
348: continue;
349: }
350:
351: if (relation.getManyToManyTableName() == null) {
352: EjbRelationshipRoleType leftRole = roles.get(0);
353: EjbRelationshipRoleType.RelationshipRoleSource leftRoleSource = leftRole
354: .getRelationshipRoleSource();
355: String leftEjbName = leftRoleSource == null ? null
356: : leftRoleSource.getEjbName();
357: EntityData leftEntityData = entities.get(moduleId + "#"
358: + leftEjbName);
359: String leftFieldName = leftRole.getCmrField()
360: .getCmrFieldName();
361:
362: RelationField field;
363: if (leftRole.isForeignKeyColumnOnSource()) {
364: field = leftEntityData.relations.get(leftFieldName);
365: // todo warn field not found
366: if (field == null) {
367: continue;
368: }
369: } else {
370: RelationField other = leftEntityData.relations
371: .get(leftFieldName);
372: // todo warn field not found
373: if (other == null) {
374: continue;
375: }
376: field = other.getRelatedField();
377: // todo warn field not found
378: if (field == null) {
379: if (other instanceof OneToMany) {
380: // for a unidirectional oneToMany, the join column declaration
381: // is placed on the oneToMany element instead of manyToOne
382: field = other;
383: } else {
384: continue;
385: }
386: }
387: }
388:
389: // For one-to-one, make sure that the field to recieve the FK
390: // is marked as the owning field
391: if (field instanceof OneToOne) {
392: OneToOne left = (OneToOne) field;
393: OneToOne right = (OneToOne) left.getRelatedField();
394: if (right != null) {
395: left.setMappedBy(null);
396: right.setMappedBy(left.getName());
397: }
398:
399: }
400: EjbRelationshipRoleType.RoleMapping roleMapping = leftRole
401: .getRoleMapping();
402: for (EjbRelationshipRoleType.RoleMapping.CmrFieldMapping cmrFieldMapping : roleMapping
403: .getCmrFieldMapping()) {
404: JoinColumn joinColumn = new JoinColumn();
405: joinColumn.setName(cmrFieldMapping
406: .getForeignKeyColumn());
407: joinColumn.setReferencedColumnName(cmrFieldMapping
408: .getKeyColumn());
409: field.getJoinColumn().add(joinColumn);
410: }
411: } else {
412: JoinTable joinTable = new JoinTable();
413: joinTable.setName(relation.getManyToManyTableName());
414:
415: //
416: // left
417: EjbRelationshipRoleType leftRole = roles.get(0);
418: RelationField left = null;
419: if (leftRole.getRelationshipRoleSource() != null) {
420: String leftEjbName = leftRole
421: .getRelationshipRoleSource().getEjbName();
422: EntityData leftEntityData = entities.get(moduleId
423: + "#" + leftEjbName);
424: if (leftEntityData == null) {
425: // todo warn no such entity in ejb-jar.xml
426: continue;
427: }
428: left = leftEntityData.relations.get(leftRole
429: .getCmrField().getCmrFieldName());
430: }
431:
432: if (left != null) {
433: left.setJoinTable(joinTable);
434:
435: EjbRelationshipRoleType.RoleMapping roleMapping = leftRole
436: .getRoleMapping();
437: for (EjbRelationshipRoleType.RoleMapping.CmrFieldMapping cmrFieldMapping : roleMapping
438: .getCmrFieldMapping()) {
439: JoinColumn joinColumn = new JoinColumn();
440: joinColumn.setName(cmrFieldMapping
441: .getForeignKeyColumn());
442: joinColumn
443: .setReferencedColumnName(cmrFieldMapping
444: .getKeyColumn());
445: joinTable.getJoinColumn().add(joinColumn);
446: }
447: }
448:
449: //
450: // right
451: if (roles.size() > 1) {
452: EjbRelationshipRoleType rightRole = roles.get(1);
453:
454: // if there wasn't a left cmr field, find the field for the right, so we can add the join table to it
455: if (left == null) {
456: RelationField right = left.getRelatedField();
457: if (right == null) {
458: if (rightRole.getCmrField() == null) {
459: // todo warn no cmr field declared for either role
460: continue;
461: }
462: if (rightRole.getRelationshipRoleSource() != null) {
463: String rightEjbName = rightRole
464: .getRelationshipRoleSource()
465: .getEjbName();
466: EntityData rightEntityData = entities
467: .get(moduleId + "#"
468: + rightEjbName);
469: if (rightEntityData == null) {
470: // todo warn no such entity in ejb-jar.xml
471: continue;
472: }
473: right = rightEntityData.relations
474: .get(rightRole.getCmrField()
475: .getCmrFieldName());
476: }
477: }
478: right.setJoinTable(joinTable);
479: }
480:
481: EjbRelationshipRoleType.RoleMapping roleMapping = rightRole
482: .getRoleMapping();
483: for (EjbRelationshipRoleType.RoleMapping.CmrFieldMapping cmrFieldMapping : roleMapping
484: .getCmrFieldMapping()) {
485: JoinColumn joinColumn = new JoinColumn();
486: joinColumn.setName(cmrFieldMapping
487: .getForeignKeyColumn());
488: joinColumn
489: .setReferencedColumnName(cmrFieldMapping
490: .getKeyColumn());
491: joinTable.getInverseJoinColumn()
492: .add(joinColumn);
493: }
494: }
495: }
496: }
497: }
498:
499: private class EntityData {
500: private final Entity entity;
501: private final Map<String, Field> fields = new TreeMap<String, Field>();
502: private final Map<String, RelationField> relations = new TreeMap<String, RelationField>();
503:
504: public EntityData(Entity entity) {
505: if (entity == null)
506: throw new NullPointerException("entity is null");
507: this .entity = entity;
508:
509: Attributes attributes = entity.getAttributes();
510: if (attributes != null) {
511: for (Id id : attributes.getId()) {
512: String name = id.getName();
513: fields.put(name, id);
514: }
515:
516: for (Basic basic : attributes.getBasic()) {
517: String name = basic.getName();
518: fields.put(name, basic);
519: }
520:
521: for (RelationField relationField : attributes
522: .getOneToOne()) {
523: String name = relationField.getName();
524: relations.put(name, relationField);
525: }
526:
527: for (RelationField relationField : attributes
528: .getOneToMany()) {
529: String name = relationField.getName();
530: relations.put(name, relationField);
531: }
532:
533: for (RelationField relationField : attributes
534: .getManyToOne()) {
535: String name = relationField.getName();
536: relations.put(name, relationField);
537: }
538:
539: for (RelationField relationField : attributes
540: .getManyToMany()) {
541: String name = relationField.getName();
542: relations.put(name, relationField);
543: }
544: }
545:
546: for (AttributeOverride attributeOverride : entity
547: .getAttributeOverride()) {
548: String name = attributeOverride.getName();
549: fields.put(name, attributeOverride);
550: }
551: }
552: }
553: }
|