From 04bc6b52d79e9d357078b28a083e63d267f33d8b Mon Sep 17 00:00:00 2001 From: Simon Brandhof Date: Mon, 27 Jan 2014 00:35:35 +0100 Subject: [PATCH] SONAR-926 feed ModuleRules --- .../org/sonar/plugins/core/CorePlugin.java | 2 - .../plugins/core/sensors/ProfileSensor.java | 70 ----- .../core/sensors/ProfileSensorTest.java | 66 ---- .../org/sonar/batch/DefaultProfileLoader.java | 119 ------- .../java/org/sonar/batch/ProfileLoader.java | 4 +- .../java/org/sonar/batch/ProfileProvider.java | 41 --- .../org/sonar/batch/rule/ModuleQProfiles.java | 131 ++++++++ .../sonar/batch/rule/ModuleRulesProvider.java | 71 +++++ .../org/sonar/batch/rule/QProfileSensor.java | 65 ++++ .../batch/rule/RulesProfileProvider.java | 78 +++++ .../sonar/batch/rule/RulesProfileWrapper.java | 154 +++++++++ .../sonar/batch/scan/ModuleScanContainer.java | 37 +-- .../sonar/batch/DefaultProfileLoaderTest.java | 291 +++++++++--------- .../org/sonar/batch/ProfileProviderTest.java | 71 ----- .../sonar/batch/rule/ModuleQProfilesTest.java | 131 ++++++++ .../batch/rule/ModuleRulesProviderTest.java | 79 +++++ .../sonar/batch/rule/QProfileSensorTest.java | 72 +++++ .../batch/rule/ModuleQProfilesTest/shared.xml | 15 + .../rule/ModuleRulesProviderTest/shared.xml | 25 ++ .../mark_profiles_as_used-result.xml | 15 + .../batch/rule/QProfileSensorTest/shared.xml | 15 + .../core/qualityprofile/db/ActiveRuleDao.java | 9 + .../qualityprofile/db/ActiveRuleMapper.java | 2 + .../qualityprofile/db/QualityProfileDao.java | 9 + .../db/QualityProfileMapper.java | 1 + .../qualityprofile/db/ActiveRuleMapper.xml | 8 + .../db/QualityProfileMapper.xml | 6 + .../qualityprofile/db/ActiveRuleDaoTest.java | 7 + .../db/QualityProfileDaoTest.java | 7 + .../update_used_column-result.xml | 6 + .../update_used_column.xml | 6 + .../batch/rule/internal/NewModuleRule.java | 4 +- 32 files changed, 1071 insertions(+), 546 deletions(-) delete mode 100644 plugins/sonar-core-plugin/src/main/java/org/sonar/plugins/core/sensors/ProfileSensor.java delete mode 100644 plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/sensors/ProfileSensorTest.java delete mode 100644 sonar-batch/src/main/java/org/sonar/batch/DefaultProfileLoader.java delete mode 100644 sonar-batch/src/main/java/org/sonar/batch/ProfileProvider.java create mode 100644 sonar-batch/src/main/java/org/sonar/batch/rule/ModuleQProfiles.java create mode 100644 sonar-batch/src/main/java/org/sonar/batch/rule/ModuleRulesProvider.java create mode 100644 sonar-batch/src/main/java/org/sonar/batch/rule/QProfileSensor.java create mode 100644 sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileProvider.java create mode 100644 sonar-batch/src/main/java/org/sonar/batch/rule/RulesProfileWrapper.java delete mode 100644 sonar-batch/src/test/java/org/sonar/batch/ProfileProviderTest.java create mode 100644 sonar-batch/src/test/java/org/sonar/batch/rule/ModuleQProfilesTest.java create mode 100644 sonar-batch/src/test/java/org/sonar/batch/rule/ModuleRulesProviderTest.java create mode 100644 sonar-batch/src/test/java/org/sonar/batch/rule/QProfileSensorTest.java create mode 100644 sonar-batch/src/test/resources/org/sonar/batch/rule/ModuleQProfilesTest/shared.xml create mode 100644 sonar-batch/src/test/resources/org/sonar/batch/rule/ModuleRulesProviderTest/shared.xml create mode 100644 sonar-batch/src/test/resources/org/sonar/batch/rule/QProfileSensorTest/mark_profiles_as_used-result.xml create mode 100644 sonar-batch/src/test/resources/org/sonar/batch/rule/QProfileSensorTest/shared.xml create mode 100644 sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update_used_column-result.xml create mode 100644 sonar-core/src/test/resources/org/sonar/core/qualityprofile/db/QualityProfileDaoTest/update_used_column.xml 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 ruleProfilesPerLanguages = new HashMap(); - 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 profilesPerLanguageKey = new HashMap(); - - // 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 profiles : profilesPerLanguageKey.entrySet()) { - LOG.info("Quality profile for {}: {}", profiles.getKey(), profiles.getValue()); - } - return profile; - } - - private RulesProfile loadSingleProfile(Settings settings) { - Map profilesPerLanguageKey = new HashMap(); - - // 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 byLanguage; + + + public ModuleQProfiles(Settings settings, Languages languages, QualityProfileDao dao, ProfileLoader[] loaders) { + ImmutableMap.Builder 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 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 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 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 profiles; + private final RulesProfile singleLanguageProfile; + + RulesProfileWrapper(Collection 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 getAlerts() { + List result = new ArrayList(); + for (RulesProfile profile : profiles) { + result.addAll(profile.getAlerts()); + } + return result; + } + + @Override + public List getActiveRules() { + List activeRules = new ArrayList(); + 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 getActiveRulesByRepository(String repositoryKey) { + List activeRules = new ArrayList(); + for (RulesProfile profile : profiles) { + activeRules.addAll(profile.getActiveRulesByRepository(repositoryKey)); + } + return activeRules; + } + + @Override + public List getActiveRules(boolean acceptDisabledRules) { + List activeRules = new ArrayList(); + 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 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 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 @@ + + + + + + + + + + + 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 @@ + + + + + + + + + + + + + + + + + + + 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 @@ + + + + + + + + + + + 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 @@ + + + + + + + + + + + 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 selectAllParams(SqlSession session) { return session.getMapper(ActiveRuleMapper.class).selectAllParams(); } + + public List 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 selectParamsByActiveRuleId(int activeRuleId); + List selectParamsByProfileId(int profileId); + List 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 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 @@ + + + + UPDATE rules_profiles SET + used_profile=#{used} + WHERE id=#{id} + + 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 @@ -270,6 +270,13 @@ public class ActiveRuleDaoTest extends AbstractDaoTestCase { assertThat(dao.selectParamsByActiveRuleIds(ImmutableList.of(1, 2))).hasSize(3); } + @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 @@ + + + + + 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 @@ + + + + + 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 params = new HashMap(); - public NewModuleRule(RuleKey ruleKey) { + NewModuleRule(RuleKey ruleKey) { this.ruleKey = ruleKey; } -- 2.39.5