mirror of
https://github.com/SonarSource/sonarqube.git
synced 2024-07-29 08:17:28 +02:00
SONAR-3895 load settings from web service
This commit is contained in:
parent
81b76d8b6c
commit
3df00fb976
@ -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;
|
||||
|
@ -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 {
|
||||
|
@ -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) {
|
||||
|
@ -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;
|
||||
}
|
||||
}
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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();
|
||||
}
|
||||
|
||||
}
|
||||
|
@ -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() {
|
||||
|
@ -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);
|
||||
|
@ -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));
|
@ -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;
|
||||
}
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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());
|
||||
}
|
||||
}
|
||||
}
|
@ -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());
|
||||
|
||||
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);
|
||||
}
|
||||
}
|
||||
|
||||
public ProjectSettings load() {
|
||||
clear();
|
||||
private void copy(BootstrapSettings bootstrapSettings) {
|
||||
setProperties(bootstrapSettings);
|
||||
}
|
||||
|
||||
// hack to obtain "sonar.branch" before loading settings from database
|
||||
loadBuildProperties();
|
||||
private ProjectSettings init(ProjectDefinition project, BootstrapSettings bootstrapSettings, Sonar wsClient) {
|
||||
addPersistedProperties(project, bootstrapSettings, wsClient);
|
||||
addBuildProperties(project);
|
||||
addEnvironmentVariables();
|
||||
addSystemProperties();
|
||||
String branch = getString(CoreProperties.PROJECT_BRANCH_PROPERTY);
|
||||
clear();
|
||||
|
||||
// order is important -> bottom-up. The last one overrides all the others.
|
||||
loadDatabaseGlobalSettings();
|
||||
loadDatabaseProjectSettings(projectDefinition, branch);
|
||||
loadBuildProperties();
|
||||
addEnvironmentVariables();
|
||||
addSystemProperties();
|
||||
|
||||
updateDeprecatedCommonsConfiguration();
|
||||
|
||||
return this;
|
||||
}
|
||||
|
||||
private void loadBuildProperties() {
|
||||
List<ProjectDefinition> orderedProjects = getOrderedProjects(projectDefinition);
|
||||
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<Property> wsProperties = wsClient.findAll(PropertyQuery.createForAll().setResourceKeyOrId(projectKey));
|
||||
for (Property wsProperty : wsProperties) {
|
||||
setProperty(wsProperty.getKey(), wsProperty.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
private void addBuildProperties(ProjectDefinition project) {
|
||||
List<ProjectDefinition> orderedProjects = getTopDownParentProjects(project);
|
||||
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();
|
||||
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());
|
||||
}
|
||||
}
|
||||
|
||||
private void loadDatabaseGlobalSettings() {
|
||||
List<PropertyDto> props = propertiesDao.selectGlobalProperties();
|
||||
for (PropertyDto dbProperty : props) {
|
||||
setProperty(dbProperty.getKey(), dbProperty.getValue());
|
||||
}
|
||||
}
|
||||
|
||||
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();
|
||||
}
|
||||
}
|
||||
|
@ -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)
|
||||
|
@ -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
|
||||
}
|
||||
}
|
@ -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));
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -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));
|
||||
|
@ -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);
|
||||
}
|
||||
|
@ -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) {
|
||||
|
@ -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")) {
|
||||
|
@ -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")
|
||||
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
@ -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 {
|
||||
|
@ -1,3 +0,0 @@
|
||||
<dataset>
|
||||
<properties id="1" prop_key="sonar.core.id" resource_id="[null]" text_value="123456" user_id="[null]"/>
|
||||
</dataset>
|
@ -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"/>
|
||||
|
@ -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));
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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'
|
||||
|
@ -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 byKey() {
|
||||
assertThat(PropertyQuery.createForKey("myprop").getUrl(), is("/api/properties/myprop?"));
|
||||
assertThat(PropertyQuery.createForKey("myprop").getModelClass().getName(), is(Property.class.getName()));
|
||||
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 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_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 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()));
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user