package org.jboss.windup.rules.apps.mavenize; import java.util.Map; import java.util.logging.Logger; 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.GraphOperation; import org.jboss.windup.config.operation.iteration.AbstractIterationOperation; import org.jboss.windup.config.phase.ArchiveExtractionPhase; import org.jboss.windup.config.phase.ArchiveMetadataExtractionPhase; import org.jboss.windup.config.phase.DependentPhase; import org.jboss.windup.config.phase.DiscoverProjectStructurePhase; import org.jboss.windup.config.query.Query; import org.jboss.windup.graph.GraphContext; import org.jboss.windup.graph.model.ProjectModel; import org.jboss.windup.graph.model.WindupConfigurationModel; import org.jboss.windup.graph.model.resource.FileModel; import org.jboss.windup.graph.service.GraphService; import org.jboss.windup.rules.apps.java.archives.config.ArchiveIdentificationConfigLoadingRuleProvider; import org.jboss.windup.rules.apps.java.archives.model.ArchiveCoordinateModel; import org.jboss.windup.rules.apps.java.archives.model.IdentifiedArchiveModel; import org.jboss.windup.rules.apps.java.condition.SourceMode; import org.jboss.windup.rules.apps.java.scan.provider.DiscoverMavenHierarchyRuleProvider; import org.jboss.windup.util.Logging; import org.jboss.windup.util.exception.WindupException; import org.ocpsoft.rewrite.config.ConditionBuilder; import org.ocpsoft.rewrite.config.Configuration; import org.ocpsoft.rewrite.config.ConfigurationBuilder; import org.ocpsoft.rewrite.context.EvaluationContext; /** * Creates a stub of Maven project structure, including pom.xml's and the proper directory structure and dependencies, * based on the project structure determined by prior Windup rules (nested deployments) and the libraries included in them. * * @author <a href="http://ondra.zizka.cz/">Ondrej Zizka, ozizka at seznam.cz</a> */ @RuleMetadata(after = { ArchiveMetadataExtractionPhase.class, ArchiveIdentificationConfigLoadingRuleProvider.class, ArchiveExtractionPhase.class, DiscoverMavenHierarchyRuleProvider.class, DiscoverProjectStructurePhase.class }, phase = DependentPhase.class) public class MavenizeRuleProvider extends AbstractRuleProvider { private static final Logger LOG = Logging.get(MavenizeRuleProvider.class); public static final MavenCoord JBOSS_PARENT = new MavenCoord("org.jboss", "jboss-parent", "20"); public static final MavenCoord JBOSS_BOM_JAVAEE6_WITH_ALL = new MavenCoord("org.jboss.bom", "jboss-javaee-6.0-with-all", "1.0.7.Final"); public static final MavenCoord JBOSS_BOM_JAVAEE7_WITH_ALL = new MavenCoord("org.jboss.bom", "wildfly-javaee7-with-tools", "10.0.1.Final"); // @formatter:off @Override public Configuration getConfiguration(RuleLoaderContext ruleLoaderContext) { ConditionBuilder applicationProjectModels = Query.fromType(WindupConfigurationModel.class); return ConfigurationBuilder.begin() // Create the BOM frame .addRule() .perform(new GraphOperation() { public void perform(GraphRewrite event, EvaluationContext context) { if (!isPerformMavenization(event.getGraphContext())) return; GlobalBomModel bom = event.getGraphContext().getFramed().addVertex(null, GlobalBomModel.class); ArchiveCoordinateModel jbossParent = event.getGraphContext().getFramed().addVertex(null, ArchiveCoordinateModel.class); copyTo(JBOSS_PARENT, jbossParent); bom.setParent(jbossParent); } }) .withId("Mavenize-BOM-data-collection") // For each IdentifiedArchive, add it to the global BOM. .addRule() .when(Query.fromType(IdentifiedArchiveModel.class)) .perform(new MavenizePutNewerVersionToGlobalBomOperation()) .withId("Mavenize-BOM-file-creation") // For each application given to Windup as input, mavenize it. .addRule() .when(applicationProjectModels, SourceMode.isDisabled()) .perform(new MavenizeApplicationOperation()) .withId("Mavenize-projects-mavenization") ; } // @formatter:on /** * This operation puts the given IdentifiedArchiveModel to the global BOM frame. * If there's already one of such G:A:P, then the newer version is used. * Eventual version collisions are overridden in pom.xml's. */ class MavenizePutNewerVersionToGlobalBomOperation extends AbstractIterationOperation<IdentifiedArchiveModel> { @Override public void perform(GraphRewrite event, EvaluationContext context, IdentifiedArchiveModel archive) { if (!isPerformMavenization(event.getGraphContext())) return; if (archive.getCoordinate() == null) { LOG.info("Warning: archive.getCoordinate() is null: " + archive.toPrettyString()); return; } LOG.info("Adding to global BOM: " + archive.getCoordinate().toPrettyString()); // BOM GraphService<GlobalBomModel> bomServ = new GraphService<>(event.getGraphContext(), GlobalBomModel.class); GlobalBomModel bom = bomServ.getUnique(); // Check for an existing coord, add the new one bom.addNewerDependency(archive.getCoordinate()); } } /** * Create a stub of Maven project structure, including pom.xml's and the proper directory structure and dependencies, * based on the project structure determined by prior Windup rules (nested deployments) and the libraries included in them. */ private class MavenizeApplicationOperation extends AbstractIterationOperation<WindupConfigurationModel> { public MavenizeApplicationOperation() { } @Override public void perform(GraphRewrite event, EvaluationContext evalContext, WindupConfigurationModel config) { if (!isPerformMavenization(event.getGraphContext())) return; for (FileModel inputPath : config.getInputPaths()) { ProjectModel projectModel = inputPath.getProjectModel(); if (projectModel == null) throw new WindupException("Error, no project found in: " + inputPath.getFilePath()); new MavenizationService(event.getGraphContext()).mavenizeApp(projectModel); } } } private static void copyTo(MavenCoord from, ArchiveCoordinateModel to) { to.setArtifactId(from.getArtifactId()); to.setGroupId(from.getGroupId()); to.setVersion(from.getVersion()); to.setClassifier(from.getClassifier()); to.setPackaging(from.getPackaging()); } /** * @return the value of the option with given name. null if the value was null. * @throws IllegalStateException if the value is not Boolean. */ public static Boolean getBooleanOption(GraphContext graphContext, String name) { Map<String, Object> options = graphContext.getOptionMap(); final Object value = options.get(name); if ( value != null && !(value instanceof Boolean)) throw new IllegalStateException("Option value expected to be Boolean, but was: " + value.getClass()); return (Boolean) options.get(name); } /** * @return the boolean value of the option with given name. Given default_ value if the value was null. * @throws IllegalStateException if the value is not Boolean. */ public static boolean getBooleanOption(GraphContext graphContext, String name, boolean default_) { Boolean val = getBooleanOption(graphContext, name); if (val == null) return default_; return val; } private static boolean isPerformMavenization(GraphContext graphContext) { return getBooleanOption(graphContext, MavenizeOption.NAME, false); } }