package org.jboss.windup.rules.apps.javaee.rules; import org.apache.commons.lang3.StringUtils; import org.jboss.forge.furnace.util.Strings; import org.jboss.windup.ast.java.data.TypeReferenceLocation; import org.jboss.windup.config.AbstractRuleProvider; import org.jboss.windup.config.GraphRewrite; import org.jboss.windup.config.loader.RuleLoaderContext; import org.jboss.windup.config.metadata.RuleMetadata; import org.jboss.windup.config.operation.iteration.AbstractIterationOperation; import org.jboss.windup.config.phase.InitialAnalysisPhase; import org.jboss.windup.graph.model.ProjectModel; import org.jboss.windup.graph.service.GraphService; import org.jboss.windup.graph.service.Service; import org.jboss.windup.config.projecttraversal.ProjectTraversalCache; import org.jboss.windup.rules.apps.java.condition.JavaClass; import org.jboss.windup.rules.apps.java.model.AbstractJavaSourceModel; import org.jboss.windup.rules.apps.java.model.JavaClassModel; import org.jboss.windup.rules.apps.java.scan.ast.JavaTypeReferenceModel; import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationListTypeValueModel; import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationLiteralTypeValueModel; import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationTypeReferenceModel; import org.jboss.windup.rules.apps.java.scan.ast.annotations.JavaAnnotationTypeValueModel; import org.jboss.windup.rules.apps.java.scan.provider.AnalyzeJavaFilesRuleProvider; import org.jboss.windup.rules.apps.javaee.model.EjbMessageDrivenModel; import org.jboss.windup.rules.apps.javaee.model.EjbSessionBeanModel; import org.jboss.windup.rules.apps.javaee.service.JmsDestinationService; import org.ocpsoft.rewrite.config.Configuration; import org.ocpsoft.rewrite.config.ConfigurationBuilder; import org.ocpsoft.rewrite.context.EvaluationContext; import java.util.Set; /** * Scans for classes with EJB related annotations, and adds EJB related metadata for these. */ @RuleMetadata(phase = InitialAnalysisPhase.class, after = AnalyzeJavaFilesRuleProvider.class) public class DiscoverEjbAnnotationsRuleProvider extends AbstractRuleProvider { @Override public Configuration getConfiguration(RuleLoaderContext ruleLoaderContext) { String ruleIDPrefix = getClass().getSimpleName(); return ConfigurationBuilder.begin() .addRule() .when(JavaClass.references("javax.ejb.{annotationType}").at(TypeReferenceLocation.ANNOTATION)) .perform(new AbstractIterationOperation<JavaTypeReferenceModel>() { public void perform(GraphRewrite event, EvaluationContext context, JavaTypeReferenceModel payload) { extractEJBMetadata(event, payload); } }) .where("annotationType").matches("Stateless|Stateful") .withId(ruleIDPrefix + "_StatelessAndStatefulRule") .addRule() .when(JavaClass.references("javax.ejb.MessageDriven").at(TypeReferenceLocation.ANNOTATION)) .perform(new AbstractIterationOperation<JavaTypeReferenceModel>() { @Override public void perform(GraphRewrite event, EvaluationContext context, JavaTypeReferenceModel payload) { extractMessageDrivenMetadata(event, payload); } }) .withId(ruleIDPrefix + "_MessageDrivenRule"); } private String getAnnotationLiteralValue(JavaAnnotationTypeReferenceModel model, String name) { JavaAnnotationTypeValueModel valueModel = model.getAnnotationValues().get(name); if (valueModel instanceof JavaAnnotationLiteralTypeValueModel) { JavaAnnotationLiteralTypeValueModel literalTypeValue = (JavaAnnotationLiteralTypeValueModel) valueModel; return literalTypeValue.getLiteralValue(); } else { return null; } } private void extractEJBMetadata(GraphRewrite event, JavaTypeReferenceModel javaTypeReference) { javaTypeReference.getFile().setGenerateSourceReport(true); JavaAnnotationTypeReferenceModel annotationTypeReference = (JavaAnnotationTypeReferenceModel) javaTypeReference; JavaClassModel ejbClass = getJavaClass(javaTypeReference); String ejbName = getAnnotationLiteralValue(annotationTypeReference, "name"); if (Strings.isNullOrEmpty(ejbName)) { ejbName = ejbClass.getClassName(); } String sessionType = javaTypeReference.getResolvedSourceSnippit() .substring(javaTypeReference.getResolvedSourceSnippit().lastIndexOf(".") + 1); Service<EjbSessionBeanModel> sessionBeanService = new GraphService<>(event.getGraphContext(), EjbSessionBeanModel.class); EjbSessionBeanModel sessionBean = sessionBeanService.create(); Set<ProjectModel> applications = ProjectTraversalCache.getApplicationsForProject(event.getGraphContext(), javaTypeReference.getFile().getProjectModel()); sessionBean.setApplications(applications); sessionBean.setBeanName(ejbName); sessionBean.setEjbClass(ejbClass); sessionBean.setSessionType(sessionType); } private void extractMessageDrivenMetadata(GraphRewrite event, JavaTypeReferenceModel javaTypeReference) { javaTypeReference.getFile().setGenerateSourceReport(true); JavaAnnotationTypeReferenceModel annotationTypeReference = (JavaAnnotationTypeReferenceModel) javaTypeReference; JavaClassModel ejbClass = getJavaClass(javaTypeReference); String ejbName = getAnnotationLiteralValue(annotationTypeReference, "name"); if (Strings.isNullOrEmpty(ejbName)) { ejbName = ejbClass.getClassName(); } JavaAnnotationTypeValueModel activationConfigAnnotation = annotationTypeReference.getAnnotationValues().get("activationConfig"); String destination = getAnnotationLiteralValue(annotationTypeReference, "mappedName"); if (StringUtils.isBlank(destination)) { destination = getDestinationFromActivationConfig(activationConfigAnnotation); } Service<EjbMessageDrivenModel> messageDrivenService = new GraphService<>(event.getGraphContext(), EjbMessageDrivenModel.class); EjbMessageDrivenModel messageDrivenBean = messageDrivenService.create(); Set<ProjectModel> applications = ProjectTraversalCache.getApplicationsForProject(event.getGraphContext(), javaTypeReference.getFile().getProjectModel()); messageDrivenBean.setApplications(applications); messageDrivenBean.setBeanName(ejbName); messageDrivenBean.setEjbClass(ejbClass); if (StringUtils.isNotBlank(destination)) { String destinationType = getPropertyFromActivationConfig(activationConfigAnnotation, "destinationType"); JmsDestinationService jmsDestinationService = new JmsDestinationService(event.getGraphContext()); messageDrivenBean.setDestination(jmsDestinationService.createUnique(applications, destination, destinationType)); } } private String getDestinationFromActivationConfig(JavaAnnotationTypeValueModel annotationTypeReferenceModel) { return this.getPropertyFromActivationConfig(annotationTypeReferenceModel, "destination"); } private String getPropertyFromActivationConfig(JavaAnnotationTypeValueModel annotationTypeReferenceModel, String property) { if (property == null) { throw new IllegalArgumentException("property cannot be null"); } if (annotationTypeReferenceModel == null) { return null; } if (annotationTypeReferenceModel instanceof JavaAnnotationListTypeValueModel) { for (JavaAnnotationTypeValueModel activationConfig : (JavaAnnotationListTypeValueModel) annotationTypeReferenceModel) { if (!(activationConfig instanceof JavaAnnotationTypeReferenceModel)) { continue; } JavaAnnotationTypeReferenceModel javaAnnotationTypeReferenceModel = (JavaAnnotationTypeReferenceModel) activationConfig; String propertyValue = getPropertyFromActivationConfig(javaAnnotationTypeReferenceModel, property); if (propertyValue != null) { return propertyValue; } } return null; } else if (annotationTypeReferenceModel instanceof JavaAnnotationTypeReferenceModel) { JavaAnnotationTypeReferenceModel javaAnnotationTypeReferenceModel = (JavaAnnotationTypeReferenceModel) annotationTypeReferenceModel; JavaAnnotationTypeValueModel propertyNameModel = javaAnnotationTypeReferenceModel.getAnnotationValues().get("propertyName"); JavaAnnotationTypeValueModel propertyValueModel = javaAnnotationTypeReferenceModel.getAnnotationValues().get("propertyValue"); if (propertyNameModel instanceof JavaAnnotationLiteralTypeValueModel && propertyValueModel instanceof JavaAnnotationLiteralTypeValueModel) { String propertyName = ((JavaAnnotationLiteralTypeValueModel) propertyNameModel).getLiteralValue(); String propertyValue = ((JavaAnnotationLiteralTypeValueModel) propertyValueModel).getLiteralValue(); if (property.equals(propertyName)) { return propertyValue; } } return null; } else { return null; } } private JavaClassModel getJavaClass(JavaTypeReferenceModel javaTypeReference) { JavaClassModel result = null; AbstractJavaSourceModel javaSource = javaTypeReference.getFile(); for (JavaClassModel javaClassModel : javaSource.getJavaClasses()) { // there can be only one public one, and the annotated class should be public if (javaClassModel.isPublic() != null && javaClassModel.isPublic()) { result = javaClassModel; break; } } if (result == null) { // no public classes found, so try to find any class (even non-public ones) result = javaSource.getJavaClasses().iterator().next(); } return result; } @Override public String toString() { return "DiscoverEJBAnnotatedClasses"; } }