summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2012-11-05 14:22:11 +0100
committerSimon Brandhof <simon.brandhof@gmail.com>2012-11-05 14:23:47 +0100
commit3df00fb97661f12dabe98cd9a279080e586e9c0d (patch)
tree2c0285918454c3a3bbd734b5c54a2d3e1dde5f5f
parent81b76d8b6cbc8cc685c57e42d7a9c5a8dfac2ab6 (diff)
downloadsonarqube-3df00fb97661f12dabe98cd9a279080e586e9c0d.tar.gz
sonarqube-3df00fb97661f12dabe98cd9a279080e586e9c0d.zip
SONAR-3895 load settings from web service
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/ApplyProjectRolesDecorator.java2
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdPlugin.java15
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdSensor.java13
-rw-r--r--plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/IndexFactory.java40
-rw-r--r--plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdPluginTest.java6
-rw-r--r--plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java61
-rw-r--r--plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/index/IndexFactoryTest.java29
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseCompatibility.java (renamed from sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibility.java)13
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectExclusions.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectModule.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/config/BootstrapSettings.java2
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/config/BootstrapSettingsLoader.java (renamed from sonar-batch/src/main/java/org/sonar/batch/config/BatchDatabaseSettingsLoader.java)34
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/config/ProjectSettings.java112
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/local/DryRunDatabase.java5
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseCompatibilityTest.java (renamed from sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibilityTest.java)49
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectModuleTest.java7
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/config/ProjectSettingsTest.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java11
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/DbTemplate.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java10
-rw-r--r--sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java5
-rw-r--r--sonar-core/src/test/java/org/sonar/core/persistence/DatabaseVersionTest.java27
-rw-r--r--sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java4
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/persistence/DatabaseVersionTest/getSonarCoreId.xml3
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml9
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java17
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/controllers/api/properties_controller.rb40
-rw-r--r--sonar-server/src/main/webapp/WEB-INF/app/models/project.rb2
-rw-r--r--sonar-ws-client/src/test/java/org/sonar/wsclient/services/PropertyQueryTest.java32
31 files changed, 300 insertions, 264 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/ApplyProjectRolesDecorator.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/ApplyProjectRolesDecorator.java
index fc5e21bc95f..d2a4e7b3f81 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/ApplyProjectRolesDecorator.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/security/ApplyProjectRolesDecorator.java
@@ -23,6 +23,7 @@ import com.google.common.collect.ImmutableSet;
import org.slf4j.LoggerFactory;
import org.sonar.api.batch.Decorator;
import org.sonar.api.batch.DecoratorContext;
+import org.sonar.api.batch.DryRunIncompatible;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.Resource;
@@ -30,6 +31,7 @@ import org.sonar.api.security.ResourcePermissions;
import java.util.Set;
+@DryRunIncompatible
public class ApplyProjectRolesDecorator implements Decorator {
private final ResourcePermissions resourcePermissions;
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdPlugin.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdPlugin.java
index d911beb4399..81ac5d09f36 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdPlugin.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdPlugin.java
@@ -20,7 +20,11 @@
package org.sonar.plugins.cpd;
import com.google.common.collect.ImmutableList;
-import org.sonar.api.*;
+import org.sonar.api.CoreProperties;
+import org.sonar.api.Properties;
+import org.sonar.api.Property;
+import org.sonar.api.PropertyType;
+import org.sonar.api.SonarPlugin;
import org.sonar.plugins.cpd.decorators.DuplicationDensityDecorator;
import org.sonar.plugins.cpd.decorators.SumDuplicationsDecorator;
import org.sonar.plugins.cpd.index.IndexFactory;
@@ -37,6 +41,15 @@ import java.util.List;
module = true,
global = true,
category = CoreProperties.CATEGORY_DUPLICATIONS,
+ type = PropertyType.BOOLEAN),
+ @Property(
+ key = CoreProperties.CPD_SKIP_PROPERTY,
+ defaultValue = "false",
+ name = "Skip",
+ description = "Disable detection of duplications",
+ // not displayed in UI
+ project = false, module = false, global = false,
+ category = CoreProperties.CATEGORY_DUPLICATIONS,
type = PropertyType.BOOLEAN)
})
public final class CpdPlugin extends SonarPlugin {
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdSensor.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdSensor.java
index 754ef176ee0..bd3f6420710 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdSensor.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/CpdSensor.java
@@ -26,6 +26,7 @@ import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.Sensor;
import org.sonar.api.batch.SensorContext;
+import org.sonar.api.config.Settings;
import org.sonar.api.resources.Project;
public class CpdSensor implements Sensor {
@@ -34,10 +35,12 @@ public class CpdSensor implements Sensor {
private CpdEngine sonarEngine;
private CpdEngine sonarBridgeEngine;
+ private Settings settings;
- public CpdSensor(SonarEngine sonarEngine, SonarBridgeEngine sonarBridgeEngine) {
+ public CpdSensor(SonarEngine sonarEngine, SonarBridgeEngine sonarBridgeEngine, Settings settings) {
this.sonarEngine = sonarEngine;
this.sonarBridgeEngine = sonarBridgeEngine;
+ this.settings = settings;
}
public boolean shouldExecuteOnProject(Project project) {
@@ -65,9 +68,11 @@ public class CpdSensor implements Sensor {
@VisibleForTesting
boolean isSkipped(Project project) {
- Configuration conf = project.getConfiguration();
- return conf.getBoolean("sonar.cpd." + project.getLanguageKey() + ".skip",
- conf.getBoolean(CoreProperties.CPD_SKIP_PROPERTY, false));
+ String key = "sonar.cpd." + project.getLanguageKey() + ".skip";
+ if (settings.hasKey(key)) {
+ return settings.getBoolean(key);
+ }
+ return settings.getBoolean(CoreProperties.CPD_SKIP_PROPERTY);
}
public void analyse(Project project, SensorContext context) {
diff --git a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/IndexFactory.java b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/IndexFactory.java
index 033e359ec00..21335c46d0a 100644
--- a/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/IndexFactory.java
+++ b/plugins/sonar-cpd-plugin/src/main/java/org/sonar/plugins/cpd/index/IndexFactory.java
@@ -38,15 +38,6 @@ public class IndexFactory implements BatchExtension {
private final ResourcePersister resourcePersister;
private final DuplicationDao dao;
- /**
- * For dry run, where is no access to database.
- */
- public IndexFactory(Settings settings) {
- this.settings = settings;
- this.resourcePersister = null;
- this.dao = null;
- }
-
public IndexFactory(Settings settings, ResourcePersister resourcePersister, DuplicationDao dao) {
this.settings = settings;
this.resourcePersister = resourcePersister;
@@ -54,23 +45,28 @@ public class IndexFactory implements BatchExtension {
}
public SonarDuplicationsIndex create(Project project) {
- if (isCrossProject(project)) {
- LOG.info("Cross-project analysis enabled");
+ if (verifyCrossProject(project, LOG)) {
return new SonarDuplicationsIndex(new DbDuplicationsIndex(resourcePersister, project, dao));
- } else {
- LOG.info("Cross-project analysis disabled");
- return new SonarDuplicationsIndex();
}
+ return new SonarDuplicationsIndex();
}
- /**
- * @return true, if was enabled by user and database is available
- */
@VisibleForTesting
- boolean isCrossProject(Project project) {
- return settings.getBoolean(CoreProperties.CPD_CROSS_RPOJECT)
- && resourcePersister != null && dao != null
- && StringUtils.isBlank(project.getBranch());
- }
+ boolean verifyCrossProject(Project project, Logger logger) {
+ boolean crossProject = false;
+ if (settings.getBoolean(CoreProperties.CPD_CROSS_RPOJECT)) {
+ if (settings.getBoolean("sonar.dryRun")) {
+ logger.info("Cross-project analysis disabled. Not supported on dry runs.");
+ } else if (StringUtils.isNotBlank(project.getBranch())) {
+ logger.info("Cross-project analysis disabled. Not supported on project branches.");
+ } else {
+ logger.info("Cross-project analysis enabled");
+ crossProject = true;
+ }
+ } else {
+ logger.info("Cross-project analysis disabled");
+ }
+ return crossProject;
+ }
}
diff --git a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdPluginTest.java b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdPluginTest.java
index 0c309396e55..a3ec3f05048 100644
--- a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdPluginTest.java
+++ b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdPluginTest.java
@@ -19,14 +19,14 @@
*/
package org.sonar.plugins.cpd;
-import static org.hamcrest.number.OrderingComparisons.greaterThan;
-import static org.junit.Assert.assertThat;
import org.junit.Test;
+import static org.fest.assertions.Assertions.assertThat;
+
public class CpdPluginTest {
@Test
public void getExtensions() {
- assertThat(new CpdPlugin().getExtensions().size(), greaterThan(1));
+ assertThat(new CpdPlugin().getExtensions()).hasSize(6);
}
}
diff --git a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java
index d49dd75daf2..4d17611c5f0 100644
--- a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java
+++ b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/CpdSensorTest.java
@@ -22,70 +22,55 @@ package org.sonar.plugins.cpd;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.junit.Before;
import org.junit.Test;
+import org.sonar.api.config.PropertyDefinitions;
+import org.sonar.api.config.Settings;
import org.sonar.api.resources.Java;
import org.sonar.api.resources.Language;
import org.sonar.api.resources.Project;
import org.sonar.plugins.cpd.index.IndexFactory;
-import static junit.framework.Assert.assertFalse;
-import static junit.framework.Assert.assertTrue;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
+import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
public class CpdSensorTest {
- private SonarEngine sonarEngine;
- private SonarBridgeEngine sonarBridgeEngine;
- private CpdSensor sensor;
+ SonarEngine sonarEngine;
+ SonarBridgeEngine sonarBridgeEngine;
+ CpdSensor sensor;
+ Settings settings;
@Before
public void setUp() {
- IndexFactory indexFactory = new IndexFactory(null);
+ IndexFactory indexFactory = mock(IndexFactory.class);
sonarEngine = new SonarEngine(indexFactory);
sonarBridgeEngine = new SonarBridgeEngine(indexFactory);
- sensor = new CpdSensor(sonarEngine, sonarBridgeEngine);
+ settings = new Settings(new PropertyDefinitions(CpdPlugin.class));
+ sensor = new CpdSensor(sonarEngine, sonarBridgeEngine, settings);
}
@Test
- public void generalSkip() {
- PropertiesConfiguration conf = new PropertiesConfiguration();
- conf.setProperty("sonar.cpd.skip", "true");
-
- Project project = createJavaProject().setConfiguration(conf);
-
- assertTrue(sensor.isSkipped(project));
+ public void test_global_skip() {
+ settings.setProperty("sonar.cpd.skip", true);
+ assertThat(sensor.isSkipped(createJavaProject())).isTrue();
}
@Test
- public void doNotSkipByDefault() {
- Project project = createJavaProject().setConfiguration(new PropertiesConfiguration());
-
- assertFalse(sensor.isSkipped(project));
+ public void should_not_skip_by_default() {
+ assertThat(sensor.isSkipped(createJavaProject())).isFalse();
}
@Test
- public void shouldSkipByLanguage() {
-
- Project phpProject = createPhpProject();
- phpProject.getConfiguration().setProperty("sonar.cpd.skip", "false");
- phpProject.getConfiguration().setProperty("sonar.cpd.php.skip", "true");
- assertTrue(sensor.isSkipped(phpProject));
-
- Project javaProject = createJavaProject();
- javaProject.getConfiguration().setProperty("sonar.cpd.skip", "false");
- javaProject.getConfiguration().setProperty("sonar.cpd.php.skip", "true");
- assertFalse(sensor.isSkipped(javaProject));
-
+ public void should_skip_by_language() {
+ settings.setProperty("sonar.cpd.skip", false);
+ settings.setProperty("sonar.cpd.php.skip", true);
+ assertThat(sensor.isSkipped(createPhpProject())).isTrue();
+ assertThat(sensor.isSkipped(createJavaProject())).isFalse();
}
@Test
- public void engine() {
- Project phpProject = createPhpProject();
- Project javaProject = createJavaProject();
-
- assertThat(sensor.getEngine(javaProject), is((CpdEngine) sonarEngine));
- assertThat(sensor.getEngine(phpProject), is((CpdEngine) sonarBridgeEngine));
+ public void test_engine() {
+ assertThat(sensor.getEngine(createJavaProject())).isSameAs(sonarEngine);
+ assertThat(sensor.getEngine(createPhpProject())).isSameAs(sonarBridgeEngine);
}
private Project createJavaProject() {
diff --git a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/index/IndexFactoryTest.java b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/index/IndexFactoryTest.java
index 840a08a1af9..e73bffa4acc 100644
--- a/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/index/IndexFactoryTest.java
+++ b/plugins/sonar-cpd-plugin/src/test/java/org/sonar/plugins/cpd/index/IndexFactoryTest.java
@@ -21,54 +21,57 @@ package org.sonar.plugins.cpd.index;
import org.junit.Before;
import org.junit.Test;
+import org.slf4j.Logger;
import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.resources.Project;
import org.sonar.batch.index.ResourcePersister;
import org.sonar.core.duplication.DuplicationDao;
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
+import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.verify;
public class IndexFactoryTest {
- private Project project;
- private Settings settings;
+ Project project;
+ Settings settings;
+ IndexFactory factory;
+ Logger logger;
@Before
public void setUp() {
project = new Project("foo");
settings = new Settings();
+ factory = new IndexFactory(settings, mock(ResourcePersister.class), mock(DuplicationDao.class));
+ logger = mock(Logger.class);
}
@Test
public void crossProjectEnabled() {
settings.setProperty(CoreProperties.CPD_CROSS_RPOJECT, "true");
- IndexFactory factory = new IndexFactory(settings, mock(ResourcePersister.class), mock(DuplicationDao.class));
- assertThat(factory.isCrossProject(project), is(true));
+ assertThat(factory.verifyCrossProject(project, logger)).isTrue();
}
@Test
public void noCrossProjectWithBranch() {
settings.setProperty(CoreProperties.CPD_CROSS_RPOJECT, "true");
- IndexFactory factory = new IndexFactory(settings, mock(ResourcePersister.class), mock(DuplicationDao.class));
project.setBranch("branch");
- assertThat(factory.isCrossProject(project), is(false));
+ assertThat(factory.verifyCrossProject(project, logger)).isFalse();
}
@Test
- public void noCrossProjectWithoutDatabase() {
+ public void cross_project_should_be_disabled_on_dry_run() {
settings.setProperty(CoreProperties.CPD_CROSS_RPOJECT, "true");
- IndexFactory factory = new IndexFactory(settings);
- assertThat(factory.isCrossProject(project), is(false));
+ settings.setProperty("sonar.dryRun", "true");
+ assertThat(factory.verifyCrossProject(project, logger)).isFalse();
+ verify(logger).info("Cross-project analysis disabled. Not supported on dry runs.");
}
@Test
public void crossProjectDisabled() {
settings.setProperty(CoreProperties.CPD_CROSS_RPOJECT, "false");
- IndexFactory factory = new IndexFactory(settings, mock(ResourcePersister.class), mock(DuplicationDao.class));
- assertThat(factory.isCrossProject(project), is(false));
+ assertThat(factory.verifyCrossProject(project, logger)).isFalse();
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java
index 590d503bcf1..0414d6ee424 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchModule.java
@@ -34,7 +34,6 @@ import org.sonar.batch.components.PastSnapshotFinderByDays;
import org.sonar.batch.components.PastSnapshotFinderByPreviousAnalysis;
import org.sonar.batch.components.PastSnapshotFinderByPreviousVersion;
import org.sonar.batch.components.PastSnapshotFinderByVersion;
-import org.sonar.batch.config.BatchDatabaseSettingsLoader;
import org.sonar.batch.index.DefaultIndex;
import org.sonar.batch.index.DefaultPersistenceManager;
import org.sonar.batch.index.DefaultResourcePersister;
@@ -111,7 +110,7 @@ public class BatchModule extends Module {
container.addSingleton(BatchDatabase.class);
container.addSingleton(MyBatis.class);
container.addSingleton(DatabaseVersion.class);
- container.addSingleton(DatabaseBatchCompatibility.class);
+ container.addSingleton(DatabaseCompatibility.class);
for (Class daoClass : DaoUtils.getDaoClasses()) {
container.addSingleton(daoClass);
}
@@ -120,7 +119,6 @@ public class BatchModule extends Module {
container.addSingleton(DefaultDatabaseConnector.class);
container.addSingleton(JpaDatabaseSession.class);
container.addSingleton(BatchDatabaseSessionFactory.class);
- container.addSingleton(BatchDatabaseSettingsLoader.class);
}
private void registerBatchExtensions() {
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java
index bff8f081095..6951993e578 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapModule.java
@@ -27,6 +27,7 @@ import org.sonar.batch.FakeMavenPluginExecutor;
import org.sonar.batch.MavenPluginExecutor;
import org.sonar.batch.ServerMetadata;
import org.sonar.batch.config.BootstrapSettings;
+import org.sonar.batch.config.BootstrapSettingsLoader;
import org.sonar.core.config.Logback;
import org.sonar.wsclient.Sonar;
@@ -60,6 +61,7 @@ public class BootstrapModule extends Module {
container.addSingleton(HttpDownloader.class);
container.addSingleton(UriReader.class);
container.addSingleton(PluginDownloader.class);
+ container.addSingleton(BootstrapSettingsLoader.class);
for (Object component : boostrapperComponents) {
if (component != null) {
container.addSingleton(component);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibility.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseCompatibility.java
index 9017d3225bf..3d1c06ec579 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibility.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/DatabaseCompatibility.java
@@ -20,6 +20,7 @@
package org.sonar.batch.bootstrap;
import org.sonar.api.BatchComponent;
+import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.database.DatabaseProperties;
import org.sonar.core.persistence.BadDatabaseVersion;
@@ -28,25 +29,27 @@ import org.sonar.core.persistence.DatabaseVersion;
/**
* Detects if database is not up-to-date with the version required by the batch.
*/
-public class DatabaseBatchCompatibility implements BatchComponent {
+public class DatabaseCompatibility implements BatchComponent {
private DatabaseVersion version;
private Settings settings;
private ServerClient server;
- public DatabaseBatchCompatibility(DatabaseVersion version, ServerClient server, Settings settings) {
+ public DatabaseCompatibility(DatabaseVersion version, ServerClient server, Settings settings) {
this.version = version;
this.server = server;
this.settings = settings;
}
public void start() {
- checkCorrectServerId();
- checkDatabaseStatus();
+ if (!settings.getBoolean("sonar.dryRun")) {
+ checkCorrectServerId();
+ checkDatabaseStatus();
+ }
}
private void checkCorrectServerId() {
- if (!version.getSonarCoreId().equals(server.getServerId())) {
+ if (!settings.getString(CoreProperties.SERVER_ID).equals(server.getServerId())) {
StringBuilder message = new StringBuilder("The current batch process and the configured remote server do not share the same DB configuration.\n");
message.append("\t- Batch side: ");
message.append(settings.getString(DatabaseProperties.PROP_URL));
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectExclusions.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectExclusions.java
index 050dae89154..9b078d2f249 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectExclusions.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectExclusions.java
@@ -42,7 +42,9 @@ public class ProjectExclusions implements BatchComponent {
private Settings settings;
private ProjectReactor reactor;
- public ProjectExclusions(Settings settings, ProjectReactor reactor, ProjectBuilder[] projectBuilders) {
+ public ProjectExclusions(Settings settings, ProjectReactor reactor,
+ // exclusions are applied when the project is completely defined by extensions
+ ProjectBuilder[] projectBuilders) {
this.settings = settings;
this.reactor = reactor;
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectModule.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectModule.java
index 4d3450b6247..0acaa7c9ba0 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectModule.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/ProjectModule.java
@@ -73,8 +73,8 @@ public class ProjectModule extends Module {
}
ProjectDefinition projectDefinition = container.getComponentByType(ProjectTree.class).getProjectDefinition(project);
container.addSingleton(projectDefinition);
- container.addSingleton(project);
container.addSingleton(project.getConfiguration());
+ container.addSingleton(project);
container.addSingleton(ProjectSettings.class);
container.addSingleton(UnsupportedProperties.class);
diff --git a/sonar-batch/src/main/java/org/sonar/batch/config/BootstrapSettings.java b/sonar-batch/src/main/java/org/sonar/batch/config/BootstrapSettings.java
index a2267e87cc7..1d7caab9509 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/config/BootstrapSettings.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/config/BootstrapSettings.java
@@ -28,7 +28,7 @@ import org.sonar.core.config.ConfigurationUtils;
/**
* @since 2.12
*/
-public final class BootstrapSettings extends Settings {
+public class BootstrapSettings extends Settings {
private Configuration deprecatedConfiguration;
private ProjectReactor reactor;
diff --git a/sonar-batch/src/main/java/org/sonar/batch/config/BatchDatabaseSettingsLoader.java b/sonar-batch/src/main/java/org/sonar/batch/config/BootstrapSettingsLoader.java
index 8a03eb01053..02563c7a240 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/config/BatchDatabaseSettingsLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/config/BootstrapSettingsLoader.java
@@ -20,44 +20,50 @@
package org.sonar.batch.config;
import org.apache.commons.lang.StringUtils;
+import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectReactor;
-import org.sonar.core.properties.PropertiesDao;
-import org.sonar.core.properties.PropertyDto;
+import org.sonar.wsclient.Sonar;
+import org.sonar.wsclient.services.Property;
+import org.sonar.wsclient.services.PropertyQuery;
import java.util.List;
/**
- * @since 2.12
+ * Load global settings and project settings. Note that the definition of modules is
+ * incomplete before the execution of ProjectBuilder extensions, so module settings
+ * are not loaded yet.
+ * @since 3.4
*/
-public final class BatchDatabaseSettingsLoader {
+public final class BootstrapSettingsLoader {
- private PropertiesDao propertiesDao;
private BootstrapSettings settings;
private ProjectReactor reactor;
+ private Sonar wsClient;
- public BatchDatabaseSettingsLoader(PropertiesDao propertiesDao, BootstrapSettings settings, ProjectReactor reactor) {
- this.propertiesDao = propertiesDao;
+ public BootstrapSettingsLoader(BootstrapSettings settings, ProjectReactor reactor, Sonar wsClient) {
this.settings = settings;
this.reactor = reactor;
+ this.wsClient = wsClient;
}
public void start() {
+ LoggerFactory.getLogger(BootstrapSettingsLoader.class).info("Load project settings");
String branch = settings.getString(CoreProperties.PROJECT_BRANCH_PROPERTY);
String projectKey = reactor.getRoot().getKey();
if (StringUtils.isNotBlank(branch)) {
projectKey = String.format("%s:%s", projectKey, branch);
}
- setIfNotDefined(propertiesDao.selectProjectProperties(projectKey));
- setIfNotDefined(propertiesDao.selectGlobalProperties());
+ List<Property> wsProperties = wsClient.findAll(PropertyQuery.createForAll().setResourceKeyOrId(projectKey));
+ for (Property wsProperty : wsProperties) {
+ setIfNotDefined(wsProperty);
+ }
settings.updateDeprecatedCommonsConfiguration();
}
- private void setIfNotDefined(List<PropertyDto> dbProperties) {
- for (PropertyDto dbProperty : dbProperties) {
- if (!settings.hasKey(dbProperty.getKey())) {
- settings.setProperty(dbProperty.getKey(), dbProperty.getValue());
- }
+ private void setIfNotDefined(Property wsProperty) {
+ if (!settings.hasKey(wsProperty.getKey())) {
+ settings.setProperty(wsProperty.getKey(), wsProperty.getValue());
}
}
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/config/ProjectSettings.java b/sonar-batch/src/main/java/org/sonar/batch/config/ProjectSettings.java
index d470a9cdb02..330100f328b 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/config/ProjectSettings.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/config/ProjectSettings.java
@@ -22,14 +22,16 @@ package org.sonar.batch.config;
import com.google.common.collect.Lists;
import org.apache.commons.configuration.Configuration;
import org.apache.commons.lang.StringUtils;
+import org.slf4j.LoggerFactory;
import org.sonar.api.CoreProperties;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
-import org.sonar.api.config.PropertyDefinitions;
import org.sonar.api.config.Settings;
-import org.sonar.api.resources.Project;
import org.sonar.core.config.ConfigurationUtils;
-import org.sonar.core.properties.PropertiesDao;
-import org.sonar.core.properties.PropertyDto;
+import org.sonar.wsclient.Sonar;
+import org.sonar.wsclient.services.Property;
+import org.sonar.wsclient.services.PropertyQuery;
+
+import javax.annotation.Nullable;
import java.util.List;
@@ -39,81 +41,77 @@ import java.util.List;
public class ProjectSettings extends Settings {
private Configuration deprecatedCommonsConf;
- private ProjectDefinition projectDefinition;
- private PropertiesDao propertiesDao;
- public ProjectSettings(PropertyDefinitions definitions, ProjectDefinition projectDefinition, PropertiesDao propertiesDao, Project project) {
- super(definitions);
- this.deprecatedCommonsConf = project.getConfiguration(); // Configuration is not a parameter to be sure that the project conf is used, not the global one
- this.projectDefinition = projectDefinition;
- this.propertiesDao = propertiesDao;
- load();
- }
+ public ProjectSettings(BootstrapSettings bootstrapSettings, ProjectDefinition project,
+ Sonar wsClient, Configuration deprecatedCommonsConf) {
+ super(bootstrapSettings.getDefinitions());
- public ProjectSettings load() {
- clear();
+ LoggerFactory.getLogger(ProjectSettings.class).info("Load module settings");
+ this.deprecatedCommonsConf = deprecatedCommonsConf;
+ if (project.getParent() == null) {
+ // root project -> no need to reload settings
+ copy(bootstrapSettings);
+ } else {
+ init(project, bootstrapSettings, wsClient);
+ }
+ }
- // hack to obtain "sonar.branch" before loading settings from database
- loadBuildProperties();
- addEnvironmentVariables();
- addSystemProperties();
- String branch = getString(CoreProperties.PROJECT_BRANCH_PROPERTY);
- clear();
+ private void copy(BootstrapSettings bootstrapSettings) {
+ setProperties(bootstrapSettings);
+ }
- // order is important -> bottom-up. The last one overrides all the others.
- loadDatabaseGlobalSettings();
- loadDatabaseProjectSettings(projectDefinition, branch);
- loadBuildProperties();
+ private ProjectSettings init(ProjectDefinition project, BootstrapSettings bootstrapSettings, Sonar wsClient) {
+ addPersistedProperties(project, bootstrapSettings, wsClient);
+ addBuildProperties(project);
addEnvironmentVariables();
addSystemProperties();
-
- updateDeprecatedCommonsConfiguration();
-
return this;
}
- private void loadBuildProperties() {
- List<ProjectDefinition> orderedProjects = getOrderedProjects(projectDefinition);
- for (ProjectDefinition p : orderedProjects) {
- addProperties(p.getProperties());
- }
- }
-
- private void loadDatabaseProjectSettings(ProjectDefinition projectDef, String branch) {
- if (projectDef.getParent() != null) {
- loadDatabaseProjectSettings(projectDef.getParent(), branch);
- }
- String projectKey = projectDef.getKey();
+ private void addPersistedProperties(ProjectDefinition project, BootstrapSettings bootstrapSettings, Sonar wsClient) {
+ String branch = bootstrapSettings.getString(CoreProperties.PROJECT_BRANCH_PROPERTY);
+ String projectKey = project.getKey();
if (StringUtils.isNotBlank(branch)) {
projectKey = String.format("%s:%s", projectKey, branch);
}
- List<PropertyDto> props = propertiesDao.selectProjectProperties(projectKey);
- for (PropertyDto dbProperty : props) {
- setProperty(dbProperty.getKey(), dbProperty.getValue());
+ List<Property> wsProperties = wsClient.findAll(PropertyQuery.createForAll().setResourceKeyOrId(projectKey));
+ for (Property wsProperty : wsProperties) {
+ setProperty(wsProperty.getKey(), wsProperty.getValue());
}
}
- private void loadDatabaseGlobalSettings() {
- List<PropertyDto> props = propertiesDao.selectGlobalProperties();
- for (PropertyDto dbProperty : props) {
- setProperty(dbProperty.getKey(), dbProperty.getValue());
+ private void addBuildProperties(ProjectDefinition project) {
+ List<ProjectDefinition> orderedProjects = getTopDownParentProjects(project);
+ for (ProjectDefinition p : orderedProjects) {
+ addProperties(p.getProperties());
}
}
- private void updateDeprecatedCommonsConfiguration() {
- ConfigurationUtils.copyToCommonsConfiguration(properties, deprecatedCommonsConf);
- }
-
/**
- * From root to module
+ * From root to given project
*/
- static List<ProjectDefinition> getOrderedProjects(ProjectDefinition project) {
+ static List<ProjectDefinition> getTopDownParentProjects(ProjectDefinition project) {
List<ProjectDefinition> result = Lists.newArrayList();
- ProjectDefinition pd = project;
- while (pd != null) {
- result.add(0, pd);
- pd = pd.getParent();
+ ProjectDefinition p = project;
+ while (p != null) {
+ result.add(0, p);
+ p = p.getParent();
}
return result;
}
+
+ @Override
+ protected void doOnSetProperty(String key, @Nullable String value) {
+ deprecatedCommonsConf.setProperty(key, value);
+ }
+
+ @Override
+ protected void doOnRemoveProperty(String key) {
+ deprecatedCommonsConf.clearProperty(key);
+ }
+
+ @Override
+ protected void doOnClearProperties() {
+ deprecatedCommonsConf.clear();
+ }
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/local/DryRunDatabase.java b/sonar-batch/src/main/java/org/sonar/batch/local/DryRunDatabase.java
index c2f69706d58..4149940feb8 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/local/DryRunDatabase.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/local/DryRunDatabase.java
@@ -71,6 +71,7 @@ public class DryRunDatabase implements BatchComponent {
return;
}
+ LOG.info("Install dry run database");
File databaseFile = tempDirectories.getFile("dry_run", "db.h2.db");
downloadDatabase(reactor.getRoot().getKey(), databaseFile);
@@ -79,8 +80,6 @@ public class DryRunDatabase implements BatchComponent {
}
private void downloadDatabase(String projectKey, File toFile) {
- LOG.info("Downloading DryRun database for project [{}]", projectKey);
-
try {
server.download(API_SYNCHRO + "?resource=" + projectKey, toFile);
} catch (SonarException e) {
@@ -95,8 +94,6 @@ public class DryRunDatabase implements BatchComponent {
}
private void replaceSettings(String databasePath) {
- LOG.info("Overriding database settings");
-
settings
.setProperty("sonar.jdbc.schema", "")
.setProperty(DatabaseProperties.PROP_DIALECT, DIALECT)
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibilityTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseCompatibilityTest.java
index bddab1a63ec..41489b7b530 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseBatchCompatibilityTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/DatabaseCompatibilityTest.java
@@ -23,31 +23,26 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
+import org.sonar.api.CoreProperties;
import org.sonar.api.config.Settings;
import org.sonar.api.database.DatabaseProperties;
-import org.sonar.api.utils.SonarException;
import org.sonar.core.persistence.BadDatabaseVersion;
import org.sonar.core.persistence.DatabaseVersion;
-import java.io.IOException;
-
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
-public class DatabaseBatchCompatibilityTest {
+public class DatabaseCompatibilityTest {
@Rule
public ExpectedException thrown = ExpectedException.none();
- private DatabaseVersion databaseVersion;
- private ServerClient server;
- private Settings settings;
+ DatabaseVersion databaseVersion;
+ ServerClient server;
+ Settings settings;
@Before
- public void init() throws Exception {
- databaseVersion = mock(DatabaseVersion.class);
- when(databaseVersion.getSonarCoreId()).thenReturn("123456");
-
+ public void init() {
server = mock(ServerClient.class);
when(server.getURL()).thenReturn("http://localhost:9000");
when(server.getServerId()).thenReturn("123456");
@@ -55,6 +50,10 @@ public class DatabaseBatchCompatibilityTest {
settings = new Settings();
settings.setProperty(DatabaseProperties.PROP_URL, "jdbc:postgresql://localhost/foo");
settings.setProperty(DatabaseProperties.PROP_USER, "bar");
+ settings.setProperty(CoreProperties.SERVER_ID, "123456");
+ settings.setProperty("sonar.dryRun", false);
+
+ databaseVersion = mock(DatabaseVersion.class);
}
@Test
@@ -64,7 +63,7 @@ public class DatabaseBatchCompatibilityTest {
thrown.expect(BadDatabaseVersion.class);
thrown.expectMessage("Database relates to a more recent version of Sonar. Please check your settings (JDBC settings, version of Maven plugin)");
- new DatabaseBatchCompatibility(databaseVersion, server, settings).start();
+ new DatabaseCompatibility(databaseVersion, server, settings).start();
}
@Test
@@ -74,33 +73,31 @@ public class DatabaseBatchCompatibilityTest {
thrown.expect(BadDatabaseVersion.class);
thrown.expectMessage("Database must be upgraded.");
- new DatabaseBatchCompatibility(databaseVersion, server, settings).start();
+ new DatabaseCompatibility(databaseVersion, server, settings).start();
}
@Test
public void shouldFailIfNotSameServerId() throws Exception {
- DatabaseVersion version = mock(DatabaseVersion.class);
- when(version.getSonarCoreId()).thenReturn("1111111");
+ settings.setProperty(CoreProperties.SERVER_ID, "11111111");
thrown.expect(BadDatabaseVersion.class);
thrown.expectMessage("The current batch process and the configured remote server do not share the same DB configuration.");
thrown.expectMessage("- Batch side: jdbc:postgresql://localhost/foo (bar / *****)");
thrown.expectMessage("- Server side: check the configuration at http://localhost:9000/system");
- new DatabaseBatchCompatibility(version, server, settings).start();
+ new DatabaseCompatibility(databaseVersion, server, settings).start();
}
@Test
public void shouldUseDefaultUserNameWhenFaillingIfNotSameServerIdAndNoUserNameFound() throws Exception {
- DatabaseVersion version = mock(DatabaseVersion.class);
- when(version.getSonarCoreId()).thenReturn("1111111");
+ settings.setProperty(CoreProperties.SERVER_ID, "11111111");
settings.removeProperty(DatabaseProperties.PROP_USER);
thrown.expect(BadDatabaseVersion.class);
thrown.expectMessage("- Batch side: jdbc:postgresql://localhost/foo (sonar / *****)");
- new DatabaseBatchCompatibility(version, server, settings).start();
+ new DatabaseCompatibility(databaseVersion, server, settings).start();
}
@Test
@@ -109,13 +106,23 @@ public class DatabaseBatchCompatibilityTest {
thrown.expect(IllegalStateException.class);
- new DatabaseBatchCompatibility(mock(DatabaseVersion.class), server, settings).start();
+ new DatabaseCompatibility(mock(DatabaseVersion.class), server, settings).start();
}
@Test
public void shouldDoNothingIfUpToDate() {
when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.UP_TO_DATE);
- new DatabaseBatchCompatibility(databaseVersion, server, settings).start();
+ new DatabaseCompatibility(databaseVersion, server, settings).start();
// no error
}
+
+ @Test
+ public void should_not_verify_compatibility_if_dry_run() {
+ settings.setProperty(CoreProperties.SERVER_ID, "11111111");
+ settings.setProperty("sonar.dryRun", true);
+
+ new DatabaseCompatibility(databaseVersion, server, settings).start();
+
+ // no failure
+ }
}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectModuleTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectModuleTest.java
index 2cacc9a4931..adad9113158 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectModuleTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/ProjectModuleTest.java
@@ -22,6 +22,8 @@ package org.sonar.batch.bootstrap;
import org.apache.commons.configuration.PropertiesConfiguration;
import org.junit.Test;
import org.mockito.Matchers;
+import org.mockito.MockSettings;
+import org.mockito.Mockito;
import org.sonar.api.batch.InstantiationStrategy;
import org.sonar.api.batch.bootstrap.ProjectDefinition;
import org.sonar.api.database.model.Snapshot;
@@ -29,9 +31,11 @@ import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.resources.Project;
import org.sonar.api.resources.Resource;
import org.sonar.batch.ProjectTree;
+import org.sonar.batch.config.BootstrapSettings;
import org.sonar.batch.config.ProjectSettings;
import org.sonar.batch.index.ResourcePersister;
import org.sonar.core.properties.PropertiesDao;
+import org.sonar.wsclient.Sonar;
import static org.fest.assertions.Assertions.assertThat;
import static org.mockito.Matchers.any;
@@ -58,7 +62,8 @@ public class ProjectModuleTest {
container.addSingleton(extensionInstaller);
container.addSingleton(projectTree);
container.addSingleton(resourcePersister);
- container.addSingleton(mock(PropertiesDao.class));
+ container.addSingleton(mock(Sonar.class));
+ container.addSingleton(mock(BootstrapSettings.class));
}
};
diff --git a/sonar-batch/src/test/java/org/sonar/batch/config/ProjectSettingsTest.java b/sonar-batch/src/test/java/org/sonar/batch/config/ProjectSettingsTest.java
index eede4877e50..753a09921a8 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/config/ProjectSettingsTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/config/ProjectSettingsTest.java
@@ -37,7 +37,7 @@ public class ProjectSettingsTest {
grandParent.addSubProject(parent);
parent.addSubProject(child);
- List<ProjectDefinition> hierarchy = ProjectSettings.getOrderedProjects(child);
+ List<ProjectDefinition> hierarchy = ProjectSettings.getTopDownParentProjects(child);
assertThat(hierarchy.get(0), Is.is(grandParent));
assertThat(hierarchy.get(1), Is.is(parent));
assertThat(hierarchy.get(2), Is.is(child));
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
index 793723d6af0..3ed5fba82fe 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/DatabaseVersion.java
@@ -66,17 +66,6 @@ public class DatabaseVersion implements BatchComponent, ServerComponent {
}
}
- public String getSonarCoreId() {
- SqlSession session = mybatis.openSession();
- try {
- PropertyDto serverIdProperty = session.getMapper(PropertiesMapper.class).selectByKey(new PropertyDto().setKey(CoreProperties.SERVER_ID));
- // this property can't be NULL
- return serverIdProperty.getValue();
- } finally {
- MyBatis.closeQuietly(session);
- }
- }
-
public Status getStatus() {
return getStatus(getVersion(), LAST_VERSION);
}
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DbTemplate.java b/sonar-core/src/main/java/org/sonar/core/persistence/DbTemplate.java
index e83bf0c0cb3..611400aab51 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/DbTemplate.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/DbTemplate.java
@@ -41,7 +41,7 @@ public class DbTemplate implements ServerComponent {
private static final Logger LOG = LoggerFactory.getLogger(DbTemplate.class);
public DbTemplate copyTable(DataSource source, DataSource dest, String table, String... whereClauses) {
- LOG.info("Copy table " + table);
+ LOG.debug("Copy table %s", table);
String selectQuery = "select * from " + table;
if (whereClauses.length > 0) {
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java b/sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java
index 82d3736f629..5f6c01e4429 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/DefaultDatabase.java
@@ -66,6 +66,7 @@ public class DefaultDatabase implements Database {
initSettings();
initDatasource();
checkConnection();
+ doAfterStart();
return this;
} catch (Exception e) {
@@ -73,6 +74,13 @@ public class DefaultDatabase implements Database {
}
}
+ /**
+ * Override to execute post-startup code.
+ */
+ protected void doAfterStart() {
+
+ }
+
@VisibleForTesting
void initSettings() {
initProperties();
@@ -93,7 +101,7 @@ public class DefaultDatabase implements Database {
if (dialect == null) {
throw new IllegalStateException("Can not guess the JDBC dialect. Please check the property sonar.jdbc.url.");
}
- if (H2.ID.equals(dialect.getId())) {
+ if (H2.ID.equals(dialect.getId()) && !settings.getBoolean("sonar.dryRun")) {
LoggerFactory.getLogger(DefaultDatabase.class).warn("H2 database should be used for evaluation purpose only");
}
if (!properties.containsKey("sonar.jdbc.driverClassName")) {
diff --git a/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java b/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java
index 9c8b5252482..6530140510d 100644
--- a/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java
+++ b/sonar-core/src/main/java/org/sonar/core/persistence/DryRunDatabaseFactory.java
@@ -63,10 +63,6 @@ public class DryRunDatabaseFactory implements ServerComponent {
}
private void copy(DataSource source, DataSource dest, Integer resourceId) {
- String notSecured = "NOT (prop_key LIKE '%.secured')";
- String defaultProperty = "((user_id IS NULL) AND (resource_id IS NULL))";
- String projectProperty = (null == resourceId) ? "" : " OR (resource_id='" + resourceId + "')";
-
new DbTemplate()
.copyTable(source, dest, "active_rules")
.copyTable(source, dest, "active_rule_parameters")
@@ -74,7 +70,6 @@ public class DryRunDatabaseFactory implements ServerComponent {
.copyTable(source, dest, "characteristic_edges")
.copyTable(source, dest, "characteristic_properties")
.copyTable(source, dest, "metrics")
- .copyTable(source, dest, "properties", notSecured, defaultProperty + projectProperty)
.copyTable(source, dest, "quality_models")
.copyTable(source, dest, "rules")
.copyTable(source, dest, "rules_parameters")
diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/DatabaseVersionTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/DatabaseVersionTest.java
index df1dce3e426..a0278eed475 100644
--- a/sonar-core/src/test/java/org/sonar/core/persistence/DatabaseVersionTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/persistence/DatabaseVersionTest.java
@@ -19,12 +19,10 @@
*/
package org.sonar.core.persistence;
-import org.hamcrest.core.Is;
+
import org.junit.Test;
-import static org.hamcrest.CoreMatchers.is;
-import static org.hamcrest.CoreMatchers.nullValue;
-import static org.junit.Assert.assertThat;
+import static org.fest.assertions.Assertions.assertThat;
public class DatabaseVersionTest extends AbstractDaoTestCase {
@Test
@@ -33,7 +31,7 @@ public class DatabaseVersionTest extends AbstractDaoTestCase {
Integer version = new DatabaseVersion(getMyBatis()).getVersion();
- assertThat(version, Is.is(123));
+ assertThat(version).isEqualTo(123);
}
@Test
@@ -42,23 +40,14 @@ public class DatabaseVersionTest extends AbstractDaoTestCase {
Integer version = new DatabaseVersion(getMyBatis()).getVersion();
- assertThat(version, nullValue());
- }
-
- @Test
- public void getSonarCoreId() {
- setupData("getSonarCoreId");
-
- String sonarCoreId = new DatabaseVersion(getMyBatis()).getSonarCoreId();
-
- assertThat(sonarCoreId, is("123456"));
+ assertThat(version).isNull();
}
@Test
public void getStatus() {
- assertThat(DatabaseVersion.getStatus(null, 150), is(DatabaseVersion.Status.FRESH_INSTALL));
- assertThat(DatabaseVersion.getStatus(123, 150), is(DatabaseVersion.Status.REQUIRES_UPGRADE));
- assertThat(DatabaseVersion.getStatus(150, 150), is(DatabaseVersion.Status.UP_TO_DATE));
- assertThat(DatabaseVersion.getStatus(200, 150), is(DatabaseVersion.Status.REQUIRES_DOWNGRADE));
+ assertThat(DatabaseVersion.getStatus(null, 150)).isEqualTo(DatabaseVersion.Status.FRESH_INSTALL);
+ assertThat(DatabaseVersion.getStatus(123, 150)).isEqualTo(DatabaseVersion.Status.REQUIRES_UPGRADE);
+ assertThat(DatabaseVersion.getStatus(150, 150)).isEqualTo(DatabaseVersion.Status.UP_TO_DATE);
+ assertThat(DatabaseVersion.getStatus(200, 150)).isEqualTo(DatabaseVersion.Status.REQUIRES_DOWNGRADE);
}
}
diff --git a/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java
index b44340a1fc5..aa284c22e13 100644
--- a/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/persistence/DryRunDatabaseFactoryTest.java
@@ -66,8 +66,8 @@ public class DryRunDatabaseFactoryTest extends AbstractDaoTestCase {
byte[] database = localDatabaseFactory.createDatabaseForDryRun(1);
dataSource = createDatabase(database);
- assertThat(rowCount("PROPERTIES")).isEqualTo(2);
- assertThat(rowCount("PROJECTS")).isZero();
+ assertThat(rowCount("metrics")).isEqualTo(2);
+ assertThat(rowCount("projects")).isZero();
}
private BasicDataSource createDatabase(byte[] db) throws IOException {
diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/DatabaseVersionTest/getSonarCoreId.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/DatabaseVersionTest/getSonarCoreId.xml
deleted file mode 100644
index 44b1e8eb5be..00000000000
--- a/sonar-core/src/test/resources/org/sonar/core/persistence/DatabaseVersionTest/getSonarCoreId.xml
+++ /dev/null
@@ -1,3 +0,0 @@
-<dataset>
- <properties id="1" prop_key="sonar.core.id" resource_id="[null]" text_value="123456" user_id="[null]"/>
-</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml b/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml
index 0e266518906..3f7360668de 100644
--- a/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml
+++ b/sonar-core/src/test/resources/org/sonar/core/persistence/DryRunDatabaseFactoryTest/should_create_database.xml
@@ -1,9 +1,8 @@
<dataset>
- <properties id="1" prop_key="resourceProperty" text_value="value1" resource_id="1" user_id="[null]"/>
- <properties id="2" prop_key="resourceProperty" text_value="value2" resource_id="2" user_id="[null]"/>
- <properties id="3" prop_key="globalProperty" text_value="value3" resource_id="[null]" user_id="[null]"/>
- <properties id="4" prop_key="userProperty" text_value="value4" resource_id="[null]" user_id="1"/>
- <properties id="5" prop_key="property.secured" text_value="value5" resource_id="[null]" user_id="[null]"/>
+ <metrics id="1" name="ncloc" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
+ enabled="true" worst_value="[null]" optimized_best_value="[null]" best_value="[null]" direction="0" hidden="false" delete_historical_data="[null]" />
+ <metrics id="2" name="coverage" VAL_TYPE="INT" DESCRIPTION="[null]" domain="[null]" short_name=""
+ enabled="true" worst_value="0" optimized_best_value="true" best_value="100" direction="1" hidden="false" delete_historical_data="[null]" />
<rules_profiles id="1" name="Sonar way with Findbugs" language="java" parent_name="" version="1"
used_profile="false"/>
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java
index 307baa2e5fc..8043a7e9e35 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/Settings.java
@@ -296,23 +296,23 @@ public class Settings implements BatchComponent, ServerComponent {
}
public final Settings setProperty(String key, @Nullable Boolean value) {
- return setProperty(key, value==null ? null : String.valueOf(value));
+ return setProperty(key, value == null ? null : String.valueOf(value));
}
public final Settings setProperty(String key, @Nullable Integer value) {
- return setProperty(key, value==null ? null : String.valueOf(value));
+ return setProperty(key, value == null ? null : String.valueOf(value));
}
public final Settings setProperty(String key, @Nullable Long value) {
- return setProperty(key, value==null ? null : String.valueOf(value));
+ return setProperty(key, value == null ? null : String.valueOf(value));
}
public final Settings setProperty(String key, @Nullable Double value) {
- return setProperty(key, value==null ? null : String.valueOf(value));
+ return setProperty(key, value == null ? null : String.valueOf(value));
}
public final Settings setProperty(String key, @Nullable Float value) {
- return setProperty(key, value==null ? null : String.valueOf(value));
+ return setProperty(key, value == null ? null : String.valueOf(value));
}
public final Settings setProperty(String key, @Nullable Date date) {
@@ -346,6 +346,13 @@ public class Settings implements BatchComponent, ServerComponent {
return addProperties(props);
}
+ public final Settings setProperties(Settings s) {
+ if (s.properties==null) {
+ return clear();
+ }
+ return setProperties(Maps.newHashMap(s.properties));
+ }
+
public final Settings setProperty(String key, @Nullable Date date, boolean includeTime) {
return setProperty(key, includeTime ? DateUtils.formatDateTime(date) : DateUtils.formatDate(date));
}
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/properties_controller.rb b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/properties_controller.rb
index 05bc74c95a3..a2b9885aaf2 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/properties_controller.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/controllers/api/properties_controller.rb
@@ -17,25 +17,45 @@
# License along with Sonar; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
#
-
-require "json"
-
class Api::PropertiesController < Api::ApiController
before_filter :admin_required, :only => [:create, :update, :destroy]
- # curl http://localhost:9000/api/properties -v
+ # GET /api/properties/index?[resource=<resource id or key>]
+ # Does NOT manage default values.
def index
- properties = Property.find(:all, :conditions => ['resource_id is null and user_id is null']).select do |property|
- viewable?(property.key)
+ keys=Set.new
+ properties=[]
+
+ # project properties
+ if params[:resource]
+ resource=Project.by_key(params[:resource])
+ if resource
+ # bottom-up projects
+ projects=[resource].concat(resource.ancestor_projects)
+ projects.each do |project|
+ Property.find(:all, :conditions => ['resource_id=? and user_id is null', project.id]).each do |prop|
+ properties<<prop if keys.add? prop.key
+ end
+ end
+ end
end
+
+ # global properties
+ Property.find(:all, :conditions => 'resource_id is null and user_id is null').each do |prop|
+ properties<<prop if keys.add? prop.key
+ end
+
+ # apply security
+ properties = properties.select{|prop| allowed?(prop.key)}
+
respond_to do |format|
format.json { render :json => jsonp(to_json(properties)) }
format.xml { render :xml => to_xml(properties) }
end
end
- # curl http://localhost:9000/api/properties/<key>[?resource=<resource>] -v
+ # GET /api/properties/<key>[?resource=<resource>]
def show
key = params[:id]
resource_id_or_key = params[:resource]
@@ -55,7 +75,7 @@ class Api::PropertiesController < Api::ApiController
format.text { render :text => message, :status => 200 }
end
end
- access_denied unless viewable?(key)
+ access_denied unless allowed?(key)
respond_to do |format|
format.json { render :json => jsonp(to_json([prop])) }
format.xml { render :xml => to_xml([prop]) }
@@ -122,8 +142,8 @@ class Api::PropertiesController < Api::ApiController
end
end
- def viewable?(property_key)
- !property_key.to_s.index('.secured') || is_admin?
+ def allowed?(property_key)
+ !property_key.end_with?('.secured') || is_admin?
end
end
diff --git a/sonar-server/src/main/webapp/WEB-INF/app/models/project.rb b/sonar-server/src/main/webapp/WEB-INF/app/models/project.rb
index 4acf953c17c..902ad57de75 100644
--- a/sonar-server/src/main/webapp/WEB-INF/app/models/project.rb
+++ b/sonar-server/src/main/webapp/WEB-INF/app/models/project.rb
@@ -131,7 +131,7 @@ class Project < ActiveRecord::Base
' from project_measures m, snapshots s ' +
' where s.id=m.snapshot_id and ' +
" s.status='%s' and " +
- ' s.project_id=%s and m.metric_id=%s ', Snapshot::STATUS_PROCESSED, self.id, metric_id]) +
+ ' s.project_id=%s and m.metric_id=%s ', 'P', self.id, metric_id]) +
' and m.rule_id IS NULL and m.rule_priority IS NULL' +
' and m.person_id IS NULL' +
' order by s.created_at'
diff --git a/sonar-ws-client/src/test/java/org/sonar/wsclient/services/PropertyQueryTest.java b/sonar-ws-client/src/test/java/org/sonar/wsclient/services/PropertyQueryTest.java
index 7d332a49864..c3639e781a3 100644
--- a/sonar-ws-client/src/test/java/org/sonar/wsclient/services/PropertyQueryTest.java
+++ b/sonar-ws-client/src/test/java/org/sonar/wsclient/services/PropertyQueryTest.java
@@ -19,28 +19,38 @@
*/
package org.sonar.wsclient.services;
+import org.junit.Test;
+
import static org.hamcrest.core.Is.is;
import static org.junit.Assert.assertThat;
-import org.junit.Test;
-
public class PropertyQueryTest extends QueryTestCase {
@Test
- public void all() {
- assertThat(PropertyQuery.createForAll().getUrl(), is("/api/properties?"));
- assertThat(PropertyQuery.createForAll().getModelClass().getName(), is(Property.class.getName()));
+ public void test_global_properties() {
+ PropertyQuery query = PropertyQuery.createForAll();
+ assertThat(query.getUrl(), is("/api/properties?"));
+ assertThat(query.getModelClass().getName(), is(Property.class.getName()));
+ }
+
+ @Test
+ public void test_project_properties() {
+ PropertyQuery query = PropertyQuery.createForAll().setResourceKeyOrId("org.apache:struts");
+ assertThat(query.getUrl(), is("/api/properties?resource=org.apache%3Astruts&"));
+ assertThat(query.getModelClass().getName(), is(Property.class.getName()));
}
@Test
- public void byKey() {
- assertThat(PropertyQuery.createForKey("myprop").getUrl(), is("/api/properties/myprop?"));
- assertThat(PropertyQuery.createForKey("myprop").getModelClass().getName(), is(Property.class.getName()));
+ public void test_global_property() {
+ PropertyQuery query = PropertyQuery.createForKey("myprop");
+ assertThat(query.getUrl(), is("/api/properties/myprop?"));
+ assertThat(query.getModelClass().getName(), is(Property.class.getName()));
}
@Test
- public void byKeyAndResource() {
- assertThat(PropertyQuery.createForResource("myprop", "my:resource").getUrl(), is("/api/properties/myprop?resource=my%3Aresource&"));
- assertThat(PropertyQuery.createForResource("myprop", "my:resource").getModelClass().getName(), is(Property.class.getName()));
+ public void test_project_property() {
+ PropertyQuery query = PropertyQuery.createForResource("myprop", "my:resource");
+ assertThat(query.getUrl(), is("/api/properties/myprop?resource=my%3Aresource&"));
+ assertThat(query.getModelClass().getName(), is(Property.class.getName()));
}
}