summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2013-07-03 14:24:11 +0200
committerSimon Brandhof <simon.brandhof@gmail.com>2013-07-03 14:24:19 +0200
commit390c80165538f0562ee3c909211c7e72b9966a20 (patch)
treeb57b1574bec494d8dd1b745eb2e0515ee108fc13
parentdbbbf4bf4547218196332b6d6b55bba245108a3f (diff)
downloadsonarqube-390c80165538f0562ee3c909211c7e72b9966a20.tar.gz
sonarqube-390c80165538f0562ee3c909211c7e72b9966a20.zip
SONAR-4433 refactor the extension point ProjectBootstrapper
-rw-r--r--plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/DefaultMavenPluginExecutor.java (renamed from plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/RealMavenPluginExecutor.java)4
-rw-r--r--plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenBatchPlugin.java2
-rw-r--r--plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectBootstrapper.java10
-rw-r--r--plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectConverter.java4
-rw-r--r--plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/DefaultMavenPluginExecutorTest.java (renamed from plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/RealMavenPluginExecutorTest.java)10
-rw-r--r--plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/MavenProjectBootstrapperTest.java71
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/DefaultProjectBootstrapper.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorReady.java10
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/DefaultProjectBootstrapperTest.java10
-rw-r--r--sonar-maven-plugin/src/main/java/org/sonar/maven/SonarMojo.java10
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBootstrapper.java16
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBuilder.java15
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/internal/ProjectBuilderContext.java44
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/internal/package-info.java23
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/package-info.java (renamed from sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBuilderContext.java)17
-rw-r--r--sonar-plugin-api/src/test/java/org/sonar/api/batch/bootstrap/ProjectBuilderTest.java9
16 files changed, 182 insertions, 75 deletions
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/DefaultMavenPluginExecutor.java
index 58a4440b9d8..a47dfc8f1fa 100644
--- 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/DefaultMavenPluginExecutor.java
@@ -38,12 +38,12 @@ import java.lang.reflect.Method;
import java.util.Arrays;
@SupportedEnvironment("maven")
-public class RealMavenPluginExecutor implements MavenPluginExecutor {
+public class DefaultMavenPluginExecutor implements MavenPluginExecutor {
private LifecycleExecutor lifecycleExecutor;
private MavenSession mavenSession;
- public RealMavenPluginExecutor(LifecycleExecutor le, MavenSession mavenSession) {
+ public DefaultMavenPluginExecutor(LifecycleExecutor le, MavenSession mavenSession) {
this.lifecycleExecutor = le;
this.mavenSession = mavenSession;
}
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 a86881c6036..af40190c032 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,6 +27,6 @@ import java.util.List;
public final class MavenBatchPlugin extends SonarPlugin {
public List getExtensions() {
- return ImmutableList.of(MavenProjectBootstrapper.class, RealMavenPluginExecutor.class, MavenProjectConverter.class);
+ return ImmutableList.of(MavenProjectBootstrapper.class, DefaultMavenPluginExecutor.class, MavenProjectConverter.class);
}
}
diff --git a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectBootstrapper.java b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectBootstrapper.java
index eb1c4f69ea8..2005eb8ca2d 100644
--- a/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectBootstrapper.java
+++ b/plugins/sonar-maven-batch-plugin/src/main/java/org/sonar/plugins/maven/MavenProjectBootstrapper.java
@@ -28,7 +28,7 @@ import org.sonar.api.batch.bootstrap.ProjectReactor;
import java.util.List;
@SupportedEnvironment("maven")
-public class MavenProjectBootstrapper extends ProjectBootstrapper {
+public class MavenProjectBootstrapper implements ProjectBootstrapper {
private MavenSession session;
private MavenProjectConverter mavenProjectConverter;
@@ -49,12 +49,10 @@ public class MavenProjectBootstrapper extends ProjectBootstrapper {
break;
}
}
- if (topLevelProject != null && sortedProjects != null) {
- return new ProjectReactor(mavenProjectConverter.configure(sortedProjects, topLevelProject));
- }
- else {
- throw new IllegalStateException("Maven session is not in a good state. No top level project or empty reactor.");
+ if (topLevelProject == null) {
+ throw new IllegalStateException("Maven session does not declare a top level project");
}
+ return new ProjectReactor(mavenProjectConverter.configure(sortedProjects, topLevelProject));
}
}
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
index bc605474136..e950325095e 100644
--- 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
@@ -228,8 +228,8 @@ public class MavenProjectConverter implements TaskExtension {
into.resetDirs(
pom.getBasedir(),
getBuildDir(pom),
- resolvePaths((List<String>) pom.getCompileSourceRoots(), pom.getBasedir()),
- resolvePaths((List<String>) pom.getTestCompileSourceRoots(), pom.getBasedir()),
+ resolvePaths(pom.getCompileSourceRoots(), pom.getBasedir()),
+ resolvePaths(pom.getTestCompileSourceRoots(), pom.getBasedir()),
Arrays.asList(resolvePath(pom.getBuild().getOutputDirectory(), pom.getBasedir())));
}
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/DefaultMavenPluginExecutorTest.java
index 74a9de56f00..f13c846f188 100644
--- 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/DefaultMavenPluginExecutorTest.java
@@ -37,16 +37,16 @@ import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.never;
import static org.mockito.Mockito.verify;
-public class RealMavenPluginExecutorTest {
+public class DefaultMavenPluginExecutorTest {
@Test
public void plugin_version_should_be_optional() {
- assertThat(RealMavenPluginExecutor.getGoal("group", "artifact", null, "goal"), is("group:artifact::goal"));
+ assertThat(DefaultMavenPluginExecutor.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"));
+ assertThat(DefaultMavenPluginExecutor.getGoal("group", "artifact", "3.54", "goal"), is("group:artifact:3.54:goal"));
}
/**
@@ -55,7 +55,7 @@ public class RealMavenPluginExecutorTest {
*/
@Test
public void should_reset_file_system_after_execution() {
- RealMavenPluginExecutor executor = new RealMavenPluginExecutor(null, null) {
+ DefaultMavenPluginExecutor executor = new DefaultMavenPluginExecutor(null, null) {
@Override
public void concreteExecute(MavenProject pom, String goal) {
pom.addCompileSourceRoot("src/java");
@@ -74,7 +74,7 @@ public class RealMavenPluginExecutorTest {
@Test
public void should_ignore_non_maven_projects() {
- RealMavenPluginExecutor executor = new RealMavenPluginExecutor(null, null) {
+ DefaultMavenPluginExecutor executor = new DefaultMavenPluginExecutor(null, null) {
@Override
public void concreteExecute(MavenProject pom, String goal) {
pom.addCompileSourceRoot("src/java");
diff --git a/plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/MavenProjectBootstrapperTest.java b/plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/MavenProjectBootstrapperTest.java
new file mode 100644
index 00000000000..f5e894113b7
--- /dev/null
+++ b/plugins/sonar-maven-batch-plugin/src/test/java/org/sonar/plugins/maven/MavenProjectBootstrapperTest.java
@@ -0,0 +1,71 @@
+/*
+ * 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.project.MavenProject;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
+
+import java.util.Arrays;
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class MavenProjectBootstrapperTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ @Test
+ public void bootstrap() throws Exception {
+ ProjectDefinition def = mock(ProjectDefinition.class);
+ MavenSession session = mock(MavenSession.class);
+ MavenProject rootProject = new MavenProject();
+ rootProject.setExecutionRoot(true);
+ List<MavenProject> projects = Arrays.asList(rootProject);
+ when(session.getSortedProjects()).thenReturn(projects);
+
+ MavenProjectConverter pomConverter = mock(MavenProjectConverter.class);
+ when(pomConverter.configure(projects, rootProject)).thenReturn(def);
+ MavenProjectBootstrapper bootstrapper = new MavenProjectBootstrapper(session, pomConverter);
+
+ ProjectReactor reactor = bootstrapper.bootstrap();
+
+ assertThat(reactor).isNotNull();
+ verify(pomConverter).configure(projects, rootProject);
+ }
+
+ @Test
+ public void should_fail_if_no_top_level_project() throws Exception {
+ thrown.expect(IllegalStateException.class);
+ thrown.expectMessage("Maven session does not declare a top level project");
+
+ MavenSession session = mock(MavenSession.class);
+ MavenProjectConverter pomConverter = new MavenProjectConverter();
+ MavenProjectBootstrapper bootstrapper = new MavenProjectBootstrapper(session, pomConverter);
+
+ bootstrapper.bootstrap();
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/DefaultProjectBootstrapper.java b/sonar-batch/src/main/java/org/sonar/batch/scan/DefaultProjectBootstrapper.java
index c70fc4fff31..e8f1a6b5fc4 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/DefaultProjectBootstrapper.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/DefaultProjectBootstrapper.java
@@ -49,7 +49,7 @@ import java.util.Properties;
/**
* Class that creates a Sonar project definition based on a set of properties.
*/
-class DefaultProjectBootstrapper extends ProjectBootstrapper {
+class DefaultProjectBootstrapper implements ProjectBootstrapper {
private static final Logger LOG = LoggerFactory.getLogger(DefaultProjectBootstrapper.class);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorReady.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorReady.java
index 2302c5757b2..7ac565a9661 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorReady.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorReady.java
@@ -20,7 +20,7 @@
package org.sonar.batch.scan;
import org.sonar.api.batch.bootstrap.ProjectBuilder;
-import org.sonar.api.batch.bootstrap.ProjectBuilderContext;
+import org.sonar.api.batch.bootstrap.internal.ProjectBuilderContext;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.config.Settings;
@@ -57,13 +57,7 @@ public class ProjectReactorReady {
public void start() {
// 1 Apply project builders
- ProjectBuilderContext context = new ProjectBuilderContext() {
-
- @Override
- public ProjectReactor getProjectReactor() {
- return reactor;
- }
- };
+ ProjectBuilderContext context = new ProjectBuilderContext(reactor);
for (ProjectBuilder projectBuilder : projectBuilders) {
projectBuilder.build(context);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/DefaultProjectBootstrapperTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/DefaultProjectBootstrapperTest.java
index 1c6d868c3db..45681f502db 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/DefaultProjectBootstrapperTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/DefaultProjectBootstrapperTest.java
@@ -642,16 +642,6 @@ public class DefaultProjectBootstrapperTest {
assertThat(DefaultProjectBootstrapper.getListFromProperty(props, "prop")).containsOnly("foo", "bar", "toto", "tutu");
}
- //
- // @Test
- // public void test_props() {
- // Properties p1 = new Properties();
- // p1.setProperty("foo", "bar");
- // Properties p2 = new Properties();
- // p2.putAll(p1);
- // assertThat(p2.getProperty("foo")).isEqualTo("bar");
- // }
-
@Test
public void shouldGetListFromFile() throws IOException {
String filePath = "shouldGetList/foo.properties";
diff --git a/sonar-maven-plugin/src/main/java/org/sonar/maven/SonarMojo.java b/sonar-maven-plugin/src/main/java/org/sonar/maven/SonarMojo.java
index 0bb664d9ffc..dc1c764a51e 100644
--- a/sonar-maven-plugin/src/main/java/org/sonar/maven/SonarMojo.java
+++ b/sonar-maven-plugin/src/main/java/org/sonar/maven/SonarMojo.java
@@ -154,11 +154,11 @@ public final class SonarMojo extends AbstractMojo {
// .unmask("org.slf4j.impl.")
.mask("org.slf4j.")
// Exclude logback
- .mask("ch.qos.logback.");
- runner.mask("org.sonar.");
- // Include everything else
- runner.unmask("")
- .addExtensions(session, getLog(), lifecycleExecutor, artifactFactory, localRepository, artifactMetadataSource, artifactCollector,
+ .mask("ch.qos.logback.")
+ .mask("org.sonar.")
+ // Include everything else
+ .unmask("");
+ runner.addExtensions(session, getLog(), lifecycleExecutor, artifactFactory, localRepository, artifactMetadataSource, artifactCollector,
dependencyTreeBuilder, projectBuilder);
if (getLog().isDebugEnabled()) {
runner.setProperty("sonar.verbose", "true");
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBootstrapper.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBootstrapper.java
index bc90921ebdb..d1671d73306 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBootstrapper.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBootstrapper.java
@@ -22,24 +22,22 @@ package org.sonar.api.batch.bootstrap;
import org.sonar.api.task.TaskExtension;
/**
- * This extension point allows to define project structure at runtime. It is executed once during task startup.
+ * This extension point initializes the project structure. It is extended by batch bootstrappers
+ * like sonar-runner or Maven plugin. It is not supposed to be used by standard plugins (.NET, ...).
* Some use-cases :
* <ul>
- * <li>Maven bootstraper create project structure from pom.xml</li>
- * <li>Sonar Runner bootstraper create project structure from sonar-runner.properties</li>
+ * <li>Maven Plugins defines project structure from pom.xml</li>
+ * <li>Sonar Runner defines project from sonar-runner.properties</li>
* </ul>
- * Only one ProjectBootstrapper is allowed per environement.
+ * Only one instance is allowed per environment.
*
* @since 3.7
*/
-public abstract class ProjectBootstrapper implements TaskExtension {
-
- protected ProjectBootstrapper() {
- }
+public interface ProjectBootstrapper extends TaskExtension {
/**
* Implement this method to create project reactor
*/
- public abstract ProjectReactor bootstrap();
+ ProjectReactor bootstrap();
}
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
index c5fe2aee67a..8ec2fd55ce7 100644
--- 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
@@ -26,7 +26,7 @@ import org.sonar.api.batch.InstantiationStrategy;
* This extension point allows to change project structure at runtime. It is executed once during task startup.
* Some use-cases :
* <ul>
- * <li>Add sub-projects which are not defined in batch bootstrapper. For example the C# plugin gets the hierarchy
+ * <li>Add sub-projects. For example the C# plugin gets the hierarchy
* of sub-projects from the Visual Studio metadata file. The single root pom.xml does not contain any declarations of
* modules</li>
* <li>Change project metadata like description or source directories.</li>
@@ -38,6 +38,13 @@ import org.sonar.api.batch.InstantiationStrategy;
public abstract class ProjectBuilder implements BatchExtension {
/**
+ * Plugins can use the implementation {@link org.sonar.api.batch.bootstrap.internal.ProjectBuilderContext}
+ * for their unit tests.
+ */
+ public static interface Context {
+ ProjectReactor projectReactor();
+ }
+ /**
* Don't inject ProjectReactor as it may not be available
* @deprecated since 3.7 use {@link #ProjectBuilder()}
*/
@@ -55,13 +62,13 @@ public abstract class ProjectBuilder implements BatchExtension {
* Override this method to change project reactor structure.
* @since 3.7
*/
- public void build(ProjectBuilderContext context) {
+ public void build(Context context) {
// Call deprecated method for backward compatibility
- build(context.getProjectReactor());
+ build(context.projectReactor());
}
/**
- * @deprecated since 3.7 override {@link #build(ProjectBuilderContext)} instead
+ * @deprecated since 3.7 override {@link #build(Context)} instead
*/
@Deprecated
protected void build(ProjectReactor reactor) {
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/internal/ProjectBuilderContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/internal/ProjectBuilderContext.java
new file mode 100644
index 00000000000..7f663057d38
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/internal/ProjectBuilderContext.java
@@ -0,0 +1,44 @@
+/*
+ * 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.api.batch.bootstrap.internal;
+
+
+import org.sonar.api.batch.bootstrap.ProjectBuilder;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
+
+/**
+ * Context that is passed to {@link org.sonar.api.batch.bootstrap.ProjectBuilder} as parameter.
+ * Important - plugins must use this class only for unit test needs.
+ *
+ * @since 3.7
+ */
+public class ProjectBuilderContext implements ProjectBuilder.Context {
+
+ private final ProjectReactor reactor;
+
+ public ProjectBuilderContext(ProjectReactor reactor) {
+ this.reactor = reactor;
+ }
+
+ public ProjectReactor projectReactor() {
+ return reactor;
+ }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/internal/package-info.java
new file mode 100644
index 00000000000..e238dd1a745
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/internal/package-info.java
@@ -0,0 +1,23 @@
+/*
+ * 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.
+ */
+@ParametersAreNonnullByDefault
+package org.sonar.api.batch.bootstrap.internal;
+
+import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBuilderContext.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/package-info.java
index 82a2b199847..989acc29cc2 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/ProjectBuilderContext.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/bootstrap/package-info.java
@@ -17,20 +17,7 @@
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/
+@ParametersAreNonnullByDefault
package org.sonar.api.batch.bootstrap;
-
-/**
- * Context that is passed to {@link ProjectBuilder} as parameter
- *
- * @since 3.7
- */
-public interface ProjectBuilderContext {
-
- /**
- * Get the current project reactor. It is allowed to modify project reactor inside the
- * {@link ProjectBuilder#build(ProjectReactor)} method.
- */
- ProjectReactor getProjectReactor();
-
-}
+import javax.annotation.ParametersAreNonnullByDefault; \ No newline at end of file
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
index 14b57bb10ac..fc5f65616aa 100644
--- 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
@@ -20,6 +20,7 @@
package org.sonar.api.batch.bootstrap;
import org.junit.Test;
+import org.sonar.api.batch.bootstrap.internal.ProjectBuilderContext;
import org.sonar.api.config.Settings;
import java.io.File;
@@ -36,13 +37,7 @@ public class ProjectBuilderTest {
final ProjectReactor projectReactor = new ProjectReactor(ProjectDefinition.create());
ProjectBuilder builder = new ProjectBuilderSample(new Settings());
- builder.build(new ProjectBuilderContext() {
-
- @Override
- public ProjectReactor getProjectReactor() {
- return projectReactor;
- }
- });
+ builder.build(new ProjectBuilderContext(projectReactor));
assertThat(projectReactor.getProjects().size(), is(2));
ProjectDefinition root = projectReactor.getRoot();