aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorDuarte Meneses <duarte.meneses@sonarsource.com>2015-09-08 15:24:50 +0200
committerDuarte Meneses <duarte.meneses@sonarsource.com>2015-09-09 11:57:38 +0200
commit4be016e61f4d1e4fed297dd7eb3b3ccb286f0f81 (patch)
tree7ce08a4beef4bf70b6521bdd04e27cc9e2907e92
parent84c39f50d53f7f4a76fcda6c58b6120875501e40 (diff)
downloadsonarqube-4be016e61f4d1e4fed297dd7eb3b3ccb286f0f81.tar.gz
sonarqube-4be016e61f4d1e4fed297dd7eb3b3ccb286f0f81.zip
SONAR-6817 Issues mode should support analysis of projects not associated
-rw-r--r--it/it-projects/shared/xoo-sample-non-associated/sonar-project.properties5
-rw-r--r--it/it-projects/shared/xoo-sample-non-associated/src/main/xoo/sample/Sample.xoo16
-rw-r--r--it/it-projects/shared/xoo-sample-non-associated/src/main/xoo/sample/Sample.xoo.measures11
-rw-r--r--it/it-tests/src/test/java/batch/IssuesModeTest.java43
-rw-r--r--sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/ProjectRepositories.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java14
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java16
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java22
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java6
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cache/DefaultProjectCacheStatus.java16
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizer.java92
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cache/PersistentCacheProvider.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheStatus.java8
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheSynchronizer.java147
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cache/ProjectSyncContainer.java62
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java21
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java5
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesFactory.java (renamed from sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesProvider.java)46
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectSettingsLoader.java56
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/DefaultQualityProfileLoader.java50
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesFactory.java28
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesFactoryProvider.java41
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesLoader.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsLoader.java28
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsProvider.java64
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsRepo.java66
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/QualityProfileLoader.java30
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/QualityProfileProvider.java48
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/repository/SyncProjectRepositoriesFactory.java74
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesLoader.java28
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java23
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/DefaultActiveRulesLoader.java43
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java5
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java1
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java14
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java1
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorBuilder.java21
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorValidator.java3
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java26
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java8
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java11
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java7
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java12
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/cache/DefaultProjectCacheStatusTest.java13
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizerTest.java91
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/cache/PersistentCacheProviderTest.java12
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/cache/ProjectCacheSynchronizerTest.java130
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/cache/ProjectSyncContainerTest.java26
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java14
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/BatchMediumTester.java67
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/cache/CacheSyncTest.java53
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/mediumtest/issuesmode/NonAssociatedProject.java90
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java18
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectSettingsLoaderTest.java77
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/repository/DefaultQualityProfileLoaderTest.java77
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/repository/QualityProfileProviderTest.java94
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/DefaultActiveRulesLoaderTest.java70
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java36
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorBuilderTest.java98
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorValidatorTest.java13
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java48
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionFactoryTest.java6
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java22
-rw-r--r--sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo16
-rw-r--r--sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_a/module_a2/src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo12
-rw-r--r--sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_b/module_b1/src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo12
-rw-r--r--sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_b/module_b2/src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo12
-rw-r--r--sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/sonar-project.properties31
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/cache/ProjectCacheSynchronizerTest/api_sources_hash_GitScmProvider.text49
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/cache/ProjectCacheSynchronizerTest/api_sources_hash_JGitBlameCommand.text149
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/scan/ProjectReactorBuilderTest/multi-module-with-basedir-not-associated/modules/module1/sources/Fake.java1
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/scan/ProjectReactorBuilderTest/multi-module-with-basedir-not-associated/sonar-project.properties14
-rw-r--r--sonar-home/src/main/java/org/sonar/home/cache/FileCache.java2
-rw-r--r--sonar-home/src/main/java/org/sonar/home/cache/FileHashes.java2
-rw-r--r--sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java67
77 files changed, 2076 insertions, 598 deletions
diff --git a/it/it-projects/shared/xoo-sample-non-associated/sonar-project.properties b/it/it-projects/shared/xoo-sample-non-associated/sonar-project.properties
new file mode 100644
index 00000000000..71b83e48b9f
--- /dev/null
+++ b/it/it-projects/shared/xoo-sample-non-associated/sonar-project.properties
@@ -0,0 +1,5 @@
+#sonar.projectKey=sample
+sonar.projectName=Sample
+sonar.projectVersion=1.0-SNAPSHOT
+sonar.sources=src/main/xoo
+sonar.language=xoo
diff --git a/it/it-projects/shared/xoo-sample-non-associated/src/main/xoo/sample/Sample.xoo b/it/it-projects/shared/xoo-sample-non-associated/src/main/xoo/sample/Sample.xoo
new file mode 100644
index 00000000000..41871e123a3
--- /dev/null
+++ b/it/it-projects/shared/xoo-sample-non-associated/src/main/xoo/sample/Sample.xoo
@@ -0,0 +1,16 @@
+package sample;
+
+public class Sample {
+
+ public Sample(int i) {
+ int j = i++;
+ }
+
+ private String myMethod() {
+ if (foo == bar) {
+ return "hello";
+ } else {
+ throw new IllegalStateException();
+ }
+ }
+}
diff --git a/it/it-projects/shared/xoo-sample-non-associated/src/main/xoo/sample/Sample.xoo.measures b/it/it-projects/shared/xoo-sample-non-associated/src/main/xoo/sample/Sample.xoo.measures
new file mode 100644
index 00000000000..3f73ea8f695
--- /dev/null
+++ b/it/it-projects/shared/xoo-sample-non-associated/src/main/xoo/sample/Sample.xoo.measures
@@ -0,0 +1,11 @@
+ncloc:13
+#Used by dashboard/widgets tests
+complexity:3
+complexity_in_classes:3
+classes:1
+comment_lines:3
+public_api:5
+public_undocumented_api:2
+duplicated_files:1
+duplicated_blocks:2
+duplicated_lines:3
diff --git a/it/it-tests/src/test/java/batch/IssuesModeTest.java b/it/it-tests/src/test/java/batch/IssuesModeTest.java
index 651546c0535..5e3c0660b66 100644
--- a/it/it-tests/src/test/java/batch/IssuesModeTest.java
+++ b/it/it-tests/src/test/java/batch/IssuesModeTest.java
@@ -69,28 +69,45 @@ public class IssuesModeTest {
}
@Test
- public void issuesAnalysisOnNewProject() throws IOException {
+ public void issues_analysis_on_new_project() throws IOException {
restoreProfile("one-issue-per-line.xml");
orchestrator.getServer().provisionProject("sample", "xoo-sample");
orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
SonarRunner runner = configureRunnerIssues("shared/xoo-sample");
- orchestrator.executeBuild(runner);
+ BuildResult result = orchestrator.executeBuild(runner);
+ assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);
}
-
+
@Test
- public void invalidIncrementalMode() throws IOException {
+ public void invalid_incremental_mode() throws IOException {
restoreProfile("one-issue-per-line.xml");
orchestrator.getServer().provisionProject("sample", "xoo-sample");
orchestrator.getServer().associateProjectToQualityProfile("sample", "xoo", "one-issue-per-line");
SonarRunner runner = configureRunner("shared/xoo-sample");
runner.setProperty("sonar.analysis.mode", "incremental");
-
+
thrown.expect(BuildFailureException.class);
BuildResult res = orchestrator.executeBuild(runner);
-
+
assertThat(res.getLogs()).contains("Invalid analysis mode: incremental. This mode was removed in SonarQube 5.2");
}
+ @Test
+ public void non_associated_mode() throws IOException {
+ restoreProfile("one-issue-per-line.xml");
+ setDefaultQualityProfile("xoo", "one-issue-per-line");
+ SonarRunner runner = configureRunnerIssues("shared/xoo-sample-non-associated");
+ BuildResult result = orchestrator.executeBuild(runner);
+
+ assertThat(result.getLogs()).contains("is not associated");
+ assertThat(result.getLogs()).contains("Cache not found, synchronizing data");
+ assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);
+
+ result = orchestrator.executeBuild(runner);
+ assertThat(ItUtils.countIssuesInJsonReport(result, true)).isEqualTo(17);
+ assertThat(result.getLogs()).contains("Found cache");
+ }
+
// SONAR-5715
@Test
public void test_issues_mode_on_project_with_space_in_filename() throws IOException {
@@ -329,16 +346,16 @@ public class IssuesModeTest {
boolean expectedError = false;
for (Future<BuildResult> result : executorService.invokeAll(tasks)) {
try {
- result.get();
- } catch(ExecutionException e) {
- if(e.getCause() instanceof BuildFailureException) {
+ result.get();
+ } catch (ExecutionException e) {
+ if (e.getCause() instanceof BuildFailureException) {
BuildFailureException bfe = (BuildFailureException) e.getCause();
assertThat(bfe.getResult().getLogs()).contains("Another SonarQube analysis is already in progress for this project");
expectedError = true;
}
}
}
- if(!expectedError) {
+ if (!expectedError) {
fail("At least one of the threads should have failed");
}
}
@@ -370,4 +387,10 @@ public class IssuesModeTest {
return runner;
}
+ private void setDefaultQualityProfile(String languageKey, String profileName) {
+ orchestrator.getServer().adminWsClient().post("api/qualityprofiles/set_default",
+ "language", languageKey,
+ "profileName", profileName);
+ }
+
}
diff --git a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/ProjectRepositories.java b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/ProjectRepositories.java
index 8e59ccd1be7..862a21152d8 100644
--- a/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/ProjectRepositories.java
+++ b/sonar-batch-protocol/src/main/java/org/sonar/batch/protocol/input/ProjectRepositories.java
@@ -45,6 +45,10 @@ public class ProjectRepositories {
public Map<String, String> settings(String moduleKey) {
return settingsByModule.containsKey(moduleKey) ? settingsByModule.get(moduleKey) : Collections.<String, String>emptyMap();
}
+
+ public Map<String, Map<String, String>> settings() {
+ return settingsByModule;
+ }
public ProjectRepositories addSettings(String moduleKey, Map<String, String> settings) {
Map<String, String> existingSettings = settingsByModule.get(moduleKey);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java b/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java
index c49b4f48327..a01928f3529 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/analysis/DefaultAnalysisMode.java
@@ -38,6 +38,7 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
private static final Logger LOG = LoggerFactory.getLogger(DefaultAnalysisMode.class);
private boolean mediumTestMode;
+ private boolean notAssociated;
public DefaultAnalysisMode(GlobalProperties globalProps, AnalysisProperties props) {
init(globalProps.properties(), props.properties());
@@ -47,6 +48,10 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
return mediumTestMode;
}
+ public boolean isNotAssociated() {
+ return notAssociated;
+ }
+
private void init(Map<String, String> globalProps, Map<String, String> analysisProps) {
// make sure analysis is consistent with global properties
boolean globalPreview = isIssues(globalProps);
@@ -64,6 +69,7 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
validate(mode);
issues = CoreProperties.ANALYSIS_MODE_ISSUES.equals(mode) || CoreProperties.ANALYSIS_MODE_PREVIEW.equals(mode);
mediumTestMode = "true".equals(getPropertyWithFallback(analysisProps, globalProps, FakePluginInstaller.MEDIUM_TEST_ENABLED));
+ notAssociated = issues && rootProjectKeyMissing(analysisProps);
}
public void printMode() {
@@ -77,6 +83,9 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
if (mediumTestMode) {
LOG.info("Medium test mode");
}
+ if (notAssociated) {
+ LOG.info("Project is not associated with the server");
+ }
}
private static String getPropertyWithFallback(Map<String, String> props1, Map<String, String> props2, String key) {
@@ -93,4 +102,9 @@ public class DefaultAnalysisMode extends AbstractAnalysisMode implements Analysi
return CoreProperties.ANALYSIS_MODE_ISSUES.equals(mode);
}
+ private static boolean rootProjectKeyMissing(Map<String, String> props) {
+ // ProjectReactorBuilder depends on this class, so it will only create this property later
+ return !props.containsKey(CoreProperties.PROJECT_KEY_PROPERTY);
+ }
+
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java
index 67e5843c8ee..5469343c55d 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/GlobalContainer.java
@@ -123,14 +123,22 @@ public class GlobalContainer extends ComponentContainer {
public void executeAnalysis(Map<String, String> analysisProperties, Object... components) {
AnalysisProperties props = new AnalysisProperties(analysisProperties, this.getComponentByType(GlobalProperties.class).property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
if (isIssuesMode(props)) {
- new ProjectSyncContainer(this, props, false).execute();
+ String projectKey = getProjectKeyWithBranch(props);
+ new ProjectSyncContainer(this, projectKey, false).execute();
}
new ProjectScanContainer(this, props, components).execute();
}
- public void syncProject(Map<String, String> analysisProperties, boolean force) {
- AnalysisProperties props = new AnalysisProperties(analysisProperties, this.getComponentByType(GlobalProperties.class).property(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
- new ProjectSyncContainer(this, props, force).execute();
+ private static String getProjectKeyWithBranch(AnalysisProperties props) {
+ String projectKey = props.property(CoreProperties.PROJECT_KEY_PROPERTY);
+ if (projectKey != null && props.property(CoreProperties.PROJECT_BRANCH_PROPERTY) != null) {
+ projectKey = projectKey + ":" + props.property(CoreProperties.PROJECT_BRANCH_PROPERTY);
+ }
+ return projectKey;
+ }
+
+ public void syncProject(String projectKey, boolean force) {
+ new ProjectSyncContainer(this, projectKey, force).execute();
}
private boolean isIssuesMode(AnalysisProperties props) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java
index 0faef082627..901e2d2cac2 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ServerClient.java
@@ -19,6 +19,9 @@
*/
package org.sonar.batch.bootstrap;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
import com.google.common.base.Joiner;
import com.google.common.base.Preconditions;
import com.google.common.base.Strings;
@@ -27,10 +30,13 @@ import com.google.gson.JsonElement;
import com.google.gson.JsonObject;
import com.google.gson.JsonParser;
+import java.io.BufferedReader;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
+import java.io.InputStreamReader;
import java.net.URI;
+import java.nio.charset.StandardCharsets;
import java.nio.file.Files;
import java.nio.file.StandardCopyOption;
import java.util.ArrayList;
@@ -55,8 +61,8 @@ import org.sonar.core.util.DefaultHttpDownloader;
*/
@BatchSide
public class ServerClient {
-
private static final String GET = "GET";
+ private static final Logger LOG = LoggerFactory.getLogger(ServerClient.class);
private GlobalProperties props;
private DefaultHttpDownloader.BaseHttpDownloader downloader;
@@ -68,6 +74,20 @@ public class ServerClient {
public String getURL() {
return StringUtils.removeEnd(StringUtils.defaultIfBlank(props.property("sonar.host.url"), "http://localhost:9000"), "/");
}
+
+ public String getServerVersion() {
+ InputStream is = this.getClass().getClassLoader().getResourceAsStream("sq-version.txt");
+ if (is == null) {
+ LOG.warn("Failed to get SQ version");
+ return null;
+ }
+ try (BufferedReader br = new BufferedReader(new InputStreamReader(is, StandardCharsets.UTF_8))) {
+ return br.readLine();
+ } catch (IOException e) {
+ LOG.warn("Failed to get SQ version", e);
+ return null;
+ }
+ }
public URI getURI(String pathStartingWithSlash) {
Preconditions.checkArgument(pathStartingWithSlash.startsWith("/"), "Path must start with slash /: " + pathStartingWithSlash);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java
index 14070c17d21..e98e6366f7a 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrapper/Batch.java
@@ -19,9 +19,6 @@
*/
package org.sonar.batch.bootstrapper;
-import com.google.common.collect.ImmutableMap;
-
-import org.sonar.api.CoreProperties;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
@@ -134,8 +131,7 @@ public final class Batch {
*/
public Batch syncProject(String projectKey) {
checkStarted();
- Map<String, String> props = ImmutableMap.of(CoreProperties.PROJECT_KEY_PROPERTY, projectKey);
- bootstrapContainer.syncProject(props, true);
+ bootstrapContainer.syncProject(projectKey, true);
return this;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/DefaultProjectCacheStatus.java b/sonar-batch/src/main/java/org/sonar/batch/cache/DefaultProjectCacheStatus.java
index 3308098c6a0..248d2b8b350 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cache/DefaultProjectCacheStatus.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cache/DefaultProjectCacheStatus.java
@@ -19,6 +19,8 @@
*/
package org.sonar.batch.cache;
+import javax.annotation.Nullable;
+
import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.home.cache.PersistentCache;
@@ -40,7 +42,7 @@ public class DefaultProjectCacheStatus implements ProjectCacheStatus {
}
@Override
- public void save(String projectKey) {
+ public void save(@Nullable String projectKey) {
Date now = new Date();
try {
@@ -55,7 +57,7 @@ public class DefaultProjectCacheStatus implements ProjectCacheStatus {
}
@Override
- public void delete(String projectKey) {
+ public void delete(@Nullable String projectKey) {
try {
cache.put(getKey(projectKey), new byte[0]);
} catch (IOException e) {
@@ -64,7 +66,7 @@ public class DefaultProjectCacheStatus implements ProjectCacheStatus {
}
@Override
- public Date getSyncStatus(String projectKey) {
+ public Date getSyncStatus(@Nullable String projectKey) {
try {
byte[] status = cache.get(getKey(projectKey), null);
if (status == null || status.length == 0) {
@@ -79,7 +81,11 @@ public class DefaultProjectCacheStatus implements ProjectCacheStatus {
}
}
- private String getKey(String projectKey) {
- return STATUS_PREFIX + client.getURL() + "-" + projectKey;
+ private String getKey(@Nullable String projectKey) {
+ if (projectKey != null) {
+ return STATUS_PREFIX + client.getURL() + "-" + client.getServerVersion() + "-" + projectKey;
+ } else {
+ return STATUS_PREFIX + client.getURL() + "-" + client.getServerVersion();
+ }
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizer.java b/sonar-batch/src/main/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizer.java
new file mode 100644
index 00000000000..e21d1420694
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizer.java
@@ -0,0 +1,92 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.cache;
+
+import org.sonar.batch.rule.ActiveRulesLoader;
+import org.sonar.batch.repository.QualityProfileLoader;
+import org.sonar.batch.protocol.input.QProfile;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.api.utils.log.Profiler;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.List;
+
+public class NonAssociatedCacheSynchronizer {
+ private static final Logger LOG = LoggerFactory.getLogger(NonAssociatedCacheSynchronizer.class);
+
+ private ProjectCacheStatus cacheStatus;
+ private QualityProfileLoader qualityProfileLoader;
+ private ActiveRulesLoader activeRulesLoader;
+
+ public NonAssociatedCacheSynchronizer(QualityProfileLoader qualityProfileLoader, ActiveRulesLoader activeRulesLoader, ProjectCacheStatus cacheStatus) {
+ this.qualityProfileLoader = qualityProfileLoader;
+ this.activeRulesLoader = activeRulesLoader;
+ this.cacheStatus = cacheStatus;
+ }
+
+ public void execute(boolean force) {
+ Date lastSync = cacheStatus.getSyncStatus(null);
+
+ if (lastSync != null) {
+ if (!force) {
+ LOG.info("Found cache [{}]", lastSync);
+ return;
+ } else {
+ LOG.info("-- Found cache [{}], synchronizing data..", lastSync);
+ }
+ cacheStatus.delete(null);
+ } else {
+ LOG.info("-- Cache not found, synchronizing data..");
+ }
+
+ loadData();
+ saveStatus();
+ }
+
+ private static Collection<String> getKeys(Collection<QProfile> qProfiles) {
+ List<String> list = new ArrayList<>(qProfiles.size());
+ for (QProfile qp : qProfiles) {
+ list.add(qp.key());
+ }
+
+ return list;
+ }
+
+ private void saveStatus() {
+ cacheStatus.save(null);
+ LOG.info("-- Succesfully synchronized cache");
+ }
+
+ private void loadData() {
+ Profiler profiler = Profiler.create(Loggers.get(ProjectCacheSynchronizer.class));
+
+ profiler.startInfo("Load default quality profiles");
+ Collection<QProfile> qProfiles = qualityProfileLoader.load(null, null);
+ profiler.stopInfo();
+
+ profiler.startInfo("Load default active rules");
+ activeRulesLoader.load(getKeys(qProfiles), null);
+ profiler.stopInfo();
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/PersistentCacheProvider.java b/sonar-batch/src/main/java/org/sonar/batch/cache/PersistentCacheProvider.java
index 878554d2499..99040ba9927 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cache/PersistentCacheProvider.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cache/PersistentCacheProvider.java
@@ -49,14 +49,14 @@ public class PersistentCacheProvider extends ProviderAdapter {
builder.setSonarHome(Paths.get(home));
}
- builder.setVersion(getVersion());
+ builder.setVersion(getServerVersion());
cache = builder.build();
}
return cache;
}
- private String getVersion() {
+ private String getServerVersion() {
InputStream is = this.getClass().getClassLoader().getResourceAsStream("sq-version.txt");
if (is == null) {
LOG.warn("Failed to get SQ version");
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheStatus.java b/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheStatus.java
index 281cd60f344..a5f97349a4b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheStatus.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheStatus.java
@@ -19,12 +19,14 @@
*/
package org.sonar.batch.cache;
+import javax.annotation.Nullable;
+
import java.util.Date;
public interface ProjectCacheStatus {
- void save(String projectKey);
+ void save(@Nullable String projectKey);
- void delete(String projectKey);
+ void delete(@Nullable String projectKey);
- Date getSyncStatus(String projectKey);
+ Date getSyncStatus(@Nullable String projectKey);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheSynchronizer.java b/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheSynchronizer.java
index 6e6bccc9572..d2d6cbcf2db 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheSynchronizer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectCacheSynchronizer.java
@@ -19,100 +19,98 @@
*/
package org.sonar.batch.cache;
-import org.sonar.batch.analysis.AnalysisProperties;
+import com.google.common.base.Function;
import org.apache.commons.lang.StringUtils;
-import org.sonar.api.utils.log.Loggers;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.batch.protocol.input.BatchInput.ServerIssue;
-import com.google.common.base.Function;
-import org.sonar.batch.protocol.input.FileData;
+import org.sonar.batch.protocol.input.QProfile;
+import org.sonar.batch.repository.ProjectSettingsLoader;
+import org.sonar.batch.repository.ProjectSettingsRepo;
+import org.sonar.batch.repository.QualityProfileLoader;
+import org.sonar.batch.repository.ServerIssuesLoader;
+import org.sonar.batch.repository.user.UserRepositoryLoader;
+import org.sonar.batch.rule.ActiveRulesLoader;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.Date;
import java.util.HashSet;
-import java.util.Map;
-import java.util.Map.Entry;
+import java.util.List;
import java.util.Set;
-import java.util.concurrent.Callable;
-import java.util.concurrent.ExecutorService;
-import java.util.concurrent.Executors;
-import java.util.concurrent.TimeUnit;
-
-import org.sonar.batch.protocol.input.ProjectRepositories;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.batch.repository.user.UserRepositoryLoader;
-import org.sonar.batch.issue.tracking.ServerLineHashesLoader;
-import org.sonar.batch.repository.ServerIssuesLoader;
-import org.sonar.batch.repository.ProjectRepositoriesLoader;
public class ProjectCacheSynchronizer {
private static final Logger LOG = LoggerFactory.getLogger(ProjectCacheSynchronizer.class);
- private static final int NUM_THREAD = 2;
- private final ProjectDefinition project;
- private final AnalysisProperties properties;
- private final ProjectRepositoriesLoader projectRepositoryLoader;
private final ServerIssuesLoader issuesLoader;
- private final ServerLineHashesLoader lineHashesLoader;
private final UserRepositoryLoader userRepository;
private final ProjectCacheStatus cacheStatus;
-
- public ProjectCacheSynchronizer(ProjectReactor project, ProjectRepositoriesLoader projectRepositoryLoader, AnalysisProperties properties,
- ServerIssuesLoader issuesLoader, ServerLineHashesLoader lineHashesLoader, UserRepositoryLoader userRepository, ProjectCacheStatus cacheStatus) {
- this.project = project.getRoot();
- this.projectRepositoryLoader = projectRepositoryLoader;
- this.properties = properties;
+ private final QualityProfileLoader qualityProfileLoader;
+ private final ProjectSettingsLoader projectSettingsLoader;
+ private final ActiveRulesLoader activeRulesLoader;
+
+ public ProjectCacheSynchronizer(QualityProfileLoader qualityProfileLoader, ProjectSettingsLoader projectSettingsLoader,
+ ActiveRulesLoader activeRulesLoader, ServerIssuesLoader issuesLoader,
+ UserRepositoryLoader userRepository, ProjectCacheStatus cacheStatus) {
+ this.qualityProfileLoader = qualityProfileLoader;
+ this.projectSettingsLoader = projectSettingsLoader;
+ this.activeRulesLoader = activeRulesLoader;
this.issuesLoader = issuesLoader;
- this.lineHashesLoader = lineHashesLoader;
this.userRepository = userRepository;
this.cacheStatus = cacheStatus;
}
- public void load(boolean force) {
- Date lastSync = cacheStatus.getSyncStatus(project.getKeyWithBranch());
+ public void load(String projectKey, boolean force) {
+ Date lastSync = cacheStatus.getSyncStatus(projectKey);
if (lastSync != null) {
if (!force) {
- LOG.info("Found project [{}] cache [{}]", project.getKeyWithBranch(), lastSync);
+ LOG.info("Found project [{}] cache [{}]", projectKey, lastSync);
return;
} else {
- LOG.info("-- Found project [{}] cache [{}], synchronizing data..", project.getKeyWithBranch(), lastSync);
+ LOG.info("-- Found project [{}] cache [{}], synchronizing data..", projectKey, lastSync);
}
- cacheStatus.delete(project.getKeyWithBranch());
+ cacheStatus.delete(projectKey);
} else {
- LOG.info("-- Cache for project [{}] not found, synchronizing data..", project.getKeyWithBranch());
+ LOG.info("-- Cache for project [{}] not found, synchronizing data..", projectKey);
}
- loadData();
- saveStatus();
+ loadData(projectKey);
+ saveStatus(projectKey);
}
- private void saveStatus() {
- cacheStatus.save(project.getKeyWithBranch());
+ private void saveStatus(String projectKey) {
+ cacheStatus.save(projectKey);
LOG.info("-- Succesfully synchronized project cache");
}
- private static String getComponentKey(String moduleKey, String filePath) {
- return moduleKey + ":" + filePath;
- }
-
- private void loadData() {
+ private void loadData(String projectKey) {
Profiler profiler = Profiler.create(Loggers.get(ProjectCacheSynchronizer.class));
- profiler.startInfo("Load project repository");
- ProjectRepositories projectRepo = projectRepositoryLoader.load(project, properties, null);
+ profiler.startInfo("Load project settings");
+ ProjectSettingsRepo settings = projectSettingsLoader.load(projectKey, null);
profiler.stopInfo();
- if (projectRepo.lastAnalysisDate() == null) {
+ if (settings.lastAnalysisDate() == null) {
LOG.debug("No previous analysis found");
return;
}
+ profiler.startInfo("Load project quality profiles");
+ Collection<QProfile> qProfiles = qualityProfileLoader.load(projectKey, null);
+ profiler.stopInfo();
+
+ Collection<String> profileKeys = getKeys(qProfiles);
+
+ profiler.startInfo("Load project active rules");
+ activeRulesLoader.load(profileKeys, projectKey);
+ profiler.stopInfo();
+
profiler.startInfo("Load server issues");
UserLoginAccumulator consumer = new UserLoginAccumulator();
- issuesLoader.load(project.getKeyWithBranch(), consumer);
+ issuesLoader.load(projectKey, consumer);
profiler.stopInfo();
profiler.startInfo("Load user information (" + consumer.loginSet.size() + " users)");
@@ -120,56 +118,15 @@ public class ProjectCacheSynchronizer {
userRepository.load(login, null);
}
profiler.stopInfo("Load user information");
-
- loadLineHashes(projectRepo.fileDataByModuleAndPath(), profiler);
}
- private void loadLineHashes(Map<String, Map<String, FileData>> fileDataByModuleAndPath, Profiler profiler) {
- ExecutorService executor = Executors.newFixedThreadPool(NUM_THREAD);
- int numFiles = 0;
-
- for (Map<String, FileData> fileDataByPath : fileDataByModuleAndPath.values()) {
- numFiles += fileDataByPath.size();
- }
- profiler.startInfo("Load line file hashes (" + numFiles + " files)");
-
- for (Entry<String, Map<String, FileData>> e1 : fileDataByModuleAndPath.entrySet()) {
- String moduleKey = e1.getKey();
-
- for (Entry<String, FileData> e2 : e1.getValue().entrySet()) {
- String filePath = e2.getKey();
- executor.submit(new LineHashLoadWorker(getComponentKey(moduleKey, filePath)));
- }
- }
-
- executor.shutdown();
-
- try {
- boolean done = executor.awaitTermination(30, TimeUnit.MINUTES);
- if (!done) {
- executor.shutdownNow();
- throw new IllegalStateException("Timeout while fetching line hashes");
- }
- } catch (InterruptedException e) {
- executor.shutdownNow();
- throw new IllegalStateException("Interrupted while fetching line hashes", e);
+ private static Collection<String> getKeys(Collection<QProfile> qProfiles) {
+ List<String> list = new ArrayList<>(qProfiles.size());
+ for (QProfile qp : qProfiles) {
+ list.add(qp.key());
}
- profiler.stopInfo("Load line file hashes (done)");
- }
-
- private class LineHashLoadWorker implements Callable<Void> {
- private String fileKey;
-
- LineHashLoadWorker(String fileKey) {
- this.fileKey = fileKey;
- }
-
- @Override
- public Void call() throws Exception {
- lineHashesLoader.getLineHashes(fileKey, null);
- return null;
- }
+ return list;
}
private static class UserLoginAccumulator implements Function<ServerIssue, Void> {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectSyncContainer.java b/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectSyncContainer.java
index 0f625f72ca0..0bd67f66261 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectSyncContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cache/ProjectSyncContainer.java
@@ -19,59 +19,73 @@
*/
package org.sonar.batch.cache;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.sonar.batch.repository.ProjectRepositoriesFactoryProvider;
+
import org.sonar.batch.analysis.DefaultAnalysisMode;
-import org.sonar.batch.cache.WSLoader.LoadStrategy;
+import org.sonar.api.CoreProperties;
+import com.google.common.collect.ImmutableMap;
+
+import java.util.Map;
+
import org.sonar.batch.analysis.AnalysisProperties;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
+import org.sonar.batch.bootstrap.GlobalProperties;
+import org.sonar.batch.repository.ProjectSettingsLoader;
+import org.sonar.batch.repository.DefaultProjectSettingsLoader;
+import org.sonar.batch.rule.ActiveRulesLoader;
+import org.sonar.batch.rule.DefaultActiveRulesLoader;
+import org.sonar.batch.repository.QualityProfileLoader;
+import org.sonar.batch.repository.DefaultQualityProfileLoader;
+import org.sonar.batch.cache.WSLoader.LoadStrategy;
import org.sonar.batch.repository.user.UserRepositoryLoader;
-import org.sonar.batch.issue.tracking.ServerLineHashesLoader;
import org.sonar.batch.repository.DefaultProjectRepositoriesLoader;
import org.sonar.batch.repository.DefaultServerIssuesLoader;
import org.sonar.batch.repository.ProjectRepositoriesLoader;
import org.sonar.batch.repository.ServerIssuesLoader;
-import org.sonar.batch.issue.tracking.DefaultServerLineHashesLoader;
import org.sonar.core.platform.ComponentContainer;
public class ProjectSyncContainer extends ComponentContainer {
private final boolean force;
- private final AnalysisProperties properties;
+ private final String projectKey;
- public ProjectSyncContainer(ComponentContainer globalContainer, AnalysisProperties analysisProperties, boolean force) {
+ public ProjectSyncContainer(ComponentContainer globalContainer, String projectKey, boolean force) {
super(globalContainer);
- this.properties = analysisProperties;
+ this.projectKey = projectKey;
this.force = force;
}
@Override
public void doBeforeStart() {
- ProjectReactor projectReactor = createProjectReactor();
- add(projectReactor);
addComponents();
}
- private ProjectReactor createProjectReactor() {
- ProjectDefinition rootProjectDefinition = ProjectDefinition.create();
- rootProjectDefinition.setProperties(properties.properties());
- return new ProjectReactor(rootProjectDefinition);
- }
-
@Override
public void doAfterStart() {
- getComponentByType(ProjectCacheSynchronizer.class).load(force);
+ if (projectKey != null) {
+ getComponentByType(ProjectCacheSynchronizer.class).load(projectKey, force);
+ } else {
+ getComponentByType(NonAssociatedCacheSynchronizer.class).execute(force);
+ }
+ }
+
+ private static DefaultAnalysisMode createIssuesAnalisysMode() {
+ Map<String, String> props = ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES);
+ GlobalProperties globalProps = new GlobalProperties(props);
+ AnalysisProperties analysisProps = new AnalysisProperties(props);
+ return new DefaultAnalysisMode(globalProps, analysisProps);
}
private void addComponents() {
- add(new StrategyWSLoaderProvider(LoadStrategy.SERVER_FIRST),
- properties,
- DefaultAnalysisMode.class,
- ProjectCacheSynchronizer.class,
- UserRepositoryLoader.class);
+ add(new StrategyWSLoaderProvider(LoadStrategy.SERVER_ONLY),
+ projectKey != null ? ProjectCacheSynchronizer.class : NonAssociatedCacheSynchronizer.class,
+ UserRepositoryLoader.class,
+ new ProjectRepositoriesFactoryProvider(projectKey),
+ createIssuesAnalisysMode());
addIfMissing(DefaultProjectCacheStatus.class, ProjectCacheStatus.class);
addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class);
addIfMissing(DefaultServerIssuesLoader.class, ServerIssuesLoader.class);
- addIfMissing(DefaultServerLineHashesLoader.class, ServerLineHashesLoader.class);
+ addIfMissing(DefaultQualityProfileLoader.class, QualityProfileLoader.class);
+ addIfMissing(DefaultActiveRulesLoader.class, ActiveRulesLoader.class);
+ addIfMissing(DefaultProjectSettingsLoader.class, ProjectSettingsLoader.class);
}
-
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java b/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java
index 092bab08b0b..d6966e97548 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/cache/WSLoader.java
@@ -51,13 +51,13 @@ public class WSLoader {
SERVER_FIRST, CACHE_FIRST, SERVER_ONLY, CACHE_ONLY;
}
- private final LoadStrategy loadStrategy;
+ private final LoadStrategy defautLoadStrategy;
private ServerStatus serverStatus;
private final ServerClient client;
private final PersistentCache cache;
public WSLoader(LoadStrategy strategy, PersistentCache cache, ServerClient client) {
- this.loadStrategy = strategy;
+ this.defautLoadStrategy = strategy;
this.serverStatus = UNKNOWN;
this.cache = cache;
this.client = client;
@@ -65,19 +65,28 @@ public class WSLoader {
@Nonnull
public WSLoaderResult<ByteSource> loadSource(String id) {
- WSLoaderResult<byte[]> byteResult = load(id);
+ WSLoaderResult<byte[]> byteResult = load(id, defautLoadStrategy);
return new WSLoaderResult<ByteSource>(ByteSource.wrap(byteResult.get()), byteResult.isFromCache());
}
@Nonnull
public WSLoaderResult<String> loadString(String id) {
- WSLoaderResult<byte[]> byteResult = load(id);
+ return loadString(id, defautLoadStrategy);
+ }
+ @Nonnull
+ public WSLoaderResult<String> loadString(String id, WSLoader.LoadStrategy strategy) {
+ WSLoaderResult<byte[]> byteResult = load(id, strategy);
return new WSLoaderResult<String>(new String(byteResult.get(), StandardCharsets.UTF_8), byteResult.isFromCache());
}
@Nonnull
public WSLoaderResult<byte[]> load(String id) {
- switch (loadStrategy) {
+ return load(id, defautLoadStrategy);
+ }
+
+ @Nonnull
+ public WSLoaderResult<byte[]> load(String id, WSLoader.LoadStrategy strategy) {
+ switch (strategy) {
case CACHE_FIRST:
return loadFromCacheFirst(id, true);
case CACHE_ONLY:
@@ -91,7 +100,7 @@ public class WSLoader {
}
public LoadStrategy getStrategy() {
- return this.loadStrategy;
+ return this.defautLoadStrategy;
}
private void switchToOffline() {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java
index 6577835f1cb..e291a05f15a 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoader.java
@@ -19,8 +19,9 @@
*/
package org.sonar.batch.issue.tracking;
-import org.sonar.batch.cache.WSLoaderResult;
+import org.sonar.batch.cache.WSLoader.LoadStrategy;
+import org.sonar.batch.cache.WSLoaderResult;
import org.sonar.batch.cache.WSLoader;
import org.apache.commons.lang.mutable.MutableBoolean;
@@ -50,7 +51,7 @@ public class DefaultServerLineHashesLoader implements ServerLineHashesLoader {
Profiler profiler = Profiler.createIfDebug(Loggers.get(getClass()))
.addContext("file", fileKey)
.startDebug("Load line hashes");
- WSLoaderResult<String> result = wsLoader.loadString("/api/sources/hash?key=" + BatchUtils.encodeForUrl(fileKey));
+ WSLoaderResult<String> result = wsLoader.loadString("/api/sources/hash?key=" + BatchUtils.encodeForUrl(fileKey), LoadStrategy.CACHE_FIRST);
try {
if (fromCache != null) {
fromCache.setValue(result.isFromCache());
diff --git a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java
index f202e552613..e0d5cc547c1 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/issue/tracking/LocalIssueTracking.java
@@ -19,16 +19,22 @@
*/
package org.sonar.batch.issue.tracking;
+import org.sonar.batch.analysis.DefaultAnalysisMode;
+
+import org.sonar.batch.repository.ProjectSettingsRepo;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
import com.google.common.collect.Sets;
+
import java.util.ArrayList;
import java.util.Collection;
import java.util.Collections;
import java.util.Date;
import java.util.List;
import java.util.Set;
+
import javax.annotation.CheckForNull;
+
import org.sonar.api.batch.BatchSide;
import org.sonar.api.batch.fs.internal.DefaultInputFile;
import org.sonar.api.batch.rule.ActiveRule;
@@ -41,7 +47,6 @@ import org.sonar.api.utils.KeyValueFormat;
import org.sonar.batch.index.BatchComponent;
import org.sonar.batch.index.BatchComponentCache;
import org.sonar.batch.issue.IssueCache;
-import org.sonar.batch.protocol.input.ProjectRepositories;
import org.sonar.batch.protocol.output.BatchReport;
import org.sonar.batch.protocol.output.BatchReportReader;
import org.sonar.batch.report.ReportPublisher;
@@ -72,7 +77,7 @@ public class LocalIssueTracking {
public LocalIssueTracking(BatchComponentCache resourceCache, IssueCache issueCache, IssueTracking tracking,
ServerLineHashesLoader lastLineHashes, IssueWorkflow workflow, IssueUpdater updater,
ActiveRules activeRules, ServerIssueRepository serverIssueRepository,
- ProjectRepositories projectRepositories, ReportPublisher reportPublisher) {
+ ProjectSettingsRepo projectRepositories, ReportPublisher reportPublisher, DefaultAnalysisMode mode) {
this.componentCache = resourceCache;
this.issueCache = issueCache;
this.tracking = tracking;
@@ -84,7 +89,7 @@ public class LocalIssueTracking {
this.analysisDate = ((Project) resourceCache.getRoot().resource()).getAnalysisDate();
this.changeContext = IssueChangeContext.createScan(analysisDate);
this.activeRules = activeRules;
- this.hasServerAnalysis = projectRepositories.lastAnalysisDate() != null;
+ this.hasServerAnalysis = !mode.isNotAssociated() && projectRepositories.lastAnalysisDate() != null;
}
public void execute() {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesProvider.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesFactory.java
index b2c86b9e2c0..3861684da2e 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesProvider.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesFactory.java
@@ -19,29 +19,42 @@
*/
package org.sonar.batch.repository;
-import org.sonar.batch.analysis.AnalysisProperties;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
+import org.sonar.batch.rule.ModuleQProfiles;
+import org.sonar.batch.analysis.AnalysisProperties;
+import org.sonar.batch.analysis.DefaultAnalysisMode;
import org.apache.commons.lang.mutable.MutableBoolean;
-import org.picocontainer.injectors.ProviderAdapter;
-import org.sonar.api.batch.AnalysisMode;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.utils.log.Logger;
import org.sonar.api.utils.log.Loggers;
import org.sonar.api.utils.log.Profiler;
import org.sonar.batch.protocol.input.ProjectRepositories;
-public class ProjectRepositoriesProvider extends ProviderAdapter {
-
+public class DefaultProjectRepositoriesFactory implements ProjectRepositoriesFactory {
private static final String LOG_MSG = "Load project repositories";
- private static final Logger LOG = Loggers.get(ProjectRepositoriesProvider.class);
+ private static final Logger LOG = Loggers.get(DefaultProjectRepositoriesFactory.class);
+ private static final String NON_EXISTING = "non1-existing2-project3-key";
+
+ private final DefaultAnalysisMode analysisMode;
+ private final ProjectRepositoriesLoader loader;
+ private final AnalysisProperties props;
+ private final ProjectReactor projectReactor;
private ProjectRepositories projectReferentials;
- public ProjectRepositories provide(ProjectRepositoriesLoader loader, ProjectReactor reactor, AnalysisProperties taskProps, AnalysisMode analysisMode) {
+ public DefaultProjectRepositoriesFactory(ProjectReactor projectReactor, DefaultAnalysisMode analysisMode, ProjectRepositoriesLoader loader, AnalysisProperties props) {
+ this.projectReactor = projectReactor;
+ this.analysisMode = analysisMode;
+ this.loader = loader;
+ this.props = props;
+ }
+
+ @Override
+ public ProjectRepositories create() {
if (projectReferentials == null) {
Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
MutableBoolean fromCache = new MutableBoolean();
- projectReferentials = loader.load(reactor.getRoot(), taskProps, fromCache);
+ projectReferentials = loader.load(getProjectKey(), getSonarProfile(), fromCache);
profiler.stopInfo(fromCache.booleanValue());
if (analysisMode.isIssues() && projectReferentials.lastAnalysisDate() == null) {
@@ -50,4 +63,19 @@ public class ProjectRepositoriesProvider extends ProviderAdapter {
}
return projectReferentials;
}
+
+ private String getProjectKey() {
+ if (analysisMode.isNotAssociated()) {
+ return NON_EXISTING;
+ }
+ return projectReactor.getRoot().getKeyWithBranch();
+ }
+
+ private String getSonarProfile() {
+ String profile = null;
+ if (!analysisMode.isIssues()) {
+ profile = props.property(ModuleQProfiles.SONAR_PROFILE_PROP);
+ }
+ return profile;
+ }
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java
index 58383811367..a3b38ee4ec5 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoader.java
@@ -23,12 +23,10 @@ import org.sonar.batch.cache.WSLoaderResult;
import org.sonar.batch.analysis.DefaultAnalysisMode;
import org.sonar.batch.cache.WSLoader;
-import org.sonar.batch.analysis.AnalysisProperties;
import javax.annotation.Nullable;
import org.apache.commons.lang.mutable.MutableBoolean;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.utils.MessageException;
@@ -50,13 +48,12 @@ public class DefaultProjectRepositoriesLoader implements ProjectRepositoriesLoad
}
@Override
- public ProjectRepositories load(ProjectDefinition projectDefinition, AnalysisProperties taskProperties, @Nullable MutableBoolean fromCache) {
- String projectKey = projectDefinition.getKeyWithBranch();
- String url = BATCH_PROJECT_URL + "?key=" + BatchUtils.encodeForUrl(projectKey);
- if (taskProperties.properties().containsKey(ModuleQProfiles.SONAR_PROFILE_PROP)) {
+ public ProjectRepositories load(String projectKeyWithBranch, @Nullable String sonarProfile, @Nullable MutableBoolean fromCache) {
+ String url = BATCH_PROJECT_URL + "?key=" + BatchUtils.encodeForUrl(projectKeyWithBranch);
+ if (sonarProfile != null) {
LOG.warn("Ability to set quality profile from command line using '" + ModuleQProfiles.SONAR_PROFILE_PROP
+ "' is deprecated and will be dropped in a future SonarQube version. Please configure quality profile used by your project on SonarQube server.");
- url += "&profile=" + BatchUtils.encodeForUrl(taskProperties.properties().get(ModuleQProfiles.SONAR_PROFILE_PROP));
+ url += "&profile=" + BatchUtils.encodeForUrl(sonarProfile);
}
url += "&preview=" + analysisMode.isIssues();
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectSettingsLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectSettingsLoader.java
new file mode 100644
index 00000000000..acb23823686
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultProjectSettingsLoader.java
@@ -0,0 +1,56 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import org.apache.commons.lang.mutable.MutableBoolean;
+
+import javax.annotation.Nullable;
+
+import java.util.Map;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+import org.sonar.batch.protocol.input.ProjectRepositories;
+
+public class DefaultProjectSettingsLoader implements ProjectSettingsLoader {
+ private ProjectRepositoriesFactory projectRepositoryFactory;
+
+ public DefaultProjectSettingsLoader(ProjectRepositoriesFactory projectRepositoryFactory) {
+ this.projectRepositoryFactory = projectRepositoryFactory;
+ }
+
+ @Override
+ public ProjectSettingsRepo load(String projectKey, @Nullable MutableBoolean fromCache) {
+ ProjectRepositories pr = projectRepositoryFactory.create();
+ return new ProjectSettingsRepo(toTable(pr.settings()), toTable(pr.fileDataByModuleAndPath()), pr.lastAnalysisDate());
+ }
+
+ private static <T, U, V> Table<T, U, V> toTable(Map<T, Map<U, V>> map) {
+ Table<T, U, V> table = HashBasedTable.create();
+
+ for (Map.Entry<T, Map<U, V>> e1 : map.entrySet()) {
+ for (Map.Entry<U, V> e2 : e1.getValue().entrySet()) {
+ table.put(e1.getKey(), e2.getKey(), e2.getValue());
+ }
+ }
+
+ return table;
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultQualityProfileLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultQualityProfileLoader.java
new file mode 100644
index 00000000000..ab86309f3d5
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/DefaultQualityProfileLoader.java
@@ -0,0 +1,50 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import javax.annotation.Nullable;
+
+import org.sonar.batch.protocol.input.ProjectRepositories;
+import org.sonar.batch.protocol.input.QProfile;
+
+import java.util.Collection;
+
+public class DefaultQualityProfileLoader implements QualityProfileLoader {
+
+ private ProjectRepositoriesFactory projectRepositoriesFactory;
+
+ public DefaultQualityProfileLoader(ProjectRepositoriesFactory projectRepositoriesFactory) {
+ this.projectRepositoriesFactory = projectRepositoriesFactory;
+ }
+
+ @Override
+ public Collection<QProfile> load(@Nullable String projectKey, @Nullable String sonarProfile) {
+ ProjectRepositories pr = projectRepositoriesFactory.create();
+ validate(pr.qProfiles());
+ return pr.qProfiles();
+ }
+
+ private static void validate(Collection<QProfile> profiles) {
+ if (profiles == null || profiles.isEmpty()) {
+ throw new IllegalStateException("No quality profiles has been found this project, you probably don't have any language plugin suitable for this analysis.");
+ }
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesFactory.java b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesFactory.java
new file mode 100644
index 00000000000..13ce299d8f9
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesFactory.java
@@ -0,0 +1,28 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import org.sonar.batch.protocol.input.ProjectRepositories;
+
+public interface ProjectRepositoriesFactory {
+
+ ProjectRepositories create();
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesFactoryProvider.java b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesFactoryProvider.java
new file mode 100644
index 00000000000..609d7a73f5d
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesFactoryProvider.java
@@ -0,0 +1,41 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import org.picocontainer.injectors.ProviderAdapter;
+
+public class ProjectRepositoriesFactoryProvider extends ProviderAdapter {
+
+ private final String projectKey;
+ private SyncProjectRepositoriesFactory factory;
+
+ public ProjectRepositoriesFactoryProvider(String projectKey) {
+ this.projectKey = projectKey;
+ this.factory = null;
+ }
+
+ public ProjectRepositoriesFactory provide(ProjectRepositoriesLoader loader) {
+ if (factory == null) {
+ factory = new SyncProjectRepositoriesFactory(projectKey, loader);
+ }
+
+ return factory;
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesLoader.java
index 444af1a3b62..d066b488940 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectRepositoriesLoader.java
@@ -19,16 +19,14 @@
*/
package org.sonar.batch.repository;
-import org.sonar.batch.analysis.AnalysisProperties;
import javax.annotation.Nullable;
import org.apache.commons.lang.mutable.MutableBoolean;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.batch.protocol.input.ProjectRepositories;
public interface ProjectRepositoriesLoader {
- ProjectRepositories load(ProjectDefinition projectDefinition, AnalysisProperties taskProperties, @Nullable MutableBoolean fromCache);
+ ProjectRepositories load(String projectKeyWithBranch, @Nullable String sonarProfile, @Nullable MutableBoolean fromCache);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsLoader.java
new file mode 100644
index 00000000000..dc0efbcc4e4
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsLoader.java
@@ -0,0 +1,28 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import org.apache.commons.lang.mutable.MutableBoolean;
+
+import javax.annotation.Nullable;
+
+public interface ProjectSettingsLoader {
+ ProjectSettingsRepo load(String projectKey, @Nullable MutableBoolean fromCache);
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsProvider.java b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsProvider.java
new file mode 100644
index 00000000000..5fa0db433b5
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsProvider.java
@@ -0,0 +1,64 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+
+import javax.annotation.Nullable;
+
+import org.sonar.batch.analysis.DefaultAnalysisMode;
+import org.sonar.batch.protocol.input.FileData;
+import com.google.common.collect.Table;
+import com.google.common.collect.ImmutableTable;
+import org.apache.commons.lang.mutable.MutableBoolean;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
+import org.picocontainer.injectors.ProviderAdapter;
+
+public class ProjectSettingsProvider extends ProviderAdapter {
+ private static final Logger LOG = Loggers.get(ProjectSettingsProvider.class);
+ private ProjectSettingsRepo settings = null;
+
+ public ProjectSettingsRepo provide(@Nullable ProjectSettingsLoader loader, ProjectReactor projectReactor, DefaultAnalysisMode mode) {
+ if (settings == null) {
+ if (mode.isNotAssociated()) {
+ settings = createNonAssociatedProjectSettings();
+ } else {
+ MutableBoolean fromCache = new MutableBoolean();
+ settings = loader.load(projectReactor.getRoot().getKeyWithBranch(), fromCache);
+ checkProject(mode);
+ }
+ }
+
+ return settings;
+ }
+
+ private void checkProject(DefaultAnalysisMode mode) {
+ if (mode.isIssues() && settings.lastAnalysisDate() == null) {
+ LOG.warn("No analysis has been found on the server for this project. All issues will be marked as 'new'.");
+ }
+ }
+
+ private static ProjectSettingsRepo createNonAssociatedProjectSettings() {
+ Table<String, String, String> emptySettings = ImmutableTable.of();
+ Table<String, String, FileData> emptyFileData = ImmutableTable.of();
+ return new ProjectSettingsRepo(emptySettings, emptyFileData, null);
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsRepo.java b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsRepo.java
new file mode 100644
index 00000000000..1e53de437bc
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/ProjectSettingsRepo.java
@@ -0,0 +1,66 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import com.google.common.collect.Table;
+
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+
+import org.sonar.batch.protocol.input.FileData;
+
+import java.util.Date;
+import java.util.Map;
+
+public class ProjectSettingsRepo {
+ private Table<String, String, String> settingsByModule = null;
+ private Table<String, String, FileData> fileDataByModuleAndPath = null;
+ private Date lastAnalysisDate;
+
+ public ProjectSettingsRepo(Table<String, String, String> settingsByModule, Table<String, String, FileData> fileDataByModuleAndPath,
+ @Nullable Date lastAnalysisDate) {
+ super();
+ this.settingsByModule = settingsByModule;
+ this.fileDataByModuleAndPath = fileDataByModuleAndPath;
+ this.lastAnalysisDate = lastAnalysisDate;
+ }
+
+ public Map<String, FileData> fileDataByPath(String moduleKey) {
+ return fileDataByModuleAndPath.row(moduleKey);
+ }
+
+ public Table<String, String, FileData> fileDataByModuleAndPath() {
+ return fileDataByModuleAndPath;
+ }
+
+ public Map<String, String> settings(String moduleKey) {
+ return settingsByModule.row(moduleKey);
+ }
+
+ @CheckForNull
+ public FileData fileData(String projectKey, String path) {
+ return fileDataByModuleAndPath.get(projectKey, path);
+ }
+
+ @CheckForNull
+ public Date lastAnalysisDate() {
+ return lastAnalysisDate;
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/QualityProfileLoader.java b/sonar-batch/src/main/java/org/sonar/batch/repository/QualityProfileLoader.java
new file mode 100644
index 00000000000..1d41398bff4
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/QualityProfileLoader.java
@@ -0,0 +1,30 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import javax.annotation.Nullable;
+
+import org.sonar.batch.protocol.input.QProfile;
+
+import java.util.Collection;
+
+public interface QualityProfileLoader {
+ Collection<QProfile> load(@Nullable String projectKey, @Nullable String sonarProfile);
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/QualityProfileProvider.java b/sonar-batch/src/main/java/org/sonar/batch/repository/QualityProfileProvider.java
new file mode 100644
index 00000000000..6f40ef0c7a8
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/QualityProfileProvider.java
@@ -0,0 +1,48 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import org.sonar.batch.protocol.input.QProfile;
+
+import java.util.Collection;
+
+import org.sonar.api.batch.AnalysisMode;
+import org.sonar.batch.analysis.AnalysisProperties;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
+import org.sonar.batch.rule.ModuleQProfiles;
+import org.picocontainer.injectors.ProviderAdapter;
+
+public class QualityProfileProvider extends ProviderAdapter {
+ private ModuleQProfiles profiles = null;
+
+ public ModuleQProfiles provide(ProjectReactor projectReactor, QualityProfileLoader loader, AnalysisProperties props, AnalysisMode mode) {
+ if (this.profiles == null) {
+ String profile = null;
+ if (!mode.isIssues()) {
+ profile = props.property(ModuleQProfiles.SONAR_PROFILE_PROP);
+ }
+ Collection<QProfile> qps = loader.load(projectReactor.getRoot().getKeyWithBranch(), profile);
+ profiles = new ModuleQProfiles(qps);
+ }
+
+ return profiles;
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/repository/SyncProjectRepositoriesFactory.java b/sonar-batch/src/main/java/org/sonar/batch/repository/SyncProjectRepositoriesFactory.java
new file mode 100644
index 00000000000..f01cce9102b
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/repository/SyncProjectRepositoriesFactory.java
@@ -0,0 +1,74 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import javax.annotation.Nullable;
+
+import org.apache.commons.lang.mutable.MutableBoolean;
+import org.sonar.api.utils.log.Logger;
+import org.sonar.api.utils.log.Loggers;
+import org.sonar.api.utils.log.Profiler;
+import org.sonar.batch.protocol.input.ProjectRepositories;
+
+public class SyncProjectRepositoriesFactory implements ProjectRepositoriesFactory {
+ private static final String LOG_MSG = "Load project repositories";
+ private static final Logger LOG = Loggers.get(SyncProjectRepositoriesFactory.class);
+ private static final String NON_EXISTING = "non1-existing2-project3-key";
+
+ private final ProjectRepositoriesLoader loader;
+ private final String projectKey;
+
+ private ProjectRepositories projectRepositories;
+
+ public SyncProjectRepositoriesFactory(@Nullable String projectKey, ProjectRepositoriesLoader loader) {
+ this.projectKey = projectKey;
+ this.loader = loader;
+ }
+
+ @Override
+ public ProjectRepositories create() {
+ if (projectRepositories == null) {
+ projectRepositories = newInstance();
+ }
+
+ return projectRepositories;
+ }
+
+ public ProjectRepositories newInstance() {
+ if (projectRepositories == null) {
+ Profiler profiler = Profiler.create(LOG).startInfo(LOG_MSG);
+ MutableBoolean fromCache = new MutableBoolean();
+ projectRepositories = loader.load(getProjectKey(projectKey), null, fromCache);
+ profiler.stopInfo(fromCache.booleanValue());
+
+ if (projectRepositories.lastAnalysisDate() == null) {
+ LOG.warn("No analysis has been found on the server for this project. All issues will be marked as 'new'.");
+ }
+ }
+ return projectRepositories;
+ }
+
+ private static String getProjectKey(@Nullable String projectKey) {
+ if (projectKey == null) {
+ return NON_EXISTING;
+ }
+ return projectKey;
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesLoader.java
new file mode 100644
index 00000000000..bf2ff6d406a
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesLoader.java
@@ -0,0 +1,28 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.rule;
+
+import org.sonar.batch.protocol.input.ActiveRule;
+
+import java.util.Collection;
+
+public interface ActiveRulesLoader {
+ Collection<ActiveRule> load(Collection<String> qualityProfileKeys, String projectKey);
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java b/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java
index 5bb0a4a86bd..ee2529cadff 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/ActiveRulesProvider.java
@@ -19,14 +19,17 @@
*/
package org.sonar.batch.rule;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.picocontainer.injectors.ProviderAdapter;
import org.sonar.api.batch.rule.ActiveRules;
import org.sonar.api.batch.rule.internal.ActiveRulesBuilder;
import org.sonar.api.batch.rule.internal.NewActiveRule;
import org.sonar.api.rule.RuleKey;
import org.sonar.batch.protocol.input.ActiveRule;
-import org.sonar.batch.protocol.input.ProjectRepositories;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
import java.util.Map.Entry;
/**
@@ -37,16 +40,16 @@ public class ActiveRulesProvider extends ProviderAdapter {
private ActiveRules singleton = null;
- public ActiveRules provide(ProjectRepositories ref) {
+ public ActiveRules provide(ActiveRulesLoader ref, ModuleQProfiles qProfiles, ProjectReactor projectReactor) {
if (singleton == null) {
- singleton = load(ref);
+ singleton = load(ref, qProfiles, projectReactor);
}
return singleton;
}
- private static ActiveRules load(ProjectRepositories ref) {
+ private static ActiveRules load(ActiveRulesLoader loader, ModuleQProfiles qProfiles, ProjectReactor projectReactor) {
ActiveRulesBuilder builder = new ActiveRulesBuilder();
- for (ActiveRule activeRule : ref.activeRules()) {
+ for (ActiveRule activeRule : loader.load(getKeys(qProfiles), projectReactor.getRoot().getKeyWithBranch())) {
NewActiveRule newActiveRule = builder.create(RuleKey.of(activeRule.repositoryKey(), activeRule.ruleKey()));
newActiveRule.setName(activeRule.name());
newActiveRule.setSeverity(activeRule.severity());
@@ -63,4 +66,14 @@ public class ActiveRulesProvider extends ProviderAdapter {
}
return builder.build();
}
+
+ private static Collection<String> getKeys(ModuleQProfiles qProfiles) {
+ List<String> keys = new ArrayList<>(qProfiles.findAll().size());
+
+ for (QProfile qp : qProfiles.findAll()) {
+ keys.add(qp.getKey());
+ }
+
+ return keys;
+ }
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/DefaultActiveRulesLoader.java b/sonar-batch/src/main/java/org/sonar/batch/rule/DefaultActiveRulesLoader.java
new file mode 100644
index 00000000000..05e58846648
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/DefaultActiveRulesLoader.java
@@ -0,0 +1,43 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.rule;
+
+import org.sonar.batch.repository.ProjectRepositoriesFactory;
+
+import org.sonar.batch.protocol.input.ActiveRule;
+
+import java.util.Collection;
+
+import org.sonar.batch.protocol.input.ProjectRepositories;
+
+public class DefaultActiveRulesLoader implements ActiveRulesLoader {
+ private final ProjectRepositoriesFactory projectRepositoriesFactory;
+
+ public DefaultActiveRulesLoader(ProjectRepositoriesFactory projectRepositoriesFactory) {
+ this.projectRepositoriesFactory = projectRepositoriesFactory;
+ }
+
+ @Override
+ public Collection<ActiveRule> load(Collection<String> qualityProfileKeys, String projectKey) {
+ ProjectRepositories pr = projectRepositoriesFactory.create();
+ return pr.activeRules();
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java b/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java
index f7474cf181d..3ac70d83150 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java
@@ -21,7 +21,6 @@ package org.sonar.batch.rule;
import com.google.common.collect.ImmutableMap;
import org.sonar.api.batch.BatchSide;
-import org.sonar.batch.protocol.input.ProjectRepositories;
import javax.annotation.CheckForNull;
@@ -37,10 +36,10 @@ public class ModuleQProfiles {
public static final String SONAR_PROFILE_PROP = "sonar.profile";
private final Map<String, QProfile> byLanguage;
- public ModuleQProfiles(ProjectRepositories ref) {
+ public ModuleQProfiles(Collection<org.sonar.batch.protocol.input.QProfile> profiles) {
ImmutableMap.Builder<String, QProfile> builder = ImmutableMap.builder();
- for (org.sonar.batch.protocol.input.QProfile qProfile : ref.qProfiles()) {
+ for (org.sonar.batch.protocol.input.QProfile qProfile : profiles) {
builder.put(qProfile.language(),
new QProfile().setKey(qProfile.key()).setName(qProfile.name()).setLanguage(qProfile.language()).setRulesUpdatedAt(qProfile.rulesUpdatedAt()));
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
index 039da7d57e0..89c5e8bcc17 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
@@ -148,7 +148,6 @@ public class ModuleScanContainer extends ComponentContainer {
CoverageExclusions.class,
// rules
- ModuleQProfiles.class,
new RulesProfileProvider(),
QProfileSensor.class,
CheckFactory.class,
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java
index f8b770f59dd..00692d53cfa 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleSettings.java
@@ -19,8 +19,9 @@
*/
package org.sonar.batch.scan;
-import org.sonar.batch.analysis.DefaultAnalysisMode;
+import org.sonar.batch.repository.ProjectSettingsRepo;
+import org.sonar.batch.analysis.DefaultAnalysisMode;
import com.google.common.collect.Lists;
import java.util.List;
@@ -30,20 +31,19 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.config.Settings;
import org.sonar.api.utils.MessageException;
import org.sonar.batch.bootstrap.GlobalSettings;
-import org.sonar.batch.protocol.input.ProjectRepositories;
/**
* @since 2.12
*/
public class ModuleSettings extends Settings {
- private final ProjectRepositories projectReferentials;
+ private final ProjectSettingsRepo projectSettingsRepo;
private DefaultAnalysisMode analysisMode;
- public ModuleSettings(GlobalSettings batchSettings, ProjectDefinition moduleDefinition, ProjectRepositories projectReferentials,
+ public ModuleSettings(GlobalSettings batchSettings, ProjectDefinition moduleDefinition, ProjectSettingsRepo projectSettingsRepo,
DefaultAnalysisMode analysisMode) {
super(batchSettings.getDefinitions());
- this.projectReferentials = projectReferentials;
+ this.projectSettingsRepo = projectSettingsRepo;
this.analysisMode = analysisMode;
getEncryption().setPathToSecretKey(batchSettings.getString(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
@@ -58,13 +58,13 @@ public class ModuleSettings extends Settings {
private void addProjectProperties(ProjectDefinition moduleDefinition, GlobalSettings batchSettings) {
addProperties(batchSettings.getProperties());
- addProperties(projectReferentials.settings(moduleDefinition.getKeyWithBranch()));
+ addProperties(projectSettingsRepo.settings(moduleDefinition.getKeyWithBranch()));
}
private void addBuildProperties(ProjectDefinition project) {
List<ProjectDefinition> orderedProjects = getTopDownParentProjects(project);
for (ProjectDefinition p : orderedProjects) {
- addProperties(p.getProperties());
+ addProperties(p.properties());
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java
index 8f42e7bc366..6266bf44e6c 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectLock.java
@@ -55,7 +55,6 @@ public class ProjectLock implements Startable {
if (lockFile == null) {
failAlreadyInProgress(null);
}
-
} catch (OverlappingFileLockException e) {
failAlreadyInProgress(e);
} catch (IOException e) {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorBuilder.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorBuilder.java
index 96d7bad1c5c..81b54609351 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorBuilder.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorBuilder.java
@@ -19,8 +19,9 @@
*/
package org.sonar.batch.scan;
-import org.apache.commons.lang.ArrayUtils;
+import org.sonar.api.batch.AnalysisMode;
+import org.apache.commons.lang.ArrayUtils;
import org.sonar.batch.analysis.AnalysisProperties;
import com.google.common.annotations.VisibleForTesting;
import com.google.common.collect.Lists;
@@ -108,12 +109,16 @@ public class ProjectReactorBuilder {
*/
private static final List<String> NON_HERITED_PROPERTIES_FOR_CHILD = Lists.newArrayList(PROPERTY_PROJECT_BASEDIR, CoreProperties.WORKING_DIRECTORY, PROPERTY_MODULES,
CoreProperties.PROJECT_DESCRIPTION_PROPERTY);
+
+ private static final String NON_ASSOCIATED_PROJECT_KEY = "project";
- private AnalysisProperties taskProps;
+ private final AnalysisProperties taskProps;
+ private final AnalysisMode analysisMode;
private File rootProjectWorkDir;
- public ProjectReactorBuilder(AnalysisProperties props) {
+ public ProjectReactorBuilder(AnalysisProperties props, AnalysisMode analysisMode) {
this.taskProps = props;
+ this.analysisMode = analysisMode;
}
public ProjectReactor execute() {
@@ -160,8 +165,16 @@ public class ProjectReactorBuilder {
extractPropertiesByModule(propertiesByModuleId, moduleId, currentModuleProperties);
}
}
-
+
+ private static void prepareNonAssociatedProject(Map<String, String> props, AnalysisMode mode) {
+ if(mode.isIssues() && !props.containsKey(CoreProperties.PROJECT_KEY_PROPERTY)) {
+ props.put(CoreProperties.PROJECT_KEY_PROPERTY, NON_ASSOCIATED_PROJECT_KEY);
+ }
+ }
+
protected ProjectDefinition defineRootProject(Map<String, String> rootProperties, @Nullable ProjectDefinition parent) {
+ prepareNonAssociatedProject(rootProperties, analysisMode);
+
if (rootProperties.containsKey(PROPERTY_MODULES)) {
checkMandatoryProperties(rootProperties, MANDATORY_PROPERTIES_FOR_MULTIMODULE_PROJECT);
} else {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorValidator.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorValidator.java
index b53e457ab7c..a856b44b894 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorValidator.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectReactorValidator.java
@@ -28,7 +28,6 @@ import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.config.Settings;
-import org.sonar.api.utils.SonarException;
import org.sonar.core.component.ComponentKeys;
/**
@@ -58,7 +57,7 @@ public class ProjectReactorValidator {
validateBranch(validationMessages, branch);
if (!validationMessages.isEmpty()) {
- throw new SonarException("Validation of project reactor failed:\n o " + Joiner.on("\n o ").join(validationMessages));
+ throw new IllegalStateException("Validation of project reactor failed:\n o " + Joiner.on("\n o ").join(validationMessages));
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
index b00888779cf..d6f58f0852a 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectScanContainer.java
@@ -19,6 +19,16 @@
*/
package org.sonar.batch.scan;
+import org.sonar.batch.repository.DefaultProjectRepositoriesFactory;
+
+import org.sonar.batch.repository.QualityProfileProvider;
+import org.sonar.batch.repository.DefaultQualityProfileLoader;
+import org.sonar.batch.repository.QualityProfileLoader;
+import org.sonar.batch.repository.ProjectSettingsLoader;
+import org.sonar.batch.repository.DefaultProjectSettingsLoader;
+import org.sonar.batch.repository.ProjectSettingsProvider;
+import org.sonar.batch.rule.DefaultActiveRulesLoader;
+import org.sonar.batch.rule.ActiveRulesLoader;
import org.sonar.batch.analysis.DefaultAnalysisMode;
import org.sonar.batch.analysis.AnalysisWSLoaderProvider;
import org.sonar.batch.analysis.AnalysisTempFolderProvider;
@@ -69,7 +79,6 @@ import org.sonar.batch.report.MetadataPublisher;
import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.report.SourcePublisher;
import org.sonar.batch.report.TestExecutionAndCoveragePublisher;
-import org.sonar.batch.repository.ProjectRepositoriesProvider;
import org.sonar.batch.repository.language.DefaultLanguagesRepository;
import org.sonar.batch.rule.ActiveRulesProvider;
import org.sonar.batch.scan.filesystem.InputPathCache;
@@ -116,6 +125,7 @@ public class ProjectScanContainer extends ComponentContainer {
props,
DefaultAnalysisMode.class,
ProjectReactorBuilder.class,
+ DefaultProjectRepositoriesFactory.class,
new MutableProjectReactorProvider(),
new ImmutableProjectReactorProvider(),
ProjectBuildersExecutor.class,
@@ -126,7 +136,6 @@ public class ProjectScanContainer extends ComponentContainer {
DefaultProjectTree.class,
ProjectExclusions.class,
ProjectReactorValidator.class,
- new ProjectRepositoriesProvider(),
new AnalysisWSLoaderProvider(),
CodeColorizers.class,
MetricProvider.class,
@@ -136,6 +145,7 @@ public class ProjectScanContainer extends ComponentContainer {
Caches.class,
BatchComponentCache.class,
DefaultIssueCallback.class,
+ new ProjectSettingsProvider(),
// temp
new AnalysisTempFolderProvider(),
@@ -146,6 +156,7 @@ public class ProjectScanContainer extends ComponentContainer {
// rules
new ActiveRulesProvider(),
+ new QualityProfileProvider(),
// issues
IssueUpdater.class,
@@ -153,8 +164,8 @@ public class ProjectScanContainer extends ComponentContainer {
IssueWorkflow.class,
IssueCache.class,
DefaultProjectIssues.class,
- LocalIssueTracking.class,
ServerIssueRepository.class,
+ LocalIssueTracking.class,
// metrics
DefaultMetricFinder.class,
@@ -190,9 +201,16 @@ public class ProjectScanContainer extends ComponentContainer {
ScanTaskObservers.class,
UserRepositoryLoader.class);
- addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class);
addIfMissing(DefaultServerIssuesLoader.class, ServerIssuesLoader.class);
addIfMissing(DefaultServerLineHashesLoader.class, ServerLineHashesLoader.class);
+ addIfMissing(DefaultActiveRulesLoader.class, ActiveRulesLoader.class);
+ addIfMissing(DefaultQualityProfileLoader.class, QualityProfileLoader.class);
+ addIfMissing(DefaultProjectRepositoriesLoader.class, ProjectRepositoriesLoader.class);
+ addIfMissing(DefaultProjectSettingsLoader.class, ProjectSettingsLoader.class);
+ }
+
+ private boolean isProjectAssociated() {
+ return !getComponentByType(DefaultAnalysisMode.class).isNotAssociated();
}
private void addBatchExtensions() {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java
index 7cd20223d20..df9b5135100 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ProjectSettings.java
@@ -19,8 +19,9 @@
*/
package org.sonar.batch.scan;
-import org.sonar.batch.analysis.DefaultAnalysisMode;
+import org.sonar.batch.repository.ProjectSettingsRepo;
+import org.sonar.batch.analysis.DefaultAnalysisMode;
import com.google.common.collect.ImmutableMap;
import java.util.Map;
@@ -32,7 +33,6 @@ import org.sonar.api.config.Settings;
import org.sonar.api.utils.MessageException;
import org.sonar.batch.bootstrap.DroppedPropertyChecker;
import org.sonar.batch.bootstrap.GlobalSettings;
-import org.sonar.batch.protocol.input.ProjectRepositories;
public class ProjectSettings extends Settings {
@@ -45,11 +45,11 @@ public class ProjectSettings extends Settings {
);
private final GlobalSettings globalSettings;
- private final ProjectRepositories projectRepositories;
+ private final ProjectSettingsRepo projectRepositories;
private final DefaultAnalysisMode mode;
public ProjectSettings(ProjectReactor reactor, GlobalSettings globalSettings, PropertyDefinitions propertyDefinitions,
- ProjectRepositories projectRepositories, DefaultAnalysisMode mode) {
+ ProjectSettingsRepo projectRepositories, DefaultAnalysisMode mode) {
super(propertyDefinitions);
this.mode = mode;
getEncryption().setPathToSecretKey(globalSettings.getString(CoreProperties.ENCRYPTION_SECRET_KEY_PATH));
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java
index 36131c29331..51232ec5701 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetection.java
@@ -19,21 +19,22 @@
*/
package org.sonar.batch.scan.filesystem;
+import org.sonar.batch.repository.ProjectSettingsRepo;
+
import org.apache.commons.lang.StringUtils;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.batch.protocol.input.FileData;
-import org.sonar.batch.protocol.input.ProjectRepositories;
class StatusDetection {
- private final ProjectRepositories projectReferentials;
+ private final ProjectSettingsRepo projectSettings;
- StatusDetection(ProjectRepositories projectReferentials) {
- this.projectReferentials = projectReferentials;
+ StatusDetection(ProjectSettingsRepo projectSettings) {
+ this.projectSettings = projectSettings;
}
InputFile.Status status(String projectKey, String relativePath, String hash) {
- FileData fileDataPerPath = projectReferentials.fileData(projectKey, relativePath);
+ FileData fileDataPerPath = projectSettings.fileData(projectKey, relativePath);
if (fileDataPerPath == null) {
return InputFile.Status.ADDED;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java
index 643f915cafc..f372b171df2 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/StatusDetectionFactory.java
@@ -19,15 +19,16 @@
*/
package org.sonar.batch.scan.filesystem;
+import org.sonar.batch.repository.ProjectSettingsRepo;
+
import org.sonar.api.batch.BatchSide;
-import org.sonar.batch.protocol.input.ProjectRepositories;
@BatchSide
public class StatusDetectionFactory {
- private final ProjectRepositories projectReferentials;
+ private final ProjectSettingsRepo projectReferentials;
- public StatusDetectionFactory(ProjectRepositories projectReferentials) {
+ public StatusDetectionFactory(ProjectSettingsRepo projectReferentials) {
this.projectReferentials = projectReferentials;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java
index 62144aa09d0..7d24836072d 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scm/ScmSensor.java
@@ -19,8 +19,11 @@
*/
package org.sonar.batch.scm;
+import org.sonar.batch.repository.ProjectSettingsRepo;
+
import java.util.LinkedList;
import java.util.List;
+
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
@@ -33,7 +36,6 @@ import org.sonar.api.batch.sensor.SensorContext;
import org.sonar.api.batch.sensor.SensorDescriptor;
import org.sonar.batch.index.BatchComponentCache;
import org.sonar.batch.protocol.input.FileData;
-import org.sonar.batch.protocol.input.ProjectRepositories;
import org.sonar.batch.report.ReportPublisher;
import org.sonar.batch.scan.filesystem.InputPathCache;
@@ -44,16 +46,16 @@ public final class ScmSensor implements Sensor {
private final ProjectDefinition projectDefinition;
private final ScmConfiguration configuration;
private final FileSystem fs;
- private final ProjectRepositories projectReferentials;
+ private final ProjectSettingsRepo projectSettings;
private final BatchComponentCache resourceCache;
private final ReportPublisher publishReportJob;
public ScmSensor(ProjectDefinition projectDefinition, ScmConfiguration configuration,
- ProjectRepositories projectReferentials, FileSystem fs, InputPathCache inputPathCache, BatchComponentCache resourceCache,
+ ProjectSettingsRepo projectSettings, FileSystem fs, InputPathCache inputPathCache, BatchComponentCache resourceCache,
ReportPublisher publishReportJob) {
this.projectDefinition = projectDefinition;
this.configuration = configuration;
- this.projectReferentials = projectReferentials;
+ this.projectSettings = projectSettings;
this.fs = fs;
this.resourceCache = resourceCache;
this.publishReportJob = publishReportJob;
@@ -95,7 +97,7 @@ public final class ScmSensor implements Sensor {
if (configuration.forceReloadAll()) {
addIfNotEmpty(filesToBlame, f);
} else {
- FileData fileData = projectReferentials.fileData(projectDefinition.getKeyWithBranch(), f.relativePath());
+ FileData fileData = projectSettings.fileData(projectDefinition.getKeyWithBranch(), f.relativePath());
if (f.status() != Status.SAME || fileData == null || fileData.needBlame()) {
addIfNotEmpty(filesToBlame, f);
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/cache/DefaultProjectCacheStatusTest.java b/sonar-batch/src/test/java/org/sonar/batch/cache/DefaultProjectCacheStatusTest.java
index 838edd04d39..4239ca1c024 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/cache/DefaultProjectCacheStatusTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/cache/DefaultProjectCacheStatusTest.java
@@ -25,7 +25,6 @@ import static org.assertj.core.api.Assertions.assertThat;
import org.sonar.home.cache.PersistentCacheLoader;
-import org.junit.internal.runners.statements.ExpectException;
import org.junit.rules.ExpectedException;
import java.io.IOException;
@@ -58,6 +57,7 @@ public class DefaultProjectCacheStatusTest {
public void setUp() {
cache = new PersistentCache(tmp.getRoot().toPath(), Long.MAX_VALUE, mock(Logger.class), null);
client = mock(ServerClient.class);
+ when(client.getServerVersion()).thenReturn("5.2");
when(client.getURL()).thenReturn("localhost");
cacheStatus = new DefaultProjectCacheStatus(cache, client);
}
@@ -85,6 +85,17 @@ public class DefaultProjectCacheStatusTest {
}
@Test
+ public void useServerVersionAsKey() {
+ cacheStatus.save(PROJ_KEY);
+ assertThat(cacheStatus.getSyncStatus(PROJ_KEY)).isNotNull();
+ assertThat(age(cacheStatus.getSyncStatus(PROJ_KEY))).isLessThan(2000);
+
+ when(client.getServerVersion()).thenReturn("5.1");
+
+ assertThat(cacheStatus.getSyncStatus(PROJ_KEY)).isNull();
+ }
+
+ @Test
public void errorStatus() throws IOException {
cache = mock(PersistentCache.class);
doThrow(IOException.class).when(cache).get(anyString(), any(PersistentCacheLoader.class));
diff --git a/sonar-batch/src/test/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizerTest.java b/sonar-batch/src/test/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizerTest.java
new file mode 100644
index 00000000000..d7b3bbd6710
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/cache/NonAssociatedCacheSynchronizerTest.java
@@ -0,0 +1,91 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.cache;
+
+import static org.mockito.Mockito.when;
+import org.sonar.batch.protocol.input.ActiveRule;
+import com.google.common.collect.ImmutableList;
+import org.sonar.batch.protocol.input.QProfile;
+import org.junit.Test;
+
+import java.util.Date;
+
+import static org.mockito.Mockito.mock;
+
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import org.mockito.MockitoAnnotations;
+import org.junit.Before;
+import org.mockito.Mock;
+import org.sonar.batch.rule.ActiveRulesLoader;
+import org.sonar.batch.repository.QualityProfileLoader;
+
+public class NonAssociatedCacheSynchronizerTest {
+ private NonAssociatedCacheSynchronizer synchronizer;
+
+ @Mock
+ private QualityProfileLoader qualityProfileLoader;
+ @Mock
+ private ActiveRulesLoader activeRulesLoader;
+ @Mock
+ private ProjectCacheStatus cacheStatus;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+
+ QProfile pf = new QProfile("profile", "profile", "lang", new Date(1000));
+ ActiveRule ar = mock(ActiveRule.class);
+
+ when(qualityProfileLoader.load(null, null)).thenReturn(ImmutableList.of(pf));
+ when(activeRulesLoader.load(ImmutableList.of("profile"), null)).thenReturn(ImmutableList.of(ar));
+
+ synchronizer = new NonAssociatedCacheSynchronizer(qualityProfileLoader, activeRulesLoader, cacheStatus);
+ }
+
+ @Test
+ public void dont_sync_if_exists() {
+ when(cacheStatus.getSyncStatus(null)).thenReturn(new Date());
+ synchronizer.execute(false);
+ verifyNoMoreInteractions(qualityProfileLoader, activeRulesLoader);
+ }
+
+ @Test
+ public void always_sync_if_force() {
+ when(cacheStatus.getSyncStatus(null)).thenReturn(new Date());
+ synchronizer.execute(true);
+ checkSync();
+ }
+
+ @Test
+ public void sync_if_doesnt_exist() {
+ synchronizer.execute(false);
+ checkSync();
+ }
+
+ private void checkSync() {
+ verify(cacheStatus).getSyncStatus(null);
+ verify(cacheStatus).save(null);
+ verify(qualityProfileLoader).load(null, null);
+ verify(activeRulesLoader).load(ImmutableList.of("profile"), null);
+
+ verifyNoMoreInteractions(qualityProfileLoader, activeRulesLoader);
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/cache/PersistentCacheProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/cache/PersistentCacheProviderTest.java
index 9e4966a5687..3f9c4af0e77 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/cache/PersistentCacheProviderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/cache/PersistentCacheProviderTest.java
@@ -19,10 +19,12 @@
*/
package org.sonar.batch.cache;
+import org.junit.Rule;
+import org.junit.rules.TemporaryFolder;
import org.sonar.batch.bootstrap.GlobalProperties;
import org.sonar.batch.cache.PersistentCacheProvider;
-import java.nio.file.Paths;
+import java.io.File;
import java.util.Collections;
import org.junit.Before;
@@ -30,6 +32,9 @@ import static org.assertj.core.api.Assertions.assertThat;
import org.junit.Test;
public class PersistentCacheProviderTest {
+ @Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
private PersistentCacheProvider provider = null;
private GlobalProperties props = null;
@@ -51,7 +56,8 @@ public class PersistentCacheProviderTest {
@Test
public void test_home() {
- props.properties().put("sonar.userHome", "myhome");
- assertThat(provider.provide(props).getBaseDirectory()).isEqualTo(Paths.get("myhome/ws_cache"));
+ File f = temp.getRoot();
+ props.properties().put("sonar.userHome", f.getAbsolutePath());
+ assertThat(provider.provide(props).getBaseDirectory()).isEqualTo(f.toPath().resolve("ws_cache"));
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/cache/ProjectCacheSynchronizerTest.java b/sonar-batch/src/test/java/org/sonar/batch/cache/ProjectCacheSynchronizerTest.java
index c36603145e3..2621af33476 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/cache/ProjectCacheSynchronizerTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/cache/ProjectCacheSynchronizerTest.java
@@ -20,11 +20,27 @@
package org.sonar.batch.cache;
import static org.mockito.Mockito.when;
+
+import org.sonar.batch.repository.ProjectRepositoriesFactory;
+
+import org.sonar.batch.repository.DefaultProjectRepositoriesFactory;
+import org.junit.Rule;
+import org.junit.rules.ExpectedException;
+import org.sonar.batch.repository.ProjectSettingsRepo;
+import com.google.common.base.Function;
+import com.google.common.collect.ImmutableList;
+import org.sonar.batch.protocol.input.ActiveRule;
+import org.sonar.batch.protocol.input.QProfile;
+import org.apache.commons.lang.mutable.MutableBoolean;
+import org.sonar.batch.repository.DefaultProjectSettingsLoader;
+import org.sonar.batch.rule.DefaultActiveRulesLoader;
+import org.sonar.batch.repository.DefaultQualityProfileLoader;
+import org.sonar.batch.repository.ProjectSettingsLoader;
+import org.sonar.batch.rule.ActiveRulesLoader;
+import org.sonar.batch.repository.QualityProfileLoader;
import org.sonar.batch.analysis.DefaultAnalysisMode;
import org.sonar.batch.analysis.AnalysisProperties;
import org.sonar.batch.protocol.input.ProjectRepositories;
-import org.apache.commons.lang.mutable.MutableBoolean;
-import org.sonar.batch.issue.tracking.DefaultServerLineHashesLoader;
import org.sonar.batch.repository.DefaultServerIssuesLoader;
import org.sonar.batch.repository.DefaultProjectRepositoriesLoader;
import org.sonar.api.batch.bootstrap.ProjectReactor;
@@ -36,6 +52,7 @@ import java.nio.charset.StandardCharsets;
import java.util.Date;
import java.util.HashMap;
+import static org.mockito.Matchers.eq;
import static org.mockito.Matchers.any;
import static org.mockito.Mockito.mock;
import static org.mockito.Matchers.anyString;
@@ -47,7 +64,6 @@ import org.junit.Before;
import org.mockito.MockitoAnnotations;
import org.mockito.Mock;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.batch.issue.tracking.ServerLineHashesLoader;
import org.sonar.batch.repository.ProjectRepositoriesLoader;
import org.sonar.batch.repository.ServerIssuesLoader;
import org.sonar.batch.repository.user.UserRepositoryLoader;
@@ -55,8 +71,10 @@ import org.sonar.batch.repository.user.UserRepositoryLoader;
public class ProjectCacheSynchronizerTest {
private static final String BATCH_PROJECT = "/batch/project?key=org.codehaus.sonar-plugins%3Asonar-scm-git-plugin&preview=true";
private static final String ISSUES = "/batch/issues?key=org.codehaus.sonar-plugins%3Asonar-scm-git-plugin";
- private static final String LINE_HASHES1 = "/api/sources/hash?key=org.codehaus.sonar-plugins%3Asonar-scm-git-plugin%3Asrc%2Ftest%2Fjava%2Forg%2Fsonar%2Fplugins%2Fscm%2Fgit%2FJGitBlameCommandTest.java";
- private static final String LINE_HASHES2 = "/api/sources/hash?key=org.codehaus.sonar-plugins%3Asonar-scm-git-plugin%3Asrc%2Fmain%2Fjava%2Forg%2Fsonar%2Fplugins%2Fscm%2Fgit%2FGitScmProvider.java";
+ private static final String PROJECT_KEY = "org.codehaus.sonar-plugins:sonar-scm-git-plugin";
+
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
@Mock
private ProjectDefinition project;
@@ -73,10 +91,10 @@ public class ProjectCacheSynchronizerTest {
private ProjectRepositoriesLoader projectRepositoryLoader;
private ServerIssuesLoader issuesLoader;
- private ServerLineHashesLoader lineHashesLoader;
private UserRepositoryLoader userRepositoryLoader;
-
- private ProjectCacheSynchronizer sync;
+ private QualityProfileLoader qualityProfileLoader;
+ private ActiveRulesLoader activeRulesLoader;
+ private ProjectSettingsLoader projectSettingsLoader;
@Before
public void setUp() throws IOException {
@@ -84,62 +102,108 @@ public class ProjectCacheSynchronizerTest {
String batchProject = getResourceAsString("batch_project.json");
ByteSource issues = getResourceAsByteSource("batch_issues.protobuf");
- String lineHashes2 = getResourceAsString("api_sources_hash_GitScmProvider.text");
- String lineHashes1 = getResourceAsString("api_sources_hash_JGitBlameCommand.text");
when(ws.loadString(BATCH_PROJECT)).thenReturn(new WSLoaderResult<>(batchProject, false));
when(ws.loadSource(ISSUES)).thenReturn(new WSLoaderResult<>(issues, false));
- when(ws.loadString(LINE_HASHES1)).thenReturn(new WSLoaderResult<>(lineHashes1, false));
- when(ws.loadString(LINE_HASHES2)).thenReturn(new WSLoaderResult<>(lineHashes2, false));
when(analysisMode.isIssues()).thenReturn(true);
- when(project.getKeyWithBranch()).thenReturn("org.codehaus.sonar-plugins:sonar-scm-git-plugin");
- when(projectReactor.getRoot()).thenReturn(project);
when(properties.properties()).thenReturn(new HashMap<String, String>());
+ }
+
+ private ProjectCacheSynchronizer create(ProjectRepositories projectRepositories) {
+ if (projectRepositories == null) {
+ projectRepositoryLoader = new DefaultProjectRepositoriesLoader(ws, analysisMode);
+ } else {
+ projectRepositoryLoader = mock(ProjectRepositoriesLoader.class);
+ when(projectRepositoryLoader.load(anyString(), anyString(), any(MutableBoolean.class))).thenReturn(projectRepositories);
+ }
+
+ ProjectReactor reactor = mock(ProjectReactor.class);
+ ProjectDefinition root = mock(ProjectDefinition.class);
+ when(root.getKeyWithBranch()).thenReturn(PROJECT_KEY);
+ when(reactor.getRoot()).thenReturn(root);
+
+ ProjectRepositoriesFactory projectRepositoriesFactory = new DefaultProjectRepositoriesFactory(reactor, analysisMode, projectRepositoryLoader, properties);
- projectRepositoryLoader = new DefaultProjectRepositoriesLoader(ws, analysisMode);
issuesLoader = new DefaultServerIssuesLoader(ws);
- lineHashesLoader = new DefaultServerLineHashesLoader(ws);
userRepositoryLoader = new UserRepositoryLoader(ws);
+ qualityProfileLoader = new DefaultQualityProfileLoader(projectRepositoriesFactory);
+ activeRulesLoader = new DefaultActiveRulesLoader(projectRepositoriesFactory);
+ projectSettingsLoader = new DefaultProjectSettingsLoader(projectRepositoriesFactory);
+
+ return new ProjectCacheSynchronizer(qualityProfileLoader, projectSettingsLoader, activeRulesLoader, issuesLoader, userRepositoryLoader, cacheStatus);
+ }
+
+ private ProjectCacheSynchronizer createMockedLoaders(Date lastAnalysisDate) {
+ issuesLoader = mock(DefaultServerIssuesLoader.class);
+ userRepositoryLoader = mock(UserRepositoryLoader.class);
+ qualityProfileLoader = mock(DefaultQualityProfileLoader.class);
+ activeRulesLoader = mock(DefaultActiveRulesLoader.class);
+ projectSettingsLoader = mock(DefaultProjectSettingsLoader.class);
+
+ QProfile pf = new QProfile("profile", "profile", "lang", new Date(1000));
+ ActiveRule ar = mock(ActiveRule.class);
+ ProjectSettingsRepo repo = mock(ProjectSettingsRepo.class);
- sync = new ProjectCacheSynchronizer(projectReactor, projectRepositoryLoader, properties, issuesLoader, lineHashesLoader, userRepositoryLoader,
- cacheStatus);
+ when(qualityProfileLoader.load(PROJECT_KEY, null)).thenReturn(ImmutableList.of(pf));
+ when(activeRulesLoader.load(ImmutableList.of("profile"), PROJECT_KEY)).thenReturn(ImmutableList.of(ar));
+ when(repo.lastAnalysisDate()).thenReturn(lastAnalysisDate);
+ when(projectSettingsLoader.load(anyString(), any(MutableBoolean.class))).thenReturn(repo);
+
+ return new ProjectCacheSynchronizer(qualityProfileLoader, projectSettingsLoader, activeRulesLoader, issuesLoader, userRepositoryLoader, cacheStatus);
}
@Test
public void testSync() {
- sync.load(false);
+ ProjectCacheSynchronizer sync = create(null);
+
+ sync.load(PROJECT_KEY, false);
verify(ws).loadString(BATCH_PROJECT);
verify(ws).loadSource(ISSUES);
- verify(ws).loadString(LINE_HASHES1);
- verify(ws).loadString(LINE_HASHES2);
verifyNoMoreInteractions(ws);
verify(cacheStatus).save(anyString());
}
@Test
+ public void testLoadersUsage() {
+ ProjectCacheSynchronizer synchronizer = createMockedLoaders(new Date());
+ synchronizer.load(PROJECT_KEY, false);
+
+ verify(issuesLoader).load(eq(PROJECT_KEY), any(Function.class));
+ verify(qualityProfileLoader).load(PROJECT_KEY, null);
+ verify(activeRulesLoader).load(ImmutableList.of("profile"), PROJECT_KEY);
+ verify(projectSettingsLoader).load(eq(PROJECT_KEY), any(MutableBoolean.class));
+
+ verifyNoMoreInteractions(issuesLoader, userRepositoryLoader, qualityProfileLoader, activeRulesLoader, projectSettingsLoader);
+ }
+
+ @Test
+ public void testLoadersUsage_NoLastAnalysis() {
+ ProjectCacheSynchronizer synchronizer = createMockedLoaders(null);
+ synchronizer.load(PROJECT_KEY, false);
+
+ verify(projectSettingsLoader).load(eq(PROJECT_KEY), any(MutableBoolean.class));
+
+ verifyNoMoreInteractions(issuesLoader, userRepositoryLoader, qualityProfileLoader, activeRulesLoader, projectSettingsLoader);
+ }
+
+ @Test
public void testSyncNoLastAnalysis() {
- projectRepositoryLoader = mock(DefaultProjectRepositoriesLoader.class);
ProjectRepositories mockedProjectRepositories = mock(ProjectRepositories.class);
when(mockedProjectRepositories.lastAnalysisDate()).thenReturn(null);
- when(projectRepositoryLoader.load(any(ProjectDefinition.class), any(AnalysisProperties.class), any(MutableBoolean.class))).thenReturn(mockedProjectRepositories);
-
- sync = new ProjectCacheSynchronizer(projectReactor, projectRepositoryLoader, properties, issuesLoader, lineHashesLoader, userRepositoryLoader,
- cacheStatus);
- sync.load(true);
- verify(cacheStatus).save("org.codehaus.sonar-plugins:sonar-scm-git-plugin");
+ ProjectCacheSynchronizer sync = create(mockedProjectRepositories);
+ sync.load(PROJECT_KEY, true);
+ verify(cacheStatus).save(PROJECT_KEY);
}
@Test
public void testDontSyncIfNotForce() {
- when(cacheStatus.getSyncStatus("org.codehaus.sonar-plugins:sonar-scm-git-plugin")).thenReturn(new Date());
-
- ProjectCacheSynchronizer sync = new ProjectCacheSynchronizer(projectReactor, projectRepositoryLoader, properties, issuesLoader, lineHashesLoader, userRepositoryLoader,
- cacheStatus);
- sync.load(false);
+ when(cacheStatus.getSyncStatus(PROJECT_KEY)).thenReturn(new Date());
+ ProjectCacheSynchronizer sync = create(null);
+ sync.load(PROJECT_KEY, false);
verifyNoMoreInteractions(ws);
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/cache/ProjectSyncContainerTest.java b/sonar-batch/src/test/java/org/sonar/batch/cache/ProjectSyncContainerTest.java
index b6d132ae8b2..15833a06ad5 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/cache/ProjectSyncContainerTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/cache/ProjectSyncContainerTest.java
@@ -19,16 +19,13 @@
*/
package org.sonar.batch.cache;
+import org.sonar.batch.protocol.input.ProjectRepositories;
+
import org.sonar.batch.bootstrap.GlobalProperties;
import org.sonar.batch.bootstrap.ServerClient;
import org.sonar.home.cache.PersistentCache;
-import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.batch.analysis.AnalysisProperties;
import java.util.HashMap;
-import java.util.Map;
-
-import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import org.sonar.core.platform.ComponentContainer;
@@ -47,24 +44,11 @@ public class ProjectSyncContainerTest {
return parent;
}
- public AnalysisProperties createProjectProperties() {
- Map<String, String> properties = new HashMap<>();
- properties.put("sonar.branch", "branch");
- properties.put("sonar.projectKey", "my:project");
- properties.put("sonar.projectName", "My project");
- properties.put("sonar.projectVersion", "1.0");
- properties.put("sonar.sources", ".");
- properties.put("sonar.projectBaseDir", ".");
- return new AnalysisProperties(properties);
- }
-
@Test
- public void testProjectKeyWithBranch() {
- ProjectSyncContainer container = new ProjectSyncContainer(createParentContainer(), createProjectProperties(), true);
+ public void testProjectRepository() {
+ ProjectSyncContainer container = new ProjectSyncContainer(createParentContainer(), "my:project", true);
container.doBeforeStart();
container.getPicoContainer().start();
-
- ProjectReactor projectReactor = container.getComponentByType(ProjectReactor.class);
- assertThat(projectReactor.getRoot().getKeyWithBranch()).isEqualTo("my:project:branch");
+ container.getComponentByType(ProjectRepositories.class);
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java
index 1ba67f296f1..9a3c25f6a34 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/issue/tracking/DefaultServerLineHashesLoaderTest.java
@@ -19,8 +19,8 @@
*/
package org.sonar.batch.issue.tracking;
+import org.sonar.batch.cache.WSLoader.LoadStrategy;
import org.sonar.batch.cache.WSLoaderResult;
-
import org.sonar.batch.cache.WSLoader;
import org.apache.commons.lang.mutable.MutableBoolean;
import org.junit.Before;
@@ -32,6 +32,8 @@ import org.sonar.api.utils.HttpDownloader;
import java.net.URI;
import java.net.URISyntaxException;
+import static org.mockito.Matchers.any;
+
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
@@ -50,19 +52,19 @@ public class DefaultServerLineHashesLoaderTest {
@Test
public void should_download_source_from_ws_if_preview_mode() {
WSLoader wsLoader = mock(WSLoader.class);
- when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult<>("ae12\n\n43fb", true));
+ when(wsLoader.loadString(anyString(), any(LoadStrategy.class))).thenReturn(new WSLoaderResult<>("ae12\n\n43fb", true));
ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(wsLoader);
String[] hashes = lastSnapshots.getLineHashes("myproject:org/foo/Bar.c", null);
assertThat(hashes).containsOnly("ae12", "", "43fb");
- verify(wsLoader).loadString("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FBar.c");
+ verify(wsLoader).loadString("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FBar.c", LoadStrategy.CACHE_FIRST);
}
@Test
public void should_download_source_with_space_from_ws_if_preview_mode() {
WSLoader server = mock(WSLoader.class);
- when(server.loadString(anyString())).thenReturn(new WSLoaderResult<>("ae12\n\n43fb", true));
+ when(server.loadString(anyString(), any(LoadStrategy.class))).thenReturn(new WSLoaderResult<>("ae12\n\n43fb", true));
ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(server);
@@ -70,13 +72,13 @@ public class DefaultServerLineHashesLoaderTest {
String[] hashes = lastSnapshots.getLineHashes("myproject:org/foo/Foo Bar.c", fromCache);
assertThat(fromCache.booleanValue()).isTrue();
assertThat(hashes).containsOnly("ae12", "", "43fb");
- verify(server).loadString("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FFoo+Bar.c");
+ verify(server).loadString("/api/sources/hash?key=myproject%3Aorg%2Ffoo%2FFoo+Bar.c", LoadStrategy.CACHE_FIRST);
}
@Test
public void should_fail_to_download_source_from_ws() throws URISyntaxException {
WSLoader server = mock(WSLoader.class);
- when(server.loadString(anyString())).thenThrow(new HttpDownloader.HttpException(new URI(""), 500));
+ when(server.loadString(anyString(), any(LoadStrategy.class))).thenThrow(new HttpDownloader.HttpException(new URI(""), 500));
ServerLineHashesLoader lastSnapshots = new DefaultServerLineHashesLoader(server);
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/BatchMediumTester.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/BatchMediumTester.java
index b14d6ac3c88..9f3e1c4f9c2 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/BatchMediumTester.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/BatchMediumTester.java
@@ -19,27 +19,26 @@
*/
package org.sonar.batch.mediumtest;
-import org.sonar.batch.analysis.AnalysisProperties;
-
+import org.apache.commons.io.FileUtils;
import org.apache.commons.lang.mutable.MutableBoolean;
import javax.annotation.Nullable;
import org.sonar.batch.cache.ProjectCacheStatus;
-import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonarqube.ws.Rules.ListResponse.Rule;
import org.sonar.batch.bootstrapper.IssueListener;
import org.sonar.api.server.rule.RulesDefinition.Repository;
import org.sonar.api.server.rule.RulesDefinition;
import org.sonar.batch.rule.RulesLoader;
import com.google.common.base.Function;
-import com.google.common.io.Files;
import java.io.File;
import java.io.FileInputStream;
+import java.io.IOException;
import java.io.InputStreamReader;
import java.io.Reader;
import java.nio.charset.StandardCharsets;
+import java.nio.file.Path;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
@@ -75,12 +74,41 @@ public class BatchMediumTester {
public static final String MEDIUM_TEST_ENABLED = "sonar.mediumTest.enabled";
private Batch batch;
+ private static Path workingDir = null;
+ private static Path globalWorkingDir = null;
+
+ private static void createWorkingDirs() throws IOException {
+ destroyWorkingDirs();
+
+ workingDir = java.nio.file.Files.createTempDirectory("mediumtest-working-dir");
+ globalWorkingDir = java.nio.file.Files.createTempDirectory("mediumtest-global-working-dir");
+ }
+
+ private static void destroyWorkingDirs() throws IOException {
+ if(workingDir != null) {
+ FileUtils.deleteDirectory(workingDir.toFile());
+ workingDir = null;
+ }
+
+ if(globalWorkingDir != null) {
+ FileUtils.deleteDirectory(globalWorkingDir.toFile());
+ globalWorkingDir = null;
+ }
+
+ }
public static BatchMediumTesterBuilder builder() {
+ try {
+ createWorkingDirs();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
+
BatchMediumTesterBuilder builder = new BatchMediumTesterBuilder().registerCoreMetrics();
builder.bootstrapProperties.put(MEDIUM_TEST_ENABLED, "true");
builder.bootstrapProperties.put(ReportPublisher.KEEP_REPORT_PROP_KEY, "true");
- builder.bootstrapProperties.put(CoreProperties.WORKING_DIRECTORY, Files.createTempDir().getAbsolutePath());
+ builder.bootstrapProperties.put(CoreProperties.WORKING_DIRECTORY, workingDir.toString());
+ builder.bootstrapProperties.put(CoreProperties.GLOBAL_WORKING_DIRECTORY, globalWorkingDir.toString());
return builder;
}
@@ -93,12 +121,18 @@ public class BatchMediumTester {
private final Map<String, String> bootstrapProperties = new HashMap<>();
private final FakeRulesLoader rulesLoader = new FakeRulesLoader();
private final FakeProjectCacheStatus projectCacheStatus = new FakeProjectCacheStatus();
+ private boolean associated = true;
private LogOutput logOutput = null;
public BatchMediumTester build() {
return new BatchMediumTester(this);
}
+ public BatchMediumTesterBuilder setAssociated(boolean associated) {
+ this.associated = associated;
+ return this;
+ }
+
public BatchMediumTesterBuilder setLogOutput(LogOutput logOutput) {
this.logOutput = logOutput;
return this;
@@ -210,6 +244,11 @@ public class BatchMediumTester {
public void stop() {
batch.stop();
+ try {
+ destroyWorkingDirs();
+ } catch (IOException e) {
+ e.printStackTrace();
+ }
}
public void syncProject(String projectKey) {
@@ -217,21 +256,24 @@ public class BatchMediumTester {
}
private BatchMediumTester(BatchMediumTesterBuilder builder) {
- batch = Batch.builder()
+ Batch.Builder batchBuilder = Batch.builder()
.setEnableLoggingConfiguration(true)
.addComponents(
new EnvironmentInformation("mediumTest", "1.0"),
builder.pluginInstaller,
builder.globalRefProvider,
- builder.projectRefProvider,
- builder.serverIssues,
- builder.serverLineHashes,
builder.rulesLoader,
builder.projectCacheStatus,
+ builder.projectRefProvider,
new DefaultDebtModel())
.setBootstrapProperties(builder.bootstrapProperties)
- .setLogOutput(builder.logOutput)
- .build();
+ .setLogOutput(builder.logOutput);
+
+ if (builder.associated) {
+ batchBuilder.addComponents(
+ builder.serverIssues);
+ }
+ batch = batchBuilder.build();
}
public TaskBuilder newTask() {
@@ -343,7 +385,7 @@ public class BatchMediumTester {
private ProjectRepositories ref = new ProjectRepositories();
@Override
- public ProjectRepositories load(ProjectDefinition projDefinition, AnalysisProperties taskProperties, @Nullable MutableBoolean fromCache) {
+ public ProjectRepositories load(String projectKey, @Nullable String sonarProfile, @Nullable MutableBoolean fromCache) {
return ref;
}
@@ -385,7 +427,6 @@ public class BatchMediumTester {
}
return true;
}
-
}
private static class FakeProjectCacheStatus implements ProjectCacheStatus {
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/cache/CacheSyncTest.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/cache/CacheSyncTest.java
index 3c5d2749926..8216eea1323 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/cache/CacheSyncTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/cache/CacheSyncTest.java
@@ -19,22 +19,25 @@
*/
package org.sonar.batch.mediumtest.cache;
-import org.sonar.batch.protocol.input.FileData;
-
-import org.junit.Test;
import com.google.common.collect.ImmutableMap;
import org.junit.After;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
import org.sonar.api.CoreProperties;
import org.sonar.batch.mediumtest.BatchMediumTester;
import org.sonar.batch.protocol.input.ActiveRule;
+import org.sonar.batch.protocol.input.FileData;
import org.sonar.xoo.XooPlugin;
import org.sonar.xoo.rule.XooRulesDefinition;
import java.util.Date;
public class CacheSyncTest {
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
- public BatchMediumTester tester;
+ private BatchMediumTester tester;
@After
public void stop() {
@@ -47,23 +50,57 @@ public class CacheSyncTest {
@Test
public void testSyncFirstTime() {
FileData file1 = new FileData("hash", true);
- String[] hashes = new String[] {
- "line1", "line2"
- };
tester = BatchMediumTester.builder()
.bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES))
.registerPlugin("xoo", new XooPlugin())
.addRules(new XooRulesDefinition())
+ .addQProfile("lang", "name")
.activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", "my/internal/key", "xoo"))
.setPreviousAnalysisDate(new Date())
.addFileData("test-project", "file1", file1)
- .mockLineHashes("test-project:file1", hashes)
.build();
tester.start();
tester.syncProject("test-project");
+ }
+
+ @Test
+ public void testNonAssociated() {
+ FileData file1 = new FileData("hash", true);
+
+ tester = BatchMediumTester.builder()
+ .bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES))
+ .registerPlugin("xoo", new XooPlugin())
+ .addRules(new XooRulesDefinition())
+ .addQProfile("lang", "name")
+ .activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", "my/internal/key", "xoo"))
+ .setPreviousAnalysisDate(new Date())
+ .addFileData("test-project", "file1", file1)
+ .build();
+ tester.start();
+ tester.syncProject(null);
+ }
+
+ @Test
+ public void testNoQProfile() {
+ FileData file1 = new FileData("hash", true);
+
+ tester = BatchMediumTester.builder()
+ .bootstrapProperties(ImmutableMap.of(CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES))
+ .registerPlugin("xoo", new XooPlugin())
+ .addRules(new XooRulesDefinition())
+ .activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", "my/internal/key", "xoo"))
+ .setPreviousAnalysisDate(new Date())
+ .addFileData("test-project", "file1", file1)
+ .build();
+
+ tester.start();
+
+ exception.expect(IllegalStateException.class);
+ exception.expectMessage("No quality");
+ tester.syncProject("test-project");
}
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issuesmode/NonAssociatedProject.java b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issuesmode/NonAssociatedProject.java
new file mode 100644
index 00000000000..6b2ae4c342c
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/mediumtest/issuesmode/NonAssociatedProject.java
@@ -0,0 +1,90 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.mediumtest.issuesmode;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.commons.io.FileUtils;
+import org.apache.commons.io.filefilter.FileFilterUtils;
+import org.junit.After;
+import org.junit.Before;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.utils.log.LogTester;
+import org.sonar.batch.mediumtest.BatchMediumTester;
+import org.sonar.batch.mediumtest.TaskResult;
+import org.sonar.batch.protocol.input.ActiveRule;
+import org.sonar.xoo.XooPlugin;
+import org.sonar.xoo.rule.XooRulesDefinition;
+
+import java.io.File;
+import java.io.IOException;
+
+public class NonAssociatedProject {
+ @org.junit.Rule
+ public TemporaryFolder temp = new TemporaryFolder();
+
+ @org.junit.Rule
+ public LogTester logTester = new LogTester();
+
+ public BatchMediumTester tester;
+
+ @Before
+ public void prepare() throws IOException {
+ tester = BatchMediumTester.builder()
+ .bootstrapProperties(ImmutableMap.of(
+ CoreProperties.ANALYSIS_MODE, CoreProperties.ANALYSIS_MODE_ISSUES,
+ CoreProperties.GLOBAL_WORKING_DIRECTORY, temp.newFolder().getAbsolutePath()))
+ .registerPlugin("xoo", new XooPlugin())
+ .addQProfile("xoo", "Sonar Way")
+ .addRules(new XooRulesDefinition())
+ .addRule("manual:MyManualIssue", "manual", "MyManualIssue", "My manual issue")
+ .addRule("manual:MyManualIssueDup", "manual", "MyManualIssue", "My manual issue")
+ .activateRule(new ActiveRule("xoo", "OneIssuePerLine", null, "One issue per line", "MAJOR", null, "xoo"))
+ .activateRule(new ActiveRule("xoo", "OneIssueOnDirPerFile", null, "OneIssueOnDirPerFile", "MAJOR", null, "xoo"))
+ .activateRule(new ActiveRule("xoo", "OneIssuePerModule", null, "OneIssuePerModule", "MAJOR", null, "xoo"))
+ .activateRule(new ActiveRule("manual", "MyManualIssue", null, "My manual issue", "MAJOR", null, null))
+ .setAssociated(false)
+ .build();
+ tester.start();
+ }
+
+ @After
+ public void stop() {
+ tester.stop();
+ }
+
+ private File copyProject(String path) throws Exception {
+ File projectDir = temp.newFolder();
+ File originalProjectDir = new File(IssueModeAndReportsMediumTest.class.getResource(path).toURI());
+ FileUtils.copyDirectory(originalProjectDir, projectDir, FileFilterUtils.notFileFilter(FileFilterUtils.nameFileFilter(".sonar")));
+ return projectDir;
+ }
+
+ @Test
+ public void testNonAssociated() throws Exception {
+ File projectDir = copyProject("/mediumtest/xoo/multi-modules-sample-not-associated");
+
+ TaskResult result = tester
+ .newScanTask(new File(projectDir, "sonar-project.properties"))
+ .start();
+
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java
index 5e59d70beda..3d2b9d18937 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectRepositoriesLoaderTest.java
@@ -23,10 +23,8 @@ import org.sonar.batch.cache.WSLoaderResult;
import org.sonar.batch.analysis.DefaultAnalysisMode;
import org.sonar.batch.cache.WSLoader;
-import org.sonar.batch.analysis.AnalysisProperties;
import org.apache.commons.lang.mutable.MutableBoolean;
import org.apache.commons.io.IOUtils;
-import com.google.common.collect.Maps;
import java.io.IOException;
import java.util.Date;
@@ -40,7 +38,6 @@ import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.utils.MessageException;
import org.sonar.batch.protocol.input.ProjectRepositories;
import org.sonar.batch.protocol.input.QProfile;
-import org.sonar.batch.rule.ModuleQProfiles;
import static org.mockito.Matchers.anyString;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.spy;
@@ -56,7 +53,6 @@ public class DefaultProjectRepositoriesLoaderTest {
private WSLoader wsLoader;
private DefaultAnalysisMode analysisMode;
private ProjectDefinition project;
- private AnalysisProperties taskProperties;
@Before
public void prepare() {
@@ -65,7 +61,6 @@ public class DefaultProjectRepositoriesLoaderTest {
loader = new DefaultProjectRepositoriesLoader(wsLoader, analysisMode);
loader = spy(loader);
when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult<>("{}", true));
- taskProperties = new AnalysisProperties(Maps.<String, String>newHashMap(), "");
}
@Test
@@ -73,11 +68,11 @@ public class DefaultProjectRepositoriesLoaderTest {
addQualityProfile();
project = ProjectDefinition.create().setKey("foo");
when(analysisMode.isIssues()).thenReturn(false);
- loader.load(project, taskProperties, null);
+ loader.load(project.getKeyWithBranch(), null, null);
verify(wsLoader).loadString("/batch/project?key=foo&preview=false");
when(analysisMode.isIssues()).thenReturn(true);
- loader.load(project, taskProperties, null);
+ loader.load(project.getKeyWithBranch(), null, null);
verify(wsLoader).loadString("/batch/project?key=foo&preview=true");
}
@@ -88,7 +83,7 @@ public class DefaultProjectRepositoriesLoaderTest {
when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult<>(response, true));
project = ProjectDefinition.create().setKey("foo");
MutableBoolean fromCache = new MutableBoolean();
- ProjectRepositories projectRepo = loader.load(project, taskProperties, fromCache);
+ ProjectRepositories projectRepo = loader.load(project.getKeyWithBranch(), null, fromCache);
assertThat(fromCache.booleanValue()).isTrue();
assertThat(projectRepo.activeRules().size()).isEqualTo(221);
@@ -100,7 +95,7 @@ public class DefaultProjectRepositoriesLoaderTest {
public void passAndEncodeProjectKeyParameter() {
addQualityProfile();
project = ProjectDefinition.create().setKey("foo bàr");
- loader.load(project, taskProperties, null);
+ loader.load(project.getKeyWithBranch(), null, null);
verify(wsLoader).loadString("/batch/project?key=foo+b%C3%A0r&preview=false");
}
@@ -108,8 +103,7 @@ public class DefaultProjectRepositoriesLoaderTest {
public void passAndEncodeProfileParameter() {
addQualityProfile();
project = ProjectDefinition.create().setKey("foo");
- taskProperties.properties().put(ModuleQProfiles.SONAR_PROFILE_PROP, "my-profile#2");
- loader.load(project, taskProperties, null);
+ loader.load(project.getKeyWithBranch(), "my-profile#2", null);
verify(wsLoader).loadString("/batch/project?key=foo&profile=my-profile%232&preview=false");
}
@@ -121,7 +115,7 @@ public class DefaultProjectRepositoriesLoaderTest {
project = ProjectDefinition.create().setKey("foo");
when(wsLoader.loadString(anyString())).thenReturn(new WSLoaderResult<>(new ProjectRepositories().toJson(), true));
- loader.load(project, taskProperties, null);
+ loader.load(project.getKeyWithBranch(), null, null);
}
private void addQualityProfile() {
diff --git a/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectSettingsLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectSettingsLoaderTest.java
new file mode 100644
index 00000000000..9d0388fd6b6
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultProjectSettingsLoaderTest.java
@@ -0,0 +1,77 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import com.google.common.collect.ImmutableMap;
+
+import org.sonar.batch.protocol.input.FileData;
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.batch.protocol.input.ProjectRepositories;
+
+import java.util.Date;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+
+public class DefaultProjectSettingsLoaderTest {
+ private DefaultProjectSettingsLoader loader;
+ private DefaultProjectRepositoriesFactory factory;
+ private ProjectRepositories projectRepositories;
+
+ private FileData f1;
+ private FileData f2;
+
+ @Before
+ public void setUp() {
+ createProjectRepo();
+ factory = mock(DefaultProjectRepositoriesFactory.class);
+ when(factory.create()).thenReturn(projectRepositories);
+ loader = new DefaultProjectSettingsLoader(factory);
+ }
+
+ private void createProjectRepo() {
+ projectRepositories = new ProjectRepositories();
+ projectRepositories.setLastAnalysisDate(new Date(1000));
+
+ f1 = new FileData("hash1", true);
+ f2 = new FileData("hash2", true);
+ projectRepositories.addFileData("module1", "file1", f1);
+ projectRepositories.addFileData("module1", "file2", f2);
+
+ projectRepositories.addSettings("module1", ImmutableMap.of("key", "value"));
+ }
+
+ @Test
+ public void test() {
+ ProjectSettingsRepo loaded = loader.load("project", null);
+
+ assertThat(loaded.fileData("module1", "file1")).isEqualTo(f1);
+ assertThat(loaded.fileData("module1", "file2")).isEqualTo(f2);
+ assertThat(loaded.settings("module1")).isEqualTo(ImmutableMap.of("key", "value"));
+ assertThat(loaded.lastAnalysisDate()).isEqualTo(new Date(1000));
+
+ verify(factory).create();
+ verifyNoMoreInteractions(factory);
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultQualityProfileLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultQualityProfileLoaderTest.java
new file mode 100644
index 00000000000..06de84fc400
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/repository/DefaultQualityProfileLoaderTest.java
@@ -0,0 +1,77 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import org.junit.Rule;
+import org.junit.rules.ExpectedException;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.batch.protocol.input.ProjectRepositories;
+import org.sonar.batch.protocol.input.QProfile;
+
+import java.util.Collection;
+import java.util.Date;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DefaultQualityProfileLoaderTest {
+ @Rule
+ public ExpectedException exception = ExpectedException.none();
+
+ private DefaultQualityProfileLoader qpLoader;
+ private DefaultProjectRepositoriesFactory factory;
+ private ProjectRepositories projectRepositories;
+
+ @Before
+ public void setUp() {
+ projectRepositories = new ProjectRepositories();
+ projectRepositories.addQProfile(new QProfile("profile", "name", "lang", new Date()));
+
+ factory = mock(DefaultProjectRepositoriesFactory.class);
+ when(factory.create()).thenReturn(projectRepositories);
+ qpLoader = new DefaultQualityProfileLoader(factory);
+ }
+
+ @Test
+ public void test() {
+ Collection<QProfile> loaded = qpLoader.load("project", null);
+
+ assertThat(loaded).hasSize(1);
+ assertThat(loaded.iterator().next().key()).isEqualTo("profile");
+ verify(factory).create();
+ verifyNoMoreInteractions(factory);
+ }
+
+ @Test
+ public void testNoProfile() {
+ projectRepositories = new ProjectRepositories();
+ when(factory.create()).thenReturn(projectRepositories);
+
+ exception.expect(IllegalStateException.class);
+ exception.expectMessage("No quality profiles");
+
+ qpLoader.load("project", null);
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/repository/QualityProfileProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/repository/QualityProfileProviderTest.java
new file mode 100644
index 00000000000..357f0bcdcc5
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/repository/QualityProfileProviderTest.java
@@ -0,0 +1,94 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.repository;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+import org.sonar.batch.protocol.input.QProfile;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+
+import static org.mockito.Mockito.verify;
+import static org.assertj.core.api.Assertions.assertThat;
+import org.sonar.batch.rule.ModuleQProfiles;
+import org.sonar.api.batch.bootstrap.ProjectDefinition;
+import org.junit.Test;
+import org.sonar.batch.analysis.AnalysisProperties;
+import org.mockito.MockitoAnnotations;
+import org.sonar.api.batch.AnalysisMode;
+import org.sonar.api.batch.bootstrap.ProjectReactor;
+import org.mockito.Mock;
+import org.junit.Before;
+
+public class QualityProfileProviderTest {
+ private QualityProfileProvider qualityProfileProvider;
+
+ @Mock
+ private QualityProfileLoader loader;
+ @Mock
+ private ProjectReactor projectReactor;
+ @Mock
+ private AnalysisMode mode;
+ @Mock
+ private AnalysisProperties props;
+
+ private Collection<QProfile> response;
+
+ @Before
+ public void setUp() {
+ MockitoAnnotations.initMocks(this);
+ qualityProfileProvider = new QualityProfileProvider();
+
+ ProjectDefinition root = mock(ProjectDefinition.class);
+ when(root.getKeyWithBranch()).thenReturn("project");
+ when(projectReactor.getRoot()).thenReturn(root);
+
+ response = new ArrayList<QProfile>(1);
+ response.add(new QProfile("profile", "name", "lang", new Date()));
+ }
+
+ @Test
+ public void testProvide() {
+ when(loader.load("project", null)).thenReturn(response);
+ ModuleQProfiles qps = qualityProfileProvider.provide(projectReactor, loader, props, mode);
+ assertResponse(qps);
+
+ verify(loader).load("project", null);
+ }
+
+ @Test
+ public void testProfileProp() {
+ when(loader.load("project", "custom")).thenReturn(response);
+ when(props.property(ModuleQProfiles.SONAR_PROFILE_PROP)).thenReturn("custom");
+
+ ModuleQProfiles qps = qualityProfileProvider.provide(projectReactor, loader, props, mode);
+ assertResponse(qps);
+
+ verify(loader).load("project", "custom");
+ }
+
+ private void assertResponse(ModuleQProfiles qps) {
+ assertThat(qps.findAll()).hasSize(1);
+ assertThat(qps.findAll()).extracting("key").containsExactly("profile");
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/DefaultActiveRulesLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/DefaultActiveRulesLoaderTest.java
new file mode 100644
index 00000000000..7c3f2e118b1
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/DefaultActiveRulesLoaderTest.java
@@ -0,0 +1,70 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2014 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.rule;
+
+import org.sonar.batch.repository.DefaultProjectRepositoriesFactory;
+
+import com.google.common.collect.ImmutableList;
+import org.sonar.batch.protocol.input.ActiveRule;
+import org.junit.Test;
+import org.sonar.batch.protocol.input.ProjectRepositories;
+
+import java.util.Collection;
+
+import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
+import static org.mockito.Mockito.verifyNoMoreInteractions;
+import static org.mockito.Mockito.when;
+import org.junit.Before;
+
+public class DefaultActiveRulesLoaderTest {
+ private DefaultActiveRulesLoader loader;
+ private DefaultProjectRepositoriesFactory factory;
+ private ProjectRepositories projectRepositories;
+
+ private ActiveRule response;
+
+ @Before
+ public void setUp() {
+ response = mock(ActiveRule.class);
+ when(response.ruleKey()).thenReturn("rule");
+
+ projectRepositories = new ProjectRepositories();
+ projectRepositories.addActiveRule(response);
+
+ factory = mock(DefaultProjectRepositoriesFactory.class);
+ when(factory.create()).thenReturn(projectRepositories);
+ loader = new DefaultActiveRulesLoader(factory);
+ }
+
+ @Test
+ public void test() {
+ Collection<String> profiles = ImmutableList.of("profile1");
+ Collection<ActiveRule> activeRules = loader.load(profiles, "project");
+
+ assertThat(activeRules).hasSize(1);
+ assertThat(activeRules.iterator().next().ruleKey()).isEqualTo("rule");
+
+ verify(factory).create();
+ verifyNoMoreInteractions(factory);
+ }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java
index c8a5f506018..b68eee07f32 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ModuleSettingsTest.java
@@ -19,9 +19,11 @@
*/
package org.sonar.batch.scan;
-import org.sonar.batch.analysis.DefaultAnalysisMode;
+import com.google.common.collect.HashBasedTable;
import com.google.common.collect.ImmutableMap;
+import com.google.common.collect.ImmutableTable;
+import com.google.common.collect.Table;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
@@ -29,10 +31,13 @@ import org.junit.rules.ExpectedException;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.utils.MessageException;
+import org.sonar.batch.analysis.DefaultAnalysisMode;
import org.sonar.batch.bootstrap.GlobalSettings;
-import org.sonar.batch.protocol.input.ProjectRepositories;
+import org.sonar.batch.protocol.input.FileData;
+import org.sonar.batch.repository.ProjectSettingsRepo;
import java.util.List;
+import java.util.Map;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
@@ -43,15 +48,23 @@ public class ModuleSettingsTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
- ProjectRepositories projectRef;
private DefaultAnalysisMode mode;
@Before
public void before() {
- projectRef = new ProjectRepositories();
mode = mock(DefaultAnalysisMode.class);
}
+ private ProjectSettingsRepo createSettings(String module, Map<String, String> settingsMap) {
+ Table<String, String, FileData> fileData = ImmutableTable.of();
+ Table<String, String, String> settings = HashBasedTable.create();
+
+ for (Map.Entry<String, String> e : settingsMap.entrySet()) {
+ settings.put(module, e.getKey(), e.getValue());
+ }
+ return new ProjectSettingsRepo(settings, fileData, null);
+ }
+
@Test
public void testOrderedProjects() {
ProjectDefinition grandParent = ProjectDefinition.create();
@@ -74,11 +87,12 @@ public class ModuleSettingsTest {
"overridding", "batch",
"on-batch", "true"
));
- projectRef.addSettings("struts-core", ImmutableMap.of("on-module", "true", "overridding", "module"));
+
+ ProjectSettingsRepo projSettingsRepo = createSettings("struts-core", ImmutableMap.of("on-module", "true", "overridding", "module"));
ProjectDefinition module = ProjectDefinition.create().setKey("struts-core");
- ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projectRef, mode);
+ ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projSettingsRepo, mode);
assertThat(moduleSettings.getString("overridding")).isEqualTo("module");
assertThat(moduleSettings.getString("on-batch")).isEqualTo("true");
@@ -93,11 +107,12 @@ public class ModuleSettingsTest {
when(batchSettings.getProperties()).thenReturn(ImmutableMap.of(
"sonar.foo.secured", "bar"
));
- projectRef.addSettings("struts-core", ImmutableMap.of("sonar.foo.license.secured", "bar2"));
+
+ ProjectSettingsRepo projSettingsRepo = createSettings("struts-core", ImmutableMap.of("sonar.foo.license.secured", "bar2"));
ProjectDefinition module = ProjectDefinition.create().setKey("struts-core");
- ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projectRef, mode);
+ ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projSettingsRepo, mode);
assertThat(moduleSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2");
assertThat(moduleSettings.getString("sonar.foo.secured")).isEqualTo("bar");
@@ -110,13 +125,14 @@ public class ModuleSettingsTest {
when(batchSettings.getProperties()).thenReturn(ImmutableMap.of(
"sonar.foo.secured", "bar"
));
- projectRef.addSettings("struts-core", ImmutableMap.of("sonar.foo.license.secured", "bar2"));
+
+ ProjectSettingsRepo projSettingsRepo = createSettings("struts-core", ImmutableMap.of("sonar.foo.license.secured", "bar2"));
when(mode.isIssues()).thenReturn(true);
ProjectDefinition module = ProjectDefinition.create().setKey("struts-core");
- ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projectRef, mode);
+ ModuleSettings moduleSettings = new ModuleSettings(batchSettings, module, projSettingsRepo, mode);
assertThat(moduleSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2");
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorBuilderTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorBuilderTest.java
index 5ba26864ec4..75900b811de 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorBuilderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorBuilderTest.java
@@ -20,7 +20,8 @@
package org.sonar.batch.scan;
import org.apache.commons.lang.StringUtils;
-
+import org.junit.Before;
+import org.sonar.api.batch.AnalysisMode;
import org.sonar.batch.analysis.AnalysisProperties;
import com.google.common.collect.Maps;
import org.junit.Rule;
@@ -38,6 +39,9 @@ import java.util.List;
import java.util.Map;
import java.util.Properties;
+import static org.mockito.Mockito.when;
+
+import static org.mockito.Mockito.mock;
import static org.assertj.core.api.Assertions.assertThat;
public class ProjectReactorBuilderTest {
@@ -45,6 +49,13 @@ public class ProjectReactorBuilderTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
+ private AnalysisMode mode;
+
+ @Before
+ public void setUp() {
+ mode = mock(AnalysisMode.class);
+ }
+
@Test
public void shouldDefineSimpleProject() {
ProjectDefinition projectDefinition = loadProjectDefinition("simple-project");
@@ -78,12 +89,11 @@ public class ProjectReactorBuilderTest {
public void shouldNotFailIfBlankSourceDirectory() {
loadProjectDefinition("simple-project-with-blank-source-dir");
}
-
+
@Test
public void modulesRepeatedIds() {
thrown.expect(IllegalStateException.class);
thrown.expectMessage("Two modules have the same id: module1");
-
loadProjectDefinition("multi-module-repeated-id");
}
@@ -101,8 +111,8 @@ public class ProjectReactorBuilderTest {
assertThat(rootProject.getTestDirs().contains("tests")).isFalse();
assertThat(rootProject.getBinaries().contains("target/classes")).isFalse();
// and module properties must have been cleaned
- assertThat(rootProject.getProperties().getProperty("module1.sonar.projectKey")).isNull();
- assertThat(rootProject.getProperties().getProperty("module2.sonar.projectKey")).isNull();
+ assertThat(rootProject.properties().get("module1.sonar.projectKey")).isNull();
+ assertThat(rootProject.properties().get("module2.sonar.projectKey")).isNull();
// Check baseDir and workDir
assertThat(rootProject.getBaseDir().getCanonicalFile())
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-all-in-root"));
@@ -125,8 +135,8 @@ public class ProjectReactorBuilderTest {
assertThat(module1.getTestDirs()).contains("tests");
assertThat(module1.getBinaries()).contains("target/classes");
// and module properties must have been cleaned
- assertThat(module1.getProperties().getProperty("module1.sonar.projectKey")).isNull();
- assertThat(module1.getProperties().getProperty("module2.sonar.projectKey")).isNull();
+ assertThat(module1.properties().get("module1.sonar.projectKey")).isNull();
+ assertThat(module1.properties().get("module2.sonar.projectKey")).isNull();
// Check baseDir and workDir
assertThat(module1.getBaseDir().getCanonicalFile())
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-all-in-root/module1"));
@@ -144,8 +154,8 @@ public class ProjectReactorBuilderTest {
assertThat(module2.getTestDirs()).contains("tests");
assertThat(module2.getBinaries()).contains("target/classes");
// and module properties must have been cleaned
- assertThat(module2.getProperties().getProperty("module1.sonar.projectKey")).isNull();
- assertThat(module2.getProperties().getProperty("module2.sonar.projectKey")).isNull();
+ assertThat(module2.properties().get("module1.sonar.projectKey")).isNull();
+ assertThat(module2.properties().get("module2.sonar.projectKey")).isNull();
// Check baseDir and workDir
assertThat(module2.getBaseDir().getCanonicalFile())
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-all-in-root/module2"));
@@ -160,8 +170,8 @@ public class ProjectReactorBuilderTest {
// CHECK ROOT
// module properties must have been cleaned
- assertThat(rootProject.getProperties().getProperty("module1.sonar.moduleKey")).isNull();
- assertThat(rootProject.getProperties().getProperty("module2.sonar.moduleKey")).isNull();
+ assertThat(rootProject.properties().get("module1.sonar.moduleKey")).isNull();
+ assertThat(rootProject.properties().get("module2.sonar.moduleKey")).isNull();
// CHECK MODULES
List<ProjectDefinition> modules = rootProject.getSubProjects();
@@ -301,8 +311,8 @@ public class ProjectReactorBuilderTest {
public void multiModuleProperties() {
ProjectDefinition projectDefinition = loadProjectDefinition("big-multi-module-definitions-all-in-root");
- assertThat(projectDefinition.getProperties().getProperty("module11.property")).isNull();
- assertThat(projectDefinition.getProperties().getProperty("sonar.profile")).isEqualTo("Foo");
+ assertThat(projectDefinition.properties().get("module11.property")).isNull();
+ assertThat(projectDefinition.properties().get("sonar.profile")).isEqualTo("Foo");
ProjectDefinition module1 = null;
ProjectDefinition module2 = null;
for (ProjectDefinition prj : projectDefinition.getSubProjects()) {
@@ -312,12 +322,12 @@ public class ProjectReactorBuilderTest {
module2 = prj;
}
}
- assertThat(module1.getProperties().getProperty("module11.property")).isNull();
- assertThat(module1.getProperties().getProperty("property")).isNull();
- assertThat(module1.getProperties().getProperty("sonar.profile")).isEqualTo("Foo");
- assertThat(module2.getProperties().getProperty("module11.property")).isNull();
- assertThat(module2.getProperties().getProperty("property")).isNull();
- assertThat(module2.getProperties().getProperty("sonar.profile")).isEqualTo("Foo");
+ assertThat(module1.properties().get("module11.property")).isNull();
+ assertThat(module1.properties().get("property")).isNull();
+ assertThat(module1.properties().get("sonar.profile")).isEqualTo("Foo");
+ assertThat(module2.properties().get("module11.property")).isNull();
+ assertThat(module2.properties().get("property")).isNull();
+ assertThat(module2.properties().get("sonar.profile")).isEqualTo("Foo");
ProjectDefinition module11 = null;
ProjectDefinition module12 = null;
@@ -328,13 +338,13 @@ public class ProjectReactorBuilderTest {
module12 = prj;
}
}
- assertThat(module11.getProperties().getProperty("module1.module11.property")).isNull();
- assertThat(module11.getProperties().getProperty("module11.property")).isNull();
- assertThat(module11.getProperties().getProperty("property")).isEqualTo("My module11 property");
- assertThat(module11.getProperties().getProperty("sonar.profile")).isEqualTo("Foo");
- assertThat(module12.getProperties().getProperty("module11.property")).isNull();
- assertThat(module12.getProperties().getProperty("property")).isNull();
- assertThat(module12.getProperties().getProperty("sonar.profile")).isEqualTo("Foo");
+ assertThat(module11.properties().get("module1.module11.property")).isNull();
+ assertThat(module11.properties().get("module11.property")).isNull();
+ assertThat(module11.properties().get("property")).isEqualTo("My module11 property");
+ assertThat(module11.properties().get("sonar.profile")).isEqualTo("Foo");
+ assertThat(module12.properties().get("module11.property")).isNull();
+ assertThat(module12.properties().get("property")).isNull();
+ assertThat(module12.properties().get("sonar.profile")).isEqualTo("Foo");
}
@Test
@@ -344,7 +354,7 @@ public class ProjectReactorBuilderTest {
AnalysisProperties taskProperties = new AnalysisProperties(props, null);
assertThat(taskProperties.property("module1.module11.property")).isEqualTo("My module11 property");
- new ProjectReactorBuilder(taskProperties).execute();
+ new ProjectReactorBuilder(taskProperties, mode).execute();
assertThat(taskProperties.property("module1.module11.property")).isNull();
}
@@ -443,19 +453,27 @@ public class ProjectReactorBuilderTest {
@Test
public void shouldInitRootWorkDir() {
- ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(Maps.<String, String>newHashMap(), null));
+ ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(Maps.<String, String>newHashMap(), null), mode);
File baseDir = new File("target/tmp/baseDir");
File workDir = builder.initRootProjectWorkDir(baseDir, Maps.<String, String>newHashMap());
assertThat(workDir).isEqualTo(new File(baseDir, ".sonar"));
}
+
+ @Test
+ public void nonAssociatedMode() {
+ when(mode.isIssues()).thenReturn(true);
+ ProjectDefinition project = loadProjectDefinition("multi-module-with-basedir-not-associated");
+
+ assertThat(project.getKey()).isEqualTo("project");
+ }
@Test
public void shouldInitWorkDirWithCustomRelativeFolder() {
Map<String, String> props = Maps.<String, String>newHashMap();
props.put("sonar.working.directory", ".foo");
- ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(props, null));
+ ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(props, null), mode);
File baseDir = new File("target/tmp/baseDir");
File workDir = builder.initRootProjectWorkDir(baseDir, props);
@@ -467,7 +485,7 @@ public class ProjectReactorBuilderTest {
public void shouldInitRootWorkDirWithCustomAbsoluteFolder() {
Map<String, String> props = Maps.<String, String>newHashMap();
props.put("sonar.working.directory", new File("src").getAbsolutePath());
- ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(props, null));
+ ProjectReactorBuilder builder = new ProjectReactorBuilder(new AnalysisProperties(props, null), mode);
File baseDir = new File("target/tmp/baseDir");
File workDir = builder.initRootProjectWorkDir(baseDir, props);
@@ -477,16 +495,16 @@ public class ProjectReactorBuilderTest {
@Test
public void shouldFailIf2ModulesWithSameKey() {
- Properties props = new Properties();
+ Map<String, String> props = new HashMap<>();
props.put("sonar.projectKey", "root");
ProjectDefinition root = ProjectDefinition.create().setProperties(props);
- Properties props1 = new Properties();
+ Map<String, String> props1 = new HashMap<>();
props1.put("sonar.projectKey", "mod1");
root.addSubProject(ProjectDefinition.create().setProperties(props1));
// Check uniqueness of a new module: OK
- Properties props2 = new Properties();
+ Map<String, String> props2 = new HashMap<>();
props2.put("sonar.projectKey", "mod2");
ProjectDefinition mod2 = ProjectDefinition.create().setProperties(props2);
ProjectReactorBuilder.checkUniquenessOfChildKey(mod2, root);
@@ -519,7 +537,7 @@ public class ProjectReactorBuilderTest {
private ProjectDefinition loadProjectDefinition(String projectFolder) {
Map<String, String> props = loadProps(projectFolder);
AnalysisProperties bootstrapProps = new AnalysisProperties(props, null);
- ProjectReactor projectReactor = new ProjectReactorBuilder(bootstrapProps).execute();
+ ProjectReactor projectReactor = new ProjectReactorBuilder(bootstrapProps,mode).execute();
return projectReactor.getRoot();
}
@@ -594,8 +612,8 @@ public class ProjectReactorBuilderTest {
assertThat(rootProject.getTestDirs().contains("tests")).isFalse();
assertThat(rootProject.getBinaries().contains("target/classes")).isFalse();
// and module properties must have been cleaned
- assertThat(rootProject.getProperties().getProperty("module1.sonar.projectKey")).isNull();
- assertThat(rootProject.getProperties().getProperty("module2.sonar.projectKey")).isNull();
+ assertThat(rootProject.properties().get("module1.sonar.projectKey")).isNull();
+ assertThat(rootProject.properties().get("module2.sonar.projectKey")).isNull();
// Check baseDir and workDir
assertThat(rootProject.getBaseDir().getCanonicalFile())
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-same-prefix"));
@@ -618,8 +636,8 @@ public class ProjectReactorBuilderTest {
assertThat(module1.getTestDirs()).contains("tests");
assertThat(module1.getBinaries()).contains("target/classes");
// and module properties must have been cleaned
- assertThat(module1.getProperties().getProperty("module1.sonar.projectKey")).isNull();
- assertThat(module1.getProperties().getProperty("module2.sonar.projectKey")).isNull();
+ assertThat(module1.properties().get("module1.sonar.projectKey")).isNull();
+ assertThat(module1.properties().get("module2.sonar.projectKey")).isNull();
// Check baseDir and workDir
assertThat(module1.getBaseDir().getCanonicalFile())
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-same-prefix/module1"));
@@ -637,8 +655,8 @@ public class ProjectReactorBuilderTest {
assertThat(module1Feature.getTestDirs()).contains("tests");
assertThat(module1Feature.getBinaries()).contains("target/classes");
// and module properties must have been cleaned
- assertThat(module1Feature.getProperties().getProperty("module1.sonar.projectKey")).isNull();
- assertThat(module1Feature.getProperties().getProperty("module2.sonar.projectKey")).isNull();
+ assertThat(module1Feature.properties().get("module1.sonar.projectKey")).isNull();
+ assertThat(module1Feature.properties().get("module2.sonar.projectKey")).isNull();
// Check baseDir and workDir
assertThat(module1Feature.getBaseDir().getCanonicalFile())
.isEqualTo(TestUtils.getResource(this.getClass(), "multi-module-definitions-same-prefix/module1.feature"));
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorValidatorTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorValidatorTest.java
index acc6fa82c34..1cb70ff6dcb 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorValidatorTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectReactorValidatorTest.java
@@ -27,7 +27,6 @@ import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.batch.bootstrap.ProjectReactor;
import org.sonar.api.config.Settings;
-import org.sonar.api.utils.SonarException;
public class ProjectReactorValidatorTest {
@@ -90,7 +89,7 @@ public class ProjectReactorValidatorTest {
public void fail_with_invalid_key() {
ProjectReactor reactor = createProjectReactor("foo$bar");
- thrown.expect(SonarException.class);
+ thrown.expect(IllegalStateException.class);
thrown.expectMessage("\"foo$bar\" is not a valid project or module key");
validator.validate(reactor);
}
@@ -99,7 +98,7 @@ public class ProjectReactorValidatorTest {
public void fail_with_backslash_in_key() {
ProjectReactor reactor = createProjectReactor("foo\\bar");
- thrown.expect(SonarException.class);
+ thrown.expect(IllegalStateException.class);
thrown.expectMessage("\"foo\\bar\" is not a valid project or module key");
validator.validate(reactor);
}
@@ -117,7 +116,7 @@ public class ProjectReactorValidatorTest {
@Test
public void fail_with_invalid_branch() {
ProjectReactor reactor = createProjectReactor("foo", "bran#ch");
- thrown.expect(SonarException.class);
+ thrown.expect(IllegalStateException.class);
thrown.expectMessage("\"bran#ch\" is not a valid branch name");
validator.validate(reactor);
}
@@ -125,7 +124,7 @@ public class ProjectReactorValidatorTest {
@Test
public void fail_with_colon_in_branch() {
ProjectReactor reactor = createProjectReactor("foo", "bran:ch");
- thrown.expect(SonarException.class);
+ thrown.expect(IllegalStateException.class);
thrown.expectMessage("\"bran:ch\" is not a valid branch name");
validator.validate(reactor);
}
@@ -134,7 +133,7 @@ public class ProjectReactorValidatorTest {
public void fail_with_only_digits() {
ProjectReactor reactor = createProjectReactor("12345");
- thrown.expect(SonarException.class);
+ thrown.expect(IllegalStateException.class);
thrown.expectMessage("\"12345\" is not a valid project or module key");
validator.validate(reactor);
}
@@ -144,7 +143,7 @@ public class ProjectReactorValidatorTest {
ProjectReactor reactor = createProjectReactor("foo");
settings.setProperty("sonar.phase", "phase");
- thrown.expect(SonarException.class);
+ thrown.expect(IllegalStateException.class);
thrown.expectMessage("\"sonar.phase\" is deprecated");
validator.validate(reactor);
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java
index de99ed8e909..412b563e2ac 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/ProjectSettingsTest.java
@@ -19,8 +19,13 @@
*/
package org.sonar.batch.scan;
-import org.sonar.batch.analysis.DefaultAnalysisMode;
+import org.sonar.batch.protocol.input.FileData;
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+import com.google.common.collect.ImmutableTable;
+import org.sonar.batch.repository.ProjectSettingsRepo;
+import org.sonar.batch.analysis.DefaultAnalysisMode;
import org.sonar.batch.bootstrap.GlobalMode;
import com.google.common.collect.ImmutableMap;
@@ -40,7 +45,6 @@ import org.sonar.api.utils.log.LoggerLevel;
import org.sonar.batch.bootstrap.GlobalProperties;
import org.sonar.batch.bootstrap.GlobalSettings;
import org.sonar.batch.protocol.input.GlobalRepositories;
-import org.sonar.batch.protocol.input.ProjectRepositories;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -52,16 +56,20 @@ public class ProjectSettingsTest {
@Rule
public LogTester logTester = new LogTester();
- ProjectRepositories projectRef;
- ProjectDefinition project = ProjectDefinition.create().setKey("struts");
- GlobalSettings bootstrapProps;
+ private ProjectSettingsRepo projectRef;
+ private ProjectDefinition project;
+ private GlobalSettings bootstrapProps;
+ private Table<String, String, FileData> emptyFileData;
+ private Table<String, String, String> emptySettings;
private GlobalMode globalMode;
private DefaultAnalysisMode mode;
@Before
public void prepare() {
- projectRef = new ProjectRepositories();
+ emptyFileData = ImmutableTable.of();
+ emptySettings = ImmutableTable.of();
+ project = ProjectDefinition.create().setKey("struts");
globalMode = mock(GlobalMode.class);
mode = mock(DefaultAnalysisMode.class);
bootstrapProps = new GlobalSettings(new GlobalProperties(Collections.<String, String>emptyMap()), new PropertyDefinitions(), new GlobalRepositories(), globalMode);
@@ -71,6 +79,7 @@ public class ProjectSettingsTest {
public void should_load_project_props() {
project.setProperty("project.prop", "project");
+ projectRef = new ProjectSettingsRepo(emptySettings, emptyFileData, null);
ProjectSettings batchSettings = new ProjectSettings(new ProjectReactor(project), bootstrapProps, new PropertyDefinitions(), projectRef, mode);
assertThat(batchSettings.getString("project.prop")).isEqualTo("project");
@@ -78,10 +87,12 @@ public class ProjectSettingsTest {
@Test
public void should_load_project_root_settings() {
- projectRef.addSettings("struts", ImmutableMap.of("sonar.cpd.cross", "true", "sonar.java.coveragePlugin", "jacoco"));
+ Table<String, String, String> settings = HashBasedTable.create();
+ settings.put("struts", "sonar.cpd.cross", "true");
+ settings.put("struts", "sonar.java.coveragePlugin", "jacoco");
+ projectRef = new ProjectSettingsRepo(settings, emptyFileData, null);
ProjectSettings batchSettings = new ProjectSettings(new ProjectReactor(project), bootstrapProps, new PropertyDefinitions(), projectRef, mode);
-
assertThat(batchSettings.getString("sonar.java.coveragePlugin")).isEqualTo("jacoco");
}
@@ -89,7 +100,11 @@ public class ProjectSettingsTest {
public void should_load_project_root_settings_on_branch() {
project.setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, "mybranch");
- projectRef.addSettings("struts:mybranch", ImmutableMap.of("sonar.cpd.cross", "true", "sonar.java.coveragePlugin", "jacoco"));
+ Table<String, String, String> settings = HashBasedTable.create();
+ settings.put("struts:mybranch", "sonar.cpd.cross", "true");
+ settings.put("struts:mybranch", "sonar.java.coveragePlugin", "jacoco");
+
+ projectRef = new ProjectSettingsRepo(settings, emptyFileData, null);
ProjectSettings batchSettings = new ProjectSettings(new ProjectReactor(project), bootstrapProps, new PropertyDefinitions(), projectRef, mode);
@@ -98,8 +113,11 @@ public class ProjectSettingsTest {
@Test
public void should_not_fail_when_accessing_secured_properties() {
- projectRef.addSettings("struts", ImmutableMap.of("sonar.foo.secured", "bar", "sonar.foo.license.secured", "bar2"));
+ Table<String, String, String> settings = HashBasedTable.create();
+ settings.put("struts", "sonar.foo.secured", "bar");
+ settings.put("struts", "sonar.foo.license.secured", "bar2");
+ projectRef = new ProjectSettingsRepo(settings, emptyFileData, null);
ProjectSettings batchSettings = new ProjectSettings(new ProjectReactor(project), bootstrapProps, new PropertyDefinitions(), projectRef, mode);
assertThat(batchSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2");
@@ -108,10 +126,13 @@ public class ProjectSettingsTest {
@Test
public void should_fail_when_accessing_secured_properties_in_issues_mode() {
- projectRef.addSettings("struts", ImmutableMap.of("sonar.foo.secured", "bar", "sonar.foo.license.secured", "bar2"));
+ Table<String, String, String> settings = HashBasedTable.create();
+ settings.put("struts", "sonar.foo.secured", "bar");
+ settings.put("struts", "sonar.foo.license.secured", "bar2");
when(mode.isIssues()).thenReturn(true);
+ projectRef = new ProjectSettingsRepo(settings, emptyFileData, null);
ProjectSettings batchSettings = new ProjectSettings(new ProjectReactor(project), bootstrapProps, new PropertyDefinitions(), projectRef, mode);
assertThat(batchSettings.getString("sonar.foo.license.secured")).isEqualTo("bar2");
@@ -123,10 +144,13 @@ public class ProjectSettingsTest {
@Test
public void should_log_a_warning_when_a_dropper_property_is_present() {
- GlobalSettings settings = new GlobalSettings(new GlobalProperties(ImmutableMap.of("sonar.qualitygate", "somevalue")), new PropertyDefinitions(), new GlobalRepositories(), globalMode);
+ GlobalSettings settings = new GlobalSettings(new GlobalProperties(ImmutableMap.of("sonar.qualitygate", "somevalue")), new PropertyDefinitions(), new GlobalRepositories(),
+ globalMode);
+ projectRef = new ProjectSettingsRepo(emptySettings, emptyFileData, null);
new ProjectSettings(new ProjectReactor(project), settings, new PropertyDefinitions(), projectRef, mode);
assertThat(logTester.logs(LoggerLevel.WARN)).containsOnly("Property 'sonar.qualitygate' is not supported any more. It will be ignored.");
}
+
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionFactoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionFactoryTest.java
index 53f5db28651..1e2f3ac3620 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionFactoryTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionFactoryTest.java
@@ -19,16 +19,16 @@
*/
package org.sonar.batch.scan.filesystem;
-import org.junit.Test;
-import org.sonar.batch.protocol.input.ProjectRepositories;
+import org.sonar.batch.repository.ProjectSettingsRepo;
+import org.junit.Test;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
public class StatusDetectionFactoryTest {
@Test
public void testCreate() throws Exception {
- StatusDetectionFactory factory = new StatusDetectionFactory(mock(ProjectRepositories.class));
+ StatusDetectionFactory factory = new StatusDetectionFactory(mock(ProjectSettingsRepo.class));
StatusDetection detection = factory.create();
assertThat(detection).isNotNull();
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java
index c8db34b4542..7aa79e5554e 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/StatusDetectionTest.java
@@ -19,23 +19,35 @@
*/
package org.sonar.batch.scan.filesystem;
+import com.google.common.collect.ImmutableTable;
+
+import com.google.common.collect.HashBasedTable;
+import com.google.common.collect.Table;
+
+import org.sonar.batch.repository.ProjectSettingsRepo;
import org.junit.Test;
import org.sonar.api.batch.fs.InputFile;
import org.sonar.batch.protocol.input.FileData;
-import org.sonar.batch.protocol.input.ProjectRepositories;
-
import static org.assertj.core.api.Assertions.assertThat;
public class StatusDetectionTest {
@Test
public void detect_status() {
- ProjectRepositories ref = new ProjectRepositories();
- ref.addFileData("foo", "src/Foo.java", new FileData("ABCDE", true));
- ref.addFileData("foo", "src/Bar.java", new FileData("FGHIJ", true));
+ Table<String, String, String> t = ImmutableTable.of();
+ ProjectSettingsRepo ref = new ProjectSettingsRepo(t, createTable(), null);
StatusDetection statusDetection = new StatusDetection(ref);
assertThat(statusDetection.status("foo", "src/Foo.java", "ABCDE")).isEqualTo(InputFile.Status.SAME);
assertThat(statusDetection.status("foo", "src/Foo.java", "XXXXX")).isEqualTo(InputFile.Status.CHANGED);
assertThat(statusDetection.status("foo", "src/Other.java", "QWERT")).isEqualTo(InputFile.Status.ADDED);
}
+
+ private static Table<String, String, FileData> createTable() {
+ Table<String, String, FileData> t = HashBasedTable.create();
+
+ t.put("foo", "src/Foo.java", new FileData("ABCDE", true));
+ t.put("foo", "src/Bar.java", new FileData("FGHIJ", true));
+
+ return t;
+ }
}
diff --git a/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo b/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo
new file mode 100644
index 00000000000..74d29a4fa08
--- /dev/null
+++ b/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_a/module_a1/src/main/xoo/com/sonar/it/samples/modules/a1/HelloA1.xoo
@@ -0,0 +1,16 @@
+package com.sonar.it.samples.modules.a1;
+
+public class HelloA1 {
+ private int i;
+ private HelloA1() {
+
+ }
+
+ public void hello() {
+ System.out.println("hello" + " xoo");
+ }
+
+ protected String getHello() {
+ return "hello";
+ }
+} \ No newline at end of file
diff --git a/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_a/module_a2/src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo b/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_a/module_a2/src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo
new file mode 100644
index 00000000000..42039538a92
--- /dev/null
+++ b/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_a/module_a2/src/main/xoo/com/sonar/it/samples/modules/a2/HelloA2.xoo
@@ -0,0 +1,12 @@
+package com.sonar.it.samples.modules.a2;
+
+public class HelloA2 {
+ private int i;
+ private HelloA2() {
+
+ }
+
+ public void hello() {
+ System.out.println("hello" + " xoo");
+ }
+} \ No newline at end of file
diff --git a/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_b/module_b1/src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo b/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_b/module_b1/src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo
new file mode 100644
index 00000000000..b83c3af128c
--- /dev/null
+++ b/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_b/module_b1/src/main/xoo/com/sonar/it/samples/modules/b1/HelloB1.xoo
@@ -0,0 +1,12 @@
+package com.sonar.it.samples.modules.b1;
+
+public class HelloB1 {
+ private int i;
+ private HelloB1() {
+
+ }
+
+ public void hello() {
+ System.out.println("hello" + " world");
+ }
+} \ No newline at end of file
diff --git a/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_b/module_b2/src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo b/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_b/module_b2/src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo
new file mode 100644
index 00000000000..20b8bb3876a
--- /dev/null
+++ b/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/module_b/module_b2/src/main/xoo/com/sonar/it/samples/modules/b2/HelloB2.xoo
@@ -0,0 +1,12 @@
+package com.sonar.it.samples.modules.b2;
+
+public class HelloB2 {
+ private int i;
+ private HelloB2() {
+
+ }
+
+ public void hello() {
+ System.out.println("hello" + " world");
+ }
+} \ No newline at end of file
diff --git a/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/sonar-project.properties b/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/sonar-project.properties
new file mode 100644
index 00000000000..c2b00ede37c
--- /dev/null
+++ b/sonar-batch/src/test/resources/mediumtest/xoo/multi-modules-sample-not-associated/sonar-project.properties
@@ -0,0 +1,31 @@
+# Root project information
+#sonar.projectKey=com.sonarsource.it.samples:multi-modules-sample
+sonar.projectName=Sonar :: Integration Tests :: Multi-modules Sample
+sonar.projectVersion=1.0-SNAPSHOT
+
+sonar.language=xoo
+
+# Some properties that will be inherited by the modules
+sonar.sources=src/main/xoo
+
+# List of the module identifiers
+sonar.modules=module_a,module_b
+
+module_a.sonar.projectKey=module_a
+module_a.sonar.projectName=Module A
+
+module_a.sonar.modules=module_a1,module_a2
+
+module_a.module_a1.sonar.projectName=Sub-module A1
+
+module_a.module_a2.sonar.projectName=Sub-module A2
+
+
+module_b.sonar.projectKey=module_b
+module_b.sonar.projectName=Module B
+
+module_b.sonar.modules=module_b1,module_b2
+
+module_b.module_b1.sonar.projectName=Sub-module B1
+
+module_b.module_b2.sonar.projectName=Sub-module B2
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/cache/ProjectCacheSynchronizerTest/api_sources_hash_GitScmProvider.text b/sonar-batch/src/test/resources/org/sonar/batch/cache/ProjectCacheSynchronizerTest/api_sources_hash_GitScmProvider.text
deleted file mode 100644
index a9ad538e80a..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/cache/ProjectCacheSynchronizerTest/api_sources_hash_GitScmProvider.text
+++ /dev/null
@@ -1,49 +0,0 @@
-523048e7f5ca9550505f2d8ea6d587e7
-50ff1975ec4309da19591231c6b5104b
-eba1d423f8632818ce94c4eac1b90713
-6112a40c70ed55453a0753030d5564a4
-3389dae361af79b04c9c8e7057f60cc6
-eac5fc1130394e7268b1cfbc54cd7e4d
-c0b153d8c08365f2de343e278d3b54c7
-eb4521cb5d193e1d37ecac25b0ffea43
-9210ed0dec59ed663c744d7fb68f0275
-3389dae361af79b04c9c8e7057f60cc6
-cd0fbdfa49d32525ecbdb8dab19dafe6
-ea12a10f5b7730daa639fe133867e088
-69739b9bc9312dfb1a6b8625a08c652a
-ec21e054f7f5748d0161fe27cdad6462
-3389dae361af79b04c9c8e7057f60cc6
-951a83e8074813100da0cba92092b385
-c93caecd79a332773cfb06cd5d3b8895
-5832d52d5fcb22a3350f62c856993f0d
-c4c9bdd47ee05028cb84873da0ebf2b5
-f89e422b117e518acef69df33f199d10
-
-90aa2aae2384f6412c3b86d085d5ffa5
-647f262205ad09f32b0091df388992ed
-
-943d54ba3e8812437c4d26ef8aa263f8
-
-340385b760d1441d3b74e5e39399cc0c
-
-a94613fd32125cd63160b0c1cf2bd078
-
-3415664f5f4a608772e6a4c73a993804
-597b7f5598c56e77bd28b9ff15a30802
-cbb184dd8e05c9709e5dcaedaa0495cf
-
-2c953c12d2eb6ea958b7f3045ecf8e81
-864d4d5a0cd65f52d791700443cec75e
-1b2437750694bba602fedc0a568c65de
-cbb184dd8e05c9709e5dcaedaa0495cf
-
-2c953c12d2eb6ea958b7f3045ecf8e81
-d18a921e891f6f9af8564a882efea289
-8bc5ef2851a7dcf1cf096a68e2a47ba6
-cbb184dd8e05c9709e5dcaedaa0495cf
-
-2c953c12d2eb6ea958b7f3045ecf8e81
-9cf0f8aa69740d88788fb437589ed33f
-0df2777822bbc7799716a10478ca58d4
-cbb184dd8e05c9709e5dcaedaa0495cf
-cbb184dd8e05c9709e5dcaedaa0495cf
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/cache/ProjectCacheSynchronizerTest/api_sources_hash_JGitBlameCommand.text b/sonar-batch/src/test/resources/org/sonar/batch/cache/ProjectCacheSynchronizerTest/api_sources_hash_JGitBlameCommand.text
deleted file mode 100644
index e21a25bd7b6..00000000000
--- a/sonar-batch/src/test/resources/org/sonar/batch/cache/ProjectCacheSynchronizerTest/api_sources_hash_JGitBlameCommand.text
+++ /dev/null
@@ -1,149 +0,0 @@
-523048e7f5ca9550505f2d8ea6d587e7
-50ff1975ec4309da19591231c6b5104b
-eba1d423f8632818ce94c4eac1b90713
-6112a40c70ed55453a0753030d5564a4
-3389dae361af79b04c9c8e7057f60cc6
-eac5fc1130394e7268b1cfbc54cd7e4d
-c0b153d8c08365f2de343e278d3b54c7
-eb4521cb5d193e1d37ecac25b0ffea43
-9210ed0dec59ed663c744d7fb68f0275
-3389dae361af79b04c9c8e7057f60cc6
-cd0fbdfa49d32525ecbdb8dab19dafe6
-ea12a10f5b7730daa639fe133867e088
-69739b9bc9312dfb1a6b8625a08c652a
-ec21e054f7f5748d0161fe27cdad6462
-3389dae361af79b04c9c8e7057f60cc6
-951a83e8074813100da0cba92092b385
-c93caecd79a332773cfb06cd5d3b8895
-5832d52d5fcb22a3350f62c856993f0d
-c4c9bdd47ee05028cb84873da0ebf2b5
-f89e422b117e518acef69df33f199d10
-
-9e0ae10d6ada18721c856844d765b465
-ea3c894506f93b88c9fc6c9790da9008
-c5c303a0f47f5f15f22b6776fc1c8c93
-4f592acdcfc11c97e7f19231de9d69b0
-6aea6951956275cb62d01063a1e695fe
-293f7a3f08e54359c17d5e984f721665
-18d24bd6a2c2c15d3914502e2776e372
-107e08f15be7e18888da7e69948ac3ba
-90aa2aae2384f6412c3b86d085d5ffa5
-ef76944333105582ae8d3a51d29b3b8a
-2a592c3d07126847ae4cbbed4a2b4d46
-6f382821d6f35beb6ae4080607046898
-
-943d54ba3e8812437c4d26ef8aa263f8
-6fa05171389dfbeda44181c98e580d18
-391715e38dad3a13b75205d527e82c8a
-bb3900a63a8cecc1e79592e054915c97
-7c8d40302b1200413bc859331a4f241d
-0e2ad2ad1ad56b970e4348a3967d1e81
-049ace1ff1516be8a5fd7cddc0ab2f30
-d2c44db3922004ac2ae41fb402d005b1
-b0ba7766e9e1fddaf40e86b62a5c2900
-
-62e220c0092e8ae61f5937f18e4b03bc
-
-a5eeb3bd06bd4499f8a9ad20ba426bbd
-
-2bb44a6b46970b3efd87cc8a68848fae
-
-5b9e24bad64529f3e35ba4f1aed892f2
-78f4e1ffbbf29629025b20f6b1be36f5
-cbb184dd8e05c9709e5dcaedaa0495cf
-
-2c953c12d2eb6ea958b7f3045ecf8e81
-0f253056876c021c4fd3f3e5ddc4d5b6
-520e98566046a173f9250aa3b7a40ec9
-c31394024dee65cba7e5c526c69af278
-80d5b17efc16ace990c07580fc3e85eb
-d28bc6d296024d650b16efe1369128b0
-38ba857d93d3a54a6b7f1bfc1b8fb090
-d41f14cd3267e8d9c17b47ddcb71b0c1
-54f339c05c18199eca937a31fdc07857
-7efc34bf8e2ba01cec26c50875ac8acd
-5a29aee8cfe3a5110dc892ab8adfc17f
-d271e10accbea4cb6365b85150505b0d
-cbb184dd8e05c9709e5dcaedaa0495cf
-cbb184dd8e05c9709e5dcaedaa0495cf
-
-319f70c2d340b01002c3539d09dabbec
-b225a5ae163bfc56684d172522993825
-791c95e71dd996b4d723f96df3f37ca4
-80d5b17efc16ace990c07580fc3e85eb
-2a8af480cbdcc0ee9b44187a078c8fe7
-4340b548cda0dbc6043cbf4cf49d1b12
-2df758e8d85494e7ee23a02d4c3aa6a7
-e44feb14b61ab99767239eaded464459
-eb375774c265dedeefeb29283ceea9bc
-c87c662bc284c5f9c01d3551957ee32e
-cbb184dd8e05c9709e5dcaedaa0495cf
-cbb184dd8e05c9709e5dcaedaa0495cf
-cbb184dd8e05c9709e5dcaedaa0495cf
-
-1fcefdfae441ded6478da69428a30f12
-8fcd1ffa896d0e214539b1bfa179f3e8
-7a64b5f6e57cc9f13d5a1be99b9f7c23
-8884d72adb8d93474c6af620a7d6fdba
-cbb184dd8e05c9709e5dcaedaa0495cf
-7e53b1d2085d8c7ae88417eccc5a0893
-cbb184dd8e05c9709e5dcaedaa0495cf
-
-5f68d8059a28922be107658c3890c230
-6ded45bc62f1d535345e67001dac69d5
-34165242e2230ffca31d7942ec577e6b
-02f5ec563dbaaef9ef402c6941a36c98
-784b65e21ca0539f3cefb1710ccc7768
-982e86cf85e0f121ba1a2f0ef462aa6b
-cbb184dd8e05c9709e5dcaedaa0495cf
-80d5b17efc16ace990c07580fc3e85eb
-34c0d764eb79cc7c6dccb53e711fd4be
-a5b2391dd7127292b7240c7c8c1ee92a
-54d7949984c901073fffda9956190c12
-da38c234aa3fdca9ec1e0e2b991d3568
-6b2decb38be3882440910fd75ec508cd
-ce51581950deb12616108c0e909f9c53
-cbb184dd8e05c9709e5dcaedaa0495cf
-cbb184dd8e05c9709e5dcaedaa0495cf
-
-e8165f1ae4cf11035542d4b60ac7b14d
-c8272ad357e7feaf2671a0612e52d3b5
-2c953c12d2eb6ea958b7f3045ecf8e81
-209935c0f7c635d91164fe2b14314a3d
-448b1c0a64288dbeac516ba67c9f2574
-540c13e9e156b687226421b24f2df178
-cbb184dd8e05c9709e5dcaedaa0495cf
-c0c97e22db5055def551d1cef15fb251
-cbb184dd8e05c9709e5dcaedaa0495cf
-
-8983f749749a87599ea48c8bc08cac86
-f298d78afda5708f64ded32af0e7f541
-248e216059cad9c12bc8ff8b3b6289e2
-80d5b17efc16ace990c07580fc3e85eb
-318ddd60a422c3d0435acd5f7aa6923c
-7c3bca9656325d15227ffac4ce5dfde9
-7d992ab2241888573c1c7bdfe5d33a35
-cd620097a91b074942d29535e822ebb0
-a50e423de97896afb97123424a960664
-35bb4ed816814a612f9605aec97c69fb
-cbb184dd8e05c9709e5dcaedaa0495cf
-280db1f26dcc577de8fc62d40627112b
-e5b027822061ae041ced3d958b6f7f37
-11a0dde589dec02e8d95c4ea6d83780f
-e5acab4c66ae60432ccc5a45d718d152
-3c4b4570f7e4c7037693b1aa1fd5a9ca
-420d9af4c91e3248bb2a4e72a683a03a
-d69bf14adaf9ea45b48c0fdfefa4f69d
-505b97969baa28c3f607a38ee02f4f2d
-cbb184dd8e05c9709e5dcaedaa0495cf
-da94121a62e940229bd622927ad7702f
-9d2a20a55b185c4a864efd3484a870fa
-cbb184dd8e05c9709e5dcaedaa0495cf
-daada2d57491a2d0b4d237f29fc039dc
-53220ad5b69915dec696a01167d5237b
-2fb05fbd558fb020eacca16faa325246
-cbb184dd8e05c9709e5dcaedaa0495cf
-423c485e2882c1fd9a1b19983b812f50
-cbb184dd8e05c9709e5dcaedaa0495cf
-
-cbb184dd8e05c9709e5dcaedaa0495cf
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/ProjectReactorBuilderTest/multi-module-with-basedir-not-associated/modules/module1/sources/Fake.java b/sonar-batch/src/test/resources/org/sonar/batch/scan/ProjectReactorBuilderTest/multi-module-with-basedir-not-associated/modules/module1/sources/Fake.java
new file mode 100644
index 00000000000..e67004defc5
--- /dev/null
+++ b/sonar-batch/src/test/resources/org/sonar/batch/scan/ProjectReactorBuilderTest/multi-module-with-basedir-not-associated/modules/module1/sources/Fake.java
@@ -0,0 +1 @@
+class Fake {}
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/scan/ProjectReactorBuilderTest/multi-module-with-basedir-not-associated/sonar-project.properties b/sonar-batch/src/test/resources/org/sonar/batch/scan/ProjectReactorBuilderTest/multi-module-with-basedir-not-associated/sonar-project.properties
new file mode 100644
index 00000000000..c572ef1f9e5
--- /dev/null
+++ b/sonar-batch/src/test/resources/org/sonar/batch/scan/ProjectReactorBuilderTest/multi-module-with-basedir-not-associated/sonar-project.properties
@@ -0,0 +1,14 @@
+#sonar.projectKey=com.foo.project
+sonar.projectName=Foo Project
+sonar.projectVersion=1.0-SNAPSHOT
+sonar.projectDescription=Description of Foo Project
+
+sonar.sources=sources
+sonar.tests=tests
+sonar.binaries=target/classes
+
+sonar.modules=module1
+
+module1.sonar.projectBaseDir=modules/module1
+module1.sonar.projectKey=com.foo.project.module1
+module1.sonar.projectName=Foo Module 1
diff --git a/sonar-home/src/main/java/org/sonar/home/cache/FileCache.java b/sonar-home/src/main/java/org/sonar/home/cache/FileCache.java
index 922a59e5e8d..6d926a918e6 100644
--- a/sonar-home/src/main/java/org/sonar/home/cache/FileCache.java
+++ b/sonar-home/src/main/java/org/sonar/home/cache/FileCache.java
@@ -117,7 +117,7 @@ public class FileCache {
return new File(dir, hash);
}
- private void mkdirQuietly(File hashDir) {
+ private static void mkdirQuietly(File hashDir) {
try {
Files.createDirectories(hashDir.toPath());
} catch (IOException e) {
diff --git a/sonar-home/src/main/java/org/sonar/home/cache/FileHashes.java b/sonar-home/src/main/java/org/sonar/home/cache/FileHashes.java
index 549f8d10f63..e79a9b4fd74 100644
--- a/sonar-home/src/main/java/org/sonar/home/cache/FileHashes.java
+++ b/sonar-home/src/main/java/org/sonar/home/cache/FileHashes.java
@@ -56,7 +56,7 @@ public class FileHashes {
}
}
- private byte[] digest(InputStream input, MessageDigest digest) throws IOException {
+ private static byte[] digest(InputStream input, MessageDigest digest) throws IOException {
final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
int read = input.read(buffer, 0, STREAM_BUFFER_LENGTH);
while (read > -1) {
diff --git a/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java b/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java
index c5c45090ed4..2b32c65b7f9 100644
--- a/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java
+++ b/sonar-home/src/main/java/org/sonar/home/cache/PersistentCache.java
@@ -19,7 +19,9 @@
*/
package org.sonar.home.cache;
+import java.io.FileInputStream;
import java.io.IOException;
+import java.io.InputStream;
import java.io.RandomAccessFile;
import java.nio.channels.FileChannel;
import java.nio.channels.FileLock;
@@ -28,6 +30,7 @@ import java.nio.charset.StandardCharsets;
import java.nio.file.DirectoryStream;
import java.nio.file.Files;
import java.nio.file.Path;
+import java.nio.file.StandardCopyOption;
import java.nio.file.attribute.BasicFileAttributes;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
@@ -77,7 +80,7 @@ public class PersistentCache {
@CheckForNull
public synchronized String getString(@Nonnull String obj, @Nullable final PersistentCacheLoader<String> valueLoader) throws IOException {
ValueLoaderDecoder decoder = valueLoader != null ? new ValueLoaderDecoder(valueLoader) : null;
-
+
byte[] cached = get(obj, decoder);
if (cached == null) {
@@ -88,6 +91,20 @@ public class PersistentCache {
}
@CheckForNull
+ public synchronized InputStream getStream(@Nonnull String obj) throws IOException {
+ String key = getKey(obj);
+
+ try {
+ lock();
+ Path path = getCacheCopy(key);
+ return new DeleteOnCloseInputStream(new FileInputStream(path.toFile()), path);
+
+ } finally {
+ unlock();
+ }
+ }
+
+ @CheckForNull
public synchronized byte[] get(@Nonnull String obj, @Nullable PersistentCacheLoader<byte[]> valueLoader) throws IOException {
String key = getKey(obj);
@@ -116,6 +133,16 @@ public class PersistentCache {
return null;
}
+
+ public synchronized void put(@Nonnull String obj, @Nonnull InputStream stream) throws IOException {
+ String key = getKey(obj);
+ try {
+ lock();
+ putCache(key, stream);
+ } finally {
+ unlock();
+ }
+ }
public synchronized void put(@Nonnull String obj, @Nonnull byte[] value) throws IOException {
String key = getKey(obj);
@@ -266,6 +293,11 @@ public class PersistentCache {
Path cachePath = getCacheEntryPath(key);
Files.write(cachePath, value, CREATE, WRITE, TRUNCATE_EXISTING);
}
+
+ private void putCache(String key, InputStream stream) throws IOException {
+ Path cachePath = getCacheEntryPath(key);
+ Files.copy(stream, cachePath, StandardCopyOption.REPLACE_EXISTING);
+ }
private byte[] getCache(String key) throws IOException {
Path cachePath = getCacheEntryPath(key);
@@ -277,6 +309,39 @@ public class PersistentCache {
return Files.readAllBytes(cachePath);
}
+ private Path getCacheCopy(String key) throws IOException {
+ Path cachePath = getCacheEntryPath(key);
+
+ if (!validateCacheEntry(cachePath, this.defaultDurationToExpireMs)) {
+ return null;
+ }
+
+ Path temp = Files.createTempFile("sonar_cache", null);
+ Files.copy(cachePath, temp, StandardCopyOption.REPLACE_EXISTING);
+ return temp;
+ }
+
+ private static class DeleteOnCloseInputStream extends InputStream {
+ private final InputStream stream;
+ private final Path p;
+
+ private DeleteOnCloseInputStream(InputStream stream, Path p) {
+ this.stream = stream;
+ this.p = p;
+ }
+
+ @Override
+ public int read() throws IOException {
+ return stream.read();
+ }
+
+ @Override
+ public void close() throws IOException {
+ stream.close();
+ Files.delete(p);
+ }
+ }
+
private boolean validateCacheEntry(Path cacheEntryPath, long durationToExpireMs) throws IOException {
if (!Files.exists(cacheEntryPath)) {
return false;