aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorSimon Brandhof <simon.brandhof@gmail.com>2014-01-27 00:35:35 +0100
committerSimon Brandhof <simon.brandhof@gmail.com>2014-01-27 07:57:21 +0100
commit04bc6b52d79e9d357078b28a083e63d267f33d8b (patch)
tree62dd77c9a40e83229f18dce8cd459d72e0820ccf
parentd9115e8f8bc07048bc0cabb9c6b0ee7f0eb43877 (diff)
downloadsonarqube-04bc6b52d79e9d357078b28a083e63d267f33d8b.tar.gz
sonarqube-04bc6b52d79e9d357078b28a083e63d267f33d8b.zip
SONAR-926 feed ModuleRules
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java2
-rw-r--r--plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileSensor.java70
-rw-r--r--plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileSensorTest.java66
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/DefaultProfileLoader.java119
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/ProfileLoader.java4
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/ProfileProvider.java41
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java131
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/ModuleRulesProvider.java71
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java65
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java78
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileWrapper.java154
-rw-r--r--sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java37
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/DefaultProfileLoaderTest.java291
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/ProfileProviderTest.java71
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/ModuleQProfilesTest.java131
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/ModuleRulesProviderTest.java79
-rw-r--r--sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java72
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/rule/ModuleQProfilesTest/shared.xml15
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/rule/ModuleRulesProviderTest/shared.xml25
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/rule/QProfileSensorTest/mark_profiles_as_used-result.xml15
-rw-r--r--sonar-batch/src/test/resources/org/sonar/batch/rule/QProfileSensorTest/shared.xml15
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDao.java9
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleMapper.java2
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java9
-rw-r--r--sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java1
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/ActiveRuleMapper.xml8
-rw-r--r--sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml6
-rw-r--r--sonar-core/src/test/java/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest.java7
-rw-r--r--sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java7
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update_used_column-result.xml6
-rw-r--r--sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update_used_column.xml6
-rw-r--r--sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewModuleRule.java4
32 files changed, 1071 insertions, 546 deletions
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
index 00009b74c6d..02f7faece03 100644
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
+++ b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/CorePlugin.java
@@ -79,7 +79,6 @@ import org.sonar.plugins.core.sensors.OverallBranchCoverageDecorator;
import org.sonar.plugins.core.sensors.OverallCoverageDecorator;
import org.sonar.plugins.core.sensors.OverallLineCoverageDecorator;
import org.sonar.plugins.core.sensors.ProfileEventsSensor;
-import org.sonar.plugins.core.sensors.ProfileSensor;
import org.sonar.plugins.core.sensors.ProjectLinksSensor;
import org.sonar.plugins.core.sensors.UnitTestDecorator;
import org.sonar.plugins.core.sensors.VersionEventsSensor;
@@ -378,7 +377,6 @@ public final class CorePlugin extends SonarPlugin {
NewTechnicalDebtDecorator.class,
// batch
- ProfileSensor.class,
ProfileEventsSensor.class,
ProjectLinksSensor.class,
UnitTestDecorator.class,
diff --git a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileSensor.java b/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileSensor.java
deleted file mode 100644
index ffff3ae321d..00000000000
--- a/plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileSensor.java
+++ /dev/null
@@ -1,70 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.plugins.core.sensors;
-
-import org.sonar.api.batch.ModuleLanguages;
-import org.sonar.api.batch.Sensor;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.measures.Measure;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.Project;
-import org.sonar.batch.RulesProfileWrapper;
-
-public class ProfileSensor implements Sensor {
-
- private final RulesProfile profile;
- private final DatabaseSession session;
- private final ModuleLanguages languages;
-
- public ProfileSensor(RulesProfile profile, DatabaseSession session, ModuleLanguages languages) {
- this.profile = profile;
- this.session = session;
- this.languages = languages;
- }
-
- public boolean shouldExecuteOnProject(Project project) {
- // Views will define a fake profile
- return profile instanceof RulesProfileWrapper;
- }
-
- public void analyse(Project project, SensorContext context) {
- RulesProfileWrapper wrapper = (RulesProfileWrapper) profile;
- for (String languageKey : languages.keys()) {
- RulesProfile realProfile = wrapper.getProfileByLanguage(languageKey);
- Measure measure = new Measure(CoreMetrics.PROFILE, profile.getName());
- Measure measureVersion = new Measure(CoreMetrics.PROFILE_VERSION, Integer.valueOf(profile.getVersion()).doubleValue());
- if (realProfile.getId() != null) {
- measure.setValue(realProfile.getId().doubleValue());
-
- realProfile.setUsed(true);
- session.merge(realProfile);
- }
- context.saveMeasure(measure);
- context.saveMeasure(measureVersion);
- }
- }
-
- @Override
- public String toString() {
- return getClass().getSimpleName();
- }
-}
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileSensorTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileSensorTest.java
deleted file mode 100644
index c1b720f3fea..00000000000
--- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileSensorTest.java
+++ /dev/null
@@ -1,66 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.plugins.core.sensors;
-
-import org.junit.Test;
-import org.sonar.api.batch.SensorContext;
-import org.sonar.api.config.Settings;
-import org.sonar.api.database.DatabaseSession;
-import org.sonar.api.measures.CoreMetrics;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.Java;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.test.IsMeasure;
-import org.sonar.batch.RulesProfileWrapper;
-import org.sonar.batch.scan.language.DefaultModuleLanguages;
-
-import java.util.HashMap;
-import java.util.Map;
-
-import static org.mockito.Matchers.argThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.when;
-
-public class ProfileSensorTest {
-
- @Test
- public void saveProfile() {
- RulesProfile profile = mock(RulesProfile.class);
- when(profile.getId()).thenReturn(22);
- when(profile.getName()).thenReturn("fake");
- when(profile.getVersion()).thenReturn(2);
-
- DefaultModuleLanguages moduleLanguages = new DefaultModuleLanguages(new Settings(), new Languages(Java.INSTANCE));
- moduleLanguages.addLanguage("java");
- Map<String, RulesProfile> ruleProfilesPerLanguages = new HashMap<String, RulesProfile>();
- ruleProfilesPerLanguages.put("java", profile);
- RulesProfileWrapper wrapper = new RulesProfileWrapper(moduleLanguages, ruleProfilesPerLanguages);
-
- SensorContext context = mock(SensorContext.class);
- DatabaseSession session = mock(DatabaseSession.class);
-
- ProfileSensor sensor = new ProfileSensor(wrapper, session, moduleLanguages);
- sensor.analyse(null, context);
-
- verify(context).saveMeasure(argThat(new IsMeasure(CoreMetrics.PROFILE, 22d)));
- verify(context).saveMeasure(argThat(new IsMeasure(CoreMetrics.PROFILE_VERSION, 2d)));
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/DefaultProfileLoader.java b/sonar-batch/src/main/java/org/sonar/batch/DefaultProfileLoader.java
deleted file mode 100644
index 78d625983c8..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/DefaultProfileLoader.java
+++ /dev/null
@@ -1,119 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.batch;
-
-import org.apache.commons.lang.StringUtils;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.sonar.api.batch.ModuleLanguages;
-import org.sonar.api.config.Settings;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.resources.Project;
-import org.sonar.api.rules.ActiveRule;
-import org.sonar.api.utils.SonarException;
-import org.sonar.jpa.dao.ProfilesDao;
-
-import java.util.HashMap;
-import java.util.Map;
-
-public class DefaultProfileLoader implements ProfileLoader {
-
- private static final Logger LOG = LoggerFactory.getLogger(DefaultProfileLoader.class);
-
- private ProfilesDao dao;
- private Languages languages;
- private ModuleLanguages moduleLanguages;
-
- public DefaultProfileLoader(ProfilesDao dao, ModuleLanguages moduleLanguages, Languages languages) {
- this.dao = dao;
- this.moduleLanguages = moduleLanguages;
- this.languages = languages;
- }
-
- public RulesProfile load(Project module, Settings settings) {
-
- if (!moduleLanguages.keys().isEmpty()) {
- return loadSingleProfile(settings);
- }
-
- return loadProfileWrapper(settings);
- }
-
- private RulesProfile loadProfileWrapper(Settings settings) {
- Map<String, RulesProfile> profilesPerLanguageKey = new HashMap<String, RulesProfile>();
-
- // We have to load profile of all languages even if module will only use part of them because language detection was not done
- for (Language language : languages.all()) {
- String languageKey = language.getKey();
-
- if (StringUtils.isNotBlank(settings.getString("sonar.profile"))) {
- throw new SonarException("Property sonar.profile should not be used in a multi-language project");
- }
- String profileName = settings.getString("sonar.profile." + languageKey);
-
- RulesProfile profile = dao.getProfile(languageKey, profileName);
- if (profile == null) {
- throw new SonarException("Quality profile not found : " + profileName + ", language " + languageKey);
- }
-
- profilesPerLanguageKey.put(languageKey, hibernateHack(profile));
- }
-
- RulesProfile profile = new RulesProfileWrapper(moduleLanguages, profilesPerLanguageKey);
- for (Map.Entry<String, RulesProfile> profiles : profilesPerLanguageKey.entrySet()) {
- LOG.info("Quality profile for {}: {}", profiles.getKey(), profiles.getValue());
- }
- return profile;
- }
-
- private RulesProfile loadSingleProfile(Settings settings) {
- Map<String, RulesProfile> profilesPerLanguageKey = new HashMap<String, RulesProfile>();
-
- // Single language is forced, load a single quality profile
- String languageKey = moduleLanguages.keys().iterator().next();
-
- String profileName = StringUtils.defaultIfBlank(
- settings.getString("sonar.profile"),
- settings.getString("sonar.profile." + languageKey));
-
- RulesProfile profile = dao.getProfile(languageKey, profileName);
- if (profile == null) {
- throw new SonarException("Quality profile not found : " + profileName + ", language " + languageKey);
- }
- profilesPerLanguageKey.put(languageKey, hibernateHack(profile));
- LOG.info("Quality profile for {}: {}", languageKey, profile);
-
- return new RulesProfileWrapper(moduleLanguages, profilesPerLanguageKey);
- }
-
- private RulesProfile hibernateHack(RulesProfile profile) {
- // hack to lazy initialize the profile collections
- profile.getActiveRules().size();
- for (ActiveRule activeRule : profile.getActiveRules()) {
- activeRule.getActiveRuleParams().size();
- activeRule.getRule().getParams().size();
- }
- profile.getAlerts().size();
- return profile;
- }
-
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/ProfileLoader.java b/sonar-batch/src/main/java/org/sonar/batch/ProfileLoader.java
index 51ce91c7b37..9617bc634c5 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/ProfileLoader.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/ProfileLoader.java
@@ -21,17 +21,17 @@ package org.sonar.batch;
import org.sonar.api.config.Settings;
import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.Project;
/**
* This interface is implemented by the views plugin!!
*
*/
+@Deprecated
public interface ProfileLoader {
/**
* Loads quality profile for specified project.
*/
- RulesProfile load(Project project, Settings settings);
+ RulesProfile load(Settings settings);
}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/ProfileProvider.java b/sonar-batch/src/main/java/org/sonar/batch/ProfileProvider.java
deleted file mode 100644
index e73f13a341b..00000000000
--- a/sonar-batch/src/main/java/org/sonar/batch/ProfileProvider.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.batch;
-
-import org.picocontainer.injectors.ProviderAdapter;
-import org.sonar.api.config.Settings;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.resources.Project;
-
-public class ProfileProvider extends ProviderAdapter {
-
- private RulesProfile profile;
-
- /**
- * @param languages This parameter is here to ensure Languages is started before this provider in order to display available languages.
- */
- public RulesProfile provide(Project project, ProfileLoader profileLoader, Settings settings, Languages languages) {
- if (profile == null) {
- profile = profileLoader.load(project, settings);
- }
- return profile;
- }
-}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java b/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java
new file mode 100644
index 00000000000..47da55b29fd
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java
@@ -0,0 +1,131 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.rule;
+
+import com.google.common.collect.ImmutableMap;
+import org.apache.commons.lang.StringUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.BatchComponent;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.utils.MessageException;
+import org.sonar.batch.ProfileLoader;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDto;
+
+import javax.annotation.CheckForNull;
+import java.util.Collection;
+import java.util.Map;
+
+/**
+ * Lists the Quality profiles enabled on the current module.
+ */
+public class ModuleQProfiles implements BatchComponent {
+
+ private static final Logger LOG = LoggerFactory.getLogger(ModuleQProfiles.class);
+
+ public static class QProfile {
+ private final String name, language;
+ private final Integer version;
+ private final int id;
+
+ public QProfile(QualityProfileDto dto) {
+ this.id = dto.getId();
+ this.name = dto.getName();
+ this.language = dto.getLanguage();
+ this.version = dto.getVersion();
+ }
+
+ public int id() {
+ return id;
+ }
+
+ public String name() {
+ return name;
+ }
+
+ public String language() {
+ return language;
+ }
+
+ public Integer version() {
+ return version;
+ }
+ }
+
+ private final Map<String, QProfile> byLanguage;
+
+
+ public ModuleQProfiles(Settings settings, Languages languages, QualityProfileDao dao, ProfileLoader[] loaders) {
+ ImmutableMap.Builder<String, QProfile> builder = ImmutableMap.builder();
+ if (loaders.length == 0) {
+ // not views plugin
+
+ String defaultName = settings.getString("sonar.profile");
+
+ for (Language language : languages.all()) {
+ QProfile profile;
+ if (StringUtils.isNotBlank(defaultName)) {
+ profile = loadDefaultQProfile(dao, defaultName, language.getKey());
+ } else {
+ profile = loadQProfile(dao, settings, language.getKey());
+ }
+ if (profile != null) {
+ LOG.info("Quality profile for {}: {}", profile.language(), profile.name());
+ builder.put(profile.language(), profile);
+ }
+ }
+ }
+ byLanguage = builder.build();
+ }
+
+ @CheckForNull
+ private QProfile loadQProfile(QualityProfileDao dao, Settings settings, String language) {
+ String profileName = settings.getString("sonar.profile." + language);
+ if (profileName != null) {
+ QualityProfileDto dto = dao.selectByNameAndLanguage(profileName, language);
+ if (dto == null) {
+ throw MessageException.of(String.format("Quality profile not found : '%s' on language '%s'", profileName, language));
+ }
+ return new QProfile(dto);
+ }
+ return null;
+ }
+
+ @CheckForNull
+ private QProfile loadDefaultQProfile(QualityProfileDao dao, String profileName, String language) {
+ QualityProfileDto dto = dao.selectByNameAndLanguage(profileName, language);
+ if (dto != null) {
+ return new QProfile(dto);
+ }
+ return null;
+ }
+
+ public Collection<QProfile> findAll() {
+ return byLanguage.values();
+ }
+
+ @CheckForNull
+ public QProfile findByLanguage(String language) {
+ return byLanguage.get(language);
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleRulesProvider.java b/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleRulesProvider.java
new file mode 100644
index 00000000000..a4bcdc3f00b
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/ModuleRulesProvider.java
@@ -0,0 +1,71 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.rule;
+
+import com.google.common.collect.ArrayListMultimap;
+import com.google.common.collect.ListMultimap;
+import org.picocontainer.injectors.ProviderAdapter;
+import org.sonar.api.batch.rule.ModuleRules;
+import org.sonar.api.batch.rule.internal.ModuleRulesBuilder;
+import org.sonar.api.batch.rule.internal.NewModuleRule;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.core.qualityprofile.db.ActiveRuleDao;
+import org.sonar.core.qualityprofile.db.ActiveRuleDto;
+import org.sonar.core.qualityprofile.db.ActiveRuleParamDto;
+
+/**
+ * Loads the rules that are activated on the Quality profiles
+ * used by the current module.
+ */
+public class ModuleRulesProvider extends ProviderAdapter {
+
+ private ModuleRules singleton = null;
+
+ public ModuleRules provide(ModuleQProfiles qProfiles, ActiveRuleDao dao, RuleFinder ruleFinder) {
+ if (singleton == null) {
+ singleton = load(qProfiles, dao, ruleFinder);
+ }
+ return singleton;
+ }
+
+ private ModuleRules load(ModuleQProfiles qProfiles, ActiveRuleDao dao, RuleFinder ruleFinder) {
+ ModuleRulesBuilder builder = new ModuleRulesBuilder();
+ for (ModuleQProfiles.QProfile qProfile : qProfiles.findAll()) {
+ ListMultimap<Integer, ActiveRuleParamDto> paramDtosByActiveRuleId = ArrayListMultimap.create();
+ for (ActiveRuleParamDto dto : dao.selectParamsByProfileId(qProfile.id())) {
+ paramDtosByActiveRuleId.put(dto.getActiveRuleId(), dto);
+ }
+
+ for (ActiveRuleDto activeDto : dao.selectByProfileId(qProfile.id())) {
+ Rule rule = ruleFinder.findById(activeDto.getRulId());
+ if (rule != null) {
+ NewModuleRule newModuleRule = builder.activate(rule.ruleKey());
+ newModuleRule.setSeverity(activeDto.getSeverityString());
+ for (ActiveRuleParamDto paramDto : paramDtosByActiveRuleId.get(activeDto.getId())) {
+ newModuleRule.setParam(paramDto.getKey(), paramDto.getValue());
+ }
+ // TODO add default values declared on rule parameters
+ }
+ }
+ }
+ return builder.build();
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java
new file mode 100644
index 00000000000..3012bbd6e3f
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java
@@ -0,0 +1,65 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.rule;
+
+import org.sonar.api.batch.ModuleLanguages;
+import org.sonar.api.batch.Sensor;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.resources.Project;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+
+/**
+ * Stores which Quality profiles have been used on the current module.
+ */
+public class QProfileSensor implements Sensor {
+
+ private final ModuleQProfiles moduleQProfiles;
+ private final ModuleLanguages moduleLanguages;
+ private final QualityProfileDao dao;
+
+ public QProfileSensor(ModuleQProfiles moduleQProfiles, ModuleLanguages moduleLanguages, QualityProfileDao dao) {
+ this.moduleQProfiles = moduleQProfiles;
+ this.moduleLanguages = moduleLanguages;
+ this.dao = dao;
+ }
+
+ public boolean shouldExecuteOnProject(Project project) {
+ return true;
+ }
+
+ public void analyse(Project project, SensorContext context) {
+ for (String language : moduleLanguages.keys()) {
+ ModuleQProfiles.QProfile qProfile = moduleQProfiles.findByLanguage(language);
+ // TODO does not support multi-language modules
+// Measure measure = new Measure(CoreMetrics.PROFILE, qProfile.name());
+// Measure measureVersion = new Measure(CoreMetrics.PROFILE_VERSION, qProfile.version().doubleValue());
+// context.saveMeasure(measure);
+// context.saveMeasure(measureVersion);
+ if (qProfile != null) {
+ dao.updateUsedColumn(qProfile.id(), true);
+ }
+ }
+ }
+
+ @Override
+ public String toString() {
+ return getClass().getSimpleName();
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java b/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java
new file mode 100644
index 00000000000..d8c0c00cd59
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java
@@ -0,0 +1,78 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.rule;
+
+import com.google.common.collect.Lists;
+import org.picocontainer.injectors.ProviderAdapter;
+import org.sonar.api.batch.ModuleLanguages;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rules.ActiveRule;
+import org.sonar.jpa.dao.ProfilesDao;
+
+import java.util.Collection;
+
+/**
+ * Ensures backward-compatibility with extensions that use {@link org.sonar.api.profiles.RulesProfile}.
+ */
+public class RulesProfileProvider extends ProviderAdapter {
+
+ private RulesProfile singleton = null;
+
+ public RulesProfile provide(ModuleQProfiles qProfiles, ModuleLanguages moduleLanguages, ProfilesDao dao) {
+ if (singleton == null) {
+ if (moduleLanguages.keys().size() == 1) {
+ // Backward-compatibility with single-language modules
+ singleton = loadSingleLanguageProfile(qProfiles, moduleLanguages.keys().iterator().next(), dao);
+ } else {
+ singleton = loadProfiles(qProfiles, dao);
+ }
+ }
+ return singleton;
+ }
+
+ private RulesProfile loadSingleLanguageProfile(ModuleQProfiles qProfiles, String language, ProfilesDao dao) {
+ ModuleQProfiles.QProfile qProfile = qProfiles.findByLanguage(language);
+ return new RulesProfileWrapper(select(qProfile, dao));
+ }
+
+ private RulesProfile loadProfiles(ModuleQProfiles qProfiles, ProfilesDao dao) {
+ Collection<RulesProfile> dtos = Lists.newArrayList();
+ for (ModuleQProfiles.QProfile qProfile : qProfiles.findAll()) {
+ dtos.add(select(qProfile, dao));
+ }
+ return new RulesProfileWrapper(dtos);
+ }
+
+ private RulesProfile select(ModuleQProfiles.QProfile qProfile, ProfilesDao dao) {
+ RulesProfile dto = dao.getProfile(qProfile.language(), qProfile.name());
+ return hibernateHack(dto);
+ }
+
+ private RulesProfile hibernateHack(RulesProfile profile) {
+ // hack to lazy initialize the profile collections
+ profile.getActiveRules().size();
+ for (ActiveRule activeRule : profile.getActiveRules()) {
+ activeRule.getActiveRuleParams().size();
+ activeRule.getRule().getParams().size();
+ }
+ profile.getAlerts().size();
+ return profile;
+ }
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileWrapper.java b/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileWrapper.java
new file mode 100644
index 00000000000..8bd0c36e98b
--- /dev/null
+++ b/sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileWrapper.java
@@ -0,0 +1,154 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.rule;
+
+import com.google.common.collect.Lists;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.sonar.api.profiles.Alert;
+import org.sonar.api.profiles.RulesProfile;
+import org.sonar.api.rules.ActiveRule;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.utils.SonarException;
+
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.List;
+
+/**
+ * This wrapper is used to try to preserve backward compatibility for plugins that used to
+ * depends on {@link org.sonar.api.profiles.RulesProfile}
+ *
+ * @since 4.2
+ */
+public class RulesProfileWrapper extends RulesProfile {
+
+ private static final Logger LOG = LoggerFactory.getLogger(RulesProfileWrapper.class);
+
+ private final Collection<RulesProfile> profiles;
+ private final RulesProfile singleLanguageProfile;
+
+ RulesProfileWrapper(Collection<RulesProfile> profiles) {
+ this.profiles = profiles;
+ this.singleLanguageProfile = null;
+ }
+
+ RulesProfileWrapper(RulesProfile profile) {
+ this.profiles = Lists.newArrayList(profile);
+ this.singleLanguageProfile = profile;
+ }
+
+ @Override
+ public Integer getId() {
+ return getSingleProfileOrFail().getId();
+ }
+
+ private RulesProfile getSingleProfileOrFail() {
+ if (singleLanguageProfile != null) {
+ throw new SonarException("Please update your plugin to support multi-language analysis");
+ }
+ return singleLanguageProfile;
+ }
+
+ @Override
+ public String getName() {
+ return getSingleProfileOrFail().getName();
+ }
+
+ @Override
+ public String getLanguage() {
+ if (singleLanguageProfile == null) {
+ // Multi-languages module
+ // FIXME This is a hack for CommonChecksDecorator that call this method in its constructor
+ LOG.debug("Please update your plugin to support multi-language analysis", new SonarException("Please update your plugin to support multi-language analysis"));
+ return "";
+ }
+ return singleLanguageProfile.getName();
+ }
+
+ @Override
+ public List<Alert> getAlerts() {
+ List<Alert> result = new ArrayList<Alert>();
+ for (RulesProfile profile : profiles) {
+ result.addAll(profile.getAlerts());
+ }
+ return result;
+ }
+
+ @Override
+ public List<ActiveRule> getActiveRules() {
+ List<ActiveRule> activeRules = new ArrayList<ActiveRule>();
+ for (RulesProfile profile : profiles) {
+ activeRules.addAll(profile.getActiveRules());
+ }
+ return activeRules;
+ }
+
+ @Override
+ public int getVersion() {
+ return getSingleProfileOrFail().getVersion();
+ }
+
+ @Override
+ public ActiveRule getActiveRule(String repositoryKey, String ruleKey) {
+ for (RulesProfile profile : profiles) {
+ ActiveRule activeRule = profile.getActiveRule(repositoryKey, ruleKey);
+ if (activeRule != null) {
+ return activeRule;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public List<ActiveRule> getActiveRulesByRepository(String repositoryKey) {
+ List<ActiveRule> activeRules = new ArrayList<ActiveRule>();
+ for (RulesProfile profile : profiles) {
+ activeRules.addAll(profile.getActiveRulesByRepository(repositoryKey));
+ }
+ return activeRules;
+ }
+
+ @Override
+ public List<ActiveRule> getActiveRules(boolean acceptDisabledRules) {
+ List<ActiveRule> activeRules = new ArrayList<ActiveRule>();
+ for (RulesProfile profile : profiles) {
+ activeRules.addAll(profile.getActiveRules(acceptDisabledRules));
+ }
+ return activeRules;
+ }
+
+ @Override
+ public ActiveRule getActiveRule(Rule rule) {
+ for (RulesProfile profile : profiles) {
+ ActiveRule activeRule = profile.getActiveRule(rule);
+ if (activeRule != null) {
+ return activeRule;
+ }
+ }
+ return null;
+ }
+
+ @Override
+ public Boolean getDefaultProfile() {
+ return getSingleProfileOrFail().getDefaultProfile();
+ }
+
+}
diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
index f0d28e30ccd..b34065bff14 100644
--- a/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
+++ b/sonar-batch/src/main/java/org/sonar/batch/scan/ModuleScanContainer.java
@@ -19,8 +19,6 @@
*/
package org.sonar.batch.scan;
-import org.sonar.batch.scan.filesystem.ComponentIndexer;
-
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.sonar.api.BatchExtension;
@@ -30,15 +28,7 @@ import org.sonar.api.platform.ComponentContainer;
import org.sonar.api.resources.Languages;
import org.sonar.api.resources.Project;
import org.sonar.api.scan.filesystem.FileExclusions;
-import org.sonar.batch.DefaultProfileLoader;
-import org.sonar.batch.DefaultProjectClasspath;
-import org.sonar.batch.DefaultSensorContext;
-import org.sonar.batch.DefaultTimeMachine;
-import org.sonar.batch.ProfileLoader;
-import org.sonar.batch.ProfileProvider;
-import org.sonar.batch.ProjectTree;
-import org.sonar.batch.ResourceFilters;
-import org.sonar.batch.ViolationFilters;
+import org.sonar.batch.*;
import org.sonar.batch.bootstrap.BatchExtensionDictionnary;
import org.sonar.batch.bootstrap.ExtensionInstaller;
import org.sonar.batch.bootstrap.ExtensionMatcher;
@@ -52,16 +42,10 @@ import org.sonar.batch.issue.IssueFilters;
import org.sonar.batch.issue.ModuleIssues;
import org.sonar.batch.phases.PhaseExecutor;
import org.sonar.batch.phases.PhasesTimeProfiler;
-import org.sonar.batch.scan.filesystem.DefaultModuleFileSystem;
-import org.sonar.batch.scan.filesystem.DeprecatedFileFilters;
-import org.sonar.batch.scan.filesystem.ExclusionFilters;
-import org.sonar.batch.scan.filesystem.FileHashes;
-import org.sonar.batch.scan.filesystem.FileIndex;
-import org.sonar.batch.scan.filesystem.FileSystemLogger;
-import org.sonar.batch.scan.filesystem.LanguageRecognizer;
-import org.sonar.batch.scan.filesystem.ModuleFileSystemInitializer;
-import org.sonar.batch.scan.filesystem.ProjectFileSystemAdapter;
-import org.sonar.batch.scan.filesystem.RemoteFileHashes;
+import org.sonar.batch.rule.ModuleRulesProvider;
+import org.sonar.batch.rule.QProfileSensor;
+import org.sonar.batch.rule.RulesProfileProvider;
+import org.sonar.batch.scan.filesystem.*;
import org.sonar.batch.scan.language.DefaultModuleLanguages;
import org.sonar.batch.scan.report.ComponentSelectorFactory;
import org.sonar.batch.scan.report.JsonReport;
@@ -95,11 +79,6 @@ public class ModuleScanContainer extends ComponentContainer {
// hack to initialize commons-configuration before ExtensionProviders
getComponentByType(ModuleSettings.class);
- // Don't override ProfileLoader provided by views plugin in parent container
- if (getComponentByType(ProfileLoader.class) == null) {
- add(DefaultProfileLoader.class);
- }
-
add(
EventBus.class,
PhaseExecutor.class,
@@ -138,7 +117,11 @@ public class ModuleScanContainer extends ComponentContainer {
IssueFilters.class,
MeasurementFilters.class,
ResourceFilters.class,
- new ProfileProvider(),
+
+ // rules
+ new ModuleRulesProvider(),
+ new RulesProfileProvider(),
+ QProfileSensor.class,
// report
JsonReport.class,
diff --git a/sonar-batch/src/test/java/org/sonar/batch/DefaultProfileLoaderTest.java b/sonar-batch/src/test/java/org/sonar/batch/DefaultProfileLoaderTest.java
index 081d7fe6f69..cbded87c5c1 100644
--- a/sonar-batch/src/test/java/org/sonar/batch/DefaultProfileLoaderTest.java
+++ b/sonar-batch/src/test/java/org/sonar/batch/DefaultProfileLoaderTest.java
@@ -19,149 +19,148 @@
*/
package org.sonar.batch;
-import org.apache.commons.configuration.PropertiesConfiguration;
-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.profiles.Alert;
-import org.sonar.api.profiles.RulesProfile;
-import org.sonar.api.resources.AbstractLanguage;
-import org.sonar.api.resources.Java;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.resources.Project;
-import org.sonar.api.rules.ActiveRule;
-import org.sonar.api.rules.RulePriority;
-import org.sonar.api.utils.SonarException;
-import org.sonar.batch.scan.language.DefaultModuleLanguages;
-import org.sonar.jpa.dao.ProfilesDao;
-
-import java.util.Arrays;
-
-import static org.fest.assertions.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class DefaultProfileLoaderTest {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- private ProfilesDao dao;
- private Languages languages;
- private Project javaProject = newProject(Java.KEY);
-
- @Before
- public void setUp() {
- dao = mock(ProfilesDao.class);
- Language cobol = new AbstractLanguage("cobol", "Cobol") {
- public String[] getFileSuffixes() {
- return null;
- };
- };
- languages = new Languages(Java.INSTANCE, cobol);
- }
-
- @Test
- public void should_get_configured_profile() {
- Settings settings = new Settings();
- settings.setProperty("sonar.profile.java", "legacy profile");
- settings.setProperty("sonar.profile.cobol", "cobol profile");
- when(dao.getProfile(Java.KEY, "legacy profile")).thenReturn(RulesProfile.create("legacy profile", "java"));
- when(dao.getProfile("cobol", "cobol profile")).thenReturn(RulesProfile.create("cobol profile", "cobol"));
-
- DefaultModuleLanguages moduleLanguages = new DefaultModuleLanguages(settings, languages);
- moduleLanguages.addLanguage("java");
- RulesProfile profile = new DefaultProfileLoader(dao, moduleLanguages, languages).load(javaProject, settings);
-
- assertThat(profile.getName()).isEqualTo("legacy profile");
- }
-
- @Test
- public void some_methods_should_support_multilanguage() {
- Settings settings = new Settings();
- settings.setProperty("sonar.profile.java", "java profile");
- settings.setProperty("sonar.profile.cobol", "cobol profile");
-
- RulesProfile javaProfile = RulesProfile.create("java profile", "java");
- org.sonar.api.rules.Rule javaRule = new org.sonar.api.rules.Rule("javaplugin", "javarule");
- ActiveRule javaActiveRule = new ActiveRule(javaProfile, javaRule, RulePriority.BLOCKER);
- javaProfile.addActiveRule(javaActiveRule);
- Alert javaAlert = mock(Alert.class);
- javaProfile.setAlerts(Arrays.asList(javaAlert));
- when(dao.getProfile(Java.KEY, "java profile")).thenReturn(javaProfile);
-
- RulesProfile cobolProfile = RulesProfile.create("cobol profile", "cobol");
- org.sonar.api.rules.Rule cobolRule = new org.sonar.api.rules.Rule("cobolplugin", "cobolrule");
- ActiveRule cobolActiveRule = new ActiveRule(cobolProfile, cobolRule, RulePriority.BLOCKER);
- cobolProfile.addActiveRule(cobolActiveRule);
- Alert cobolAlert = mock(Alert.class);
- cobolProfile.setAlerts(Arrays.asList(cobolAlert));
- when(dao.getProfile("cobol", "cobol profile")).thenReturn(cobolProfile);
-
- DefaultModuleLanguages moduleLanguages = new DefaultModuleLanguages(settings, languages);
- RulesProfile profile = new DefaultProfileLoader(dao, moduleLanguages, languages).load(javaProject, settings);
-
- // Languages are detected later
- moduleLanguages.addLanguage("java");
- moduleLanguages.addLanguage("cobol");
-
- assertThat(profile.getActiveRules()).containsOnly(javaActiveRule, cobolActiveRule);
- assertThat(profile.getActiveRules(true)).containsOnly(javaActiveRule, cobolActiveRule);
- assertThat(profile.getActiveRulesByRepository("javaplugin")).containsOnly(javaActiveRule);
- assertThat(profile.getActiveRulesByRepository("cobolplugin")).containsOnly(cobolActiveRule);
- assertThat(profile.getActiveRule("javaplugin", "javarule")).isEqualTo(javaActiveRule);
- assertThat(profile.getActiveRule(javaRule)).isEqualTo(javaActiveRule);
- assertThat(profile.getActiveRule("cobolplugin", "cobolrule")).isEqualTo(cobolActiveRule);
- assertThat(profile.getActiveRule(cobolRule)).isEqualTo(cobolActiveRule);
- assertThat(profile.getAlerts()).containsOnly(javaAlert, cobolAlert);
- // Hack for CommonChecksDecorator
- assertThat(profile.getLanguage()).isEqualTo("");
- }
-
- @Test
- public void some_methods_should_not_support_multilanguage() {
- Settings settings = new Settings();
- settings.setProperty("sonar.profile.java", "java profile");
- settings.setProperty("sonar.profile.cobol", "cobol profile");
-
- RulesProfile javaProfile = RulesProfile.create("java profile", "java");
- org.sonar.api.rules.Rule javaRule = new org.sonar.api.rules.Rule("javaplugin", "javarule");
- ActiveRule javaActiveRule = new ActiveRule(javaProfile, javaRule, RulePriority.BLOCKER);
- javaProfile.addActiveRule(javaActiveRule);
- when(dao.getProfile(Java.KEY, "java profile")).thenReturn(javaProfile);
-
- RulesProfile cobolProfile = RulesProfile.create("cobol profile", "cobol");
- org.sonar.api.rules.Rule cobolRule = new org.sonar.api.rules.Rule("cobolplugin", "cobolrule");
- ActiveRule cobolActiveRule = new ActiveRule(cobolProfile, cobolRule, RulePriority.BLOCKER);
- cobolProfile.addActiveRule(cobolActiveRule);
- when(dao.getProfile("cobol", "cobol profile")).thenReturn(cobolProfile);
-
- DefaultModuleLanguages moduleLanguages = new DefaultModuleLanguages(settings, languages);
- moduleLanguages.addLanguage("java");
- moduleLanguages.addLanguage("cobol");
- RulesProfile profile = new DefaultProfileLoader(dao, moduleLanguages, languages).load(javaProject, settings);
-
- thrown.expect(SonarException.class);
- thrown.expectMessage("Please update your plugin to support multi-language analysis");
- profile.getId();
- }
-
- @Test
- public void should_fail_if_not_found() {
- Settings settings = new Settings();
- settings.setProperty("sonar.profile.java", "unknown");
-
- thrown.expect(SonarException.class);
- thrown.expectMessage("Quality profile not found : unknown, language java");
- new DefaultProfileLoader(dao, new DefaultModuleLanguages(settings, languages), languages).load(javaProject, settings);
- }
-
- private Project newProject(String language) {
- PropertiesConfiguration configuration = new PropertiesConfiguration();
- configuration.setProperty("sonar.language", language);
- return new Project("project").setConfiguration(configuration);
- }
-}
+//import org.apache.commons.configuration.PropertiesConfiguration;
+//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.profiles.Alert;
+//import org.sonar.api.profiles.RulesProfile;
+//import org.sonar.api.resources.AbstractLanguage;
+//import org.sonar.api.resources.Java;
+//import org.sonar.api.resources.Language;
+//import org.sonar.api.resources.Languages;
+//import org.sonar.api.resources.Project;
+//import org.sonar.api.rules.ActiveRule;
+//import org.sonar.api.rules.RulePriority;
+//import org.sonar.api.utils.SonarException;
+//import org.sonar.batch.scan.language.DefaultModuleLanguages;
+//import org.sonar.jpa.dao.ProfilesDao;
+//
+//import java.util.Arrays;
+//
+//import static org.fest.assertions.Assertions.assertThat;
+//import static org.mockito.Mockito.mock;
+//import static org.mockito.Mockito.when;
+//
+//public class DefaultProfileLoaderTest {
+//
+// @Rule
+// public ExpectedException thrown = ExpectedException.none();
+//
+// ProfilesDao dao;
+// Languages languages;
+//
+// @Before
+// public void setUp() {
+// dao = mock(ProfilesDao.class);
+// Language cobol = new AbstractLanguage("cobol", "Cobol") {
+// public String[] getFileSuffixes() {
+// return null;
+// }
+// };
+// languages = new Languages(Java.INSTANCE, cobol);
+// }
+//
+// @Test
+// public void should_get_configured_profile() {
+// Settings settings = new Settings();
+// settings.setProperty("sonar.profile.java", "legacy profile");
+// settings.setProperty("sonar.profile.cobol", "cobol profile");
+// when(dao.getProfile(Java.KEY, "legacy profile")).thenReturn(RulesProfile.create("legacy profile", "java"));
+// when(dao.getProfile("cobol", "cobol profile")).thenReturn(RulesProfile.create("cobol profile", "cobol"));
+//
+// DefaultModuleLanguages moduleLanguages = new DefaultModuleLanguages(settings, languages);
+// moduleLanguages.addLanguage("java");
+// RulesProfile profile = new DefaultProfileLoader(dao, moduleLanguages, languages).load(settings);
+//
+// assertThat(profile.getName()).isEqualTo("legacy profile");
+// }
+//
+// @Test
+// public void some_methods_should_support_multilanguage() {
+// Settings settings = new Settings();
+// settings.setProperty("sonar.profile.java", "java profile");
+// settings.setProperty("sonar.profile.cobol", "cobol profile");
+//
+// RulesProfile javaProfile = RulesProfile.create("java profile", "java");
+// org.sonar.api.rules.Rule javaRule = new org.sonar.api.rules.Rule("javaplugin", "javarule");
+// ActiveRule javaActiveRule = new ActiveRule(javaProfile, javaRule, RulePriority.BLOCKER);
+// javaProfile.addActiveRule(javaActiveRule);
+// Alert javaAlert = mock(Alert.class);
+// javaProfile.setAlerts(Arrays.asList(javaAlert));
+// when(dao.getProfile(Java.KEY, "java profile")).thenReturn(javaProfile);
+//
+// RulesProfile cobolProfile = RulesProfile.create("cobol profile", "cobol");
+// org.sonar.api.rules.Rule cobolRule = new org.sonar.api.rules.Rule("cobolplugin", "cobolrule");
+// ActiveRule cobolActiveRule = new ActiveRule(cobolProfile, cobolRule, RulePriority.BLOCKER);
+// cobolProfile.addActiveRule(cobolActiveRule);
+// Alert cobolAlert = mock(Alert.class);
+// cobolProfile.setAlerts(Arrays.asList(cobolAlert));
+// when(dao.getProfile("cobol", "cobol profile")).thenReturn(cobolProfile);
+//
+// DefaultModuleLanguages moduleLanguages = new DefaultModuleLanguages(settings, languages);
+// RulesProfile profile = new DefaultProfileLoader(dao, moduleLanguages, languages).load(settings);
+//
+// // Languages are detected later
+// moduleLanguages.addLanguage("java");
+// moduleLanguages.addLanguage("cobol");
+//
+// assertThat(profile.getActiveRules()).containsOnly(javaActiveRule, cobolActiveRule);
+// assertThat(profile.getActiveRules(true)).containsOnly(javaActiveRule, cobolActiveRule);
+// assertThat(profile.getActiveRulesByRepository("javaplugin")).containsOnly(javaActiveRule);
+// assertThat(profile.getActiveRulesByRepository("cobolplugin")).containsOnly(cobolActiveRule);
+// assertThat(profile.getActiveRule("javaplugin", "javarule")).isEqualTo(javaActiveRule);
+// assertThat(profile.getActiveRule(javaRule)).isEqualTo(javaActiveRule);
+// assertThat(profile.getActiveRule("cobolplugin", "cobolrule")).isEqualTo(cobolActiveRule);
+// assertThat(profile.getActiveRule(cobolRule)).isEqualTo(cobolActiveRule);
+// assertThat(profile.getAlerts()).containsOnly(javaAlert, cobolAlert);
+// // Hack for CommonChecksDecorator
+// assertThat(profile.getLanguage()).isEqualTo("");
+// }
+//
+// @Test
+// public void some_methods_should_not_support_multilanguage() {
+// Settings settings = new Settings();
+// settings.setProperty("sonar.profile.java", "java profile");
+// settings.setProperty("sonar.profile.cobol", "cobol profile");
+//
+// RulesProfile javaProfile = RulesProfile.create("java profile", "java");
+// org.sonar.api.rules.Rule javaRule = new org.sonar.api.rules.Rule("javaplugin", "javarule");
+// ActiveRule javaActiveRule = new ActiveRule(javaProfile, javaRule, RulePriority.BLOCKER);
+// javaProfile.addActiveRule(javaActiveRule);
+// when(dao.getProfile(Java.KEY, "java profile")).thenReturn(javaProfile);
+//
+// RulesProfile cobolProfile = RulesProfile.create("cobol profile", "cobol");
+// org.sonar.api.rules.Rule cobolRule = new org.sonar.api.rules.Rule("cobolplugin", "cobolrule");
+// ActiveRule cobolActiveRule = new ActiveRule(cobolProfile, cobolRule, RulePriority.BLOCKER);
+// cobolProfile.addActiveRule(cobolActiveRule);
+// when(dao.getProfile("cobol", "cobol profile")).thenReturn(cobolProfile);
+//
+// DefaultModuleLanguages moduleLanguages = new DefaultModuleLanguages(settings, languages);
+// moduleLanguages.addLanguage("java");
+// moduleLanguages.addLanguage("cobol");
+// RulesProfile profile = new DefaultProfileLoader(dao, moduleLanguages, languages).load(settings);
+//
+// thrown.expect(SonarException.class);
+// thrown.expectMessage("Please update your plugin to support multi-language analysis");
+// profile.getId();
+// }
+//
+// @Test
+// public void should_fail_if_not_found() {
+// Settings settings = new Settings();
+// settings.setProperty("sonar.profile.java", "unknown");
+//
+// thrown.expect(SonarException.class);
+// thrown.expectMessage("Quality profile not found : unknown, language java");
+// new DefaultProfileLoader(dao, new DefaultModuleLanguages(settings, languages), languages).load(settings);
+// }
+//
+// private Project newProject(String language) {
+// PropertiesConfiguration configuration = new PropertiesConfiguration();
+// configuration.setProperty("sonar.language", language);
+// return new Project("project").setConfiguration(configuration);
+// }
+//}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/ProfileProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/ProfileProviderTest.java
deleted file mode 100644
index 12c7cb251b7..00000000000
--- a/sonar-batch/src/test/java/org/sonar/batch/ProfileProviderTest.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * SonarQube, open source software quality management tool.
- * Copyright (C) 2008-2013 SonarSource
- * mailto:contact AT sonarsource DOT com
- *
- * SonarQube is free software; you can redistribute it and/or
- * modify it under the terms of the GNU Lesser General Public
- * License as published by the Free Software Foundation; either
- * version 3 of the License, or (at your option) any later version.
- *
- * SonarQube is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
- * Lesser General Public License for more details.
- *
- * You should have received a copy of the GNU Lesser General Public License
- * along with this program; if not, write to the Free Software Foundation,
- * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- */
-package org.sonar.batch;
-
-import org.apache.commons.configuration.PropertiesConfiguration;
-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.profiles.RulesProfile;
-import org.sonar.api.resources.Languages;
-import org.sonar.api.resources.Project;
-
-import static org.hamcrest.Matchers.is;
-import static org.junit.Assert.assertThat;
-import static org.mockito.Matchers.any;
-import static org.mockito.Matchers.eq;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verify;
-import static org.mockito.Mockito.verifyNoMoreInteractions;
-import static org.mockito.Mockito.when;
-
-public class ProfileProviderTest {
-
- @Rule
- public ExpectedException thrown = ExpectedException.none();
-
- private Project javaProject;
-
- @Before
- public void setUp() {
- javaProject = newProject("java");
- }
-
- @Test
- public void shouldProvideProfile() {
- ProfileProvider provider = new ProfileProvider();
- ProfileLoader loader = mock(ProfileLoader.class);
- RulesProfile profile = RulesProfile.create();
- when(loader.load(eq(javaProject), any(Settings.class))).thenReturn(profile);
-
- assertThat(provider.provide(javaProject, loader, new Settings(), mock(Languages.class)), is(profile));
- assertThat(provider.provide(javaProject, loader, new Settings(), mock(Languages.class)), is(profile));
- verify(loader).load(eq(javaProject), any(Settings.class));
- verifyNoMoreInteractions(loader);
- }
-
- private Project newProject(String language) {
- PropertiesConfiguration configuration = new PropertiesConfiguration();
- configuration.setProperty("sonar.language", language);
- return new Project("project").setConfiguration(configuration);
- }
-}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/ModuleQProfilesTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/ModuleQProfilesTest.java
new file mode 100644
index 00000000000..478b4fa71dc
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/ModuleQProfilesTest.java
@@ -0,0 +1,131 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.rule;
+
+import com.google.common.collect.Lists;
+import org.junit.Test;
+import org.sonar.api.config.Settings;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.api.utils.MessageException;
+import org.sonar.batch.ProfileLoader;
+import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+
+import java.util.List;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.fest.assertions.Fail.fail;
+
+public class ModuleQProfilesTest extends AbstractDaoTestCase {
+
+ Languages languages = new Languages(new SimpleLanguage("java"), new SimpleLanguage("php"));
+ Settings settings = new Settings();
+
+ @Test
+ public void find_profiles() throws Exception {
+ setupData("shared");
+ QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+
+ settings.setProperty("sonar.profile.java", "Java Two");
+ settings.setProperty("sonar.profile.abap", "Abap One");
+ settings.setProperty("sonar.profile.php", "Php One");
+
+ ModuleQProfiles moduleQProfiles = new ModuleQProfiles(settings, languages, dao, new ProfileLoader[0]);
+ List<ModuleQProfiles.QProfile> qProfiles = Lists.newArrayList(moduleQProfiles.findAll());
+
+ assertThat(qProfiles).hasSize(2);
+ assertThat(moduleQProfiles.findByLanguage("java")).isNotNull();
+ assertThat(moduleQProfiles.findByLanguage("php")).isNotNull();
+ assertThat(moduleQProfiles.findByLanguage("abap")).isNull();
+ ModuleQProfiles.QProfile javaProfile = qProfiles.get(0);
+ assertThat(javaProfile.id()).isEqualTo(2);
+ assertThat(javaProfile.name()).isEqualTo("Java Two");
+ assertThat(javaProfile.language()).isEqualTo("java");
+ assertThat(javaProfile.version()).isEqualTo(20);
+ ModuleQProfiles.QProfile phpProfile = qProfiles.get(1);
+ assertThat(phpProfile.id()).isEqualTo(3);
+ assertThat(phpProfile.name()).isEqualTo("Php One");
+ assertThat(phpProfile.language()).isEqualTo("php");
+ assertThat(phpProfile.version()).isEqualTo(30);
+
+ }
+
+ @Test
+ public void use_deprecated_property() throws Exception {
+ setupData("shared");
+ QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+
+ settings.setProperty("sonar.profile", "Java Two");
+ settings.setProperty("sonar.profile.php", "Php One");
+
+ ModuleQProfiles moduleQProfiles = new ModuleQProfiles(settings, languages, dao, new ProfileLoader[0]);
+ List<ModuleQProfiles.QProfile> qProfiles = Lists.newArrayList(moduleQProfiles.findAll());
+
+ assertThat(qProfiles).hasSize(1);
+ ModuleQProfiles.QProfile javaProfile = qProfiles.get(0);
+ assertThat(javaProfile.id()).isEqualTo(2);
+ assertThat(javaProfile.name()).isEqualTo("Java Two");
+ assertThat(javaProfile.language()).isEqualTo("java");
+ assertThat(javaProfile.version()).isEqualTo(20);
+
+ // the php profile is not found as sonar.profile overrides all other properties.
+ }
+
+ @Test
+ public void fail_if_unknown_profile() throws Exception {
+ setupData("shared");
+ QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+
+ settings.setProperty("sonar.profile.java", "Unknown");
+ settings.setProperty("sonar.profile.php", "Php One");
+
+ try {
+ new ModuleQProfiles(settings, languages, dao, new ProfileLoader[0]);
+ fail();
+ } catch (MessageException e) {
+ assertThat(e).hasMessage("Quality profile not found : 'Unknown' on language 'java'");
+ }
+ }
+
+ private static class SimpleLanguage implements Language {
+
+ private final String key;
+
+ private SimpleLanguage(String key) {
+ this.key = key;
+ }
+
+ @Override
+ public String getKey() {
+ return key;
+ }
+
+ @Override
+ public String getName() {
+ return key;
+ }
+
+ @Override
+ public String[] getFileSuffixes() {
+ return new String[0];
+ }
+ }
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/ModuleRulesProviderTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/ModuleRulesProviderTest.java
new file mode 100644
index 00000000000..5d1fdcfc8d5
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/ModuleRulesProviderTest.java
@@ -0,0 +1,79 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.rule;
+
+import org.junit.Before;
+import org.junit.Test;
+import org.sonar.api.batch.rule.ModuleRule;
+import org.sonar.api.batch.rule.ModuleRules;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+import org.sonar.api.rules.Rule;
+import org.sonar.api.rules.RuleFinder;
+import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.sonar.core.qualityprofile.db.ActiveRuleDao;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+
+import java.util.Arrays;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
+
+public class ModuleRulesProviderTest extends AbstractDaoTestCase {
+
+ ModuleQProfiles qProfiles = mock(ModuleQProfiles.class);
+ RuleFinder ruleFinder = mock(RuleFinder.class);
+
+ @Before
+ public void init_rules() {
+ when(ruleFinder.findById(10)).thenReturn(new Rule().setRepositoryKey("squid").setKey("S0001"));
+ when(ruleFinder.findById(100)).thenReturn(new Rule().setRepositoryKey("phpunit").setKey("P1"));
+ }
+ @Test
+ public void build_module_rules() throws Exception {
+ setupData("shared");
+ QualityProfileDao profileDao = new QualityProfileDao(getMyBatis());
+ when(qProfiles.findAll()).thenReturn(Arrays.asList(
+ // 1 rule is enabled on java with severity INFO
+ new ModuleQProfiles.QProfile(profileDao.selectById(2)),
+ // 1 rule is enabled on php with severity BLOCKER
+ new ModuleQProfiles.QProfile(profileDao.selectById(3))
+ ));
+
+ ModuleRulesProvider provider = new ModuleRulesProvider();
+ ActiveRuleDao activeRuleDao = new ActiveRuleDao(getMyBatis());
+ ModuleRules moduleRules = provider.provide(qProfiles, activeRuleDao, ruleFinder);
+
+ assertThat(moduleRules.findAll()).hasSize(2);
+ assertThat(moduleRules.findByRepository("squid")).hasSize(1);
+ assertThat(moduleRules.findByRepository("phpunit")).hasSize(1);
+ assertThat(moduleRules.findByRepository("unknown")).isEmpty();
+ ModuleRule squidRule = moduleRules.find(RuleKey.of("squid", "S0001"));
+ assertThat(squidRule.severity()).isEqualTo(Severity.INFO);
+ assertThat(squidRule.params()).hasSize(2);
+ assertThat(squidRule.param("max")).isEqualTo("20");
+ assertThat(squidRule.param("format")).isEqualTo("html");
+ ModuleRule phpRule = moduleRules.find(RuleKey.of("phpunit", "P1"));
+ assertThat(phpRule.severity()).isEqualTo(Severity.BLOCKER);
+ assertThat(phpRule.params()).isEmpty();
+ }
+
+}
diff --git a/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java
new file mode 100644
index 00000000000..c8fab70ad6c
--- /dev/null
+++ b/sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java
@@ -0,0 +1,72 @@
+/*
+ * SonarQube, open source software quality management tool.
+ * Copyright (C) 2008-2013 SonarSource
+ * mailto:contact AT sonarsource DOT com
+ *
+ * SonarQube is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * SonarQube is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.batch.rule;
+
+import edu.emory.mathcs.backport.java.util.Collections;
+import org.junit.Test;
+import org.sonar.api.batch.ModuleLanguages;
+import org.sonar.api.batch.SensorContext;
+import org.sonar.api.resources.Project;
+import org.sonar.core.persistence.AbstractDaoTestCase;
+import org.sonar.core.qualityprofile.db.QualityProfileDao;
+
+import java.util.Arrays;
+
+import static org.fest.assertions.Assertions.assertThat;
+import static org.mockito.Mockito.*;
+
+public class QProfileSensorTest extends AbstractDaoTestCase {
+
+ ModuleQProfiles moduleQProfiles = mock(ModuleQProfiles.class);
+ ModuleLanguages moduleLanguages = mock(ModuleLanguages.class);
+ Project project = mock(Project.class);
+ SensorContext sensorContext = mock(SensorContext.class);
+
+ @Test
+ public void no_qprofiles() throws Exception {
+ setupData("shared");
+ QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+ when(moduleQProfiles.findAll()).thenReturn(Collections.emptyList());
+
+ QProfileSensor sensor = new QProfileSensor(moduleQProfiles, moduleLanguages, dao);
+ assertThat(sensor.shouldExecuteOnProject(project)).isTrue();
+ sensor.analyse(project, sensorContext);
+
+ // measures are not saved
+ verifyZeroInteractions(sensorContext);
+ }
+
+ @Test
+ public void mark_profiles_as_used() throws Exception {
+ setupData("shared");
+
+ QualityProfileDao dao = new QualityProfileDao(getMyBatis());
+ when(moduleQProfiles.findByLanguage("java")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(2)));
+ when(moduleQProfiles.findByLanguage("php")).thenReturn(new ModuleQProfiles.QProfile(dao.selectById(3)));
+ when(moduleQProfiles.findByLanguage("abap")).thenReturn(null);
+ when(moduleLanguages.keys()).thenReturn(Arrays.asList("java", "php", "abap"));
+
+ QProfileSensor sensor = new QProfileSensor(moduleQProfiles, moduleLanguages, dao);
+ assertThat(sensor.shouldExecuteOnProject(project)).isTrue();
+ sensor.analyse(project, sensorContext);
+
+ checkTable("mark_profiles_as_used", "rules_profiles");
+ }
+}
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/rule/ModuleQProfilesTest/shared.xml b/sonar-batch/src/test/resources/org/sonar/batch/rule/ModuleQProfilesTest/shared.xml
new file mode 100644
index 00000000000..425b89de3b0
--- /dev/null
+++ b/sonar-batch/src/test/resources/org/sonar/batch/rule/ModuleQProfilesTest/shared.xml
@@ -0,0 +1,15 @@
+<dataset>
+
+ <rules_profiles id="1" name="Java One" language="java" parent_name="[null]" version="10"
+ used_profile="[false]"/>
+
+ <rules_profiles id="2" name="Java Two" language="java" parent_name="[null]" version="20"
+ used_profile="[false]"/>
+
+ <rules_profiles id="3" name="Php One" language="php" parent_name="[null]" version="30"
+ used_profile="[false]"/>
+
+ <rules_profiles id="4" name="Cobol One" language="cbl" parent_name="[null]" version="40"
+ used_profile="[false]"/>
+
+</dataset>
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/rule/ModuleRulesProviderTest/shared.xml b/sonar-batch/src/test/resources/org/sonar/batch/rule/ModuleRulesProviderTest/shared.xml
new file mode 100644
index 00000000000..2c4953c0dc9
--- /dev/null
+++ b/sonar-batch/src/test/resources/org/sonar/batch/rule/ModuleRulesProviderTest/shared.xml
@@ -0,0 +1,25 @@
+<dataset>
+
+ <rules_profiles id="1" name="Java One" language="java" parent_name="[null]" version="10"
+ used_profile="[false]"/>
+
+ <rules_profiles id="2" name="Java Two" language="java" parent_name="[null]" version="20"
+ used_profile="[false]"/>
+
+ <rules_profiles id="3" name="Php One" language="php" parent_name="[null]" version="30"
+ used_profile="[false]"/>
+
+ <rules_profiles id="4" name="Cobol One" language="cbl" parent_name="[null]" version="40"
+ used_profile="[false]"/>
+
+ <!-- java -->
+ <active_rules id="1" profile_id="2" rule_id="10" failure_level="0" inheritance="[null]"
+ note_created_at="2013-12-18" note_updated_at="2013-12-18" note_user_login="john" note_data="other note"/>
+
+ <active_rule_parameters id="1" active_rule_id="1" rules_parameter_id="1" rules_parameter_key="max" value="20"/>
+ <active_rule_parameters id="2" active_rule_id="1" rules_parameter_id="2" rules_parameter_key="format" value="html"/>
+
+ <!-- php -->
+ <active_rules id="2" profile_id="3" rule_id="100" failure_level="4" inheritance="[null]"
+ note_created_at="2013-12-18" note_updated_at="2013-12-18" note_user_login="john" note_data="other note"/>
+</dataset>
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/rule/QProfileSensorTest/mark_profiles_as_used-result.xml b/sonar-batch/src/test/resources/org/sonar/batch/rule/QProfileSensorTest/mark_profiles_as_used-result.xml
new file mode 100644
index 00000000000..7794819e4e4
--- /dev/null
+++ b/sonar-batch/src/test/resources/org/sonar/batch/rule/QProfileSensorTest/mark_profiles_as_used-result.xml
@@ -0,0 +1,15 @@
+<dataset>
+
+ <rules_profiles id="1" name="Java One" language="java" parent_name="[null]" version="1"
+ used_profile="[false]"/>
+
+ <rules_profiles id="2" name="Java Two" language="java" parent_name="[null]" version="1"
+ used_profile="[true]"/>
+
+ <rules_profiles id="3" name="Php One" language="php" parent_name="[null]" version="1"
+ used_profile="[true]"/>
+
+ <rules_profiles id="4" name="Cobol One" language="cbl" parent_name="[null]" version="1"
+ used_profile="[false]"/>
+
+</dataset>
diff --git a/sonar-batch/src/test/resources/org/sonar/batch/rule/QProfileSensorTest/shared.xml b/sonar-batch/src/test/resources/org/sonar/batch/rule/QProfileSensorTest/shared.xml
new file mode 100644
index 00000000000..c3ec8e0148a
--- /dev/null
+++ b/sonar-batch/src/test/resources/org/sonar/batch/rule/QProfileSensorTest/shared.xml
@@ -0,0 +1,15 @@
+<dataset>
+
+ <rules_profiles id="1" name="Java One" language="java" parent_name="[null]" version="1"
+ used_profile="[false]"/>
+
+ <rules_profiles id="2" name="Java Two" language="java" parent_name="[null]" version="1"
+ used_profile="[false]"/>
+
+ <rules_profiles id="3" name="Php One" language="php" parent_name="[null]" version="1"
+ used_profile="[false]"/>
+
+ <rules_profiles id="4" name="Cobol One" language="cbl" parent_name="[null]" version="1"
+ used_profile="[false]"/>
+
+</dataset>
diff --git a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDao.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDao.java
index bdc607fef25..e41c91c708c 100644
--- a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDao.java
+++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleDao.java
@@ -347,4 +347,13 @@ public class ActiveRuleDao implements ServerComponent {
public List<ActiveRuleParamDto> selectAllParams(SqlSession session) {
return session.getMapper(ActiveRuleMapper.class).selectAllParams();
}
+
+ public List<ActiveRuleParamDto> selectParamsByProfileId(int profileId) {
+ SqlSession session = mybatis.openSession();
+ try {
+ return session.getMapper(ActiveRuleMapper.class).selectParamsByProfileId(profileId);
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
}
diff --git a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleMapper.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleMapper.java
index aae23290ee5..4c974f09e33 100644
--- a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleMapper.java
+++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/ActiveRuleMapper.java
@@ -70,6 +70,8 @@ public interface ActiveRuleMapper {
List<ActiveRuleParamDto> selectParamsByActiveRuleId(int activeRuleId);
+ List<ActiveRuleParamDto> selectParamsByProfileId(int profileId);
+
List<ActiveRuleParamDto> selectAllParams();
diff --git a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java
index e736686264f..2f8ab8a38b5 100644
--- a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java
+++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileDao.java
@@ -211,4 +211,13 @@ public class QualityProfileDao implements ServerComponent {
}
}
+ public void updateUsedColumn(int profileId, boolean used) {
+ SqlSession session = mybatis.openSession();
+ try {
+ session.getMapper(QualityProfileMapper.class).updatedUsedColumn(profileId, used);
+ session.commit();
+ } finally {
+ MyBatis.closeQuietly(session);
+ }
+ }
}
diff --git a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java
index 8338ab6c885..5ddf7e3b98f 100644
--- a/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java
+++ b/sonar-core/src/main/java/org/sonar/core/qualityprofile/db/QualityProfileMapper.java
@@ -65,4 +65,5 @@ public interface QualityProfileMapper {
List<QualityProfileDto> selectByProject(@Param("projectId") Long projectId, @Param("key") String propertyKeyPrefix);
+ void updatedUsedColumn(@Param("id") int profileId, @Param("used") boolean used);
}
diff --git a/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/ActiveRuleMapper.xml b/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/ActiveRuleMapper.xml
index cf389856b45..a41353bf019 100644
--- a/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/ActiveRuleMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/ActiveRuleMapper.xml
@@ -185,6 +185,14 @@
</where>
</select>
+ <select id="selectParamsByProfileId" parameterType="int" resultType="ActiveRuleParam">
+ select
+ <include refid="activeRuleParamColumns"/>
+ from active_rule_parameters p
+ inner join active_rules ar on ar.id=p.active_rule_id
+ where ar.profile_id=#{profileId}
+ </select>
+
<select id="selectAllParams" parameterType="map" resultType="ActiveRuleParam">
SELECT <include refid="activeRuleParamColumns"/>
FROM active_rule_parameters p
diff --git a/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml b/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml
index 9bf019e41d6..876fc40df5c 100644
--- a/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml
+++ b/sonar-core/src/main/resources/org/sonar/core/qualityprofile/db/QualityProfileMapper.xml
@@ -129,5 +129,11 @@
AND prop.text_value LIKE p.name
</select>
+ <update id="updatedUsedColumn" parameterType="map">
+ UPDATE rules_profiles SET
+ used_profile=#{used}
+ WHERE id=#{id}
+ </update>
+
</mapper>
diff --git a/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest.java b/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest.java
index 9b3ba405b71..165dd319dee 100644
--- a/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/ActiveRuleDaoTest.java
@@ -271,6 +271,13 @@ public class ActiveRuleDaoTest extends AbstractDaoTestCase {
}
@Test
+ public void select_params_by_profile_id() {
+ setupData("shared");
+
+ assertThat(dao.selectParamsByProfileId(1)).hasSize(2);
+ }
+
+ @Test
public void select_all_params() {
setupData("shared");
diff --git a/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java b/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java
index 863471257c9..f01091d9963 100644
--- a/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java
+++ b/sonar-core/src/test/java/org/sonar/core/qualityprofile/db/QualityProfileDaoTest.java
@@ -223,5 +223,12 @@ public class QualityProfileDaoTest extends AbstractDaoTestCase {
assertThat(dao.selectByProject(1L, "sonar.profile.%")).hasSize(2);
}
+ @Test
+ public void update_used_column() {
+ setupData("update_used_column");
+
+ dao.updateUsedColumn(123, true);
+ checkTables("update_used_column", "rules_profiles");
+ }
}
diff --git a/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update_used_column-result.xml b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update_used_column-result.xml
new file mode 100644
index 00000000000..8d050e782ee
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update_used_column-result.xml
@@ -0,0 +1,6 @@
+<dataset>
+
+ <rules_profiles id="123" name="Sonar Way" language="java" parent_name="[null]" version="1"
+ used_profile="[true]"/>
+
+</dataset>
diff --git a/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update_used_column.xml b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update_used_column.xml
new file mode 100644
index 00000000000..8b135112f5a
--- /dev/null
+++ b/sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update_used_column.xml
@@ -0,0 +1,6 @@
+<dataset>
+
+ <rules_profiles id="123" name="Sonar Way" language="java" parent_name="[null]" version="1"
+ used_profile="[false]"/>
+
+</dataset>
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewModuleRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewModuleRule.java
index cc95045ec3e..2cfecd7c9af 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewModuleRule.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/internal/NewModuleRule.java
@@ -26,12 +26,12 @@ import javax.annotation.Nullable;
import java.util.HashMap;
import java.util.Map;
-class NewModuleRule {
+public class NewModuleRule {
final RuleKey ruleKey;
String severity = Severity.defaultSeverity();
Map<String, String> params = new HashMap<String, String>();
- public NewModuleRule(RuleKey ruleKey) {
+ NewModuleRule(RuleKey ruleKey) {
this.ruleKey = ruleKey;
}