From: Julien Lancelot Date: Mon, 29 Feb 2016 09:32:00 +0000 (+0100) Subject: Revert "SONAR-7330 Remove RubyRuleService" X-Git-Tag: 5.5-M6~96 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=9f98785363d377ca3d320dc8c26e8ed87efcd180;p=sonarqube.git Revert "SONAR-7330 Remove RubyRuleService" This reverts commit f4af3e943fbfd629e34b26f97473d08ba315551c. --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index 08e83e1d6a1..9dfc23730e3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -248,6 +248,7 @@ import org.sonar.server.qualityprofile.ws.SetDefaultAction; import org.sonar.server.rule.CommonRuleDefinitionsImpl; import org.sonar.server.rule.DefaultRuleFinder; import org.sonar.server.rule.DeprecatedRulesDefinitionLoader; +import org.sonar.server.rule.RubyRuleService; import org.sonar.server.rule.RuleCreator; import org.sonar.server.rule.RuleDefinitionsLoader; import org.sonar.server.rule.RuleDeleter; @@ -433,6 +434,7 @@ public class PlatformLevel4 extends PlatformLevel { XMLRuleParser.class, DefaultRuleFinder.class, RuleOperations.class, + RubyRuleService.class, RuleRepositories.class, DeprecatedRulesDefinitionLoader.class, RuleDefinitionsLoader.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java new file mode 100644 index 00000000000..1bafcec918e --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RubyRuleService.java @@ -0,0 +1,166 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.server.rule; + +import com.google.common.base.Strings; +import java.util.List; +import java.util.Map; +import javax.annotation.CheckForNull; +import org.picocontainer.Startable; +import org.sonar.api.server.ServerSide; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.server.debt.DebtRemediationFunction; +import org.sonar.api.server.debt.internal.DefaultDebtRemediationFunction; +import org.sonar.server.paging.PagedResult; +import org.sonar.server.paging.PagingResult; +import org.sonar.server.rule.index.RuleDoc; +import org.sonar.server.rule.index.RuleNormalizer; +import org.sonar.server.rule.index.RuleQuery; +import org.sonar.server.search.QueryContext; +import org.sonar.server.search.Result; +import org.sonar.server.user.UserSession; +import org.sonar.server.util.RubyUtils; + +import static com.google.common.collect.Lists.newArrayList; + +/** + * Used through ruby code
Internal.rules
+ * + * @deprecated in 4.4 because Ruby on Rails is deprecated too ! + */ +@Deprecated +@ServerSide +public class RubyRuleService implements Startable { + + private final RuleService service; + private final RuleUpdater updater; + private final UserSession userSession; + + public RubyRuleService(RuleService service, RuleUpdater updater, UserSession userSession) { + this.service = service; + this.updater = updater; + this.userSession = userSession; + } + + /** + * Used in issues_controller.rb and in manual_rules_controller.rb and in SQALE + */ + @CheckForNull + public Rule findByKey(String ruleKey) { + return service.getByKey(RuleKey.parse(ruleKey)); + } + + /** + * Used in SQALE + * If 'pageSize' params is set no -1, all rules are returned (using scrolling) + */ + public PagedResult find(Map params) { + RuleQuery query = new RuleQuery(); + query.setQueryText(Strings.emptyToNull((String) params.get("searchQuery"))); + query.setKey(Strings.emptyToNull((String) params.get("key"))); + query.setLanguages(RubyUtils.toStrings(params.get("languages"))); + query.setRepositories(RubyUtils.toStrings(params.get("repositories"))); + query.setSeverities(RubyUtils.toStrings(params.get("severities"))); + query.setStatuses(RubyUtils.toEnums(params.get("statuses"), RuleStatus.class)); + query.setTags(RubyUtils.toStrings(params.get("tags"))); + query.setSortField(RuleNormalizer.RuleField.NAME); + String profile = Strings.emptyToNull((String) params.get("profile")); + if (profile != null) { + query.setQProfileKey(profile); + query.setActivation(true); + } + + QueryContext options = new QueryContext(userSession); + Integer pageSize = RubyUtils.toInteger(params.get("pageSize")); + int size = pageSize != null ? pageSize : 50; + if (size > -1) { + Integer page = RubyUtils.toInteger(params.get("p")); + int pageIndex = page != null ? page : 1; + options.setPage(pageIndex, size); + Result result = service.search(query, options); + return new PagedResult<>(result.getHits(), PagingResult.create(options.getLimit(), pageIndex, result.getTotal())); + } else { + List rules = newArrayList(service.search(query, new QueryContext(userSession).setScroll(true)).scroll()); + return new PagedResult<>(rules, PagingResult.create(Integer.MAX_VALUE, 1, rules.size())); + } + } + + /** + * Used in manual_rules_controller.rb + */ + public List searchManualRules() { + return service.search(new RuleQuery().setRepositories(newArrayList(RuleDoc.MANUAL_REPOSITORY)) + .setSortField(RuleNormalizer.RuleField.NAME), new QueryContext(userSession)).getHits(); + } + + // sqale + public void updateRule(Map params) { + RuleUpdate update = RuleUpdate.createForPluginRule(RuleKey.parse((String) params.get("ruleKey"))); + String fn = (String) params.get("debtRemediationFunction"); + if (fn == null) { + update.setDebtRemediationFunction(null); + } else { + update.setDebtRemediationFunction(new DefaultDebtRemediationFunction( + DebtRemediationFunction.Type.valueOf(fn), + Strings.emptyToNull((String) params.get("debtRemediationCoefficient")), + Strings.emptyToNull((String) params.get("debtRemediationOffset"))) + ); + } + updater.update(update, userSession); + } + + /** + * Used in manual_rules_controller.rb + */ + public void createManualRule(Map params) { + NewRule newRule = NewRule.createForManualRule((String) params.get("manualKey")) + .setName((String) params.get("name")) + .setMarkdownDescription((String) params.get("markdownDescription")); + service.create(newRule); + } + + /** + * Used in manual_rules_controller.rb + */ + public void updateManualRule(Map params) { + RuleUpdate update = RuleUpdate.createForManualRule(RuleKey.parse((String) params.get("ruleKey"))) + .setName((String) params.get("name")) + .setMarkdownDescription((String) params.get("markdownDescription")); + service.update(update); + } + + /** + * Used in manual_rules_controller.rb + */ + public void deleteManualRule(String ruleKey) { + service.delete(RuleKey.parse(ruleKey)); + } + + @Override + public void start() { + // used to force pico to instantiate the singleton at startup + } + + @Override + public void stop() { + // implement startable + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleService.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleService.java index 5010d7fb505..5d09a3d8701 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleService.java @@ -101,6 +101,11 @@ public class RuleService { return ruleCreator.create(newRule); } + public void update(RuleUpdate update) { + checkPermission(); + ruleUpdater.update(update, userSession); + } + public void delete(RuleKey ruleKey) { checkPermission(); ruleDeleter.delete(ruleKey); diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java index d7248f5b522..98a95b97eca 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/RuleUpdater.java @@ -54,6 +54,22 @@ public class RuleUpdater { this.system = system; } + /** + * Update manual rules and custom rules (rules instantiated from templates) + */ + public boolean update(RuleUpdate update, UserSession userSession) { + if (update.isEmpty()) { + return false; + } + + DbSession dbSession = dbClient.openSession(false); + try { + return update(dbSession, update, userSession); + } finally { + dbSession.close(); + } + } + /** * Update manual rules and custom rules (rules instantiated from templates) */ diff --git a/server/sonar-server/src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java b/server/sonar-server/src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java new file mode 100644 index 00000000000..886a6b4012f --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/rule/RubyRuleServiceTest.java @@ -0,0 +1,198 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.server.rule; + +import com.google.common.collect.ImmutableMap; +import java.util.HashMap; +import java.util.List; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.ArgumentCaptor; +import org.mockito.Captor; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.rule.RuleKey; +import org.sonar.api.rule.RuleStatus; +import org.sonar.api.server.ws.WebService.Param; +import org.sonar.server.paging.PagedResult; +import org.sonar.server.rule.index.RuleQuery; +import org.sonar.server.search.QueryContext; +import org.sonar.server.search.Result; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.user.ThreadLocalUserSession; + +import static com.google.common.collect.Lists.newArrayList; +import static com.google.common.collect.Maps.newHashMap; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class RubyRuleServiceTest { + + @org.junit.Rule + public UserSessionRule userSessionRule = UserSessionRule.standalone(); + + @Mock + RuleService ruleService; + + @Mock + RuleUpdater updater; + + @Captor + ArgumentCaptor optionsCaptor; + + @Captor + ArgumentCaptor ruleQueryCaptor; + + RubyRuleService service; + + @Before + public void setUp() { + service = new RubyRuleService(ruleService, updater, userSessionRule); + } + + @Test + public void find_by_key() { + service.findByKey("squid:S001"); + verify(ruleService).getByKey(RuleKey.of("squid", "S001")); + } + + @Test + public void search_rules() { + when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(mock(Result.class)); + + HashMap params = newHashMap(); + params.put("searchQuery", "Exception"); + params.put("key", "S001"); + params.put("languages", "xoo,js"); + params.put("repositories", "checkstyle,pmd"); + params.put("severities", "MAJOR,MINOR"); + params.put("statuses", "BETA,READY"); + params.put("tags", "tag1,tag2"); + params.put(Param.PAGE, "1"); + params.put("pageSize", "40"); + service.find(params); + + verify(ruleService).search(ruleQueryCaptor.capture(), optionsCaptor.capture()); + + assertThat(ruleQueryCaptor.getValue().getQueryText()).isEqualTo("Exception"); + assertThat(ruleQueryCaptor.getValue().getKey()).isEqualTo("S001"); + assertThat(ruleQueryCaptor.getValue().getLanguages()).containsOnly("xoo", "js"); + assertThat(ruleQueryCaptor.getValue().getRepositories()).containsOnly("checkstyle", "pmd"); + assertThat(ruleQueryCaptor.getValue().getRepositories()).containsOnly("checkstyle", "pmd"); + assertThat(ruleQueryCaptor.getValue().getSeverities()).containsOnly("MAJOR", "MINOR"); + assertThat(ruleQueryCaptor.getValue().getStatuses()).containsOnly(RuleStatus.BETA, RuleStatus.READY); + assertThat(ruleQueryCaptor.getValue().getTags()).containsOnly("tag1", "tag2"); + assertThat(ruleQueryCaptor.getValue().getQProfileKey()).isNull(); + assertThat(ruleQueryCaptor.getValue().getActivation()).isNull(); + + assertThat(optionsCaptor.getValue().getLimit()).isEqualTo(40); + assertThat(optionsCaptor.getValue().getOffset()).isEqualTo(0); + } + + @Test + public void search_rules_activated_on_a_profile() { + when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(mock(Result.class)); + + HashMap params = newHashMap(); + params.put("profile", "xoo-profile"); + service.find(params); + + verify(ruleService).search(ruleQueryCaptor.capture(), optionsCaptor.capture()); + + assertThat(ruleQueryCaptor.getValue().getQProfileKey()).isEqualTo("xoo-profile"); + assertThat(ruleQueryCaptor.getValue().getActivation()).isTrue(); + } + + @Test + public void search_rules_without_page_size_param() { + when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(mock(Result.class)); + + HashMap params = newHashMap(); + params.put(Param.PAGE, "1"); + service.find(params); + + verify(ruleService).search(ruleQueryCaptor.capture(), optionsCaptor.capture()); + + assertThat(optionsCaptor.getValue().getLimit()).isEqualTo(50); + assertThat(optionsCaptor.getValue().getOffset()).isEqualTo(0); + } + + @Test + public void search_all_rules() { + List rules = newArrayList(mock(Rule.class)); + Result serviceResult = mock(Result.class); + when(serviceResult.scroll()).thenReturn(rules.iterator()); + + when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(serviceResult); + + HashMap params = newHashMap(); + params.put("pageSize", "-1"); + PagedResult result = service.find(params); + + verify(serviceResult).scroll(); + + verify(ruleService).search(ruleQueryCaptor.capture(), optionsCaptor.capture()); + assertThat(result.paging().pageSize()).isEqualTo(Integer.MAX_VALUE); + } + + @Test + public void update_rule() { + when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(mock(Result.class)); + + service.updateRule(ImmutableMap.of("ruleKey", "squid:S001")); + + verify(updater).update(any(RuleUpdate.class), any(ThreadLocalUserSession.class)); + } + + @Test + public void search_manual_rules() { + when(ruleService.search(any(RuleQuery.class), any(QueryContext.class))).thenReturn(mock(Result.class)); + + service.searchManualRules(); + + verify(ruleService).search(any(RuleQuery.class), any(QueryContext.class)); + } + + @Test + public void create_manual_rules() { + service.createManualRule(ImmutableMap.of("manualKey", "MY_MANUAL")); + + verify(ruleService).create(any(NewRule.class)); + } + + @Test + public void update_manual_rules() { + service.updateManualRule(ImmutableMap.of("ruleKey", "manual:MY_MANUAL")); + + verify(ruleService).update(any(RuleUpdate.class)); + } + + @Test + public void delete_manual_rules() { + service.deleteManualRule("manual:MY_MANUAL"); + + verify(ruleService).delete(RuleKey.of("manual", "MY_MANUAL")); + } +}