001/* 002 * Copyright 2017-2022 original authors 003 * 004 * Licensed under the Apache License, Version 2.0 (the "License"); 005 * you may not use this file except in compliance with the License. 006 * You may obtain a copy of the License at 007 * 008 * https://www.apache.org/licenses/LICENSE-2.0 009 * 010 * Unless required by applicable law or agreed to in writing, software 011 * distributed under the License is distributed on an "AS IS" BASIS, 012 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 013 * See the License for the specific language governing permissions and 014 * limitations under the License. 015 */ 016package io.micronaut.maven.services; 017 018import io.micronaut.core.util.StringUtils; 019import org.apache.maven.execution.MavenSession; 020import org.apache.maven.model.Plugin; 021import org.apache.maven.model.PluginExecution; 022import org.apache.maven.plugin.BuildPluginManager; 023import org.apache.maven.plugin.MojoExecutionException; 024import org.apache.maven.project.MavenProject; 025import org.apache.maven.shared.invoker.DefaultInvocationRequest; 026import org.apache.maven.shared.invoker.InvocationResult; 027import org.apache.maven.shared.invoker.Invoker; 028import org.apache.maven.shared.invoker.MavenInvocationException; 029import org.codehaus.plexus.util.xml.Xpp3Dom; 030import org.slf4j.Logger; 031import org.slf4j.LoggerFactory; 032import org.twdata.maven.mojoexecutor.MojoExecutor; 033 034import javax.inject.Inject; 035import javax.inject.Singleton; 036import java.io.File; 037import java.util.Arrays; 038import java.util.Optional; 039import java.util.Properties; 040import java.util.concurrent.atomic.AtomicReference; 041 042import static io.micronaut.maven.testresources.TestResourcesConfiguration.TEST_RESOURCES_ENABLED_PROPERTY; 043import static org.twdata.maven.mojoexecutor.MojoExecutor.configuration; 044import static org.twdata.maven.mojoexecutor.MojoExecutor.executeMojo; 045import static org.twdata.maven.mojoexecutor.MojoExecutor.executionEnvironment; 046import static org.twdata.maven.mojoexecutor.MojoExecutor.goal; 047import static org.twdata.maven.mojoexecutor.MojoExecutor.plugin; 048 049/** 050 * Provides methods to execute goals on the current project. 051 * 052 * @author Álvaro Sánchez-Mariscal 053 * @since 1.1 054 */ 055@Singleton 056public class ExecutorService { 057 058 private static final Logger LOG = LoggerFactory.getLogger(ExecutorService.class); 059 060 private final MojoExecutor.ExecutionEnvironment executionEnvironment; 061 private final MavenProject mavenProject; 062 private final MavenSession mavenSession; 063 private final Invoker invoker; 064 065 @SuppressWarnings("CdiInjectionPointsInspection") 066 @Inject 067 public ExecutorService(MavenProject mavenProject, MavenSession mavenSession, BuildPluginManager pluginManager, 068 Invoker invoker) { 069 this.executionEnvironment = executionEnvironment(mavenProject, mavenSession, pluginManager); 070 this.mavenProject = mavenProject; 071 this.mavenSession = mavenSession; 072 this.invoker = invoker; 073 } 074 075 /** 076 * Executes the given goal from the given plugin coordinates. 077 * 078 * @param pluginKey The plugin coordinates in the format groupId:artifactId:version 079 * @param goal The goal to execute 080 * @throws MojoExecutionException If the goal execution fails 081 */ 082 public void executeGoal(String pluginKey, String goal) throws MojoExecutionException { 083 final Plugin plugin = mavenProject.getPlugin(pluginKey); 084 if (plugin != null) { 085 var executionId = new AtomicReference<>(goal); 086 if (goal != null && goal.indexOf('#') > -1) { 087 int pos = goal.indexOf('#'); 088 executionId.set(goal.substring(pos + 1)); 089 goal = goal.substring(0, pos); 090 } 091 Optional<PluginExecution> execution = plugin 092 .getExecutions() 093 .stream() 094 .filter(e -> e.getId().equals(executionId.get())) 095 .findFirst(); 096 Xpp3Dom configuration; 097 if (execution.isPresent()) { 098 configuration = (Xpp3Dom) execution.get().getConfiguration(); 099 } else if (plugin.getConfiguration() != null) { 100 configuration = (Xpp3Dom) plugin.getConfiguration(); 101 } else { 102 configuration = configuration(); 103 } 104 executeMojo(plugin, goal(goal), configuration, executionEnvironment); 105 } else { 106 throw new MojoExecutionException("Plugin not found: " + pluginKey); 107 } 108 } 109 110 /** 111 * Executes a goal using the given arguments. 112 * 113 * @param pluginGroup plugin group id 114 * @param pluginArtifact plugin artifact id 115 * @param pluginVersion plugin version 116 * @param goal goal to execute 117 * @param configuration configuration for the goal 118 * @throws MojoExecutionException if the goal execution fails 119 */ 120 public void executeGoal(String pluginGroup, String pluginArtifact, String pluginVersion, String goal, Xpp3Dom configuration) throws MojoExecutionException { 121 final Plugin plugin = plugin(pluginGroup, pluginArtifact, pluginVersion); 122 executeMojo(plugin, goal(goal), configuration, executionEnvironment); 123 } 124 125 /** 126 * Executes a goal using the Maven shared invoker. 127 * 128 * @param pluginKey The plugin coordinates in the format groupId:artifactId 129 * @param goal The goal to execute 130 * @return The result of the invocation 131 * @throws MavenInvocationException If the goal execution fails 132 */ 133 public InvocationResult invokeGoal(String pluginKey, String goal) throws MavenInvocationException { 134 return invokeGoals(pluginKey + ":" + goal); 135 } 136 137 /** 138 * Executes a goal using the Maven shared invoker. 139 * 140 * @param goals The goals to execute 141 * @return The result of the invocation 142 * @throws MavenInvocationException If the goal execution fails 143 */ 144 public InvocationResult invokeGoals(String... goals) throws MavenInvocationException { 145 var request = new DefaultInvocationRequest(); 146 request.setPomFile(mavenProject.getFile()); 147 File settingsFile = mavenSession.getRequest().getUserSettingsFile(); 148 if (settingsFile.exists()) { 149 request.setUserSettingsFile(settingsFile); 150 } 151 var properties = new Properties(); 152 properties.put(TEST_RESOURCES_ENABLED_PROPERTY, StringUtils.FALSE); 153 154 request.setLocalRepositoryDirectory(new File(mavenSession.getLocalRepository().getBasedir())); 155 request.addArgs(Arrays.asList(goals)); 156 request.setBatchMode(true); 157 request.setQuiet(true); 158 request.setErrorHandler(LOG::error); 159 request.setOutputHandler(LOG::info); 160 request.setProperties(properties); 161 return invoker.execute(request); 162 } 163}