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;
import java.util.Set;
+@DryRunIncompatible
public class ApplyProjectRolesDecorator implements Decorator {
private final ResourcePermissions resourcePermissions;
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;
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 {
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 {
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) {
@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) {
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;
}
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;
+ }
}
*/
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);
}
}
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() {
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();
}
}
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;
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);
}
container.addSingleton(DefaultDatabaseConnector.class);
container.addSingleton(JpaDatabaseSession.class);
container.addSingleton(BatchDatabaseSessionFactory.class);
- container.addSingleton(BatchDatabaseSettingsLoader.class);
}
private void registerBatchExtensions() {
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;
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);
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.batch.bootstrap;
-
-import org.sonar.api.BatchComponent;
-import org.sonar.api.config.Settings;
-import org.sonar.api.database.DatabaseProperties;
-import org.sonar.core.persistence.BadDatabaseVersion;
-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 {
-
- private DatabaseVersion version;
- private Settings settings;
- private ServerClient server;
-
- public DatabaseBatchCompatibility(DatabaseVersion version, ServerClient server, Settings settings) {
- this.version = version;
- this.server = server;
- this.settings = settings;
- }
-
- public void start() {
- checkCorrectServerId();
- checkDatabaseStatus();
- }
-
- private void checkCorrectServerId() {
- if (!version.getSonarCoreId().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));
- message.append(" (");
- String userName = settings.getString(DatabaseProperties.PROP_USER);
- message.append(userName == null ? "sonar" : userName);
- message.append(" / *****)\n\t- Server side: check the configuration at ");
- message.append(server.getURL());
- message.append("/system\n");
- throw new BadDatabaseVersion(message.toString());
- }
- }
-
- private void checkDatabaseStatus() {
- DatabaseVersion.Status status = version.getStatus();
- if (status == DatabaseVersion.Status.REQUIRES_DOWNGRADE) {
- throw new BadDatabaseVersion("Database relates to a more recent version of Sonar. Please check your settings (JDBC settings, version of Maven plugin)");
- }
- if (status == DatabaseVersion.Status.REQUIRES_UPGRADE) {
- throw new BadDatabaseVersion("Database must be upgraded. Please browse " + server.getURL() + "/setup");
- }
- if (status != DatabaseVersion.Status.UP_TO_DATE) {
- // Support other future values
- throw new BadDatabaseVersion("Unknown database status: " + status);
- }
- }
-
-}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.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;
+import org.sonar.core.persistence.DatabaseVersion;
+
+/**
+ * Detects if database is not up-to-date with the version required by the batch.
+ */
+public class DatabaseCompatibility implements BatchComponent {
+
+ private DatabaseVersion version;
+ private Settings settings;
+ private ServerClient server;
+
+ public DatabaseCompatibility(DatabaseVersion version, ServerClient server, Settings settings) {
+ this.version = version;
+ this.server = server;
+ this.settings = settings;
+ }
+
+ public void start() {
+ if (!settings.getBoolean("sonar.dryRun")) {
+ checkCorrectServerId();
+ checkDatabaseStatus();
+ }
+ }
+
+ private void checkCorrectServerId() {
+ 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));
+ message.append(" (");
+ String userName = settings.getString(DatabaseProperties.PROP_USER);
+ message.append(userName == null ? "sonar" : userName);
+ message.append(" / *****)\n\t- Server side: check the configuration at ");
+ message.append(server.getURL());
+ message.append("/system\n");
+ throw new BadDatabaseVersion(message.toString());
+ }
+ }
+
+ private void checkDatabaseStatus() {
+ DatabaseVersion.Status status = version.getStatus();
+ if (status == DatabaseVersion.Status.REQUIRES_DOWNGRADE) {
+ throw new BadDatabaseVersion("Database relates to a more recent version of Sonar. Please check your settings (JDBC settings, version of Maven plugin)");
+ }
+ if (status == DatabaseVersion.Status.REQUIRES_UPGRADE) {
+ throw new BadDatabaseVersion("Database must be upgraded. Please browse " + server.getURL() + "/setup");
+ }
+ if (status != DatabaseVersion.Status.UP_TO_DATE) {
+ // Support other future values
+ throw new BadDatabaseVersion("Unknown database status: " + status);
+ }
+ }
+
+}
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;
}
}
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);
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.batch.config;
-
-import org.apache.commons.lang.StringUtils;
-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 java.util.List;
-
-/**
- * @since 2.12
- */
-public final class BatchDatabaseSettingsLoader {
-
- private PropertiesDao propertiesDao;
- private BootstrapSettings settings;
- private ProjectReactor reactor;
-
- public BatchDatabaseSettingsLoader(PropertiesDao propertiesDao, BootstrapSettings settings, ProjectReactor reactor) {
- this.propertiesDao = propertiesDao;
- this.settings = settings;
- this.reactor = reactor;
- }
-
- public void start() {
- 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());
- settings.updateDeprecatedCommonsConfiguration();
- }
-
- private void setIfNotDefined(List<PropertyDto> dbProperties) {
- for (PropertyDto dbProperty : dbProperties) {
- if (!settings.hasKey(dbProperty.getKey())) {
- settings.setProperty(dbProperty.getKey(), dbProperty.getValue());
- }
- }
- }
-}
/**
* @since 2.12
*/
-public final class BootstrapSettings extends Settings {
+public class BootstrapSettings extends Settings {
private Configuration deprecatedConfiguration;
private ProjectReactor reactor;
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.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.wsclient.Sonar;
+import org.sonar.wsclient.services.Property;
+import org.sonar.wsclient.services.PropertyQuery;
+
+import java.util.List;
+
+/**
+ * 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 BootstrapSettingsLoader {
+
+ private BootstrapSettings settings;
+ private ProjectReactor reactor;
+ private Sonar wsClient;
+
+ 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);
+ }
+ List<Property> wsProperties = wsClient.findAll(PropertyQuery.createForAll().setResourceKeyOrId(projectKey));
+ for (Property wsProperty : wsProperties) {
+ setIfNotDefined(wsProperty);
+ }
+ settings.updateDeprecatedCommonsConfiguration();
+ }
+
+ private void setIfNotDefined(Property wsProperty) {
+ if (!settings.hasKey(wsProperty.getKey())) {
+ settings.setProperty(wsProperty.getKey(), wsProperty.getValue());
+ }
+ }
+}
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;
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();
+ }
}
return;
}
+ LOG.info("Install dry run database");
File databaseFile = tempDirectories.getFile("dry_run", "db.h2.db");
downloadDatabase(reactor.getRoot().getKey(), databaseFile);
}
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) {
}
private void replaceSettings(String databasePath) {
- LOG.info("Overriding database settings");
-
settings
.setProperty("sonar.jdbc.schema", "")
.setProperty(DatabaseProperties.PROP_DIALECT, DIALECT)
+++ /dev/null
-/*
- * Sonar, open source software quality management tool.
- * Copyright (C) 2008-2012 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * Sonar is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * Sonar is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public
- * License along with Sonar; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
- */
-package org.sonar.batch.bootstrap;
-
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-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 {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- private DatabaseVersion databaseVersion;
- private ServerClient server;
- private Settings settings;
-
- @Before
- public void init() throws Exception {
- databaseVersion = mock(DatabaseVersion.class);
- when(databaseVersion.getSonarCoreId()).thenReturn("123456");
-
- server = mock(ServerClient.class);
- when(server.getURL()).thenReturn("http://localhost:9000");
- when(server.getServerId()).thenReturn("123456");
-
- settings = new Settings();
- settings.setProperty(DatabaseProperties.PROP_URL, "jdbc:postgresql://localhost/foo");
- settings.setProperty(DatabaseProperties.PROP_USER, "bar");
- }
-
- @Test
- public void shouldFailIfRequiresDowngrade() {
- when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_DOWNGRADE);
-
- 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();
- }
-
- @Test
- public void shouldFailIfRequiresUpgrade() {
- when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_UPGRADE);
-
- thrown.expect(BadDatabaseVersion.class);
- thrown.expectMessage("Database must be upgraded.");
-
- new DatabaseBatchCompatibility(databaseVersion, server, settings).start();
- }
-
- @Test
- public void shouldFailIfNotSameServerId() throws Exception {
- DatabaseVersion version = mock(DatabaseVersion.class);
- when(version.getSonarCoreId()).thenReturn("1111111");
-
- 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();
- }
-
- @Test
- public void shouldUseDefaultUserNameWhenFaillingIfNotSameServerIdAndNoUserNameFound() throws Exception {
- DatabaseVersion version = mock(DatabaseVersion.class);
- when(version.getSonarCoreId()).thenReturn("1111111");
-
- settings.removeProperty(DatabaseProperties.PROP_USER);
-
- thrown.expect(BadDatabaseVersion.class);
- thrown.expectMessage("- Batch side: jdbc:postgresql://localhost/foo (sonar / *****)");
-
- new DatabaseBatchCompatibility(version, server, settings).start();
- }
-
- @Test
- public void shouldFailIfCantGetServerId() throws Exception {
- when(server.getServerId()).thenThrow(new IllegalStateException());
-
- thrown.expect(IllegalStateException.class);
-
- new DatabaseBatchCompatibility(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();
- // no error
- }
-}
--- /dev/null
+/*
+ * Sonar, open source software quality management tool.
+ * Copyright (C) 2008-2012 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * Sonar is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * Sonar is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public
+ * License along with Sonar; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02
+ */
+package org.sonar.batch.bootstrap;
+
+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.core.persistence.BadDatabaseVersion;
+import org.sonar.core.persistence.DatabaseVersion;
+
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class DatabaseCompatibilityTest {
+
+ @Rule
+ public ExpectedException thrown = ExpectedException.none();
+
+ DatabaseVersion databaseVersion;
+ ServerClient server;
+ Settings settings;
+
+ @Before
+ public void init() {
+ server = mock(ServerClient.class);
+ when(server.getURL()).thenReturn("http://localhost:9000");
+ when(server.getServerId()).thenReturn("123456");
+
+ 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
+ public void shouldFailIfRequiresDowngrade() {
+ when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_DOWNGRADE);
+
+ 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 DatabaseCompatibility(databaseVersion, server, settings).start();
+ }
+
+ @Test
+ public void shouldFailIfRequiresUpgrade() {
+ when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.REQUIRES_UPGRADE);
+
+ thrown.expect(BadDatabaseVersion.class);
+ thrown.expectMessage("Database must be upgraded.");
+
+ new DatabaseCompatibility(databaseVersion, server, settings).start();
+ }
+
+ @Test
+ public void shouldFailIfNotSameServerId() throws Exception {
+ 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 DatabaseCompatibility(databaseVersion, server, settings).start();
+ }
+
+ @Test
+ public void shouldUseDefaultUserNameWhenFaillingIfNotSameServerIdAndNoUserNameFound() throws Exception {
+ 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 DatabaseCompatibility(databaseVersion, server, settings).start();
+ }
+
+ @Test
+ public void shouldFailIfCantGetServerId() throws Exception {
+ when(server.getServerId()).thenThrow(new IllegalStateException());
+
+ thrown.expect(IllegalStateException.class);
+
+ new DatabaseCompatibility(mock(DatabaseVersion.class), server, settings).start();
+ }
+
+ @Test
+ public void shouldDoNothingIfUpToDate() {
+ when(databaseVersion.getStatus()).thenReturn(DatabaseVersion.Status.UP_TO_DATE);
+ 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
+ }
+}
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;
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;
container.addSingleton(extensionInstaller);
container.addSingleton(projectTree);
container.addSingleton(resourcePersister);
- container.addSingleton(mock(PropertiesDao.class));
+ container.addSingleton(mock(Sonar.class));
+ container.addSingleton(mock(BootstrapSettings.class));
}
};
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));
}
}
- 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);
}
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) {
initSettings();
initDatasource();
checkConnection();
+ doAfterStart();
return this;
} catch (Exception e) {
}
}
+ /**
+ * Override to execute post-startup code.
+ */
+ protected void doAfterStart() {
+
+ }
+
@VisibleForTesting
void initSettings() {
initProperties();
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")) {
}
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")
.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")
*/
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
Integer version = new DatabaseVersion(getMyBatis()).getVersion();
- assertThat(version, Is.is(123));
+ assertThat(version).isEqualTo(123);
}
@Test
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);
}
}
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 {
+++ /dev/null
-<dataset>
- <properties id="1" prop_key="sonar.core.id" resource_id="[null]" text_value="123456" user_id="[null]"/>
-</dataset>
<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"/>
}
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) {
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));
}
# 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]
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]) }
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
' 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'
*/
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()));
}
}