aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-batch/src/main/java/org
diff options
context:
space:
mode:
authorEvgeny Mandrikov <mandrikov@gmail.com>2011-04-09 02:19:28 +0400
committerEvgeny Mandrikov <mandrikov@gmail.com>2011-04-26 13:00:11 +0400
commite174628696636f74808f61c76a44da994edcadc7 (patch)
tree06af7a9e94d17294cce72ddded48a84c8b2b3f1f /sonar-batch/src/main/java/org
parent4eb630d0ff939898efdd9ef29330736ca4e50ebc (diff)
downloadsonarqube-e174628696636f74808f61c76a44da994edcadc7.tar.gz
sonarqube-e174628696636f74808f61c76a44da994edcadc7.zip
SONAR-2298 Add support for multi-modules for non-Maven projects
* Use ProjectDefinition in ProjectTree instead of MavenProject * Allow to specify extensions for project's container via ProjectDefinition, so MavenProject not passed directly to batch in mojos * ProjectDefinition should store all information in properties * Replace DefaultProjectFileSystem by DefaultProjectFileSystem2, which works not only for Maven projects * Add DefaultProjectClasspath, which works not only for Maven projects * Enable ProjectLinksSensor only for Maven
Diffstat (limited to 'sonar-batch/src/main/java/org')
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/DefaultProjectClasspath.java61
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/DefaultProjectFileSystem2.java166
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/InMemoryPomCreator.java120
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/MavenProjectBuilder.java62
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/MavenProjectConverter.java85
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/MavenProjectFileSystem.java114
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/MavenReactor.java43
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java20
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/ProjectConfiguration.java15
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java110
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java75
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/phases/MavenPluginsConfigurator.java20
12 files changed, 512 insertions, 379 deletions
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultProjectClasspath.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultProjectClasspath.java
new file mode 100644
index 00000000000..978acf4b5d5
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultProjectClasspath.java
@@ -0,0 +1,61 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * 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.batch;
+
+import com.google.common.collect.Lists;
+import org.apache.maven.project.MavenProject;
+import org.sonar.api.batch.ProjectClasspath;
+import org.sonar.api.resources.ProjectFileSystem;
+import org.sonar.batch.bootstrapper.ProjectDefinition;
+
+import java.io.File;
+import java.util.List;
+
+public class DefaultProjectClasspath extends ProjectClasspath {
+
+ private ProjectDefinition def;
+ private ProjectFileSystem projectFileSystem;
+
+ public DefaultProjectClasspath(ProjectDefinition def, ProjectFileSystem projectFileSystem) {
+ this(def, projectFileSystem, null);
+ }
+
+ public DefaultProjectClasspath(ProjectDefinition def, ProjectFileSystem projectFileSystem, MavenProject pom) {
+ super(pom);
+ this.def = def;
+ this.projectFileSystem = projectFileSystem;
+ }
+
+ @Override
+ protected List<File> createElements() {
+ if (pom != null) {
+ return super.createElements();
+ } else {
+ List<File> elements = Lists.newArrayList();
+ for (String path : def.getBinaries()) {
+ elements.add(projectFileSystem.resolvePath(path));
+ }
+ for (String path : def.getLibraries()) {
+ elements.add(projectFileSystem.resolvePath(path));
+ }
+ return elements;
+ }
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultProjectFileSystem2.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultProjectFileSystem2.java
new file mode 100644
index 00000000000..82302af4973
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/DefaultProjectFileSystem2.java
@@ -0,0 +1,166 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * 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.batch;
+
+import org.apache.commons.io.FileUtils;
+import org.apache.maven.project.MavenProject;
+import org.sonar.api.resources.DefaultProjectFileSystem;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.resources.Project;
+import org.sonar.api.resources.ProjectFileSystem;
+import org.sonar.api.utils.SonarException;
+import org.sonar.batch.bootstrapper.ProjectDefinition;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+
+/**
+ * Implementation of {@link ProjectFileSystem} based on {@link ProjectDefinition} and {@link MavenProject}.
+ */
+public class DefaultProjectFileSystem2 extends DefaultProjectFileSystem {
+
+ private ProjectDefinition def;
+ private MavenProject pom;
+
+ public DefaultProjectFileSystem2(Project project, Languages languages, ProjectDefinition def) {
+ super(project, languages);
+ this.def = def;
+ }
+
+ /**
+ * For Maven.
+ */
+ public DefaultProjectFileSystem2(Project project, Languages languages, ProjectDefinition def, MavenProject pom) {
+ this(project, languages, def);
+ this.pom = pom;
+ }
+
+ public File getBasedir() {
+ if (pom != null) {
+ return pom.getBasedir();
+ } else {
+ return def.getBaseDir();
+ }
+ }
+
+ public File getBuildDir() {
+ if (pom != null) {
+ return resolvePath(pom.getBuild().getDirectory());
+ } else {
+ // TODO workaround
+ return new File(getSonarWorkingDirectory(), "target");
+ }
+ }
+
+ public File getBuildOutputDir() {
+ if (pom != null) {
+ return resolvePath(pom.getBuild().getOutputDirectory());
+ } else {
+ if (def.getBinaries().isEmpty()) {
+ // workaround for IndexOutOfBoundsException
+ return new File(getBuildDir(), "classes");
+ }
+ // TODO we assume that there is only one directory which contains compiled code
+ return resolvePath(def.getBinaries().get(0));
+ }
+ }
+
+ public List<File> getSourceDirs() {
+ if (pom != null) {
+ // Maven can modify source directories during Sonar execution - see MavenPhaseExecutor.
+ return resolvePaths(pom.getCompileSourceRoots());
+ } else {
+ return resolvePaths(def.getSourceDirs());
+ }
+ }
+
+ /**
+ * @deprecated since 2.6, because should be immutable
+ */
+ @Deprecated
+ public DefaultProjectFileSystem addSourceDir(File dir) {
+ if (dir == null) {
+ throw new IllegalArgumentException("Can not add null to project source dirs");
+ }
+ if (pom != null) {
+ pom.getCompileSourceRoots().add(0, dir.getAbsolutePath());
+ } else {
+ def.addSourceDir(dir.getAbsolutePath());
+ }
+ return this;
+ }
+
+ /**
+ * Maven can modify test directories during Sonar execution - see MavenPhaseExecutor.
+ */
+ public List<File> getTestDirs() {
+ if (pom != null) {
+ // Maven can modify test directories during Sonar execution - see MavenPhaseExecutor.
+ return resolvePaths(pom.getTestCompileSourceRoots());
+ } else {
+ return resolvePaths(def.getTestDirs());
+ }
+ }
+
+ /**
+ * @deprecated since 2.6, because should be immutable
+ */
+ @Deprecated
+ public DefaultProjectFileSystem addTestDir(File dir) {
+ if (dir == null) {
+ throw new IllegalArgumentException("Can not add null to project test dirs");
+ }
+ if (pom != null) {
+ pom.getTestCompileSourceRoots().add(0, dir.getAbsolutePath());
+ } else {
+ def.addTestDir(dir.getAbsolutePath());
+ }
+ return this;
+ }
+
+ /**
+ * TODO Godin: seems that used only by Cobertura and Clover
+ */
+ public File getReportOutputDir() {
+ if (pom != null) {
+ return resolvePath(pom.getReporting().getOutputDirectory());
+ } else {
+ return new File(getBuildDir(), "site");
+ }
+ }
+
+ @Override
+ public File getSonarWorkingDirectory() {
+ if (pom != null) {
+ try {
+ File dir = new File(getBuildDir(), "sonar");
+ FileUtils.forceMkdir(dir);
+ return dir;
+
+ } catch (IOException e) {
+ throw new SonarException("Unable to retrieve Sonar working directory.", e);
+ }
+ } else {
+ return def.getWorkDir();
+ }
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/InMemoryPomCreator.java b/sonar-batch/src/main/java/org/sonar/batch/InMemoryPomCreator.java
deleted file mode 100644
index 73c79ad8548..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/InMemoryPomCreator.java
+++ /dev/null
@@ -1,120 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2011 SonarSource
- * 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.batch;
-
-import org.apache.commons.lang.StringUtils;
-import org.apache.maven.artifact.DependencyResolutionRequiredException;
-import org.apache.maven.model.Reporting;
-import org.apache.maven.project.MavenProject;
-import org.sonar.api.CoreProperties;
-import org.sonar.api.utils.SonarException;
-import org.sonar.batch.bootstrapper.ProjectDefinition;
-
-import java.io.File;
-import java.util.ArrayList;
-import java.util.Collections;
-import java.util.List;
-import java.util.Properties;
-
-/**
- * This is a dirty hack for for non-Maven environments,
- * which allows to create {@link MavenProject} based on {@link ProjectDefinition}.
- */
-public class InMemoryPomCreator {
-
- private ProjectDefinition project;
-
- public InMemoryPomCreator(ProjectDefinition project) {
- this.project = project;
- }
-
- public MavenProject create() {
- File workDir = project.getWorkDir();
- String buildDirectory = workDir.getAbsolutePath() + "/target";
- Properties properties = project.getProperties();
-
- if (project.getBinaries().size() == 0) {
- project.addBinaryDir(buildDirectory + "/classes");
- }
-
- final MavenProject pom = new MavenProject() {
- /**
- * This allows to specify base directory without specifying location of a pom.xml
- */
- @Override
- public File getBasedir() {
- return project.getBaseDir();
- };
-
- /**
- * This allows to specify project classpath (binaries + libraries).
- */
- @Override
- public List<String> getCompileClasspathElements() throws DependencyResolutionRequiredException {
- List<String> cp = new ArrayList<String>();
- cp.addAll(project.getBinaries());
- cp.addAll(project.getLibraries());
- return cp;
- }
- };
-
- String key = getPropertyOrDie(properties, CoreProperties.PROJECT_KEY_PROPERTY);
- String[] keys = key.split(":");
- pom.setGroupId(keys[0]);
- pom.setArtifactId(keys[1]);
- pom.setVersion(getPropertyOrDie(properties, CoreProperties.PROJECT_VERSION_PROPERTY));
-
- pom.setName(properties.getProperty(CoreProperties.PROJECT_NAME_PROPERTY, "Unnamed - " + key));
- pom.setDescription(properties.getProperty(CoreProperties.PROJECT_DESCRIPTION_PROPERTY, ""));
-
- pom.getModel().setProperties(properties);
-
- pom.setArtifacts(Collections.EMPTY_SET);
-
- // Configure fake directories
- pom.getBuild().setDirectory(buildDirectory);
- pom.getBuild().setOutputDirectory(project.getBinaries().get(0));
- Reporting reporting = new Reporting();
- String reportingOutputDirectory = buildDirectory + "/site";
- reporting.setOutputDirectory(reportingOutputDirectory);
- pom.setReporting(reporting);
-
- // Configure source directories
- for (String dir : project.getSourceDirs()) {
- pom.addCompileSourceRoot(dir);
- }
-
- // Configure test directories
- for (String dir : project.getTestDirs()) {
- pom.addTestCompileSourceRoot(dir);
- }
-
- return pom;
- }
-
- private static String getPropertyOrDie(Properties properties, String key) {
- String value = properties.getProperty(key);
- if (StringUtils.isBlank(value)) {
- throw new SonarException("Property '" + key + "' must be specified");
- }
- return value;
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/MavenProjectBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/MavenProjectBuilder.java
index 0086f1015c0..48bc41730b0 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/MavenProjectBuilder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/MavenProjectBuilder.java
@@ -19,14 +19,9 @@
*/
package org.sonar.batch;
-import java.text.DateFormat;
-import java.text.ParseException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-
import org.apache.commons.configuration.*;
+import org.apache.commons.lang.StringUtils;
import org.apache.commons.lang.time.DateUtils;
-import org.apache.maven.project.MavenProject;
import org.sonar.api.CoreProperties;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.database.model.ResourceModel;
@@ -34,7 +29,14 @@ import org.sonar.api.database.model.Snapshot;
import org.sonar.api.resources.Java;
import org.sonar.api.resources.Project;
import org.sonar.api.utils.SonarException;
+import org.sonar.batch.bootstrapper.ProjectDefinition;
+
+import java.text.DateFormat;
+import java.text.ParseException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+// TODO Godin: rename to ProjectBuilder ?
public class MavenProjectBuilder {
private DatabaseSession databaseSession;
@@ -43,43 +45,55 @@ public class MavenProjectBuilder {
this.databaseSession = databaseSession;
}
- public Project create(MavenProject pom) {
- Configuration configuration = getStartupConfiguration(pom);
- return new Project(loadProjectKey(pom), loadProjectBranch(configuration), pom.getName())
- .setPom(pom)
- .setDescription(pom.getDescription())
- .setPackaging(pom.getPackaging());
+ public Project create(ProjectDefinition project) {
+ Configuration configuration = getStartupConfiguration(project);
+ return new Project(loadProjectKey(project), loadProjectBranch(configuration), loadProjectName(project))
+ .setDescription(project.getProperties().getProperty(CoreProperties.PROJECT_DESCRIPTION_PROPERTY))
+ .setPackaging("jar"); // FIXME http://jira.codehaus.org/browse/SONAR-2341
}
- Configuration getStartupConfiguration(MavenProject pom) {
+ Configuration getStartupConfiguration(ProjectDefinition project) {
CompositeConfiguration configuration = new CompositeConfiguration();
configuration.addConfiguration(new SystemConfiguration());
configuration.addConfiguration(new EnvironmentConfiguration());
- configuration.addConfiguration(new MapConfiguration(pom.getModel().getProperties()));
+ configuration.addConfiguration(new MapConfiguration(project.getProperties()));
return configuration;
}
- String loadProjectKey(MavenProject pom) {
- return new StringBuilder().append(pom.getGroupId()).append(":").append(pom.getArtifactId()).toString();
+ private String getPropertyOrDie(ProjectDefinition project, String key) {
+ String value = project.getProperties().getProperty(key);
+ if (StringUtils.isBlank(value)) {
+ throw new SonarException("Property '" + key + "' must be specified");
+ }
+ return value;
+ }
+
+ String loadProjectKey(ProjectDefinition projectDefinition) {
+ return getPropertyOrDie(projectDefinition, CoreProperties.PROJECT_KEY_PROPERTY);
+ }
+
+ String loadProjectName(ProjectDefinition projectDefinition) {
+ return projectDefinition.getProperties().getProperty(
+ CoreProperties.PROJECT_NAME_PROPERTY,
+ "Unnamed - " + loadProjectKey(projectDefinition));
}
String loadProjectBranch(Configuration configuration) {
return configuration.getString(CoreProperties.PROJECT_BRANCH_PROPERTY, configuration.getString("branch" /* deprecated property */));
}
- public void configure(Project project) {
- ProjectConfiguration projectConfiguration = new ProjectConfiguration(databaseSession, project);
+ public void configure(Project project, ProjectDefinition def) {
+ ProjectConfiguration projectConfiguration = new ProjectConfiguration(databaseSession, project, def.getProperties());
configure(project, projectConfiguration);
}
void configure(Project project, Configuration projectConfiguration) {
Date analysisDate = loadAnalysisDate(projectConfiguration);
- MavenProject pom = project.getPom();
project.setConfiguration(projectConfiguration)
.setExclusionPatterns(loadExclusionPatterns(projectConfiguration))
.setAnalysisDate(analysisDate)
.setLatestAnalysis(isLatestAnalysis(project.getKey(), analysisDate))
- .setAnalysisVersion(loadAnalysisVersion(projectConfiguration, pom))
+ .setAnalysisVersion(loadAnalysisVersion(projectConfiguration))
.setAnalysisType(loadAnalysisType(projectConfiguration))
.setLanguageKey(loadLanguageKey(projectConfiguration));
}
@@ -133,12 +147,8 @@ public class MavenProjectBuilder {
return Project.AnalysisType.STATIC;
}
- String loadAnalysisVersion(Configuration configuration, MavenProject pom) {
- String version = configuration.getString(CoreProperties.PROJECT_VERSION_PROPERTY);
- if (version == null && pom != null) {
- version = pom.getVersion();
- }
- return version;
+ String loadAnalysisVersion(Configuration configuration) {
+ return configuration.getString(CoreProperties.PROJECT_VERSION_PROPERTY);
}
String loadLanguageKey(Configuration configuration) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/MavenProjectConverter.java b/sonar-batch/src/main/java/org/sonar/batch/MavenProjectConverter.java
new file mode 100644
index 00000000000..450509870be
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/MavenProjectConverter.java
@@ -0,0 +1,85 @@
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2011 SonarSource
+ * 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.batch;
+
+import com.google.common.collect.Maps;
+import org.apache.maven.project.MavenProject;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.utils.SonarException;
+import org.sonar.batch.bootstrapper.ProjectDefinition;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.List;
+import java.util.Map;
+import java.util.Properties;
+
+public class MavenProjectConverter {
+
+ private MavenProjectConverter() {
+ }
+
+ public static ProjectDefinition convert(List<MavenProject> poms) {
+ Map<String, MavenProject> paths = Maps.newHashMap(); // projects by canonical path
+ Map<MavenProject, ProjectDefinition> defs = Maps.newHashMap();
+
+ try {
+ for (MavenProject pom : poms) {
+ String basedir = pom.getBasedir().getCanonicalPath();
+ paths.put(basedir, pom);
+ defs.put(pom, convert(pom));
+ }
+
+ for (Map.Entry<String, MavenProject> entry : paths.entrySet()) {
+ MavenProject pom = entry.getValue();
+ for (Object moduleId : pom.getModules()) {
+ File modulePath = new File(pom.getBasedir(), (String) moduleId);
+ MavenProject module = paths.get(modulePath.getCanonicalPath());
+ defs.get(pom).addModule(defs.get(module));
+ }
+ }
+ } catch (IOException e) {
+ throw new SonarException(e);
+ }
+
+ return defs.get(poms.get(0));
+ }
+
+ public static ProjectDefinition convert(MavenProject pom) {
+ Properties properties = new Properties();
+
+ String key = new StringBuilder().append(pom.getGroupId()).append(":").append(pom.getArtifactId()).toString();
+ setProperty(properties, CoreProperties.PROJECT_KEY_PROPERTY, key);
+ setProperty(properties, CoreProperties.PROJECT_VERSION_PROPERTY, pom.getVersion());
+ setProperty(properties, CoreProperties.PROJECT_NAME_PROPERTY, pom.getName());
+ setProperty(properties, CoreProperties.PROJECT_DESCRIPTION_PROPERTY, pom.getDescription());
+ properties.putAll(pom.getModel().getProperties());
+
+ ProjectDefinition def = new ProjectDefinition(pom.getBasedir(), null, properties); // TODO work directory ?
+ def.addContainerExtension(pom);
+ return def;
+ }
+
+ private static void setProperty(Properties properties, String key, String value) {
+ if (value != null) {
+ properties.setProperty(key, value);
+ }
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/MavenProjectFileSystem.java b/sonar-batch/src/main/java/org/sonar/batch/MavenProjectFileSystem.java
deleted file mode 100644
index 39ac4ad7c18..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/MavenProjectFileSystem.java
+++ /dev/null
@@ -1,114 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2011 SonarSource
- * 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.batch;
-
-import org.apache.commons.io.FileUtils;
-import org.apache.maven.project.MavenProject;
-import org.sonar.api.resources.DefaultProjectFileSystem;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.resources.Project;
-import org.sonar.api.resources.ProjectFileSystem;
-import org.sonar.api.utils.SonarException;
-
-import java.io.File;
-import java.io.IOException;
-import java.util.List;
-
-/**
- * Implementation of {@link ProjectFileSystem} based on {@link MavenProject}.
- */
-public class MavenProjectFileSystem extends DefaultProjectFileSystem {
-
- private MavenProject pom;
-
- public MavenProjectFileSystem(Project project, Languages languages) {
- super(project, languages);
- this.pom = project.getPom();
- }
-
- @Override
- public File getBasedir() {
- return pom.getBasedir();
- }
-
- @Override
- public File getBuildDir() {
- return resolvePath(pom.getBuild().getDirectory());
- }
-
- @Override
- public File getBuildOutputDir() {
- return resolvePath(pom.getBuild().getOutputDirectory());
- }
-
- /**
- * Maven can modify source directories during Sonar execution - see MavenPhaseExecutor.
- */
- @Override
- public List<File> getSourceDirs() {
- return resolvePaths(pom.getCompileSourceRoots());
- }
-
- @Override
- public DefaultProjectFileSystem addSourceDir(File dir) {
- if (dir == null) {
- throw new IllegalArgumentException("Can not add null to project source dirs");
- }
- pom.getCompileSourceRoots().add(0, dir.getAbsolutePath());
- return this;
- }
-
- /**
- * Maven can modify test directories during Sonar execution - see MavenPhaseExecutor.
- */
- @Override
- public List<File> getTestDirs() {
- return resolvePaths(pom.getTestCompileSourceRoots());
- }
-
- /**
- * @deprecated since 2.6, because should be immutable
- */
- @Override
- public DefaultProjectFileSystem addTestDir(File dir) {
- if (dir == null) {
- throw new IllegalArgumentException("Can not add null to project test dirs");
- }
- pom.getTestCompileSourceRoots().add(0, dir.getAbsolutePath());
- return this;
- }
-
- @Override
- public File getReportOutputDir() {
- return resolvePath(pom.getReporting().getOutputDirectory());
- }
-
- @Override
- public File getSonarWorkingDirectory() {
- try {
- File dir = new File(getBuildDir(), "sonar");
- FileUtils.forceMkdir(dir);
- return dir;
-
- } catch (IOException e) {
- throw new SonarException("Unable to retrieve Sonar working directory.", e);
- }
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/MavenReactor.java b/sonar-batch/src/main/java/org/sonar/batch/MavenReactor.java
deleted file mode 100644
index fff85d35e34..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/MavenReactor.java
+++ /dev/null
@@ -1,43 +0,0 @@
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2011 SonarSource
- * 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.batch;
-
-import org.apache.maven.execution.MavenSession;
-import org.apache.maven.project.MavenProject;
-
-import java.util.List;
-
-public class MavenReactor {
-
- private List<MavenProject> sortedProjects;
-
- public MavenReactor(MavenSession mavenSession) {
- this.sortedProjects = mavenSession.getSortedProjects();
- }
-
- public MavenReactor(List<MavenProject> sortedProjects) {
- this.sortedProjects = sortedProjects;
- }
-
- public List<MavenProject> getSortedProjects() {
- return sortedProjects;
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java b/sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java
index 95355bc08ef..7a6ea61b454 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/ProjectBatch.java
@@ -19,8 +19,8 @@
*/
package org.sonar.batch;
+import org.apache.maven.project.MavenProject;
import org.sonar.api.batch.BatchExtensionDictionnary;
-import org.sonar.api.batch.ProjectClasspath;
import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric;
import org.sonar.api.measures.Metrics;
@@ -32,6 +32,7 @@ import org.sonar.api.resources.ProjectFileSystem;
import org.sonar.api.rules.DefaultRulesManager;
import org.sonar.api.utils.SonarException;
import org.sonar.batch.bootstrap.BatchPluginRepository;
+import org.sonar.batch.bootstrapper.ProjectDefinition;
import org.sonar.batch.components.PastViolationsLoader;
import org.sonar.batch.components.TimeMachineConfiguration;
import org.sonar.batch.events.EventBus;
@@ -103,10 +104,21 @@ public class ProjectBatch {
@Override
protected void configure() {
+ ProjectDefinition projectDefinition = getComponent(ProjectTree.class).getProjectDefinition(project.getKey());
+ addComponent(projectDefinition);
+ for (Object component : projectDefinition.getContainerExtensions()) {
+ addComponent(component);
+ if (component instanceof MavenProject) {
+ // For backward compatibility we must set POM and actual packaging
+ MavenProject pom = (MavenProject) component;
+ project.setPom(pom);
+ project.setPackaging(pom.getPackaging());
+ }
+ }
+
addComponent(project);
- addComponent(project.getPom());
- addComponent(ProjectClasspath.class);
- addComponent(MavenProjectFileSystem.class);
+ addComponent(DefaultProjectClasspath.class);
+ addComponent(DefaultProjectFileSystem2.class);
addComponent(project.getConfiguration());
// need to be registered after the Configuration
diff --git a/sonar-batch/src/main/java/org/sonar/batch/ProjectConfiguration.java b/sonar-batch/src/main/java/org/sonar/batch/ProjectConfiguration.java
index ddae656f1d8..f89e9d644fa 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/ProjectConfiguration.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/ProjectConfiguration.java
@@ -20,20 +20,26 @@
package org.sonar.batch;
import org.apache.commons.configuration.*;
-import org.apache.maven.project.MavenProject;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.resources.Project;
+import java.util.Properties;
+
public class ProjectConfiguration extends CompositeConfiguration {
private PropertiesConfiguration runtimeConfiguration;
+ // FIXME remove
public ProjectConfiguration(DatabaseSession session, Project project) {
+ this(session, project, project.getPom().getProperties());
+ }
+
+ public ProjectConfiguration(DatabaseSession session, Project project, Properties properties) {
runtimeConfiguration = new PropertiesConfiguration();
addConfiguration(runtimeConfiguration);
loadSystemSettings();
loadProjectDatabaseSettings(session, project);
- loadMavenSettings(project.getPom());
+ addConfiguration(new MapConfiguration(properties));
loadGlobalDatabaseSettings(session);
}
@@ -56,13 +62,8 @@ public class ProjectConfiguration extends CompositeConfiguration {
addConfiguration(new EnvironmentConfiguration());
}
- private void loadMavenSettings(MavenProject pom) {
- addConfiguration(new MapConfiguration(pom.getModel().getProperties()));
- }
-
@Override
public void setProperty(String s, Object o) {
runtimeConfiguration.setProperty(s, o);
}
}
-
diff --git a/sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java b/sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java
index 4a03586a2e8..ac2db745ec3 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/ProjectTree.java
@@ -21,42 +21,30 @@ package org.sonar.batch;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
+import org.apache.commons.lang.StringUtils;
import org.apache.maven.project.MavenProject;
import org.slf4j.LoggerFactory;
+import org.sonar.api.CoreProperties;
import org.sonar.api.database.DatabaseSession;
import org.sonar.api.resources.Project;
import org.sonar.batch.bootstrapper.ProjectDefinition;
import org.sonar.batch.bootstrapper.Reactor;
-import java.io.File;
import java.io.IOException;
import java.util.*;
public class ProjectTree {
private List<Project> projects;
- private List<MavenProject> poms;
private MavenProjectBuilder projectBuilder;
+ private List<ProjectDefinition> definitions;
- public ProjectTree(MavenReactor mavenReactor, DatabaseSession databaseSession) {
- this.poms = mavenReactor.getSortedProjects();
- this.projectBuilder = new MavenProjectBuilder(databaseSession);
- }
-
- /**
- * Hack for non-Maven environments.
- */
public ProjectTree(Reactor sonarReactor, DatabaseSession databaseSession) {
- this(createMavenReactor(sonarReactor), databaseSession);
- }
-
- private static MavenReactor createMavenReactor(Reactor sonarReactor) {
- List<ProjectDefinition> sonarProjects = sonarReactor.getSortedProjects();
- List<MavenProject> mavenProjects = Lists.newArrayList();
- for (ProjectDefinition project : sonarProjects) {
- mavenProjects.add(new InMemoryPomCreator(project).create());
+ this.projectBuilder = new MavenProjectBuilder(databaseSession);
+ definitions = Lists.newArrayList();
+ for (ProjectDefinition project : sonarReactor.getSortedProjects()) {
+ collectProjects(project, definitions);
}
- return new MavenReactor(mavenProjects);
}
/**
@@ -64,7 +52,8 @@ public class ProjectTree {
*/
protected ProjectTree(MavenProjectBuilder projectBuilder, List<MavenProject> poms) {
this.projectBuilder = projectBuilder;
- this.poms = poms;
+ definitions = Lists.newArrayList();
+ collectProjects(MavenProjectConverter.convert(poms), definitions);
}
/**
@@ -74,36 +63,40 @@ public class ProjectTree {
this.projects = new ArrayList<Project>(projects);
}
+ /**
+ * Populates list of projects from hierarchy.
+ */
+ private static void collectProjects(ProjectDefinition root, List<ProjectDefinition> collected) {
+ collected.add(root);
+ for (ProjectDefinition module : root.getModules()) {
+ collectProjects(module, collected);
+ }
+ }
+
public void start() throws IOException {
projects = Lists.newArrayList();
- Map<String, Project> paths = Maps.newHashMap(); // projects by canonical path
+ Map<ProjectDefinition, Project> map = Maps.newHashMap();
- for (MavenProject pom : poms) {
- Project project = projectBuilder.create(pom);
+ for (ProjectDefinition def : definitions) {
+ Project project = projectBuilder.create(def);
+ map.put(def, project);
projects.add(project);
- paths.put(pom.getBasedir().getCanonicalPath(), project);
}
- for (Map.Entry<String, Project> entry : paths.entrySet()) {
+ for (Map.Entry<ProjectDefinition, Project> entry : map.entrySet()) {
+ ProjectDefinition def = entry.getKey();
Project project = entry.getValue();
- MavenProject pom = project.getPom();
- for (Object moduleId : pom.getModules()) {
- File modulePath = new File(pom.getBasedir(), (String) moduleId);
- Project module = paths.get(modulePath.getCanonicalPath());
- if (module != null) {
- module.setParent(project);
- }
+ for (ProjectDefinition module : def.getModules()) {
+ map.get(module).setParent(project);
}
}
- configureProjects();
- applyModuleExclusions();
- }
-
- private void configureProjects() {
- for (Project project : projects) {
- projectBuilder.configure(project);
+ // Configure
+ for (Map.Entry<ProjectDefinition, Project> entry : map.entrySet()) {
+ projectBuilder.configure(entry.getValue(), entry.getKey());
}
+
+ applyModuleExclusions();
}
void applyModuleExclusions() {
@@ -125,7 +118,7 @@ public class ProjectTree {
if (!includedModulesIdSet.isEmpty()) {
for (Project currentProject : projects) {
- if (!includedModulesIdSet.contains(currentProject.getPom().getArtifactId())) {
+ if (!includedModulesIdSet.contains(getArtifactId(currentProject))) {
exclude(currentProject);
}
}
@@ -160,9 +153,19 @@ public class ProjectTree {
return projects;
}
+ private String getArtifactId(Project project) {
+ String key = project.getKey();
+ if (StringUtils.isNotBlank(project.getBranch())) {
+ // remove branch part
+ key = StringUtils.removeEnd(project.getKey(), ":" + project.getBranch());
+ }
+ return StringUtils.substringAfterLast(key, ":");
+ }
+
public Project getProjectByArtifactId(String artifactId) {
for (Project project : projects) {
- if (project.getPom().getArtifactId().equals(artifactId)) {
+ // TODO see http://jira.codehaus.org/browse/SONAR-2324
+ if (StringUtils.equals(getArtifactId(project), artifactId)) {
return project;
}
}
@@ -177,4 +180,27 @@ public class ProjectTree {
}
throw new IllegalStateException("Can not find the root project from the list of Maven modules");
}
-} \ No newline at end of file
+
+ private String getProjectKey(ProjectDefinition def) {
+ String key = def.getProperties().getProperty(CoreProperties.PROJECT_KEY_PROPERTY);
+ String branch = def.getProperties().getProperty(CoreProperties.PROJECT_BRANCH_PROPERTY);
+ if (StringUtils.isNotBlank(branch)) {
+ return key + ":" + branch;
+ } else {
+ return key;
+ }
+ }
+
+ public ProjectDefinition getProjectDefinition(String key) {
+ for (ProjectDefinition def : definitions) {
+ if (StringUtils.equals(key, getProjectKey(def))) {
+ return def;
+ }
+ }
+ return null;
+ }
+
+ public List<Object> getProjectExtensions(String key) {
+ return getProjectDefinition(key).getContainerExtensions();
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java
index b632feb60ac..907f30940ac 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/ProjectDefinition.java
@@ -19,12 +19,14 @@
*/
package org.sonar.batch.bootstrapper;
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.StringUtils;
+
import java.io.File;
+import java.util.Arrays;
import java.util.List;
import java.util.Properties;
-import com.google.common.collect.Lists;
-
/**
* Describes project in a form suitable to bootstrap Sonar batch.
* We assume that project is just a set of configuration properties and directories.
@@ -33,13 +35,19 @@ import com.google.common.collect.Lists;
*/
public class ProjectDefinition {
+ private static final String PROJECT_SOURCES_PROPERTY = "sonar.sources";
+ private static final String PROJECT_TESTS_PROPERTY = "sonar.tests";
+ private static final String PROJECT_BINARIES_PROPERTY = "sonar.binaries";
+ private static final String PROJECT_LIBRARIES_PROPERTY = "sonar.libraries";
+
+ private static final char SEPARATOR = ',';
+
private File baseDir;
private File workDir;
private Properties properties;
- private List<String> sourceDirs = Lists.newArrayList();
- private List<String> testDirs = Lists.newArrayList();
- private List<String> binaries = Lists.newArrayList();
- private List<String> libraries = Lists.newArrayList();
+ private List<ProjectDefinition> modules = Lists.newArrayList();
+
+ private List<Object> containerExtensions = Lists.newArrayList();
/**
* @param baseDir project base directory
@@ -63,8 +71,14 @@ public class ProjectDefinition {
return properties;
}
+ private void appendProperty(String key, String value) {
+ String newValue = properties.getProperty(key, "") + SEPARATOR + value;
+ properties.put(key, newValue);
+ }
+
public List<String> getSourceDirs() {
- return sourceDirs;
+ String sources = properties.getProperty(PROJECT_SOURCES_PROPERTY, "");
+ return Arrays.asList(StringUtils.split(sources, SEPARATOR));
}
/**
@@ -72,11 +86,12 @@ public class ProjectDefinition {
* It can be absolute or relative to project directory.
*/
public void addSourceDir(String path) {
- sourceDirs.add(path);
+ appendProperty(PROJECT_SOURCES_PROPERTY, path);
}
public List<String> getTestDirs() {
- return testDirs;
+ String sources = properties.getProperty(PROJECT_TESTS_PROPERTY, "");
+ return Arrays.asList(StringUtils.split(sources, SEPARATOR));
}
/**
@@ -84,11 +99,12 @@ public class ProjectDefinition {
* It can be absolute or relative to project directory.
*/
public void addTestDir(String path) {
- testDirs.add(path);
+ appendProperty(PROJECT_TESTS_PROPERTY, path);
}
public List<String> getBinaries() {
- return binaries;
+ String sources = properties.getProperty(PROJECT_BINARIES_PROPERTY, "");
+ return Arrays.asList(StringUtils.split(sources, SEPARATOR));
}
/**
@@ -97,11 +113,12 @@ public class ProjectDefinition {
* @TODO currently Sonar supports only one such directory due to dependency on MavenProject
*/
public void addBinaryDir(String path) {
- binaries.add(path);
+ appendProperty(PROJECT_BINARIES_PROPERTY, path);
}
public List<String> getLibraries() {
- return libraries;
+ String sources = properties.getProperty(PROJECT_LIBRARIES_PROPERTY, "");
+ return Arrays.asList(StringUtils.split(sources, SEPARATOR));
}
/**
@@ -109,6 +126,36 @@ public class ProjectDefinition {
* It can be absolute or relative to project directory.
*/
public void addLibrary(String path) {
- libraries.add(path);
+ appendProperty(PROJECT_LIBRARIES_PROPERTY, path);
+ }
+
+ /**
+ * Adds an extension, which would be available in PicoContainer during analysis of this project.
+ *
+ * @since 2.8
+ */
+ public void addContainerExtension(Object extension) {
+ containerExtensions.add(extension);
+ }
+
+ /**
+ * @since 2.8
+ */
+ public List<Object> getContainerExtensions() {
+ return containerExtensions;
+ }
+
+ /**
+ * @since 2.8
+ */
+ public void addModule(ProjectDefinition projectDefinition) {
+ modules.add(projectDefinition);
+ }
+
+ /**
+ * @since 2.8
+ */
+ public List<ProjectDefinition> getModules() {
+ return modules;
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/phases/MavenPluginsConfigurator.java b/sonar-batch/src/main/java/org/sonar/batch/phases/MavenPluginsConfigurator.java
index 49560b6126e..ab6c9915123 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/phases/MavenPluginsConfigurator.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/phases/MavenPluginsConfigurator.java
@@ -60,16 +60,18 @@ public class MavenPluginsConfigurator implements BatchComponent {
protected void savePom(Project project) {
MavenProject pom = project.getPom();
- File targetPom = new File(project.getFileSystem().getSonarWorkingDirectory(), "sonar-pom.xml");
- FileWriter fileWriter = null;
- try {
- fileWriter = new FileWriter(targetPom, false);
- pom.writeModel(fileWriter);
+ if (pom != null) {
+ File targetPom = new File(project.getFileSystem().getSonarWorkingDirectory(), "sonar-pom.xml");
+ FileWriter fileWriter = null;
+ try {
+ fileWriter = new FileWriter(targetPom, false);
+ pom.writeModel(fileWriter);
- } catch (IOException e) {
- throw new SonarException("Can not save pom to " + targetPom, e);
- } finally {
- IOUtils.closeQuietly(fileWriter);
+ } catch (IOException e) {
+ throw new SonarException("Can not save pom to " + targetPom, e);
+ } finally {
+ IOUtils.closeQuietly(fileWriter);
+ }
}
}
}