From: Julien HENRY Date: Wed, 19 Jun 2013 13:00:30 +0000 (+0200) Subject: SONAR-4047 Move Maven specific classes to the new Maven Batch plugin X-Git-Tag: 3.7~438 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=2a52174013f4ab8407146888b0b0be2d35717d23;p=sonarqube.git SONAR-4047 Move Maven specific classes to the new Maven Batch plugin --- diff --git a/plugins/sonar-maven-batch-plugin/pom.xml b/plugins/sonar-maven-batch-plugin/pom.xml index 8cdaa95f80e..58e073fe901 100644 --- a/plugins/sonar-maven-batch-plugin/pom.xml +++ b/plugins/sonar-maven-batch-plugin/pom.xml @@ -40,6 +40,13 @@ ${maven.version} provided + + + + org.codehaus.sonar + sonar-testing-harness + test + diff --git a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenBatchPlugin.java b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenBatchPlugin.java index d8a44dd84a1..257d9dcb1d3 100644 --- a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenBatchPlugin.java +++ b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenBatchPlugin.java @@ -27,7 +27,6 @@ import java.util.List; public final class MavenBatchPlugin extends SonarPlugin { public List getExtensions() { - return ImmutableList.builder().add(SonarMavenProjectBuilder.class, MavenPluginExecutor.class) - .build(); + return ImmutableList.of(SonarMavenProjectBuilder.class, RealMavenPluginExecutor.class); } } diff --git a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenPluginExecutor.java b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenPluginExecutor.java deleted file mode 100644 index d11003cc9af..00000000000 --- a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenPluginExecutor.java +++ /dev/null @@ -1,96 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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 this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.plugins.maven; - -import org.apache.maven.execution.MavenSession; -import org.apache.maven.execution.ReactorManager; -import org.apache.maven.lifecycle.LifecycleExecutor; -import org.apache.maven.project.MavenProject; -import org.sonar.api.batch.SupportedEnvironment; -import org.sonar.api.task.TaskExtension; -import org.sonar.api.utils.SonarException; -import org.sonar.batch.scan.maven.AbstractMavenPluginExecutor; - -import java.lang.reflect.Method; -import java.util.Arrays; - -@SupportedEnvironment("maven") -public class MavenPluginExecutor extends AbstractMavenPluginExecutor implements TaskExtension { - - private LifecycleExecutor lifecycleExecutor; - private MavenSession mavenSession; - - public MavenPluginExecutor(LifecycleExecutor le, MavenSession mavenSession) { - this.lifecycleExecutor = le; - this.mavenSession = mavenSession; - } - - @Override - public void concreteExecute(MavenProject pom, String goal) throws Exception { - Method executeMethod = null; - for (Method m : lifecycleExecutor.getClass().getMethods()) { - if (m.getName().equals("execute")) { - executeMethod = m; - break; - } - } - if (executeMethod == null) { - throw new SonarException("Unable to find execute method on Maven LifecycleExecutor. Please check your Maven version."); - } - if (executeMethod.getParameterTypes().length == 1) { - concreteExecuteMaven3(pom, goal); - } - else if (executeMethod.getParameterTypes().length == 3) { - concreteExecuteMaven2(executeMethod, pom, goal); - } - else { - throw new SonarException("Unexpected parameter count on Maven LifecycleExecutor#execute method. Please check your Maven version."); - } - } - - public void concreteExecuteMaven3(MavenProject pom, String goal) { - MavenSession projectSession = mavenSession.clone(); - projectSession.setCurrentProject(pom); - projectSession.setProjects(Arrays.asList(pom)); - projectSession.getRequest().setRecursive(false); - projectSession.getRequest().setPom(pom.getFile()); - projectSession.getRequest().setGoals(Arrays.asList(goal)); - projectSession.getRequest().setInteractiveMode(false); - lifecycleExecutor.execute(projectSession); - if (projectSession.getResult().hasExceptions()) { - throw new SonarException("Exception during execution of " + goal); - } - } - - public void concreteExecuteMaven2(Method executeMethod, MavenProject pom, String goal) throws Exception { - ReactorManager reactor = new ReactorManager(Arrays.asList(pom)); - MavenSession clonedSession = new MavenSession(mavenSession.getContainer(), - mavenSession.getSettings(), - mavenSession.getLocalRepository(), - mavenSession.getEventDispatcher(), - reactor, - Arrays.asList(goal), - mavenSession.getExecutionRootDirectory(), - mavenSession.getExecutionProperties(), - mavenSession.getStartTime()); - executeMethod.invoke(lifecycleExecutor, clonedSession, reactor, clonedSession.getEventDispatcher()); - } - -} diff --git a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectConverter.java b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectConverter.java new file mode 100644 index 00000000000..5a884f3e628 --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectConverter.java @@ -0,0 +1,260 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.plugins.maven; + +import com.google.common.annotations.VisibleForTesting; +import com.google.common.base.Predicate; +import com.google.common.collect.Collections2; +import com.google.common.collect.Lists; +import com.google.common.collect.Maps; +import org.apache.commons.lang.StringUtils; +import org.apache.maven.model.CiManagement; +import org.apache.maven.model.IssueManagement; +import org.apache.maven.model.Scm; +import org.apache.maven.project.MavenProject; +import org.sonar.api.CoreProperties; +import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.api.batch.maven.MavenUtils; +import org.sonar.api.utils.SonarException; +import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; +import org.sonar.java.api.JavaUtils; + +import java.io.File; +import java.io.IOException; +import java.util.Arrays; +import java.util.List; +import java.util.Map; + +public class MavenProjectConverter { + + private static final String UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE = "Unable to determine structure of project." + + " Probably you use Maven Advanced Reactor Options, which is not supported by Sonar and should not be used."; + + private MavenProjectConverter() { + // only static methods + } + + public static ProjectDefinition convert(List poms, MavenProject root) { + ProjectDefinition def = ProjectDefinition.create(); + configure(def, poms, root); + return def; + } + + public static void configure(ProjectDefinition rootProjectDefinition, List poms, MavenProject root) { + // projects by canonical path to pom.xml + Map paths = Maps.newHashMap(); + Map defs = Maps.newHashMap(); + + try { + for (MavenProject pom : poms) { + paths.put(pom.getFile().getCanonicalPath(), pom); + ProjectDefinition def = pom == root ? rootProjectDefinition : ProjectDefinition.create(); + merge(pom, def); + defs.put(pom, def); + } + + for (Map.Entry entry : paths.entrySet()) { + MavenProject pom = entry.getValue(); + for (Object m : pom.getModules()) { + String moduleId = (String) m; + File modulePath = new File(pom.getBasedir(), moduleId); + MavenProject module = findMavenProject(modulePath, paths); + + ProjectDefinition parentProject = defs.get(pom); + if (parentProject == null) { + throw new IllegalStateException(UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE); + } + ProjectDefinition subProject = defs.get(module); + if (subProject == null) { + throw new IllegalStateException(UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE); + } + parentProject.addSubProject(subProject); + } + } + } catch (IOException e) { + throw new SonarException(e); + } + + ProjectDefinition rootProject = defs.get(root); + if (rootProject == null) { + throw new IllegalStateException(UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE); + } + } + + private static MavenProject findMavenProject(final File modulePath, Map paths) throws IOException { + if (modulePath.exists() && modulePath.isDirectory()) { + for (Map.Entry entry : paths.entrySet()) { + String pomFileParentDir = new File(entry.getKey()).getParent(); + if (pomFileParentDir.equals(modulePath.getCanonicalPath())) { + return entry.getValue(); + } + } + return null; + } else { + return paths.get(modulePath.getCanonicalPath()); + } + } + + @VisibleForTesting + static void merge(MavenProject pom, ProjectDefinition definition) { + String key = getSonarKey(pom); + // IMPORTANT NOTE : reference on properties from POM model must not be saved, + // instead they should be copied explicitly - see SONAR-2896 + definition + .setProperties(pom.getModel().getProperties()) + .setKey(key) + .setVersion(pom.getVersion()) + .setName(pom.getName()) + .setDescription(pom.getDescription()) + .addContainerExtension(pom); + guessJavaVersion(pom, definition); + guessEncoding(pom, definition); + convertMavenLinksToProperties(definition, pom); + synchronizeFileSystem(pom, definition); + } + + public static String getSonarKey(MavenProject pom) { + return new StringBuilder().append(pom.getGroupId()).append(":").append(pom.getArtifactId()).toString(); + } + + private static void guessEncoding(MavenProject pom, ProjectDefinition definition) { + // See http://jira.codehaus.org/browse/SONAR-2151 + String encoding = MavenUtils.getSourceEncoding(pom); + if (encoding != null) { + definition.setProperty(CoreProperties.ENCODING_PROPERTY, encoding); + } + } + + private static void guessJavaVersion(MavenProject pom, ProjectDefinition definition) { + // See http://jira.codehaus.org/browse/SONAR-2148 + // Get Java source and target versions from maven-compiler-plugin. + String version = MavenUtils.getJavaSourceVersion(pom); + if (version != null) { + definition.setProperty(JavaUtils.JAVA_SOURCE_PROPERTY, version); + } + version = MavenUtils.getJavaVersion(pom); + if (version != null) { + definition.setProperty(JavaUtils.JAVA_TARGET_PROPERTY, version); + } + } + + /** + * For SONAR-3676 + */ + private static void convertMavenLinksToProperties(ProjectDefinition definition, MavenProject pom) { + setPropertyIfNotAlreadyExists(definition, CoreProperties.LINKS_HOME_PAGE, pom.getUrl()); + + Scm scm = pom.getScm(); + if (scm == null) { + scm = new Scm(); + } + setPropertyIfNotAlreadyExists(definition, CoreProperties.LINKS_SOURCES, scm.getUrl()); + setPropertyIfNotAlreadyExists(definition, CoreProperties.LINKS_SOURCES_DEV, scm.getDeveloperConnection()); + + CiManagement ci = pom.getCiManagement(); + if (ci == null) { + ci = new CiManagement(); + } + setPropertyIfNotAlreadyExists(definition, CoreProperties.LINKS_CI, ci.getUrl()); + + IssueManagement issues = pom.getIssueManagement(); + if (issues == null) { + issues = new IssueManagement(); + } + setPropertyIfNotAlreadyExists(definition, CoreProperties.LINKS_ISSUE_TRACKER, issues.getUrl()); + } + + private static void setPropertyIfNotAlreadyExists(ProjectDefinition definition, String propertyKey, String propertyValue) { + if (StringUtils.isBlank(definition.getProperties().getProperty(propertyKey))) { + definition.setProperty(propertyKey, StringUtils.defaultString(propertyValue)); + } + } + + public static void synchronizeFileSystem(MavenProject pom, ProjectDefinition into) { + into.setBaseDir(pom.getBasedir()); + File buildDir = getBuildDir(pom); + if (buildDir != null) { + into.setBuildDir(buildDir); + into.setWorkDir(getSonarWorkDir(pom)); + } + List filteredCompileSourceRoots = filterExisting(pom.getCompileSourceRoots(), pom.getBasedir()); + List filteredTestCompileSourceRoots = filterExisting(pom.getTestCompileSourceRoots(), pom.getBasedir()); + into.setSourceDirs((String[]) filteredCompileSourceRoots.toArray(new String[filteredCompileSourceRoots.size()])); + into.setTestDirs((String[]) filteredTestCompileSourceRoots.toArray(new String[filteredTestCompileSourceRoots.size()])); + File binaryDir = resolvePath(pom.getBuild().getOutputDirectory(), pom.getBasedir()); + if (binaryDir != null) { + into.addBinaryDir(binaryDir); + } + } + + public static File getSonarWorkDir(MavenProject pom) { + return new File(getBuildDir(pom), "sonar"); + } + + private static File getBuildDir(MavenProject pom) { + return resolvePath(pom.getBuild().getDirectory(), pom.getBasedir()); + } + + private static List filterExisting(List filePaths, final File baseDir) { + return Lists.newArrayList(Collections2.filter(filePaths, new Predicate() { + @Override + public boolean apply(String filePath) { + File file = resolvePath(filePath, baseDir); + return file != null && file.exists(); + } + })); + } + + public static void synchronizeFileSystem(MavenProject pom, DefaultModuleFileSystem into) { + into.resetDirs( + pom.getBasedir(), + getBuildDir(pom), + resolvePaths((List) pom.getCompileSourceRoots(), pom.getBasedir()), + resolvePaths((List) pom.getTestCompileSourceRoots(), pom.getBasedir()), + Arrays.asList(resolvePath(pom.getBuild().getOutputDirectory(), pom.getBasedir())) + ); + } + + static File resolvePath(String path, File basedir) { + if (path != null) { + File file = new File(path); + if (!file.isAbsolute()) { + try { + file = new File(basedir, path).getCanonicalFile(); + } catch (IOException e) { + throw new SonarException("Unable to resolve path '" + path + "'", e); + } + } + return file; + } + return null; + } + + static List resolvePaths(List paths, File basedir) { + List result = Lists.newArrayList(); + for (String path : paths) { + File dir = resolvePath(path, basedir); + if (dir != null) { + result.add(dir); + } + } + return result; + } +} diff --git a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/RealMavenPluginExecutor.java b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/RealMavenPluginExecutor.java new file mode 100644 index 00000000000..69a0d6b36f5 --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/RealMavenPluginExecutor.java @@ -0,0 +1,140 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.plugins.maven; + +import org.apache.maven.execution.MavenSession; +import org.apache.maven.execution.ReactorManager; +import org.apache.maven.lifecycle.LifecycleExecutor; +import org.apache.maven.project.MavenProject; +import org.sonar.api.batch.SupportedEnvironment; +import org.sonar.api.batch.maven.MavenPlugin; +import org.sonar.api.batch.maven.MavenPluginHandler; +import org.sonar.api.resources.Project; +import org.sonar.api.utils.SonarException; +import org.sonar.api.utils.TimeProfiler; +import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; +import org.sonar.batch.scan.maven.MavenPluginExecutor; + +import java.lang.reflect.Method; +import java.util.Arrays; + +@SupportedEnvironment("maven") +public class RealMavenPluginExecutor implements MavenPluginExecutor { + + private LifecycleExecutor lifecycleExecutor; + private MavenSession mavenSession; + + public RealMavenPluginExecutor(LifecycleExecutor le, MavenSession mavenSession) { + this.lifecycleExecutor = le; + this.mavenSession = mavenSession; + } + + @Override + public final MavenPluginHandler execute(Project project, DefaultModuleFileSystem fs, MavenPluginHandler handler) { + for (String goal : handler.getGoals()) { + MavenPlugin plugin = MavenPlugin.getPlugin(project.getPom(), handler.getGroupId(), handler.getArtifactId()); + execute(project, + fs, + getGoal(handler.getGroupId(), handler.getArtifactId(), (plugin != null && plugin.getPlugin() != null ? plugin.getPlugin().getVersion() : null), goal)); + } + return handler; + } + + @Override + public final void execute(Project project, DefaultModuleFileSystem fs, String goal) { + if (project.getPom() != null) { + TimeProfiler profiler = new TimeProfiler().start("Execute " + goal); + ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); + try { + concreteExecute(project.getPom(), goal); + } catch (Exception e) { + throw new SonarException("Unable to execute maven plugin", e); + } finally { + // Reset original ClassLoader that may have been changed during Maven Execution (see SONAR-1800) + Thread.currentThread().setContextClassLoader(currentClassLoader); + profiler.stop(); + } + + MavenProjectConverter.synchronizeFileSystem(project.getPom(), fs); + } + } + + static String getGoal(String groupId, String artifactId, String version, String goal) { + String defaultVersion = (version == null ? "" : version); + return new StringBuilder() + .append(groupId).append(":") + .append(artifactId).append(":") + .append(defaultVersion) + .append(":") + .append(goal) + .toString(); + } + + public void concreteExecute(MavenProject pom, String goal) throws Exception { + Method executeMethod = null; + for (Method m : lifecycleExecutor.getClass().getMethods()) { + if (m.getName().equals("execute")) { + executeMethod = m; + break; + } + } + if (executeMethod == null) { + throw new SonarException("Unable to find execute method on Maven LifecycleExecutor. Please check your Maven version."); + } + if (executeMethod.getParameterTypes().length == 1) { + concreteExecuteMaven3(pom, goal); + } + else if (executeMethod.getParameterTypes().length == 3) { + concreteExecuteMaven2(executeMethod, pom, goal); + } + else { + throw new SonarException("Unexpected parameter count on Maven LifecycleExecutor#execute method. Please check your Maven version."); + } + } + + public void concreteExecuteMaven3(MavenProject pom, String goal) { + MavenSession projectSession = mavenSession.clone(); + projectSession.setCurrentProject(pom); + projectSession.setProjects(Arrays.asList(pom)); + projectSession.getRequest().setRecursive(false); + projectSession.getRequest().setPom(pom.getFile()); + projectSession.getRequest().setGoals(Arrays.asList(goal)); + projectSession.getRequest().setInteractiveMode(false); + lifecycleExecutor.execute(projectSession); + if (projectSession.getResult().hasExceptions()) { + throw new SonarException("Exception during execution of " + goal); + } + } + + public void concreteExecuteMaven2(Method executeMethod, MavenProject pom, String goal) throws Exception { + ReactorManager reactor = new ReactorManager(Arrays.asList(pom)); + MavenSession clonedSession = new MavenSession(mavenSession.getContainer(), + mavenSession.getSettings(), + mavenSession.getLocalRepository(), + mavenSession.getEventDispatcher(), + reactor, + Arrays.asList(goal), + mavenSession.getExecutionRootDirectory(), + mavenSession.getExecutionProperties(), + mavenSession.getStartTime()); + executeMethod.invoke(lifecycleExecutor, clonedSession, reactor, clonedSession.getEventDispatcher()); + } + +} diff --git a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/SonarMavenProjectBuilder.java b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/SonarMavenProjectBuilder.java index d8b66f64743..0c576dc32cb 100644 --- a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/SonarMavenProjectBuilder.java +++ b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/SonarMavenProjectBuilder.java @@ -24,7 +24,6 @@ import org.apache.maven.project.MavenProject; import org.sonar.api.batch.SupportedEnvironment; import org.sonar.api.batch.bootstrap.ProjectBuilder; import org.sonar.api.batch.bootstrap.ProjectBuilderContext; -import org.sonar.batch.scan.maven.MavenProjectConverter; import java.util.List; diff --git a/plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/MavenProjectConverterTest.java b/plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/MavenProjectConverterTest.java new file mode 100644 index 00000000000..d1ae22d872e --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/MavenProjectConverterTest.java @@ -0,0 +1,243 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.plugins.maven; + +import org.apache.commons.io.FileUtils; +import org.apache.maven.model.Model; +import org.apache.maven.model.io.xpp3.MavenXpp3Reader; +import org.apache.maven.project.MavenProject; +import org.codehaus.plexus.util.xml.pull.XmlPullParserException; +import org.hamcrest.core.Is; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.CoreProperties; +import org.sonar.api.batch.bootstrap.ProjectDefinition; +import org.sonar.test.TestUtils; + +import java.io.File; +import java.io.IOException; +import java.io.StringReader; +import java.net.URISyntaxException; +import java.util.Arrays; +import java.util.Properties; + +import static org.fest.assertions.Assertions.assertThat; +import static org.hamcrest.Matchers.containsString; +import static org.hamcrest.Matchers.is; +import static org.junit.Assert.assertNull; +import static org.junit.Assert.assertThat; +import static org.junit.Assert.fail; + +public class MavenProjectConverterTest { + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + /** + * See SONAR-2681 + */ + @Test + public void shouldThrowExceptionWhenUnableToDetermineProjectStructure() { + MavenProject root = new MavenProject(); + root.setFile(new File("/foo/pom.xml")); + root.getBuild().setDirectory("target"); + root.getModules().add("module/pom.xml"); + + try { + MavenProjectConverter.convert(Arrays.asList(root), root); + fail(); + } catch (IllegalStateException e) { + assertThat(e.getMessage(), containsString("Advanced Reactor Options")); + } + } + + @Test + public void shouldConvertModules() throws IOException { + File basedir = temp.newFolder(); + + MavenProject root = newMavenProject("com.foo", "parent", "1.0-SNAPSHOT"); + root.setFile(new File(basedir, "pom.xml")); + root.getBuild().setDirectory("target"); + root.getBuild().setOutputDirectory("target/classes"); + root.getModules().add("module/pom.xml"); + MavenProject module = newMavenProject("com.foo", "moduleA", "1.0-SNAPSHOT"); + module.setFile(new File(basedir, "module/pom.xml")); + module.getBuild().setDirectory("target"); + module.getBuild().setOutputDirectory("target/classes"); + ProjectDefinition project = MavenProjectConverter.convert(Arrays.asList(root, module), root); + + assertThat(project.getSubProjects().size(), is(1)); + } + + private MavenProject newMavenProject(String groupId, String artifactId, String version) { + Model model = new Model(); + model.setGroupId(groupId); + model.setArtifactId(artifactId); + model.setVersion(version); + return new MavenProject(model); + } + + @Test + public void shouldConvertProperties() { + MavenProject pom = new MavenProject(); + pom.setGroupId("foo"); + pom.setArtifactId("bar"); + pom.setVersion("1.0.1"); + pom.setName("Test"); + pom.setDescription("just test"); + pom.setFile(new File("/foo/pom.xml")); + pom.getBuild().setDirectory("target"); + ProjectDefinition project = ProjectDefinition.create(); + MavenProjectConverter.merge(pom, project); + + Properties properties = project.getProperties(); + assertThat(properties.getProperty(CoreProperties.PROJECT_KEY_PROPERTY), is("foo:bar")); + assertThat(properties.getProperty(CoreProperties.PROJECT_VERSION_PROPERTY), is("1.0.1")); + assertThat(properties.getProperty(CoreProperties.PROJECT_NAME_PROPERTY), is("Test")); + assertThat(properties.getProperty(CoreProperties.PROJECT_DESCRIPTION_PROPERTY), is("just test")); + } + + @Test + public void moduleNameShouldEqualArtifactId() throws Exception { + File rootDir = TestUtils.getResource("/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/"); + MavenProject parent = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/pom.xml", true); + MavenProject module1 = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module1/pom.xml", false); + MavenProject module2 = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module2/pom.xml", false); + + ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(parent, module1, module2), parent); + + assertThat(rootDef.getSubProjects().size(), Is.is(2)); + assertThat(rootDef.getKey(), Is.is("org.test:parent")); + assertNull(rootDef.getParent()); + assertThat(rootDef.getBaseDir(), is(rootDir)); + + ProjectDefinition module1Def = rootDef.getSubProjects().get(0); + assertThat(module1Def.getKey(), Is.is("org.test:module1")); + assertThat(module1Def.getParent(), Is.is(rootDef)); + assertThat(module1Def.getBaseDir(), Is.is(new File(rootDir, "module1"))); + assertThat(module1Def.getSubProjects().size(), Is.is(0)); + } + + @Test + public void moduleNameDifferentThanArtifactId() throws Exception { + File rootDir = TestUtils.getResource("/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/"); + MavenProject parent = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/pom.xml", true); + MavenProject module1 = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path1/pom.xml", false); + MavenProject module2 = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path2/pom.xml", false); + + ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(parent, module1, module2), parent); + + assertThat(rootDef.getSubProjects().size(), is(2)); + assertThat(rootDef.getKey(), is("org.test:parent")); + assertNull(rootDef.getParent()); + assertThat(rootDef.getBaseDir(), is(rootDir)); + + ProjectDefinition module1Def = rootDef.getSubProjects().get(0); + assertThat(module1Def.getKey(), Is.is("org.test:module1")); + assertThat(module1Def.getParent(), Is.is(rootDef)); + assertThat(module1Def.getBaseDir(), Is.is(new File(rootDir, "path1"))); + assertThat(module1Def.getSubProjects().size(), Is.is(0)); + } + + @Test + public void should_find_module_with_maven_project_file_naming_different_from_pom_xml() throws Exception { + File rootDir = TestUtils.getResource("/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/"); + MavenProject parent = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/pom.xml", true); + MavenProject module = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom_having_different_name.xml", false); + + ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(parent, module), parent); + + assertThat(rootDef.getSubProjects().size(), Is.is(1)); + assertThat(rootDef.getKey(), Is.is("org.test:parent")); + assertNull(rootDef.getParent()); + assertThat(rootDef.getBaseDir(), is(rootDir)); + + ProjectDefinition module1Def = rootDef.getSubProjects().get(0); + assertThat(module1Def.getKey(), Is.is("org.test:module")); + assertThat(module1Def.getParent(), Is.is(rootDef)); + assertThat(module1Def.getBaseDir(), Is.is(new File(rootDir, "module"))); + assertThat(module1Def.getSubProjects().size(), Is.is(0)); + } + + @Test + public void testSingleProjectWithoutModules() throws Exception { + File rootDir = TestUtils.getResource("/org/sonar/plugins/maven/MavenProjectConverterTest/singleProjectWithoutModules/"); + MavenProject pom = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/singleProjectWithoutModules/pom.xml", true); + + ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(pom), pom); + + assertThat(rootDef.getKey(), is("org.test:parent")); + assertThat(rootDef.getSubProjects().size(), is(0)); + assertNull(rootDef.getParent()); + assertThat(rootDef.getBaseDir(), is(rootDir)); + } + + @Test + public void shouldConvertLinksToProperties() throws Exception { + MavenProject pom = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/projectWithLinks/pom.xml", true); + + ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(pom), pom); + + Properties props = rootDef.getProperties(); + assertThat(props.getProperty(CoreProperties.LINKS_HOME_PAGE)).isEqualTo("http://home.com"); + assertThat(props.getProperty(CoreProperties.LINKS_CI)).isEqualTo("http://ci.com"); + assertThat(props.getProperty(CoreProperties.LINKS_ISSUE_TRACKER)).isEqualTo("http://issues.com"); + assertThat(props.getProperty(CoreProperties.LINKS_SOURCES)).isEqualTo("http://sources.com"); + assertThat(props.getProperty(CoreProperties.LINKS_SOURCES_DEV)).isEqualTo("http://sources-dev.com"); + } + + @Test + public void shouldNotConvertLinksToPropertiesIfPropertyAlreadyDefined() throws Exception { + MavenProject pom = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/projectWithLinksAndProperties/pom.xml", true); + + ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(pom), pom); + + Properties props = rootDef.getProperties(); + + // Those properties have been fed by the POM elements , , ... + assertThat(props.getProperty(CoreProperties.LINKS_CI)).isEqualTo("http://ci.com"); + assertThat(props.getProperty(CoreProperties.LINKS_ISSUE_TRACKER)).isEqualTo("http://issues.com"); + assertThat(props.getProperty(CoreProperties.LINKS_SOURCES_DEV)).isEqualTo("http://sources-dev.com"); + + // ... but those ones have been overridden by in the POM + assertThat(props.getProperty(CoreProperties.LINKS_SOURCES)).isEqualTo("http://sources.com-OVERRIDEN-BY-PROPS"); + assertThat(props.getProperty(CoreProperties.LINKS_HOME_PAGE)).isEqualTo("http://home.com-OVERRIDEN-BY-PROPS"); + } + + @Test + public void shouldLoadSourceEncoding() throws Exception { + MavenProject pom = loadPom("/org/sonar/plugins/maven/MavenProjectConverterTest/sourceEncoding/pom.xml", true); + + ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(pom), pom); + + assertThat(rootDef.getProperties().getProperty(CoreProperties.ENCODING_PROPERTY)).isEqualTo("Shift_JIS"); + } + + private MavenProject loadPom(String pomPath, boolean isRoot) throws URISyntaxException, IOException, XmlPullParserException { + File pomFile = new File(getClass().getResource(pomPath).toURI()); + Model model = new MavenXpp3Reader().read(new StringReader(FileUtils.readFileToString(pomFile))); + MavenProject pom = new MavenProject(model); + pom.setFile(pomFile); + pom.getBuild().setDirectory("target"); + pom.setExecutionRoot(isRoot); + return pom; + } +} diff --git a/plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/RealMavenPluginExecutorTest.java b/plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/RealMavenPluginExecutorTest.java new file mode 100644 index 00000000000..ae359d9272e --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/RealMavenPluginExecutorTest.java @@ -0,0 +1,115 @@ +package org.sonar.plugins.maven; + +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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 this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ + +import org.apache.maven.project.MavenProject; +import org.junit.Test; +import org.sonar.api.batch.maven.MavenPlugin; +import org.sonar.api.batch.maven.MavenPluginHandler; +import org.sonar.api.resources.Project; +import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; + +import java.io.File; + +import static org.hamcrest.CoreMatchers.is; +import static org.junit.Assert.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyList; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.never; +import static org.mockito.Mockito.verify; + +public class RealMavenPluginExecutorTest { + + @Test + public void plugin_version_should_be_optional() { + assertThat(RealMavenPluginExecutor.getGoal("group", "artifact", null, "goal"), is("group:artifact::goal")); + } + + @Test + public void test_plugin_version() { + assertThat(RealMavenPluginExecutor.getGoal("group", "artifact", "3.54", "goal"), is("group:artifact:3.54:goal")); + } + + /** + * The maven plugin sometimes changes the project structure (for example mvn build-helper:add-source). These changes + * must be applied to the internal structure. + */ + @Test + public void should_reset_file_system_after_execution() { + RealMavenPluginExecutor executor = new RealMavenPluginExecutor(null, null) { + @Override + public void concreteExecute(MavenProject pom, String goal) throws Exception { + pom.addCompileSourceRoot("src/java"); + } + }; + MavenProject pom = new MavenProject(); + pom.setFile(new File("target/AbstractMavenPluginExecutorTest/pom.xml")); + pom.getBuild().setDirectory("target"); + Project foo = new Project("foo"); + foo.setPom(pom); + DefaultModuleFileSystem fs = mock(DefaultModuleFileSystem.class); + executor.execute(foo, fs, new AddSourceMavenPluginHandler()); + + verify(fs).resetDirs(any(File.class), any(File.class), anyList(), anyList(), anyList()); + } + + @Test + public void should_ignore_non_maven_projects() { + RealMavenPluginExecutor executor = new RealMavenPluginExecutor(null, null) { + @Override + public void concreteExecute(MavenProject pom, String goal) throws Exception { + pom.addCompileSourceRoot("src/java"); + } + }; + Project foo = new Project("foo"); + DefaultModuleFileSystem fs = mock(DefaultModuleFileSystem.class); + executor.execute(foo, fs, new AddSourceMavenPluginHandler()); + + verify(fs, never()).resetDirs(any(File.class), any(File.class), anyList(), anyList(), anyList()); + } + + static class AddSourceMavenPluginHandler implements MavenPluginHandler { + public String getGroupId() { + return "fake"; + } + + public String getArtifactId() { + return "fake"; + } + + public String getVersion() { + return "2.2"; + } + + public boolean isFixedVersion() { + return false; + } + + public String[] getGoals() { + return new String[] {"fake"}; + } + + public void configure(Project project, MavenPlugin plugin) { + } + } + +} diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom.xml new file mode 100644 index 00000000000..7b49562c2e0 --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + + org.test + parent + 0.1-SNAPSHOT + + module + jar + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom_having_different_name.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom_having_different_name.xml new file mode 100644 index 00000000000..7b49562c2e0 --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom_having_different_name.xml @@ -0,0 +1,11 @@ + + 4.0.0 + + org.test + parent + 0.1-SNAPSHOT + + module + jar + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/pom.xml new file mode 100644 index 00000000000..9d2244eb148 --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + org.test + parent + 0.1-SNAPSHOT + pom + + module + + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path1/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path1/pom.xml new file mode 100644 index 00000000000..470f2d1f6e5 --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path1/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + + org.test + parent + 0.1-SNAPSHOT + + module1 + jar + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path2/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path2/pom.xml new file mode 100644 index 00000000000..88101678e0f --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path2/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + + org.test + parent + 0.1-SNAPSHOT + + module2 + jar + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/pom.xml new file mode 100644 index 00000000000..afd92c0dbee --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/pom.xml @@ -0,0 +1,12 @@ + + 4.0.0 + org.test + parent + 0.1-SNAPSHOT + pom + + path1 + path2 + + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module1/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module1/pom.xml new file mode 100644 index 00000000000..470f2d1f6e5 --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module1/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + + org.test + parent + 0.1-SNAPSHOT + + module1 + jar + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module2/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module2/pom.xml new file mode 100644 index 00000000000..88101678e0f --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module2/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + + org.test + parent + 0.1-SNAPSHOT + + module2 + jar + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/pom.xml new file mode 100644 index 00000000000..cc73a43ec08 --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/pom.xml @@ -0,0 +1,12 @@ + + 4.0.0 + org.test + parent + 0.1-SNAPSHOT + pom + + module1 + module2 + + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/projectWithLinks/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/projectWithLinks/pom.xml new file mode 100644 index 00000000000..460e8967e5c --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/projectWithLinks/pom.xml @@ -0,0 +1,18 @@ + + 4.0.0 + org.test + parent + 0.1-SNAPSHOT + pom + http://home.com + + http://ci.com + + + http://issues.com + + + http://sources.com + http://sources-dev.com + + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/projectWithLinksAndProperties/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/projectWithLinksAndProperties/pom.xml new file mode 100644 index 00000000000..5b024e5c4a7 --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/projectWithLinksAndProperties/pom.xml @@ -0,0 +1,27 @@ + + 4.0.0 + org.test + parent + 0.1-SNAPSHOT + pom + http://home.com + + http://ci.com + + + http://issues.com + + + http://sources.com + http://sources-dev.com + + + + + + http://home.com-OVERRIDEN-BY-PROPS + http://sources.com-OVERRIDEN-BY-PROPS + + + + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/singleProjectWithoutModules/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/singleProjectWithoutModules/pom.xml new file mode 100644 index 00000000000..ffd40530c5d --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/singleProjectWithoutModules/pom.xml @@ -0,0 +1,8 @@ + + 4.0.0 + org.test + parent + 0.1-SNAPSHOT + pom + \ No newline at end of file diff --git a/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/sourceEncoding/pom.xml b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/sourceEncoding/pom.xml new file mode 100644 index 00000000000..01bf73cfa9e --- /dev/null +++ b/plugins/sonar-maven-batch-plugin/src/test/resources/org/sonar/plugins/maven/MavenProjectConverterTest/sourceEncoding/pom.xml @@ -0,0 +1,11 @@ + + 4.0.0 + org.test + parent + 0.1-SNAPSHOT + pom + http://home.com + + Shift_JIS + + \ No newline at end of file diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/maven/AbstractMavenPluginExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/scan/maven/AbstractMavenPluginExecutor.java deleted file mode 100644 index f835c600ef3..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/maven/AbstractMavenPluginExecutor.java +++ /dev/null @@ -1,76 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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 this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.scan.maven; - -import org.apache.maven.project.MavenProject; -import org.sonar.api.batch.maven.MavenPlugin; -import org.sonar.api.batch.maven.MavenPluginHandler; -import org.sonar.api.resources.Project; -import org.sonar.api.utils.SonarException; -import org.sonar.api.utils.TimeProfiler; -import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; - -/** - * Abstract implementation of {@link org.sonar.batch.scan.maven.MavenPluginExecutor} to reduce duplications in concrete implementations for different Maven versions. - */ -public abstract class AbstractMavenPluginExecutor implements MavenPluginExecutor { - - public final MavenPluginHandler execute(Project project, DefaultModuleFileSystem fs, MavenPluginHandler handler) { - for (String goal : handler.getGoals()) { - MavenPlugin plugin = MavenPlugin.getPlugin(project.getPom(), handler.getGroupId(), handler.getArtifactId()); - execute(project, - fs, - getGoal(handler.getGroupId(), handler.getArtifactId(), (plugin != null && plugin.getPlugin() != null ? plugin.getPlugin().getVersion() : null), goal)); - } - return handler; - } - - public final void execute(Project project, DefaultModuleFileSystem fs, String goal) { - if (project.getPom() != null) { - TimeProfiler profiler = new TimeProfiler().start("Execute " + goal); - ClassLoader currentClassLoader = Thread.currentThread().getContextClassLoader(); - try { - concreteExecute(project.getPom(), goal); - } catch (Exception e) { - throw new SonarException("Unable to execute maven plugin", e); - } finally { - // Reset original ClassLoader that may have been changed during Maven Execution (see SONAR-1800) - Thread.currentThread().setContextClassLoader(currentClassLoader); - profiler.stop(); - } - - MavenProjectConverter.synchronizeFileSystem(project.getPom(), fs); - } - } - - public abstract void concreteExecute(MavenProject pom, String goal) throws Exception; - - static String getGoal(String groupId, String artifactId, String version, String goal) { - String defaultVersion = (version == null ? "" : version); - return new StringBuilder() - .append(groupId).append(":") - .append(artifactId).append(":") - .append(defaultVersion) - .append(":") - .append(goal) - .toString(); - } - -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/maven/FakeMavenPluginExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/scan/maven/FakeMavenPluginExecutor.java index 6de93f38130..df53510f444 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/maven/FakeMavenPluginExecutor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/maven/FakeMavenPluginExecutor.java @@ -22,15 +22,17 @@ package org.sonar.batch.scan.maven; import org.sonar.api.batch.maven.MavenPluginHandler; import org.sonar.api.resources.Project; import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; -import org.sonar.batch.scan.maven.MavenPluginExecutor; public final class FakeMavenPluginExecutor implements MavenPluginExecutor { + + @Override public void execute(Project project, DefaultModuleFileSystem fs, String goal) { // do nothing } + @Override public MavenPluginHandler execute(Project project, DefaultModuleFileSystem fs, MavenPluginHandler handler) { // do nothing return handler; } -} \ No newline at end of file +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/maven/MavenPluginExecutor.java b/sonar-batch/src/main/java/org/sonar/batch/scan/maven/MavenPluginExecutor.java index 646f9c7ddbc..3ff7f0dabfa 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/maven/MavenPluginExecutor.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/maven/MavenPluginExecutor.java @@ -19,12 +19,12 @@ */ package org.sonar.batch.scan.maven; -import org.sonar.api.BatchComponent; import org.sonar.api.batch.maven.MavenPluginHandler; import org.sonar.api.resources.Project; +import org.sonar.api.task.TaskExtension; import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; -public interface MavenPluginExecutor extends BatchComponent { +public interface MavenPluginExecutor extends TaskExtension { void execute(Project project, DefaultModuleFileSystem def, String goal); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/maven/MavenProjectConverter.java b/sonar-batch/src/main/java/org/sonar/batch/scan/maven/MavenProjectConverter.java deleted file mode 100644 index 41f0e8f72e1..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/maven/MavenProjectConverter.java +++ /dev/null @@ -1,260 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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 this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.scan.maven; - -import com.google.common.annotations.VisibleForTesting; -import com.google.common.base.Predicate; -import com.google.common.collect.Collections2; -import com.google.common.collect.Lists; -import com.google.common.collect.Maps; -import org.apache.commons.lang.StringUtils; -import org.apache.maven.model.CiManagement; -import org.apache.maven.model.IssueManagement; -import org.apache.maven.model.Scm; -import org.apache.maven.project.MavenProject; -import org.sonar.api.CoreProperties; -import org.sonar.api.batch.bootstrap.ProjectDefinition; -import org.sonar.api.batch.maven.MavenUtils; -import org.sonar.api.utils.SonarException; -import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; -import org.sonar.java.api.JavaUtils; - -import java.io.File; -import java.io.IOException; -import java.util.Arrays; -import java.util.List; -import java.util.Map; - -public class MavenProjectConverter { - - private static final String UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE = "Unable to determine structure of project." + - " Probably you use Maven Advanced Reactor Options, which is not supported by Sonar and should not be used."; - - private MavenProjectConverter() { - // only static methods - } - - public static ProjectDefinition convert(List poms, MavenProject root) { - ProjectDefinition def = ProjectDefinition.create(); - configure(def, poms, root); - return def; - } - - public static void configure(ProjectDefinition rootProjectDefinition, List poms, MavenProject root) { - // projects by canonical path to pom.xml - Map paths = Maps.newHashMap(); - Map defs = Maps.newHashMap(); - - try { - for (MavenProject pom : poms) { - paths.put(pom.getFile().getCanonicalPath(), pom); - ProjectDefinition def = pom == root ? rootProjectDefinition : ProjectDefinition.create(); - merge(pom, def); - defs.put(pom, def); - } - - for (Map.Entry entry : paths.entrySet()) { - MavenProject pom = entry.getValue(); - for (Object m : pom.getModules()) { - String moduleId = (String) m; - File modulePath = new File(pom.getBasedir(), moduleId); - MavenProject module = findMavenProject(modulePath, paths); - - ProjectDefinition parentProject = defs.get(pom); - if (parentProject == null) { - throw new IllegalStateException(UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE); - } - ProjectDefinition subProject = defs.get(module); - if (subProject == null) { - throw new IllegalStateException(UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE); - } - parentProject.addSubProject(subProject); - } - } - } catch (IOException e) { - throw new SonarException(e); - } - - ProjectDefinition rootProject = defs.get(root); - if (rootProject == null) { - throw new IllegalStateException(UNABLE_TO_DETERMINE_PROJECT_STRUCTURE_EXCEPTION_MESSAGE); - } - } - - private static MavenProject findMavenProject(final File modulePath, Map paths) throws IOException { - if (modulePath.exists() && modulePath.isDirectory()) { - for (Map.Entry entry : paths.entrySet()) { - String pomFileParentDir = new File(entry.getKey()).getParent(); - if (pomFileParentDir.equals(modulePath.getCanonicalPath())) { - return entry.getValue(); - } - } - return null; - } else { - return paths.get(modulePath.getCanonicalPath()); - } - } - - @VisibleForTesting - static void merge(MavenProject pom, ProjectDefinition definition) { - String key = getSonarKey(pom); - // IMPORTANT NOTE : reference on properties from POM model must not be saved, - // instead they should be copied explicitly - see SONAR-2896 - definition - .setProperties(pom.getModel().getProperties()) - .setKey(key) - .setVersion(pom.getVersion()) - .setName(pom.getName()) - .setDescription(pom.getDescription()) - .addContainerExtension(pom); - guessJavaVersion(pom, definition); - guessEncoding(pom, definition); - convertMavenLinksToProperties(definition, pom); - synchronizeFileSystem(pom, definition); - } - - public static String getSonarKey(MavenProject pom) { - return new StringBuilder().append(pom.getGroupId()).append(":").append(pom.getArtifactId()).toString(); - } - - private static void guessEncoding(MavenProject pom, ProjectDefinition definition) { - // See http://jira.codehaus.org/browse/SONAR-2151 - String encoding = MavenUtils.getSourceEncoding(pom); - if (encoding != null) { - definition.setProperty(CoreProperties.ENCODING_PROPERTY, encoding); - } - } - - private static void guessJavaVersion(MavenProject pom, ProjectDefinition definition) { - // See http://jira.codehaus.org/browse/SONAR-2148 - // Get Java source and target versions from maven-compiler-plugin. - String version = MavenUtils.getJavaSourceVersion(pom); - if (version != null) { - definition.setProperty(JavaUtils.JAVA_SOURCE_PROPERTY, version); - } - version = MavenUtils.getJavaVersion(pom); - if (version != null) { - definition.setProperty(JavaUtils.JAVA_TARGET_PROPERTY, version); - } - } - - /** - * For SONAR-3676 - */ - private static void convertMavenLinksToProperties(ProjectDefinition definition, MavenProject pom) { - setPropertyIfNotAlreadyExists(definition, CoreProperties.LINKS_HOME_PAGE, pom.getUrl()); - - Scm scm = pom.getScm(); - if (scm == null) { - scm = new Scm(); - } - setPropertyIfNotAlreadyExists(definition, CoreProperties.LINKS_SOURCES, scm.getUrl()); - setPropertyIfNotAlreadyExists(definition, CoreProperties.LINKS_SOURCES_DEV, scm.getDeveloperConnection()); - - CiManagement ci = pom.getCiManagement(); - if (ci == null) { - ci = new CiManagement(); - } - setPropertyIfNotAlreadyExists(definition, CoreProperties.LINKS_CI, ci.getUrl()); - - IssueManagement issues = pom.getIssueManagement(); - if (issues == null) { - issues = new IssueManagement(); - } - setPropertyIfNotAlreadyExists(definition, CoreProperties.LINKS_ISSUE_TRACKER, issues.getUrl()); - } - - private static void setPropertyIfNotAlreadyExists(ProjectDefinition definition, String propertyKey, String propertyValue) { - if (StringUtils.isBlank(definition.getProperties().getProperty(propertyKey))) { - definition.setProperty(propertyKey, StringUtils.defaultString(propertyValue)); - } - } - - public static void synchronizeFileSystem(MavenProject pom, ProjectDefinition into) { - into.setBaseDir(pom.getBasedir()); - File buildDir = getBuildDir(pom); - if (buildDir != null) { - into.setBuildDir(buildDir); - into.setWorkDir(getSonarWorkDir(pom)); - } - List filteredCompileSourceRoots = filterExisting(pom.getCompileSourceRoots(), pom.getBasedir()); - List filteredTestCompileSourceRoots = filterExisting(pom.getTestCompileSourceRoots(), pom.getBasedir()); - into.setSourceDirs((String[]) filteredCompileSourceRoots.toArray(new String[filteredCompileSourceRoots.size()])); - into.setTestDirs((String[]) filteredTestCompileSourceRoots.toArray(new String[filteredTestCompileSourceRoots.size()])); - File binaryDir = resolvePath(pom.getBuild().getOutputDirectory(), pom.getBasedir()); - if (binaryDir != null) { - into.addBinaryDir(binaryDir); - } - } - - public static File getSonarWorkDir(MavenProject pom) { - return new File(getBuildDir(pom), "sonar"); - } - - private static File getBuildDir(MavenProject pom) { - return resolvePath(pom.getBuild().getDirectory(), pom.getBasedir()); - } - - private static List filterExisting(List filePaths, final File baseDir) { - return Lists.newArrayList(Collections2.filter(filePaths, new Predicate() { - @Override - public boolean apply(String filePath) { - File file = resolvePath(filePath, baseDir); - return file != null && file.exists(); - } - })); - } - - public static void synchronizeFileSystem(MavenProject pom, DefaultModuleFileSystem into) { - into.resetDirs( - pom.getBasedir(), - getBuildDir(pom), - resolvePaths((List) pom.getCompileSourceRoots(), pom.getBasedir()), - resolvePaths((List) pom.getTestCompileSourceRoots(), pom.getBasedir()), - Arrays.asList(resolvePath(pom.getBuild().getOutputDirectory(), pom.getBasedir())) - ); - } - - static File resolvePath(String path, File basedir) { - if (path != null) { - File file = new File(path); - if (!file.isAbsolute()) { - try { - file = new File(basedir, path).getCanonicalFile(); - } catch (IOException e) { - throw new SonarException("Unable to resolve path '" + path + "'", e); - } - } - return file; - } - return null; - } - - static List resolvePaths(List paths, File basedir) { - List result = Lists.newArrayList(); - for (String path : paths) { - File dir = resolvePath(path, basedir); - if (dir != null) { - result.add(dir); - } - } - return result; - } -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/maven/AbstractMavenPluginExecutorTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/maven/AbstractMavenPluginExecutorTest.java deleted file mode 100644 index 82462203e4e..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/maven/AbstractMavenPluginExecutorTest.java +++ /dev/null @@ -1,114 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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 this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.scan.maven; - -import org.apache.maven.project.MavenProject; -import org.junit.Test; -import org.sonar.api.batch.maven.MavenPlugin; -import org.sonar.api.batch.maven.MavenPluginHandler; -import org.sonar.api.resources.Project; -import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem; - -import java.io.File; - -import static org.hamcrest.CoreMatchers.is; -import static org.junit.Assert.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyList; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.never; -import static org.mockito.Mockito.verify; - -public class AbstractMavenPluginExecutorTest { - - @Test - public void plugin_version_should_be_optional() { - assertThat(AbstractMavenPluginExecutor.getGoal("group", "artifact", null, "goal"), is("group:artifact::goal")); - } - - @Test - public void test_plugin_version() { - assertThat(AbstractMavenPluginExecutor.getGoal("group", "artifact", "3.54", "goal"), is("group:artifact:3.54:goal")); - } - - /** - * The maven plugin sometimes changes the project structure (for example mvn build-helper:add-source). These changes - * must be applied to the internal structure. - */ - @Test - public void should_reset_file_system_after_execution() { - AbstractMavenPluginExecutor executor = new AbstractMavenPluginExecutor() { - @Override - public void concreteExecute(MavenProject pom, String goal) throws Exception { - pom.addCompileSourceRoot("src/java"); - } - }; - MavenProject pom = new MavenProject(); - pom.setFile(new File("target/AbstractMavenPluginExecutorTest/pom.xml")); - pom.getBuild().setDirectory("target"); - Project foo = new Project("foo"); - foo.setPom(pom); - DefaultModuleFileSystem fs = mock(DefaultModuleFileSystem.class); - executor.execute(foo, fs, new AddSourceMavenPluginHandler()); - - verify(fs).resetDirs(any(File.class), any(File.class), anyList(), anyList(), anyList()); - } - - @Test - public void should_ignore_non_maven_projects() { - AbstractMavenPluginExecutor executor = new AbstractMavenPluginExecutor() { - @Override - public void concreteExecute(MavenProject pom, String goal) throws Exception { - pom.addCompileSourceRoot("src/java"); - } - }; - Project foo = new Project("foo"); - DefaultModuleFileSystem fs = mock(DefaultModuleFileSystem.class); - executor.execute(foo, fs, new AddSourceMavenPluginHandler()); - - verify(fs, never()).resetDirs(any(File.class), any(File.class), anyList(), anyList(), anyList()); - } - - static class AddSourceMavenPluginHandler implements MavenPluginHandler { - public String getGroupId() { - return "fake"; - } - - public String getArtifactId() { - return "fake"; - } - - public String getVersion() { - return "2.2"; - } - - public boolean isFixedVersion() { - return false; - } - - public String[] getGoals() { - return new String[]{"fake"}; - } - - public void configure(Project project, MavenPlugin plugin) { - } - } - -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/maven/MavenProjectConverterTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/maven/MavenProjectConverterTest.java deleted file mode 100644 index f4fc136cab9..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/maven/MavenProjectConverterTest.java +++ /dev/null @@ -1,243 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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 this program; if not, write to the Free Software Foundation, - * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. - */ -package org.sonar.batch.scan.maven; - -import org.apache.commons.io.FileUtils; -import org.apache.maven.model.Model; -import org.apache.maven.model.io.xpp3.MavenXpp3Reader; -import org.apache.maven.project.MavenProject; -import org.codehaus.plexus.util.xml.pull.XmlPullParserException; -import org.hamcrest.core.Is; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; -import org.sonar.api.CoreProperties; -import org.sonar.api.batch.bootstrap.ProjectDefinition; -import org.sonar.test.TestUtils; - -import java.io.File; -import java.io.IOException; -import java.io.StringReader; -import java.net.URISyntaxException; -import java.util.Arrays; -import java.util.Properties; - -import static org.fest.assertions.Assertions.assertThat; -import static org.hamcrest.Matchers.containsString; -import static org.hamcrest.Matchers.is; -import static org.junit.Assert.assertNull; -import static org.junit.Assert.assertThat; -import static org.junit.Assert.fail; - -public class MavenProjectConverterTest { - - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - - /** - * See SONAR-2681 - */ - @Test - public void shouldThrowExceptionWhenUnableToDetermineProjectStructure() { - MavenProject root = new MavenProject(); - root.setFile(new File("/foo/pom.xml")); - root.getBuild().setDirectory("target"); - root.getModules().add("module/pom.xml"); - - try { - MavenProjectConverter.convert(Arrays.asList(root), root); - fail(); - } catch (IllegalStateException e) { - assertThat(e.getMessage(), containsString("Advanced Reactor Options")); - } - } - - @Test - public void shouldConvertModules() throws IOException { - File basedir = temp.newFolder(); - - MavenProject root = newMavenProject("com.foo", "parent", "1.0-SNAPSHOT"); - root.setFile(new File(basedir, "pom.xml")); - root.getBuild().setDirectory("target"); - root.getBuild().setOutputDirectory("target/classes"); - root.getModules().add("module/pom.xml"); - MavenProject module = newMavenProject("com.foo", "moduleA", "1.0-SNAPSHOT"); - module.setFile(new File(basedir, "module/pom.xml")); - module.getBuild().setDirectory("target"); - module.getBuild().setOutputDirectory("target/classes"); - ProjectDefinition project = MavenProjectConverter.convert(Arrays.asList(root, module), root); - - assertThat(project.getSubProjects().size(), is(1)); - } - - private MavenProject newMavenProject(String groupId, String artifactId, String version) { - Model model = new Model(); - model.setGroupId(groupId); - model.setArtifactId(artifactId); - model.setVersion(version); - return new MavenProject(model); - } - - @Test - public void shouldConvertProperties() { - MavenProject pom = new MavenProject(); - pom.setGroupId("foo"); - pom.setArtifactId("bar"); - pom.setVersion("1.0.1"); - pom.setName("Test"); - pom.setDescription("just test"); - pom.setFile(new File("/foo/pom.xml")); - pom.getBuild().setDirectory("target"); - ProjectDefinition project = ProjectDefinition.create(); - MavenProjectConverter.merge(pom, project); - - Properties properties = project.getProperties(); - assertThat(properties.getProperty(CoreProperties.PROJECT_KEY_PROPERTY), is("foo:bar")); - assertThat(properties.getProperty(CoreProperties.PROJECT_VERSION_PROPERTY), is("1.0.1")); - assertThat(properties.getProperty(CoreProperties.PROJECT_NAME_PROPERTY), is("Test")); - assertThat(properties.getProperty(CoreProperties.PROJECT_DESCRIPTION_PROPERTY), is("just test")); - } - - @Test - public void moduleNameShouldEqualArtifactId() throws Exception { - File rootDir = TestUtils.getResource("/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/"); - MavenProject parent = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/pom.xml", true); - MavenProject module1 = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module1/pom.xml", false); - MavenProject module2 = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module2/pom.xml", false); - - ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(parent, module1, module2), parent); - - assertThat(rootDef.getSubProjects().size(), Is.is(2)); - assertThat(rootDef.getKey(), Is.is("org.test:parent")); - assertNull(rootDef.getParent()); - assertThat(rootDef.getBaseDir(), is(rootDir)); - - ProjectDefinition module1Def = rootDef.getSubProjects().get(0); - assertThat(module1Def.getKey(), Is.is("org.test:module1")); - assertThat(module1Def.getParent(), Is.is(rootDef)); - assertThat(module1Def.getBaseDir(), Is.is(new File(rootDir, "module1"))); - assertThat(module1Def.getSubProjects().size(), Is.is(0)); - } - - @Test - public void moduleNameDifferentThanArtifactId() throws Exception { - File rootDir = TestUtils.getResource("/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/"); - MavenProject parent = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/pom.xml", true); - MavenProject module1 = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path1/pom.xml", false); - MavenProject module2 = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path2/pom.xml", false); - - ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(parent, module1, module2), parent); - - assertThat(rootDef.getSubProjects().size(), is(2)); - assertThat(rootDef.getKey(), is("org.test:parent")); - assertNull(rootDef.getParent()); - assertThat(rootDef.getBaseDir(), is(rootDir)); - - ProjectDefinition module1Def = rootDef.getSubProjects().get(0); - assertThat(module1Def.getKey(), Is.is("org.test:module1")); - assertThat(module1Def.getParent(), Is.is(rootDef)); - assertThat(module1Def.getBaseDir(), Is.is(new File(rootDir, "path1"))); - assertThat(module1Def.getSubProjects().size(), Is.is(0)); - } - - @Test - public void should_find_module_with_maven_project_file_naming_different_from_pom_xml() throws Exception { - File rootDir = TestUtils.getResource("/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/"); - MavenProject parent = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/pom.xml", true); - MavenProject module = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom_having_different_name.xml", false); - - ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(parent, module), parent); - - assertThat(rootDef.getSubProjects().size(), Is.is(1)); - assertThat(rootDef.getKey(), Is.is("org.test:parent")); - assertNull(rootDef.getParent()); - assertThat(rootDef.getBaseDir(), is(rootDir)); - - ProjectDefinition module1Def = rootDef.getSubProjects().get(0); - assertThat(module1Def.getKey(), Is.is("org.test:module")); - assertThat(module1Def.getParent(), Is.is(rootDef)); - assertThat(module1Def.getBaseDir(), Is.is(new File(rootDir, "module"))); - assertThat(module1Def.getSubProjects().size(), Is.is(0)); - } - - @Test - public void testSingleProjectWithoutModules() throws Exception { - File rootDir = TestUtils.getResource("/org/sonar/batch/scan/maven/MavenProjectConverterTest/singleProjectWithoutModules/"); - MavenProject pom = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/singleProjectWithoutModules/pom.xml", true); - - ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(pom), pom); - - assertThat(rootDef.getKey(), is("org.test:parent")); - assertThat(rootDef.getSubProjects().size(), is(0)); - assertNull(rootDef.getParent()); - assertThat(rootDef.getBaseDir(), is(rootDir)); - } - - @Test - public void shouldConvertLinksToProperties() throws Exception { - MavenProject pom = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/projectWithLinks/pom.xml", true); - - ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(pom), pom); - - Properties props = rootDef.getProperties(); - assertThat(props.getProperty(CoreProperties.LINKS_HOME_PAGE)).isEqualTo("http://home.com"); - assertThat(props.getProperty(CoreProperties.LINKS_CI)).isEqualTo("http://ci.com"); - assertThat(props.getProperty(CoreProperties.LINKS_ISSUE_TRACKER)).isEqualTo("http://issues.com"); - assertThat(props.getProperty(CoreProperties.LINKS_SOURCES)).isEqualTo("http://sources.com"); - assertThat(props.getProperty(CoreProperties.LINKS_SOURCES_DEV)).isEqualTo("http://sources-dev.com"); - } - - @Test - public void shouldNotConvertLinksToPropertiesIfPropertyAlreadyDefined() throws Exception { - MavenProject pom = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/projectWithLinksAndProperties/pom.xml", true); - - ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(pom), pom); - - Properties props = rootDef.getProperties(); - - // Those properties have been fed by the POM elements , , ... - assertThat(props.getProperty(CoreProperties.LINKS_CI)).isEqualTo("http://ci.com"); - assertThat(props.getProperty(CoreProperties.LINKS_ISSUE_TRACKER)).isEqualTo("http://issues.com"); - assertThat(props.getProperty(CoreProperties.LINKS_SOURCES_DEV)).isEqualTo("http://sources-dev.com"); - - // ... but those ones have been overridden by in the POM - assertThat(props.getProperty(CoreProperties.LINKS_SOURCES)).isEqualTo("http://sources.com-OVERRIDEN-BY-PROPS"); - assertThat(props.getProperty(CoreProperties.LINKS_HOME_PAGE)).isEqualTo("http://home.com-OVERRIDEN-BY-PROPS"); - } - - @Test - public void shouldLoadSourceEncoding() throws Exception { - MavenProject pom = loadPom("/org/sonar/batch/scan/maven/MavenProjectConverterTest/sourceEncoding/pom.xml", true); - - ProjectDefinition rootDef = MavenProjectConverter.convert(Arrays.asList(pom), pom); - - assertThat(rootDef.getProperties().getProperty(CoreProperties.ENCODING_PROPERTY)).isEqualTo("Shift_JIS"); - } - - private MavenProject loadPom(String pomPath, boolean isRoot) throws URISyntaxException, IOException, XmlPullParserException { - File pomFile = new File(getClass().getResource(pomPath).toURI()); - Model model = new MavenXpp3Reader().read(new StringReader(FileUtils.readFileToString(pomFile))); - MavenProject pom = new MavenProject(model); - pom.setFile(pomFile); - pom.getBuild().setDirectory("target"); - pom.setExecutionRoot(isRoot); - return pom; - } -} diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom.xml deleted file mode 100644 index 7b49562c2e0..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom.xml +++ /dev/null @@ -1,11 +0,0 @@ - - 4.0.0 - - org.test - parent - 0.1-SNAPSHOT - - module - jar - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom_having_different_name.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom_having_different_name.xml deleted file mode 100644 index 7b49562c2e0..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/module/pom_having_different_name.xml +++ /dev/null @@ -1,11 +0,0 @@ - - 4.0.0 - - org.test - parent - 0.1-SNAPSHOT - - module - jar - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/pom.xml deleted file mode 100644 index 9d2244eb148..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/mavenProjectFileNameNotEqualsToPomXml/pom.xml +++ /dev/null @@ -1,11 +0,0 @@ - - 4.0.0 - org.test - parent - 0.1-SNAPSHOT - pom - - module - - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path1/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path1/pom.xml deleted file mode 100644 index 470f2d1f6e5..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path1/pom.xml +++ /dev/null @@ -1,11 +0,0 @@ - - 4.0.0 - - org.test - parent - 0.1-SNAPSHOT - - module1 - jar - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path2/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path2/pom.xml deleted file mode 100644 index 88101678e0f..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/path2/pom.xml +++ /dev/null @@ -1,11 +0,0 @@ - - 4.0.0 - - org.test - parent - 0.1-SNAPSHOT - - module2 - jar - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/pom.xml deleted file mode 100644 index afd92c0dbee..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameDifferentThanArtifactId/pom.xml +++ /dev/null @@ -1,12 +0,0 @@ - - 4.0.0 - org.test - parent - 0.1-SNAPSHOT - pom - - path1 - path2 - - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module1/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module1/pom.xml deleted file mode 100644 index 470f2d1f6e5..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module1/pom.xml +++ /dev/null @@ -1,11 +0,0 @@ - - 4.0.0 - - org.test - parent - 0.1-SNAPSHOT - - module1 - jar - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module2/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module2/pom.xml deleted file mode 100644 index 88101678e0f..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/module2/pom.xml +++ /dev/null @@ -1,11 +0,0 @@ - - 4.0.0 - - org.test - parent - 0.1-SNAPSHOT - - module2 - jar - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/pom.xml deleted file mode 100644 index cc73a43ec08..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/moduleNameShouldEqualArtifactId/pom.xml +++ /dev/null @@ -1,12 +0,0 @@ - - 4.0.0 - org.test - parent - 0.1-SNAPSHOT - pom - - module1 - module2 - - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/projectWithLinks/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/projectWithLinks/pom.xml deleted file mode 100644 index 460e8967e5c..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/projectWithLinks/pom.xml +++ /dev/null @@ -1,18 +0,0 @@ - - 4.0.0 - org.test - parent - 0.1-SNAPSHOT - pom - http://home.com - - http://ci.com - - - http://issues.com - - - http://sources.com - http://sources-dev.com - - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/projectWithLinksAndProperties/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/projectWithLinksAndProperties/pom.xml deleted file mode 100644 index 5b024e5c4a7..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/projectWithLinksAndProperties/pom.xml +++ /dev/null @@ -1,27 +0,0 @@ - - 4.0.0 - org.test - parent - 0.1-SNAPSHOT - pom - http://home.com - - http://ci.com - - - http://issues.com - - - http://sources.com - http://sources-dev.com - - - - - - http://home.com-OVERRIDEN-BY-PROPS - http://sources.com-OVERRIDEN-BY-PROPS - - - - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/singleProjectWithoutModules/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/singleProjectWithoutModules/pom.xml deleted file mode 100644 index ffd40530c5d..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/singleProjectWithoutModules/pom.xml +++ /dev/null @@ -1,8 +0,0 @@ - - 4.0.0 - org.test - parent - 0.1-SNAPSHOT - pom - \ No newline at end of file diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/sourceEncoding/pom.xml b/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/sourceEncoding/pom.xml deleted file mode 100644 index 01bf73cfa9e..00000000000 --- a/sonar-batch/src/test/resources/org/sonar/batch/scan/maven/MavenProjectConverterTest/sourceEncoding/pom.xml +++ /dev/null @@ -1,11 +0,0 @@ - - 4.0.0 - org.test - parent - 0.1-SNAPSHOT - pom - http://home.com - - Shift_JIS - - \ No newline at end of file