/* * Licensed to the Apache Software Foundation (ASF) under one or more * contributor license agreements. See the NOTICE file distributed with * this work for additional information regarding copyright ownership. * The ASF licenses this file to You under the Apache License, Version 2.0 * (the "License"); you may not use this file except in compliance with * the License. You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. */ package org.apache.openejb.config; import org.apache.openejb.jee.ActivationConfig; import org.apache.openejb.jee.ActivationConfigProperty; import org.apache.openejb.jee.EjbJar; import org.apache.openejb.jee.EjbRef; import org.apache.openejb.jee.EnterpriseBean; import org.apache.openejb.jee.MessageDrivenBean; import org.apache.openejb.jee.jpa.AttributeOverride; import org.apache.openejb.jee.jpa.Attributes; import org.apache.openejb.jee.jpa.Basic; import org.apache.openejb.jee.jpa.Column; import org.apache.openejb.jee.jpa.Entity; import org.apache.openejb.jee.jpa.EntityMappings; import org.apache.openejb.jee.jpa.Field; import org.apache.openejb.jee.jpa.GeneratedValue; import org.apache.openejb.jee.jpa.GenerationType; import org.apache.openejb.jee.jpa.Id; import org.apache.openejb.jee.jpa.JoinColumn; import org.apache.openejb.jee.jpa.JoinTable; import org.apache.openejb.jee.jpa.NamedQuery; import org.apache.openejb.jee.jpa.OneToMany; import org.apache.openejb.jee.jpa.OneToOne; import org.apache.openejb.jee.jpa.RelationField; import org.apache.openejb.jee.jpa.Table; import org.apache.openejb.jee.oejb2.ActivationConfigPropertyType; import org.apache.openejb.jee.oejb2.ActivationConfigType; import org.apache.openejb.jee.oejb2.EjbLocalRefType; import org.apache.openejb.jee.oejb2.EjbRefType; import org.apache.openejb.jee.oejb2.EjbRelationType; import org.apache.openejb.jee.oejb2.EjbRelationshipRoleType; import org.apache.openejb.jee.oejb2.EntityBeanType; import org.apache.openejb.jee.oejb2.GeronimoEjbJarType; import org.apache.openejb.jee.oejb2.JaxbOpenejbJar2; import org.apache.openejb.jee.oejb2.Jndi; import org.apache.openejb.jee.oejb2.MessageDrivenBeanType; import org.apache.openejb.jee.oejb2.OpenejbJarType; import org.apache.openejb.jee.oejb2.PatternType; import org.apache.openejb.jee.oejb2.QueryType; import org.apache.openejb.jee.oejb2.RpcBean; import org.apache.openejb.jee.oejb2.SessionBeanType; import org.apache.openejb.jee.oejb2.TssLinkType; import org.apache.openejb.jee.oejb2.WebServiceBindingType; import org.apache.openejb.jee.oejb2.WebServiceSecurityType; import org.apache.openejb.jee.oejb3.EjbDeployment; import org.apache.openejb.jee.oejb3.EjbLink; import org.apache.openejb.jee.oejb3.OpenejbJar; import org.apache.openejb.loader.IO; import org.slf4j.LoggerFactory; import javax.xml.bind.JAXBElement; import java.io.ByteArrayInputStream; import java.net.URL; import java.util.List; import java.util.Map; import java.util.Set; import java.util.TreeMap; import java.util.TreeSet; public class OpenEjb2Conversion implements DynamicDeployer { @Override public final AppModule deploy(final AppModule appModule) { for (final EjbModule ejbModule : appModule.getEjbModules()) { final Object altDD = getOpenejbJarType(ejbModule); if (OpenejbJarType.class.isInstance(altDD)) { final OpenejbJarType openejbJarType = OpenejbJarType.class.cast(altDD); convertEjbRefs(ejbModule.getEjbJar(), ejbModule.getOpenejbJar(), openejbJarType); convertMdbConfigs(ejbModule.getEjbJar(), openejbJarType); mergeEntityMappings(ejbModule.getModuleId(), appModule.getCmpMappings(), ejbModule.getOpenejbJar(), openejbJarType); } } return appModule; } private OpenejbJarType getOpenejbJarType(final EjbModule ejbModule) { Object altDD = ejbModule.getAltDDs().get("openejb-jar.xml"); if (altDD instanceof String) { try { altDD = JaxbOpenejbJar2.unmarshal(OpenejbJarType.class, new ByteArrayInputStream(((String) altDD).getBytes()), false); } catch (final Exception e) { // todo warn about not being able to parse sun descriptor } } if (altDD instanceof URL) { try { altDD = JaxbOpenejbJar2.unmarshal(OpenejbJarType.class, IO.read((URL) altDD), false); } catch (final Exception e) { // todo warn about not being able to parse sun descriptor } } if (altDD instanceof JAXBElement) { altDD = ((JAXBElement) altDD).getValue(); } if (altDD instanceof OpenejbJarType) { return (OpenejbJarType) altDD; } return null; } public final void convertEjbRefs(final EjbJar ejbJar, final OpenejbJar openejbJar, final OpenejbJarType openejbJarType) { openejbJar.getProperties().putAll(openejbJarType.getProperties()); final Map<String, EnterpriseBean> ejbs = ejbJar.getEnterpriseBeansByEjbName(); final Map<String, EjbDeployment> deployments = openejbJar.getDeploymentsByEjbName(); for (final org.apache.openejb.jee.oejb2.EnterpriseBean enterpriseBean : openejbJarType.getEnterpriseBeans()) { final EnterpriseBean ejb = ejbs.get(enterpriseBean.getEjbName()); if (ejb == null) { // todo warn no such ejb in the ejb-jar.xml continue; } final Map<String, EjbRef> ejbRefs = ejb.getEjbRefMap(); final EjbDeployment deployment = deployments.get(enterpriseBean.getEjbName()); if (deployment == null) { // todo warn no such ejb in the ejb-jar.xml continue; } // Add WS Security if (enterpriseBean instanceof SessionBeanType) { final SessionBeanType sessionBean = (SessionBeanType) enterpriseBean; final WebServiceSecurityType webServiceSecurityType = sessionBean.getWebServiceSecurity(); if (webServiceSecurityType != null) { if (webServiceSecurityType.getRealmName() != null) { deployment.addProperty("webservice.security.realm", webServiceSecurityType.getRealmName()); } if (webServiceSecurityType.getSecurityRealmName() != null) { deployment.addProperty("webservice.security.securityRealm", webServiceSecurityType.getSecurityRealmName()); } if (webServiceSecurityType.getTransportGuarantee() != null) { deployment.addProperty("webservice.security.transportGarantee", webServiceSecurityType.getTransportGuarantee().value()); } else { deployment.addProperty("webservice.security.transportGarantee", "NONE"); } if (webServiceSecurityType.getAuthMethod() != null) { deployment.addProperty("webservice.security.authMethod", webServiceSecurityType.getAuthMethod().value()); } else { deployment.addProperty("webservice.security.authMethod", "NONE"); } deployment.getProperties().putAll(webServiceSecurityType.getProperties()); } if (sessionBean.getWebServiceAddress() != null) { deployment.getProperties().put("openejb.webservice.deployment.address", sessionBean.getWebServiceAddress()); } } deployment.getProperties().putAll(enterpriseBean.getProperties()); for (final String name : enterpriseBean.getLocalJndiName()) { deployment.getJndi().add(new org.apache.openejb.jee.oejb3.Jndi(name, "LocalHome")); } for (final String name : enterpriseBean.getJndiName()) { deployment.getJndi().add(new org.apache.openejb.jee.oejb3.Jndi(name, "RemoteHome")); } for (final Jndi jndi : enterpriseBean.getJndi()) { deployment.getJndi().add(new org.apache.openejb.jee.oejb3.Jndi(jndi.getName(), jndi.getInterface())); } final Set<String> ejbLinks = new TreeSet<String>(); for (final EjbLink ejbLink : deployment.getEjbLink()) { ejbLinks.add(ejbLink.getEjbRefName()); } for (final EjbRefType refType : enterpriseBean.getEjbRef()) { final String refName = refType.getRefName(); if (ejbLinks.contains(refName)) { // don't overwrite refs that have been already set continue; } final String nsCorbaloc = refType.getNsCorbaloc(); if (nsCorbaloc != null) { final EjbRef ref = ejbRefs.get(refName); if (ref != null) { ref.setMappedName("jndi:" + nsCorbaloc); } } else if (refType.getEjbLink() != null) { final EjbRef ref = ejbRefs.get(refName); if (ref != null) { ref.setEjbLink(refType.getEjbLink()); } } else { final PatternType pattern = refType.getPattern(); addEjbLink(deployment, refName, pattern); } } for (final EjbLocalRefType refType : enterpriseBean.getEjbLocalRef()) { final String refName = refType.getRefName(); if (ejbLinks.contains(refName)) { // don't overwrite refs that have been already set continue; } if (refType.getEjbLink() != null) { final EjbRef ref = ejbRefs.get(refName); if (ref != null) { ref.setEjbLink(refType.getEjbLink()); } } else { final PatternType pattern = refType.getPattern(); addEjbLink(deployment, refName, pattern); } } } } private void addEjbLink(final EjbDeployment deployment, final String refName, final PatternType pattern) { String module = pattern.getModule(); if (module == null) { module = pattern.getArtifactId(); } final String ejbName = pattern.getName(); final String deploymentId = module + "/" + ejbName; final EjbLink ejbLink = new EjbLink(refName, deploymentId); deployment.getEjbLink().add(ejbLink); } public final void convertMdbConfigs(final EjbJar ejbJar, final OpenejbJarType openejbJarType) { final Map<String, MessageDrivenBean> mdbs = new TreeMap<String, MessageDrivenBean>(); for (final EnterpriseBean enterpriseBean : ejbJar.getEnterpriseBeans()) { if (!(enterpriseBean instanceof MessageDrivenBean)) { continue; } mdbs.put(enterpriseBean.getEjbName(), (MessageDrivenBean) enterpriseBean); } for (final org.apache.openejb.jee.oejb2.EnterpriseBean enterpriseBean : openejbJarType.getEnterpriseBeans()) { if (!(enterpriseBean instanceof MessageDrivenBeanType)) { continue; } final MessageDrivenBeanType bean = (MessageDrivenBeanType) enterpriseBean; final MessageDrivenBean mdb = mdbs.get(bean.getEjbName()); if (mdb == null) { // todo warn no such ejb in the ejb-jar.xml continue; } final ActivationConfigType activationConfigType = bean.getActivationConfig(); if (activationConfigType != null) { ActivationConfig activationConfig = mdb.getActivationConfig(); if (activationConfig == null) { activationConfig = new ActivationConfig(); mdb.setActivationConfig(activationConfig); } for (final ActivationConfigPropertyType propertyType : activationConfigType.getActivationConfigProperty()) { final ActivationConfigProperty property = new ActivationConfigProperty( propertyType.getActivationConfigPropertyName(), propertyType.getActivationConfigPropertyValue()); activationConfig.getActivationConfigProperty().add(property); } } } } public final void mergeEntityMappings(final String moduleId, final EntityMappings entityMappings, final OpenejbJar openejbJar, final OpenejbJarType openejbJarType) { final Map<String, EntityData> entities = new TreeMap<String, EntityData>(); if (entityMappings != null) { for (final Entity entity : entityMappings.getEntity()) { try { entities.put(entity.getDescription(), new EntityData(entity)); } catch (final IllegalArgumentException e) { LoggerFactory.getLogger(this.getClass()).error(e.getMessage(), e); } } } for (final org.apache.openejb.jee.oejb2.EnterpriseBean enterpriseBean : openejbJarType.getEnterpriseBeans()) { if (!(enterpriseBean instanceof EntityBeanType)) { continue; } final EntityBeanType bean = (EntityBeanType) enterpriseBean; final EntityData entityData = entities.get(moduleId + "#" + bean.getEjbName()); if (entityData == null) { // todo warn no such ejb in the ejb-jar.xml continue; } final Table table = new Table(); table.setName(bean.getTableName()); entityData.entity.setTable(table); for (final EntityBeanType.CmpFieldMapping cmpFieldMapping : bean.getCmpFieldMapping()) { final String cmpFieldName = cmpFieldMapping.getCmpFieldName(); final Field field = entityData.fields.get(cmpFieldName); if (field == null) { // todo warn no such cmp-field in the ejb-jar.xml continue; } final Column column = new Column(); column.setName(cmpFieldMapping.getTableColumn()); field.setColumn(column); } if (bean.getKeyGenerator() != null) { // todo support complex primary keys final Attributes attributes = entityData.entity.getAttributes(); if (attributes != null && attributes.getId().size() == 1) { final Id id = attributes.getId().get(0); // todo detect specific generation strategy id.setGeneratedValue(new GeneratedValue(GenerationType.IDENTITY)); } } for (final QueryType query : bean.getQuery()) { final NamedQuery namedQuery = new NamedQuery(); final QueryType.QueryMethod queryMethod = query.getQueryMethod(); // todo deployment id could change in one of the later conversions... use entity name instead, but we need to save it off final StringBuilder name = new StringBuilder(); name.append(entityData.entity.getName()).append(".").append(queryMethod.getMethodName()); if (queryMethod.getMethodParams() != null && !queryMethod.getMethodParams().getMethodParam().isEmpty()) { name.append('('); boolean first = true; for (final String methodParam : queryMethod.getMethodParams().getMethodParam()) { if (!first) { name.append(","); } name.append(methodParam); first = false; } name.append(')'); } namedQuery.setName(name.toString()); namedQuery.setQuery(query.getEjbQl()); entityData.entity.getNamedQuery().add(namedQuery); } } for (final EjbRelationType relation : openejbJarType.getEjbRelation()) { final List<EjbRelationshipRoleType> roles = relation.getEjbRelationshipRole(); if (roles.isEmpty()) { continue; } if (relation.getManyToManyTableName() == null) { final EjbRelationshipRoleType leftRole = roles.get(0); final EjbRelationshipRoleType.RelationshipRoleSource leftRoleSource = leftRole.getRelationshipRoleSource(); final String leftEjbName = leftRoleSource == null ? null : leftRoleSource.getEjbName(); final EntityData leftEntityData = entities.get(moduleId + "#" + leftEjbName); final EjbRelationshipRoleType.CmrField cmrField = leftRole.getCmrField(); final String leftFieldName = null != cmrField ? cmrField.getCmrFieldName() : null; RelationField field; if (leftRole.isForeignKeyColumnOnSource()) { field = null != leftFieldName && null != leftEntityData ? leftEntityData.relations.get(leftFieldName) : null; // todo warn field not found if (field == null) { continue; } } else { final RelationField other = null != leftFieldName && null != leftEntityData ? leftEntityData.relations.get(leftFieldName) : null; // todo warn field not found if (other == null) { continue; } field = other.getRelatedField(); // todo warn field not found if (field == null) { if (other instanceof OneToMany) { // for a unidirectional oneToMany, the join column declaration // is placed on the oneToMany element instead of manyToOne field = other; } else { continue; } } } // For one-to-one, make sure that the field to recieve the FK // is marked as the owning field if (field instanceof OneToOne) { final OneToOne left = (OneToOne) field; final OneToOne right = (OneToOne) left.getRelatedField(); if (right != null) { left.setMappedBy(null); right.setMappedBy(left.getName()); } } final EjbRelationshipRoleType.RoleMapping roleMapping = leftRole.getRoleMapping(); for (final EjbRelationshipRoleType.RoleMapping.CmrFieldMapping cmrFieldMapping : roleMapping.getCmrFieldMapping()) { final JoinColumn joinColumn = new JoinColumn(); joinColumn.setName(cmrFieldMapping.getForeignKeyColumn()); joinColumn.setReferencedColumnName(cmrFieldMapping.getKeyColumn()); field.getJoinColumn().add(joinColumn); } } else { final JoinTable joinTable = new JoinTable(); joinTable.setName(relation.getManyToManyTableName()); // // left final EjbRelationshipRoleType leftRole = roles.get(0); RelationField left = null; if (leftRole.getRelationshipRoleSource() != null) { final String leftEjbName = leftRole.getRelationshipRoleSource().getEjbName(); final EntityData leftEntityData = entities.get(moduleId + "#" + leftEjbName); if (leftEntityData == null) { // todo warn no such entity in ejb-jar.xml continue; } final EjbRelationshipRoleType.CmrField lcf = leftRole.getCmrField(); left = (null != lcf ? leftEntityData.relations.get(lcf.getCmrFieldName()) : null); } if (left != null) { left.setJoinTable(joinTable); final EjbRelationshipRoleType.RoleMapping roleMapping = leftRole.getRoleMapping(); for (final EjbRelationshipRoleType.RoleMapping.CmrFieldMapping cmrFieldMapping : roleMapping.getCmrFieldMapping()) { final JoinColumn joinColumn = new JoinColumn(); joinColumn.setName(cmrFieldMapping.getForeignKeyColumn()); joinColumn.setReferencedColumnName(cmrFieldMapping.getKeyColumn()); joinTable.getJoinColumn().add(joinColumn); } } // // right if (roles.size() > 1) { final EjbRelationshipRoleType rightRole = roles.get(1); // if there wasn't a left cmr field, find the field for the right, so we can add the join table to it if (left == null) { final EjbRelationshipRoleType.CmrField rcf = rightRole.getCmrField(); if (rcf == null) { // todo warn no cmr field declared for either role continue; } else if (rightRole.getRelationshipRoleSource() != null) { final String rightEjbName = rightRole.getRelationshipRoleSource().getEjbName(); final EntityData rightEntityData = entities.get(moduleId + "#" + rightEjbName); if (rightEntityData == null) { // todo warn no such entity in ejb-jar.xml continue; } final RelationField right = rightEntityData.relations.get(rcf.getCmrFieldName()); right.setJoinTable(joinTable); } } final EjbRelationshipRoleType.RoleMapping roleMapping = rightRole.getRoleMapping(); for (final EjbRelationshipRoleType.RoleMapping.CmrFieldMapping cmrFieldMapping : roleMapping.getCmrFieldMapping()) { final JoinColumn joinColumn = new JoinColumn(); joinColumn.setName(cmrFieldMapping.getForeignKeyColumn()); joinColumn.setReferencedColumnName(cmrFieldMapping.getKeyColumn()); joinTable.getInverseJoinColumn().add(joinColumn); } } } } } /** * Actually called from ReadDescriptors as Geronimo needs this info early * * @param o2 OpenejbJarType * @return GeronimoEjbJarType */ public static GeronimoEjbJarType convertToGeronimoOpenejbXml(final OpenejbJarType o2) { final GeronimoEjbJarType g2 = new GeronimoEjbJarType(); g2.setEnvironment(o2.getEnvironment()); g2.setSecurity(o2.getSecurity()); g2.getService().addAll(o2.getService()); g2.getMessageDestination().addAll(o2.getMessageDestination()); g2.getPersistence().addAll(o2.getPersistence()); for (final org.apache.openejb.jee.oejb2.EnterpriseBean bean : o2.getEnterpriseBeans()) { g2.getAbstractNamingEntry().addAll(bean.getAbstractNamingEntry()); g2.getPersistenceContextRef().addAll(bean.getPersistenceContextRef()); g2.getPersistenceUnitRef().addAll(bean.getPersistenceUnitRef()); g2.getEjbLocalRef().addAll(bean.getEjbLocalRef()); g2.getEjbRef().addAll(bean.getEjbRef()); g2.getResourceEnvRef().addAll(bean.getResourceEnvRef()); g2.getResourceRef().addAll(bean.getResourceRef()); g2.getServiceRef().addAll(bean.getServiceRef()); if (bean instanceof RpcBean) { final RpcBean rpcBean = (RpcBean) bean; if (rpcBean.getTssLink() != null) { g2.getTssLink().add(new TssLinkType(rpcBean.getEjbName(), rpcBean.getTssLink(), rpcBean.getJndiName())); } } if (bean instanceof SessionBeanType) { final SessionBeanType sb = (SessionBeanType) bean; final WebServiceBindingType b = new WebServiceBindingType(); b.setEjbName(sb.getEjbName()); b.setWebServiceAddress(sb.getWebServiceAddress()); b.setWebServiceVirtualHost(sb.getWebServiceVirtualHost()); b.setWebServiceSecurity(sb.getWebServiceSecurity()); if (b.containsData()) { g2.getWebServiceBinding().add(b); } } } return g2; } private static class EntityData { private final Entity entity; private final Map<String, Field> fields = new TreeMap<String, Field>(); private final Map<String, RelationField> relations = new TreeMap<String, RelationField>(); public EntityData(final Entity e) { this.entity = e; if (this.entity == null) { throw new IllegalArgumentException("entity is null"); } final Attributes attributes = this.entity.getAttributes(); if (attributes != null) { for (final Id id : attributes.getId()) { this.fields.put(id.getName(), id); } for (final Basic basic : attributes.getBasic()) { this.fields.put(basic.getName(), basic); } for (final RelationField relationField : attributes.getOneToOne()) { this.relations.put(relationField.getName(), relationField); } for (final RelationField relationField : attributes.getOneToMany()) { this.relations.put(relationField.getName(), relationField); } for (final RelationField relationField : attributes.getManyToOne()) { this.relations.put(relationField.getName(), relationField); } for (final RelationField relationField : attributes.getManyToMany()) { this.relations.put(relationField.getName(), relationField); } } for (final AttributeOverride attributeOverride : this.entity.getAttributeOverride()) { this.fields.put(attributeOverride.getName(), attributeOverride); } } } }