aboutsummaryrefslogtreecommitdiffstats
path: root/sonar-plugin-api/src
diff options
context:
space:
mode:
authorsimonbrandhof <simon.brandhof@gmail.com>2011-05-27 12:25:05 +0200
committersimonbrandhof <simon.brandhof@gmail.com>2011-05-27 12:25:16 +0200
commit5e5916cd83e20df7331bb3534e82f3845951b160 (patch)
treeecd59c3f473109fd75050ace9d78dd924cdaab75 /sonar-plugin-api/src
parentc073a325c80ef5d4c0d805b2545dd6be40b1892e (diff)
downloadsonarqube-5e5916cd83e20df7331bb3534e82f3845951b160.tar.gz
sonarqube-5e5916cd83e20df7331bb3534e82f3845951b160.zip
SONAR-2468 new extension point org.sonar.api.bootstrap.ProjectBuilder
Diffstat (limited to 'sonar-plugin-api/src')
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBuilder.java43
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java245
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectReactor.java59
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectBuilderTest.java52
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectDefinitionTest.java111
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectReactorTest.java51
6 files changed, 561 insertions, 0 deletions
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBuilder.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBuilder.java
new file mode 100644
index 00000000000..bdd90512ede
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBuilder.java
@@ -0,0 +1,43 @@
+/*
+ * 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.api.batch.bootstrap;
+
+import org.sonar.api.BatchExtension;
+import org.sonar.api.batch.InstantiationStrategy;
+
+/**
+ *
+ * @since 2.9
+ */
+@InstantiationStrategy(InstantiationStrategy.PER_BATCH)
+public abstract class ProjectBuilder implements BatchExtension {
+
+ private ProjectReactor reactor;
+
+ protected ProjectBuilder(final ProjectReactor reactor) {
+ this.reactor = reactor;
+ }
+
+ public final void start() {
+ build(reactor);
+ }
+
+ protected abstract void build(ProjectReactor reactor);
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java
new file mode 100644
index 00000000000..195b886fcbc
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectDefinition.java
@@ -0,0 +1,245 @@
+/*
+ * 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.api.batch.bootstrap;
+
+import com.google.common.collect.Lists;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.CoreProperties;
+
+import java.io.File;
+import java.util.Arrays;
+import java.util.List;
+import java.util.Properties;
+
+/**
+ * @since 2.9
+ */
+public final class ProjectDefinition implements BatchComponent {
+
+ public static final String SOURCES_PROPERTY = "sonar.sources";
+ public static final String TESTS_PROPERTY = "sonar.tests";
+ public static final String BINARIES_PROPERTY = "sonar.binaries";
+ public static final String LIBRARIES_PROPERTY = "sonar.libraries";
+
+ private static final char SEPARATOR = ',';
+
+ private File baseDir;
+ private File workDir;
+ private Properties properties;
+ private ProjectDefinition parent = null;
+ private List<ProjectDefinition> subProjects = Lists.newArrayList();
+ private List<Object> containerExtensions = Lists.newArrayList();
+
+ /**
+ * TODO use factory methods
+ */
+ public ProjectDefinition(File baseDir, File workDir, Properties properties) {
+ this.baseDir = baseDir;
+ this.workDir = workDir;
+ this.properties = properties;
+ }
+
+ private ProjectDefinition() {
+ }
+
+ public static ProjectDefinition create() {
+ return new ProjectDefinition();
+ }
+
+ public File getBaseDir() {
+ return baseDir;
+ }
+
+ public ProjectDefinition setBaseDir(File baseDir) {
+ this.baseDir = baseDir;
+ return this;
+ }
+
+ public ProjectDefinition setWorkDir(File workDir) {
+ this.workDir = workDir;
+ return this;
+ }
+
+ public File getWorkDir() {
+ return workDir;
+ }
+
+ public Properties getProperties() {
+ return properties;
+ }
+
+ public ProjectDefinition setKey(String key) {
+ properties.setProperty(CoreProperties.PROJECT_KEY_PROPERTY, key);
+ return this;
+ }
+
+ public ProjectDefinition setVersion(String s) {
+ properties.setProperty(CoreProperties.PROJECT_VERSION_PROPERTY, StringUtils.defaultString(s));
+ return this;
+ }
+
+ public ProjectDefinition setName(String s) {
+ properties.setProperty(CoreProperties.PROJECT_NAME_PROPERTY, StringUtils.defaultString(s));
+ return this;
+ }
+
+ public ProjectDefinition setDescription(String s) {
+ properties.setProperty(CoreProperties.PROJECT_DESCRIPTION_PROPERTY, StringUtils.defaultString(s));
+ return this;
+ }
+
+ public String getKey() {
+ return properties.getProperty(CoreProperties.PROJECT_KEY_PROPERTY);
+ }
+
+ public String getVersion() {
+ return properties.getProperty(CoreProperties.PROJECT_VERSION_PROPERTY);
+ }
+
+ public String getName() {
+ String name = properties.getProperty(CoreProperties.PROJECT_NAME_PROPERTY);
+ if (StringUtils.isBlank(name)) {
+ name = "Unnamed - " + getKey();
+ }
+ return name;
+ }
+
+ public String getDescription() {
+ return properties.getProperty(CoreProperties.PROJECT_DESCRIPTION_PROPERTY);
+ }
+
+ private void appendProperty(String key, String value) {
+ String newValue = properties.getProperty(key, "") + SEPARATOR + value;
+ properties.put(key, newValue);
+ }
+
+ public List<String> getSourceDirs() {
+ String sources = properties.getProperty(SOURCES_PROPERTY, "");
+ return Arrays.asList(StringUtils.split(sources, SEPARATOR));
+ }
+
+ /**
+ * @param path path to directory with main sources.
+ * It can be absolute or relative to project directory.
+ */
+ public ProjectDefinition addSourceDir(String path) {
+ appendProperty(SOURCES_PROPERTY, path);
+ return this;
+ }
+
+ public ProjectDefinition addSourceDir(File path) {
+ addSourceDir(path.getAbsolutePath());
+ return this;
+ }
+
+ public ProjectDefinition setSourceDir(String path) {
+ properties.setProperty(SOURCES_PROPERTY, path);
+ return this;
+ }
+
+ public ProjectDefinition setSourceDir(File path) {
+ setSourceDir(path.getAbsolutePath());
+ return this;
+ }
+
+ public List<String> getTestDirs() {
+ String sources = properties.getProperty(TESTS_PROPERTY, "");
+ return Arrays.asList(StringUtils.split(sources, SEPARATOR));
+ }
+
+ /**
+ * @param path path to directory with test sources.
+ * It can be absolute or relative to project directory.
+ */
+ public ProjectDefinition addTestDir(String path) {
+ appendProperty(TESTS_PROPERTY, path);
+ return this;
+ }
+
+ public List<String> getBinaries() {
+ String sources = properties.getProperty(BINARIES_PROPERTY, "");
+ return Arrays.asList(StringUtils.split(sources, SEPARATOR));
+ }
+
+ /**
+ * @param path path to directory with compiled source. In case of Java this is directory with class files.
+ * It can be absolute or relative to project directory.
+ * @TODO currently Sonar supports only one such directory due to dependency on MavenProject
+ */
+ public ProjectDefinition addBinaryDir(String path) {
+ appendProperty(BINARIES_PROPERTY, path);
+ return this;
+ }
+
+ public List<String> getLibraries() {
+ String sources = properties.getProperty(LIBRARIES_PROPERTY, "");
+ return Arrays.asList(StringUtils.split(sources, SEPARATOR));
+ }
+
+ /**
+ * @param path path to file with third-party library. In case of Java this is path to jar file.
+ * It can be absolute or relative to project directory.
+ */
+ public void addLibrary(String path) {
+ appendProperty(LIBRARIES_PROPERTY, path);
+ }
+
+ /**
+ * Adds an extension, which would be available in PicoContainer during analysis of this project.
+ *
+ * @since 2.8
+ */
+ public ProjectDefinition addContainerExtension(Object extension) {
+ containerExtensions.add(extension);
+ return this;
+ }
+
+ /**
+ * @since 2.8
+ */
+ public List<Object> getContainerExtensions() {
+ return containerExtensions;
+ }
+
+ /**
+ * @since 2.8
+ */
+ public ProjectDefinition addSubProject(ProjectDefinition child) {
+ subProjects.add(child);
+ child.setParent(this);
+ return this;
+ }
+
+ public ProjectDefinition getParent() {
+ return parent;
+ }
+
+ private void setParent(ProjectDefinition parent) {
+ this.parent = parent;
+ }
+
+ /**
+ * @since 2.8
+ */
+ public List<ProjectDefinition> getSubProjects() {
+ return subProjects;
+ }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectReactor.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectReactor.java
new file mode 100644
index 00000000000..4cbe4c0a3f7
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectReactor.java
@@ -0,0 +1,59 @@
+/*
+ * 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.api.batch.bootstrap;
+
+import org.sonar.api.BatchComponent;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * @since 2.9
+ */
+public final class ProjectReactor implements BatchComponent {
+
+ private ProjectDefinition root;
+
+ public ProjectReactor(ProjectDefinition root) {
+ if (root.getParent()!=null) {
+ throw new IllegalArgumentException("Not a root project: " + root);
+ }
+ this.root = root;
+ }
+
+ public List<ProjectDefinition> getProjects() {
+ return collectProjects(root, new ArrayList<ProjectDefinition>());
+ }
+
+ /**
+ * Populates list of projects from hierarchy.
+ */
+ private static List<ProjectDefinition> collectProjects(ProjectDefinition def, List<ProjectDefinition> collected) {
+ collected.add(def);
+ for (ProjectDefinition child : def.getSubProjects()) {
+ collectProjects(child, collected);
+ }
+ return collected;
+ }
+
+ public ProjectDefinition getRoot() {
+ return root;
+ }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectBuilderTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectBuilderTest.java
new file mode 100644
index 00000000000..a4f6811cde3
--- /dev/null
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectBuilderTest.java
@@ -0,0 +1,52 @@
+/*
+ * 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.api.batch.bootstrap;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Properties;
+
+import static org.hamcrest.core.Is.is;
+import static org.junit.Assert.assertThat;
+
+public class ProjectBuilderTest {
+
+ @Test
+ public void shouldBuild() {
+ FakeProjectBuilder builder = new FakeProjectBuilder(new ProjectReactor(new ProjectDefinition(new File("."), new File("."), new Properties())));
+ builder.start();
+
+ assertThat(builder.built, is(true));
+ }
+
+ private static class FakeProjectBuilder extends ProjectBuilder {
+ private boolean built=false;
+
+ FakeProjectBuilder(final ProjectReactor reactor) {
+ super(reactor);
+ }
+
+ @Override
+ protected void build(ProjectReactor reactor) {
+ built=true;
+ }
+ }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectDefinitionTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectDefinitionTest.java
new file mode 100644
index 00000000000..49f1e1c916a
--- /dev/null
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectDefinitionTest.java
@@ -0,0 +1,111 @@
+/*
+ * 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.api.batch.bootstrap;
+
+import org.junit.Test;
+import org.sonar.api.CoreProperties;
+
+import java.io.File;
+import java.util.List;
+import java.util.Properties;
+
+import static org.hamcrest.CoreMatchers.nullValue;
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ProjectDefinitionTest {
+
+ @Test
+ public void shouldSetKey() {
+ ProjectDefinition def = new ProjectDefinition(new File("."), new File("."), new Properties());
+ def.setKey("mykey");
+ assertThat(def.getKey(), is("mykey"));
+ }
+
+ @Test
+ public void shouldSetOptionalFields() {
+ ProjectDefinition def = new ProjectDefinition(new File("."), new File("."), new Properties());
+ def.setName("myname");
+ def.setDescription("desc");
+ assertThat(def.getName(), is("myname"));
+ assertThat(def.getDescription(), is("desc"));
+ }
+
+ @Test
+ public void shouldSupportDefaultName() {
+ ProjectDefinition def = new ProjectDefinition(new File("."), new File("."), new Properties());
+ def.setKey("myKey");
+ assertThat(def.getName(), is("Unnamed - myKey"));
+ }
+ @Test
+ public void shouldGetKeyFromProperties() {
+ Properties props = new Properties();
+ props.setProperty(CoreProperties.PROJECT_KEY_PROPERTY, "foo");
+ ProjectDefinition def = new ProjectDefinition(new File("."), new File("."), props);
+ assertThat(def.getKey(), is("foo"));
+ }
+
+ @Test
+ public void testDefaultValues() {
+ ProjectDefinition def = new ProjectDefinition(new File("."), new File("."), new Properties());
+ assertThat(def.getSourceDirs().size(), is(0));
+ assertThat(def.getTestDirs().size(), is(0));
+ assertThat(def.getBinaries().size(), is(0));
+ assertThat(def.getLibraries().size(), is(0));
+ }
+
+ @Test
+ public void shouldAddDirectories() {
+ ProjectDefinition def = new ProjectDefinition(new File("."), new File("."), new Properties());
+ def.addSourceDir("src/main/java");
+ def.addSourceDir("src/main/java2");
+ def.addTestDir("src/test/java");
+ def.addTestDir("src/test/java2");
+ def.addBinaryDir("target/classes");
+ def.addBinaryDir("target/classes2");
+ def.addLibrary("junit.jar");
+ def.addLibrary("mockito.jar");
+
+ assertDirs(def.getSourceDirs(), "src/main/java", "src/main/java2");
+ assertDirs(def.getTestDirs(), "src/test/java", "src/test/java2");
+ assertDirs(def.getBinaries(), "target/classes", "target/classes2");
+ assertDirs(def.getLibraries(), "junit.jar", "mockito.jar");
+ }
+
+ @Test
+ public void shouldManageRelationships() {
+ ProjectDefinition root = new ProjectDefinition(new File("."), new File("."), new Properties());
+ ProjectDefinition child = new ProjectDefinition(new File("."), new File("."), new Properties());
+ root.addSubProject(child);
+
+ assertThat(root.getSubProjects().size(), is(1));
+ assertThat(child.getSubProjects().size(), is(0));
+
+ assertThat(root.getParent(), nullValue());
+ assertThat(child.getParent(), is(root));
+ }
+
+ private static void assertDirs(List<String> dirs, String... values) {
+ assertThat(dirs.size(), is(values.length));
+ for (int i = 0; i < values.length; i++) {
+ assertThat(dirs.get(i), is(values[i]));
+ }
+ }
+}
diff --git a/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectReactorTest.java b/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectReactorTest.java
new file mode 100644
index 00000000000..4385cb1455a
--- /dev/null
+++ b/sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectReactorTest.java
@@ -0,0 +1,51 @@
+/*
+ * 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.api.batch.bootstrap;
+
+import org.junit.Test;
+
+import java.io.File;
+import java.util.Properties;
+
+import static org.hamcrest.Matchers.is;
+import static org.junit.Assert.assertThat;
+
+public class ProjectReactorTest {
+
+ @Test
+ public void shouldSupportMultipleProjects() {
+ ProjectDefinition root = new ProjectDefinition(new File("."), new File("."), new Properties());
+ ProjectDefinition child = new ProjectDefinition(new File("."), new File("."), new Properties());
+ root.addSubProject(child);
+
+ ProjectReactor reactor = new ProjectReactor(root);
+ assertThat(reactor.getProjects().size(), is(2));
+ assertThat(reactor.getRoot(), is(root));
+ }
+
+ @Test(expected = IllegalArgumentException.class)
+ public void shouldFailIfNotRoot() {
+ ProjectDefinition root = new ProjectDefinition(new File("."), new File("."), new Properties());
+ ProjectDefinition child = new ProjectDefinition(new File("."), new File("."), new Properties());
+ root.addSubProject(child);
+
+ new ProjectReactor(child);
+ }
+}