package org.jboss.windup.rules.apps.javaee.rules; import static org.joox.JOOX.$; import java.util.HashMap; import java.util.Map; import java.util.Set; import org.apache.commons.lang3.StringUtils; import org.jboss.windup.config.GraphRewrite; import org.jboss.windup.config.metadata.RuleMetadata; import org.jboss.windup.config.phase.InitialAnalysisPhase; import org.jboss.windup.config.query.Query; import org.jboss.windup.config.ruleprovider.IteratingRuleProvider; import org.jboss.windup.graph.GraphContext; import org.jboss.windup.graph.model.ProjectModel; import org.jboss.windup.config.projecttraversal.ProjectTraversalCache; import org.jboss.windup.reporting.model.TechnologyTagLevel; import org.jboss.windup.reporting.model.TechnologyTagModel; import org.jboss.windup.reporting.service.TechnologyTagService; import org.jboss.windup.rules.apps.java.model.JavaClassModel; import org.jboss.windup.rules.apps.java.service.JavaClassService; import org.jboss.windup.rules.apps.javaee.model.DataSourceModel; import org.jboss.windup.rules.apps.javaee.model.JPAConfigurationFileModel; import org.jboss.windup.rules.apps.javaee.model.JPAEntityModel; import org.jboss.windup.rules.apps.javaee.model.JPAPersistenceUnitModel; import org.jboss.windup.rules.apps.javaee.service.DataSourceService; import org.jboss.windup.rules.apps.javaee.service.JPAConfigurationFileService; import org.jboss.windup.rules.apps.javaee.service.JPAEntityService; import org.jboss.windup.rules.apps.javaee.service.JPAPersistenceUnitService; import org.jboss.windup.rules.apps.javaee.util.HibernateDialectDataSourceTypeResolver; import org.jboss.windup.rules.apps.xml.model.NamespaceMetaModel; import org.jboss.windup.rules.apps.xml.model.XmlFileModel; import org.jboss.windup.rules.apps.xml.service.XmlFileService; import org.ocpsoft.rewrite.config.ConditionBuilder; import org.ocpsoft.rewrite.context.EvaluationContext; import org.w3c.dom.Document; import org.w3c.dom.Element; /** * Discovers persistence.xml files and parses the related metadata * * @author <a href="mailto:bradsdavis@gmail.com">Brad Davis</a> */ @RuleMetadata(phase = InitialAnalysisPhase.class, perform = "Discover JPA Persistence XML Files") public class DiscoverJpaConfigurationXmlRuleProvider extends IteratingRuleProvider<NamespaceMetaModel> { private static final String TECH_TAG = "JPA XML"; private static final TechnologyTagLevel TECH_TAG_LEVEL = TechnologyTagLevel.INFORMATIONAL; @Override public ConditionBuilder when() { return Query.fromType(NamespaceMetaModel.class).withProperty(NamespaceMetaModel.NAMESPACE_URI, "http://java.sun.com/xml/ns/persistence"); } public void perform(GraphRewrite event, EvaluationContext context, NamespaceMetaModel payload) { for (XmlFileModel xml : payload.getXmlResources()) { if (StringUtils.equals(xml.getRootTagName(), "persistence")) continue; try { Document doc = new XmlFileService(event.getGraphContext()).loadDocument(event, context, xml); extractMetadata(event.getGraphContext(), xml, doc); } catch (Exception ex) { xml.setParseError("Failed to parse JPA configuration: " + ex.getMessage()); } } } private void extractMetadata(GraphContext graphContext, XmlFileModel xmlFileModel, Document doc) { DataSourceService dataSourceService = new DataSourceService(graphContext); JavaClassService javaClassService = new JavaClassService(graphContext); JPAConfigurationFileService jpaConfigurationFileService = new JPAConfigurationFileService(graphContext); JPAPersistenceUnitService jpaPersistenceUnitService = new JPAPersistenceUnitService(graphContext); JPAEntityService jpaEntityService = new JPAEntityService(graphContext); TechnologyTagService technologyTagService = new TechnologyTagService(graphContext); TechnologyTagModel technologyTag = technologyTagService.addTagToFileModel(xmlFileModel, TECH_TAG, TECH_TAG_LEVEL); String version = $(doc).attr("version"); if (StringUtils.isNotBlank(version)) { technologyTag.setVersion(version); } // check the root XML node. JPAConfigurationFileModel jpaConfigurationModel = jpaConfigurationFileService.addTypeToModel(xmlFileModel); if (StringUtils.isNotBlank(version)) { jpaConfigurationModel.setSpecificationVersion(version); } Set<ProjectModel> applications = ProjectTraversalCache.getApplicationsForProject(graphContext, xmlFileModel.getProjectModel()); for (Element element : $(doc).find("persistence-unit").get()) { JPAPersistenceUnitModel persistenceUnitModel = jpaPersistenceUnitService.create(); persistenceUnitModel.setApplication(xmlFileModel.getApplication()); String persistenceUnitName = $(element).attr("name"); persistenceUnitModel.setName(persistenceUnitName); jpaConfigurationModel.addPersistenceUnit(persistenceUnitModel); if ($(element).find("jta-data-source").isNotEmpty()) { final String dataSourceJndiName = $(element).find("jta-data-source").text(); String dataSourceName = dataSourceJndiName; if (StringUtils.contains(dataSourceName, "/")) { dataSourceName = StringUtils.substringAfterLast(dataSourceName, "/"); } DataSourceModel dataSource = dataSourceService.createUnique(applications, dataSourceName, dataSourceJndiName); persistenceUnitModel.addDataSource(dataSource); } if ($(element).find("non-jta-data-source").isNotEmpty()) { final String dataSourceJndiName = $(element).find("non-jta-data-source").text(); String dataSourceName = dataSourceJndiName; if (StringUtils.contains(dataSourceName, "/")) { dataSourceName = StringUtils.substringAfterLast(dataSourceName, "/"); } DataSourceModel dataSource = dataSourceService.createUnique(applications, dataSourceName, dataSourceJndiName); persistenceUnitModel.addDataSource(dataSource); } for (Element clz : $(element).find("class").get()) { String clzName = $(clz).text(); JavaClassModel javaClz = javaClassService.getOrCreatePhantom(clzName); JPAEntityModel entityModel = jpaEntityService.create(); entityModel.setApplications(applications); entityModel.setJavaClass(javaClz); } Map<String, String> persistenceUnitProperties = new HashMap<>(); for (Element propElement : $(element).find("property")) { String propKey = $(propElement).attr("name"); String propValue = $(propElement).attr("value"); persistenceUnitProperties.put(propKey, propValue); } if (persistenceUnitProperties.containsKey("hibernate.dialect")) { String dialect = persistenceUnitProperties.get("hibernate.dialect"); for (DataSourceModel datasource : persistenceUnitModel.getDataSources()) { datasource.setDatabaseTypeName(HibernateDialectDataSourceTypeResolver.resolveDataSourceTypeFromDialect(dialect)); } } persistenceUnitModel.setProperties(persistenceUnitProperties); } } }