org.sonar.maven.SonarMojo Maven / Gradle / Ivy
/*
* Sonar, open source software quality management tool.
* Copyright (C) 2009 SonarSource SA
* mailto:contact AT sonarsource DOT com
*
* Sonar is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 3 of the License, or (at your option) any later version.
*
* Sonar is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with Sonar; if not, write to the Free Software
* Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
*/
package org.sonar.maven;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.collections.Predicate;
import org.apache.commons.lang.StringUtils;
import org.apache.maven.cli.ConsoleDownloadMonitor;
import org.apache.maven.embedder.MavenEmbedderException;
import org.apache.maven.embedder.PlexusLoggerAdapter;
import org.apache.maven.execution.MavenSession;
import org.apache.maven.monitor.event.DefaultEventMonitor;
import org.apache.maven.monitor.event.EventMonitor;
import org.apache.maven.plugin.AbstractMojo;
import org.apache.maven.plugin.MojoExecutionException;
import org.apache.maven.project.MavenProject;
import org.apache.maven.settings.Settings;
import org.sonar.commons.ServerHttpClient;
import java.io.File;
import java.io.FileWriter;
import java.io.IOException;
import java.util.*;
/**
* Main sonar bootstrap plugin
*
* @goal sonar
* @aggregator
*/
public class SonarMojo extends AbstractMojo {
public final static String ADDITIONAL_GOALS_PROPERTY = "sonar.bootstrap.additional.goals";
/**
* The plugin version
*
* @parameter expression="${plugin.version}"
* @readonly
*/
private String pluginVersion;
/**
* The current maven session
*
* @parameter expression="${session}"
* @readonly
*/
private MavenSession session;
/**
* The projects in the reactor.
*
* @parameter expression="${reactorProjects}"
* @readonly
*/
private List reactorProjects;
/**
* The maven settings this project is using
*
* @parameter expression="${settings}"
* @required
* @readonly
*/
private Settings settings;
/**
* Sonar host URL
*
* @parameter expression="${sonar.host.url}" default-value="http://localhost:9000" alias="sonar.host.url"
*/
private String sonarHostURL;
/**
* Modules from the project to skip
*
* @parameter expression="${sonar.skippedModules}" alias="sonar.skippedModules"
*/
private String skippedModules;
/**
* For internal use only. Used for benchmarks.
*
* @parameter expression="${sonar.collectOnly}" default-value="false" alias="sonar.collectOnly"
*/
private Boolean collectOnly = Boolean.FALSE;
public void execute() throws MojoExecutionException {
ServerHttpClient server = new ServerHttpClient(sonarHostURL);
server.checkUp();
String sonarServerVersion = getServerVersion(server);
reactorProjects = getReactorProjects(reactorProjects);
fixProjectsReportingDir(reactorProjects);
executeGoals(sonarServerVersion);
}
protected List getReactorProjects(List projects) throws MojoExecutionException {
if (StringUtils.isEmpty(skippedModules)) {
return new ArrayList(projects);
}
getLog().info("Filtering projects: " + skippedModules);
final List skippedNames = new ArrayList(Arrays.asList(StringUtils.split(skippedModules, ',')));
Collection skipped = (Collection) CollectionUtils.select(projects, new Predicate() {
public boolean evaluate(Object o) {
MavenProject p = (MavenProject) o;
boolean match = skippedNames.contains(p.getArtifactId());
if (match) {
skippedNames.remove(p.getArtifactId());
}
return match;
}
});
if (!skippedNames.isEmpty()) {
getLog().warn("Unable to filter the following projects: " + skippedNames);
}
List filteredProjects = new ArrayList(projects);
MavenProjectHierarchy root = MavenProjectHierarchy.getProjectHierarchy(projects);
for (MavenProject toSkip : skipped) {
MavenProjectHierarchy toSkipHierarchy = root.getModule(toSkip);
Collection childrens = toSkipHierarchy.getChildrensProjects();
filteredProjects.remove(toSkip);
filteredProjects.removeAll(childrens);
}
getLog().info("Filtered reactor build order:");
for (MavenProject filteredProject : filteredProjects) {
getLog().info("\t" + filteredProject.getName());
}
return filteredProjects;
}
private String getServerVersion(ServerHttpClient srv)
throws MojoExecutionException {
String sonarServerVersion = null;
try {
sonarServerVersion = srv.getVersion();
} catch (IOException e) {
throw new MojoExecutionException("Unable to retreive sonar server version");
}
if (!sonarServerVersion.equals(pluginVersion)) {
String error = "Sonar plugin (" + pluginVersion + ") and server (" + sonarServerVersion + ") version do not matchExclusionPattern.\n";
error += "Either update your server to the " + pluginVersion + " plugin version or launch\n";
error += "the mvn org.codehaus.sonar:sonar-maven-plugin:" + sonarServerVersion + ":sonar plugin command.";
throw new MojoExecutionException(error);
}
return sonarServerVersion;
}
protected List getBoostrapGoals(String sonarServerVersion) {
List goals = new ArrayList();
Properties sonarProperties = new Properties(System.getProperties());
sonarProperties.put("sonar.server.version", sonarServerVersion);
if (!collectOnly) {
BootstrapGoal dependencies = new BootstrapGoal();
dependencies.setGoal("org.codehaus.sonar:sonar-core-maven-plugin:" + sonarServerVersion + ":dependencies");
goals.add(dependencies);
BootstrapGoal prepare = new BootstrapGoal();
prepare.setGoal("org.codehaus.sonar:sonar-core-maven-plugin:" + sonarServerVersion + ":prepare");
goals.add(prepare);
}
BootstrapGoal collect = new BootstrapGoal();
collect.setGoal("org.codehaus.sonar:sonar-core-maven-plugin:" + sonarServerVersion + ":collect");
goals.add(collect);
BootstrapGoal batch = new BootstrapGoal();
batch.setGoal("org.codehaus.sonar:sonar-core-maven-plugin:" + sonarServerVersion + ":batch");
goals.add(batch);
for (BootstrapGoal bootstrapGoal : goals) {
bootstrapGoal.setGoalProps(new Properties(sonarProperties));
}
return goals;
}
private SonarMavenEmbedder getNewMavenEmbedder() throws MojoExecutionException {
SonarMavenEmbedder maven = null;
try {
maven = new SonarMavenEmbedder(settings, session.getContainer().getContainerRealm().getWorld());
maven.setLogger(new SonarMavenEmbedderLogger(getLog()));
maven.start();
} catch (Exception e) {
throw new MojoExecutionException("Cannot start the maven embedder", e);
}
return maven;
}
private MavenProject saveSonarPom(SonarMavenEmbedder maven, MavenProject project) throws MojoExecutionException {
File targetDir = new File(project.getBuild().getDirectory() + "/sonar");
if (!targetDir.exists() && !targetDir.mkdirs()) {
throw new MojoExecutionException("Unable to created directory " + targetDir.getPath());
}
File targetPom = new File(targetDir, "sonar-pom.xml");
try {
project.writeModel(new FileWriter(targetPom, false));
} catch (Exception e) {
throw new MojoExecutionException("Cannot save sonar-pom.xml to " + targetDir, e);
}
try {
boolean executionRoot = project.isExecutionRoot();
project = maven.readProjectWithDependencies(targetPom);
// copy the isExecutionRoot flag to avoid problems with aggregator style mojos
project.setExecutionRoot(executionRoot);
} catch (Exception e) {
throw new MojoExecutionException("Cannot read the sonar-pom.xml", e);
}
return project;
}
private void fixProjectsReportingDir(List executedProjects) {
for (MavenProject executedProject : executedProjects) {
// force the report dir with a complete path to avoid issues with some reporting tools
String reportDir = executedProject.getBuild().getDirectory() + "/site";
executedProject.getReporting().setOutputDirectory(reportDir);
}
}
private void saveExecutedProjects(SonarMavenEmbedder maven, List executedProjects) throws MojoExecutionException {
for (int i = 0; i < executedProjects.size(); i++) {
MavenProject executedProject = executedProjects.get(i);
File baseDir = executedProject.getBasedir();
executedProject = saveSonarPom(maven, executedProject);
executedProject.setFile(new File(baseDir, "pom.xml"));
executedProjects.set(i, executedProject);
}
}
private void executeGoals(String sonarServerVersion) throws MojoExecutionException {
List goals = getBoostrapGoals(sonarServerVersion);
for (BootstrapGoal goal : goals) {
executeMaven(reactorProjects, goal);
}
}
private void executeMaven(List executedProjects, BootstrapGoal goal) throws MojoExecutionException {
SonarMavenEmbedder maven = getNewMavenEmbedder();
EventMonitor eventMonitor = new DefaultEventMonitor(new PlexusLoggerAdapter(maven.getLogger()));
// very important clone the project objects to avoid problems with maven embedder
List executedProjectsClone = new ArrayList();
for (MavenProject mavenProject : executedProjects) {
executedProjectsClone.add(cloneMavenProject(mavenProject));
}
saveExecutedProjects(maven, executedProjects);
try {
maven.execute(Collections.unmodifiableList(executedProjectsClone), Arrays.asList(goal.getGoal()), eventMonitor,
new ConsoleDownloadMonitor(), goal.goalProps, new File("."));
} catch (Throwable e) {
getLog().error("Cannot execute the command " + goal.getGoal(), e);
throw new MojoExecutionException("Cannot execute the command " + goal.getGoal(), e);
}
// put back the cloned objects in the original array
int i = 0;
for (MavenProject executedProjectClone : executedProjectsClone) {
executedProjects.set(i++, executedProjectClone);
}
saveExecutedProjects(maven, executedProjects);
// required to correcly load plugin dependencies potentially done during the previous phase
maven = getNewMavenEmbedder();
// now call the additional goals potentially created by the called previous goal
for (MavenProject executedProject : executedProjects) {
List additionalGoals = getBootstrapAdditionalGoals(executedProject, goal);
for (BootstrapGoal bootstrapAdditionalGoal : additionalGoals) {
try {
maven.execute(executedProject, Arrays.asList(bootstrapAdditionalGoal.getGoal()), eventMonitor,
new ConsoleDownloadMonitor(), bootstrapAdditionalGoal.getGoalProps(), executedProject.getBasedir());
} catch (Throwable e) {
throw new MojoExecutionException("Cannot execute the command " + bootstrapAdditionalGoal.getGoal(), e);
}
}
}
saveExecutedProjects(maven, executedProjects);
finalizeMavenEmbedder(maven);
}
protected MavenProject cloneMavenProject(MavenProject mavenProject) {
MavenProject clone = new MavenProject(mavenProject);
clone.getProperties().putAll(mavenProject.getProperties());
clone.getProperties().putAll(System.getProperties());
return clone;
}
protected List getBootstrapAdditionalGoals(MavenProject executedProject, BootstrapGoal currentGoal) {
List additionalGoals = new ArrayList();
String prepareGoalsToExecute = executedProject.getProperties().getProperty(ADDITIONAL_GOALS_PROPERTY);
if (prepareGoalsToExecute != null) {
String[] goals = prepareGoalsToExecute.split(",");
for (String goal : goals) {
BootstrapGoal additionalGoal = new BootstrapGoal();
additionalGoal.setGoal(goal);
additionalGoal.setGoalProps(new Properties(currentGoal.goalProps));
additionalGoals.add(additionalGoal);
}
executedProject.getProperties().remove(ADDITIONAL_GOALS_PROPERTY);
}
return additionalGoals;
}
private void finalizeMavenEmbedder(SonarMavenEmbedder maven) {
try {
maven.stop();
} catch (MavenEmbedderException e) {
getLog().warn("Cannot stop the maven embedder", e);
}
}
protected static class BootstrapGoal {
private String goal;
private Properties goalProps;
public String getGoal() {
return goal;
}
public void setGoal(String goal) {
this.goal = goal;
}
public Properties getGoalProps() {
return goalProps;
}
public void setGoalProps(Properties goalProps) {
this.goalProps = goalProps;
}
}
} © 2015 - 2025 Weber Informatics LLC | Privacy Policy