diff options
author | Jean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com> | 2015-01-07 17:33:27 +0100 |
---|---|---|
committer | Jean-Baptiste Lievremont <jean-baptiste.lievremont@sonarsource.com> | 2015-01-07 17:41:23 +0100 |
commit | 31a84b47965aeedfc21e750ea1f295d8839685fb (patch) | |
tree | c3028d36427d93984713f801fa07e890096edc81 /server | |
parent | bde531603464da7c5dacf2e7f4c5ea2e4555a986 (diff) | |
download | sonarqube-31a84b47965aeedfc21e750ea1f295d8839685fb.tar.gz sonarqube-31a84b47965aeedfc21e750ea1f295d8839685fb.zip |
SONAR-5893 Add internal web service to list n most violated tags on a component
Diffstat (limited to 'server')
13 files changed, 436 insertions, 41 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java index 83d0785d475..2974678533a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java @@ -370,4 +370,8 @@ public class IssueService implements ServerComponent { session.close(); } } + + public Map<String, Long> listTagsForComponent(String componentUuid, int pageSize) { + return indexClient.get(IssueIndex.class).listTagsForComponent(componentUuid, pageSize); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java index 0a4f530099e..c443c821158 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java @@ -61,6 +61,7 @@ import org.sonar.server.user.UserSession; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import java.util.Arrays; import java.util.Collection; import java.util.Date; import java.util.List; @@ -272,32 +273,38 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> { } private void addComponentRelatedFilters(IssueQuery query, Map<String, FilterBuilder> filters) { + Collection<String> componentUuids = query.componentUuids(); if (BooleanUtils.isTrue(query.onComponentOnly())) { Set<String> allComponents = Sets.newHashSet(); allComponents.addAll(query.projectUuids()); allComponents.addAll(query.moduleUuids()); - allComponents.addAll(query.componentUuids()); + allComponents.addAll(componentUuids); filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, allComponents)); } else { filters.put(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, matchFilter(IssueIndexDefinition.FIELD_ISSUE_PROJECT_UUID, query.projectUuids())); filters.put(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_UUID, query.moduleUuids())); - FilterBuilder componentFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, query.componentUuids()); - FilterBuilder modulePathFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_PATH, query.componentUuids()); - FilterBuilder compositeFilter = null; - if (componentFilter != null) { - if (modulePathFilter != null) { - compositeFilter = FilterBuilders.orFilter(componentFilter, modulePathFilter); - } else { - compositeFilter = componentFilter; - } - } else if (modulePathFilter != null) { - compositeFilter = modulePathFilter; - } + FilterBuilder compositeFilter = componentFilter(componentUuids); filters.put(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, compositeFilter); } } + private FilterBuilder componentFilter(Collection<String> componentUuids) { + FilterBuilder componentFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_COMPONENT_UUID, componentUuids); + FilterBuilder modulePathFilter = matchFilter(IssueIndexDefinition.FIELD_ISSUE_MODULE_PATH, componentUuids); + FilterBuilder compositeFilter = null; + if (componentFilter != null) { + if (modulePathFilter != null) { + compositeFilter = FilterBuilders.orFilter(componentFilter, modulePathFilter); + } else { + compositeFilter = componentFilter; + } + } else if (modulePathFilter != null) { + compositeFilter = modulePathFilter; + } + return compositeFilter; + } + private FilterBuilder getAuthorizationFilter(QueryContext options) { String user = options.getUserLogin(); Set<String> groups = options.getUserGroups(); @@ -504,4 +511,25 @@ public class IssueIndex extends BaseIndex<Issue, FakeIssueDto, String> { } }); } + + public Map<String, Long> listTagsForComponent(String componentUuid, int pageSize) { + SearchRequestBuilder count = getClient().prepareSearch(IssueIndexDefinition.INDEX) + .setTypes(IssueIndexDefinition.TYPE_ISSUE) + .setQuery(QueryBuilders.filteredQuery(QueryBuilders.matchAllQuery(), + FilterBuilders.boolFilter() + .must(getAuthorizationFilter(new QueryContext())) + .must(componentFilter(Arrays.asList(componentUuid))))); + TermsBuilder aggreg = AggregationBuilders.terms("_ref") + .field(IssueIndexDefinition.FIELD_ISSUE_TAGS) + .size(pageSize) + .order(Order.count(false)) + .minDocCount(1L); + Terms result = count.addAggregation(aggreg).get().getAggregations().get("_ref"); + + Map<String, Long> map = Maps.newHashMap(); + for (Bucket bucket: result.getBuckets()) { + map.put(bucket.getKey(), bucket.getDocCount()); + } + return map; + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/ComponentTagsAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/ComponentTagsAction.java new file mode 100644 index 00000000000..e642686d0bb --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/ComponentTagsAction.java @@ -0,0 +1,78 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 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.server.issue.ws; + +import com.google.common.io.Resources; +import org.sonar.api.server.ws.Request; +import org.sonar.api.server.ws.RequestHandler; +import org.sonar.api.server.ws.Response; +import org.sonar.api.server.ws.WebService; +import org.sonar.api.server.ws.WebService.NewAction; +import org.sonar.api.utils.text.JsonWriter; +import org.sonar.server.issue.IssueService; + +import java.util.Map; + +/** + * List issue tags matching a given query. + * @since 5.1 + */ +public class ComponentTagsAction implements RequestHandler { + + private final IssueService service; + + public ComponentTagsAction(IssueService service) { + this.service = service; + } + + void define(WebService.NewController controller) { + NewAction action = controller.createAction("component_tags") + .setHandler(this) + .setSince("5.1") + .setInternal(true) + .setDescription("List tags for the issues under a given component (including issues on the descendants of the component)") + .setResponseExample(Resources.getResource(getClass(), "example-component-tags.json")); + action.createParam("componentUuid") + .setDescription("A component UUID") + .setRequired(true) + .setExampleValue("7d8749e8-3070-4903-9188-bdd82933bb92"); + action.createParam("ps") + .setDescription("The maximum size of the list to return") + .setExampleValue("25") + .setDefaultValue("10"); + } + + @Override + public void handle(Request request, Response response) throws Exception { + String componentUuid = request.mandatoryParam("componentUuid"); + int pageSize = request.mandatoryParamAsInt("ps"); + JsonWriter json = response.newJsonWriter().beginObject().name("tags").beginArray(); + for (Map.Entry<String, Long> tag : service.listTagsForComponent(componentUuid, pageSize).entrySet()) { + json.beginObject() + .prop("key", tag.getKey()) + .prop("value", tag.getValue()) + .endObject(); + } + json.endArray() + .endObject() + .close(); + } + +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java index c17a6f782bb..ef3146df4d6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java @@ -46,12 +46,14 @@ public class IssuesWs implements WebService { private final SearchAction esSearchAction; private final TagsAction tagsAction; private final SetTagsAction setTagsAction; + private final ComponentTagsAction componentTagsAction; - public IssuesWs(IssueShowAction showAction, SearchAction searchAction, TagsAction tagsAction, SetTagsAction setTagsAction) { + public IssuesWs(IssueShowAction showAction, SearchAction searchAction, TagsAction tagsAction, SetTagsAction setTagsAction, ComponentTagsAction componentTagsAction) { this.showAction = showAction; this.esSearchAction = searchAction; this.tagsAction = tagsAction; this.setTagsAction = setTagsAction; + this.componentTagsAction = componentTagsAction; } @Override @@ -64,6 +66,7 @@ public class IssuesWs implements WebService { esSearchAction.define(controller); tagsAction.define(controller); setTagsAction.define(controller); + componentTagsAction.define(controller); defineChangelogAction(controller); defineAssignAction(controller); diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java index 5f2acb4df47..033e1114262 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java @@ -54,7 +54,13 @@ import org.sonar.core.measure.db.MeasureFilterDao; import org.sonar.core.metric.DefaultMetricFinder; import org.sonar.core.notification.DefaultNotificationManager; import org.sonar.core.permission.PermissionFacade; -import org.sonar.core.persistence.*; +import org.sonar.core.persistence.DaoUtils; +import org.sonar.core.persistence.DatabaseVersion; +import org.sonar.core.persistence.DefaultDatabase; +import org.sonar.core.persistence.MyBatis; +import org.sonar.core.persistence.PreviewDatabaseFactory; +import org.sonar.core.persistence.SemaphoreUpdater; +import org.sonar.core.persistence.SemaphoresImpl; import org.sonar.core.preview.PreviewCache; import org.sonar.core.profiling.Profiling; import org.sonar.core.purge.PurgeProfiler; @@ -80,7 +86,11 @@ import org.sonar.server.activity.index.ActivityNormalizer; import org.sonar.server.activity.ws.ActivitiesWebService; import org.sonar.server.activity.ws.ActivityMapping; import org.sonar.server.authentication.ws.AuthenticationWs; -import org.sonar.server.batch.*; +import org.sonar.server.batch.BatchIndex; +import org.sonar.server.batch.BatchWs; +import org.sonar.server.batch.GlobalReferentialsAction; +import org.sonar.server.batch.ProjectReferentialsAction; +import org.sonar.server.batch.ProjectReferentialsLoader; import org.sonar.server.charts.ChartFactory; import org.sonar.server.component.ComponentCleanerService; import org.sonar.server.component.ComponentService; @@ -88,14 +98,31 @@ import org.sonar.server.component.DefaultComponentFinder; import org.sonar.server.component.DefaultRubyComponentService; import org.sonar.server.component.db.ComponentDao; import org.sonar.server.component.db.SnapshotDao; -import org.sonar.server.component.ws.*; -import org.sonar.server.computation.*; +import org.sonar.server.component.ws.ComponentAppAction; +import org.sonar.server.component.ws.ComponentsWs; +import org.sonar.server.component.ws.EventsWs; +import org.sonar.server.component.ws.ProjectsWs; +import org.sonar.server.component.ws.ResourcesWs; +import org.sonar.server.computation.AnalysisReportQueue; +import org.sonar.server.computation.AnalysisReportService; +import org.sonar.server.computation.AnalysisReportTaskCleaner; +import org.sonar.server.computation.AnalysisReportTaskLauncher; +import org.sonar.server.computation.ComputationService; +import org.sonar.server.computation.ComputeEngineIssueStorageFactory; import org.sonar.server.computation.db.AnalysisReportDao; -import org.sonar.server.computation.step.*; -import org.sonar.server.computation.ws.QueueWsAction; -import org.sonar.server.computation.ws.HistoryWsAction; +import org.sonar.server.computation.step.CleanReportStep; +import org.sonar.server.computation.step.ComponentIndexationInDatabaseStep; +import org.sonar.server.computation.step.ComputationStepRegistry; +import org.sonar.server.computation.step.DataCleanerStep; +import org.sonar.server.computation.step.DigestReportStep; +import org.sonar.server.computation.step.IndexProjectIssuesStep; +import org.sonar.server.computation.step.InvalidatePreviewCacheStep; +import org.sonar.server.computation.step.SwitchSnapshotStep; +import org.sonar.server.computation.step.SynchronizeProjectPermissionsStep; import org.sonar.server.computation.ws.ComputationWebService; +import org.sonar.server.computation.ws.HistoryWsAction; import org.sonar.server.computation.ws.IsQueueEmptyWsAction; +import org.sonar.server.computation.ws.QueueWsAction; import org.sonar.server.computation.ws.SubmitReportWsAction; import org.sonar.server.config.ws.PropertiesWs; import org.sonar.server.dashboard.db.DashboardDao; @@ -108,7 +135,14 @@ import org.sonar.server.db.DbClient; import org.sonar.server.db.EmbeddedDatabaseFactory; import org.sonar.server.db.migrations.DatabaseMigrations; import org.sonar.server.db.migrations.DatabaseMigrator; -import org.sonar.server.debt.*; +import org.sonar.server.debt.DebtCharacteristicsXMLImporter; +import org.sonar.server.debt.DebtModelBackup; +import org.sonar.server.debt.DebtModelLookup; +import org.sonar.server.debt.DebtModelOperations; +import org.sonar.server.debt.DebtModelPluginRepository; +import org.sonar.server.debt.DebtModelService; +import org.sonar.server.debt.DebtModelXMLExporter; +import org.sonar.server.debt.DebtRulesXMLImporter; import org.sonar.server.design.FileDesignWidget; import org.sonar.server.duplication.ws.DuplicationsJsonWriter; import org.sonar.server.duplication.ws.DuplicationsParser; @@ -116,14 +150,34 @@ import org.sonar.server.duplication.ws.DuplicationsWs; import org.sonar.server.es.EsClient; import org.sonar.server.es.IndexCreator; import org.sonar.server.es.IndexRegistry; -import org.sonar.server.issue.*; +import org.sonar.server.issue.ActionService; +import org.sonar.server.issue.AddTagsAction; +import org.sonar.server.issue.AssignAction; +import org.sonar.server.issue.CommentAction; +import org.sonar.server.issue.InternalRubyIssueService; +import org.sonar.server.issue.IssueBulkChangeService; +import org.sonar.server.issue.IssueChangelogFormatter; +import org.sonar.server.issue.IssueChangelogService; +import org.sonar.server.issue.IssueCommentService; +import org.sonar.server.issue.IssueQueryService; +import org.sonar.server.issue.IssueService; +import org.sonar.server.issue.PlanAction; +import org.sonar.server.issue.RemoveTagsAction; +import org.sonar.server.issue.ServerIssueStorage; +import org.sonar.server.issue.SetSeverityAction; +import org.sonar.server.issue.TransitionAction; import org.sonar.server.issue.actionplan.ActionPlanService; import org.sonar.server.issue.actionplan.ActionPlanWs; import org.sonar.server.issue.db.IssueDao; import org.sonar.server.issue.filter.IssueFilterService; import org.sonar.server.issue.filter.IssueFilterWriter; import org.sonar.server.issue.filter.IssueFilterWs; -import org.sonar.server.issue.index.*; +import org.sonar.server.issue.index.IssueAuthorizationIndexer; +import org.sonar.server.issue.index.IssueIndex; +import org.sonar.server.issue.index.IssueIndexDefinition; +import org.sonar.server.issue.index.IssueIndexer; +import org.sonar.server.issue.index.IssueNormalizer; +import org.sonar.server.issue.ws.ComponentTagsAction; import org.sonar.server.issue.ws.IssueActionsWriter; import org.sonar.server.issue.ws.IssueShowAction; import org.sonar.server.issue.ws.IssuesWs; @@ -146,34 +200,118 @@ import org.sonar.server.platform.ws.L10nWs; import org.sonar.server.platform.ws.RestartHandler; import org.sonar.server.platform.ws.ServerWs; import org.sonar.server.platform.ws.SystemWs; -import org.sonar.server.plugins.*; +import org.sonar.server.plugins.InstalledPluginReferentialFactory; +import org.sonar.server.plugins.PluginDownloader; +import org.sonar.server.plugins.ServerExtensionInstaller; +import org.sonar.server.plugins.ServerPluginJarInstaller; +import org.sonar.server.plugins.ServerPluginJarsInstaller; +import org.sonar.server.plugins.ServerPluginRepository; +import org.sonar.server.plugins.UpdateCenterClient; +import org.sonar.server.plugins.UpdateCenterMatrixFactory; import org.sonar.server.properties.ProjectSettingsFactory; import org.sonar.server.qualitygate.QgateProjectFinder; import org.sonar.server.qualitygate.QualityGates; import org.sonar.server.qualitygate.RegisterQualityGates; -import org.sonar.server.qualitygate.ws.*; -import org.sonar.server.qualityprofile.*; +import org.sonar.server.qualitygate.ws.QGatesAppAction; +import org.sonar.server.qualitygate.ws.QGatesCopyAction; +import org.sonar.server.qualitygate.ws.QGatesCreateAction; +import org.sonar.server.qualitygate.ws.QGatesCreateConditionAction; +import org.sonar.server.qualitygate.ws.QGatesDeleteConditionAction; +import org.sonar.server.qualitygate.ws.QGatesDeselectAction; +import org.sonar.server.qualitygate.ws.QGatesDestroyAction; +import org.sonar.server.qualitygate.ws.QGatesListAction; +import org.sonar.server.qualitygate.ws.QGatesRenameAction; +import org.sonar.server.qualitygate.ws.QGatesSearchAction; +import org.sonar.server.qualitygate.ws.QGatesSelectAction; +import org.sonar.server.qualitygate.ws.QGatesSetAsDefaultAction; +import org.sonar.server.qualitygate.ws.QGatesShowAction; +import org.sonar.server.qualitygate.ws.QGatesUnsetDefaultAction; +import org.sonar.server.qualitygate.ws.QGatesUpdateConditionAction; +import org.sonar.server.qualitygate.ws.QGatesWs; +import org.sonar.server.qualityprofile.BuiltInProfiles; +import org.sonar.server.qualityprofile.QProfileBackuper; +import org.sonar.server.qualityprofile.QProfileCopier; +import org.sonar.server.qualityprofile.QProfileExporters; +import org.sonar.server.qualityprofile.QProfileFactory; +import org.sonar.server.qualityprofile.QProfileLoader; +import org.sonar.server.qualityprofile.QProfileLookup; +import org.sonar.server.qualityprofile.QProfileProjectLookup; +import org.sonar.server.qualityprofile.QProfileProjectOperations; +import org.sonar.server.qualityprofile.QProfileReset; +import org.sonar.server.qualityprofile.QProfileService; +import org.sonar.server.qualityprofile.QProfiles; +import org.sonar.server.qualityprofile.RegisterQualityProfiles; +import org.sonar.server.qualityprofile.RuleActivator; +import org.sonar.server.qualityprofile.RuleActivatorContextFactory; import org.sonar.server.qualityprofile.db.ActiveRuleDao; import org.sonar.server.qualityprofile.index.ActiveRuleIndex; import org.sonar.server.qualityprofile.index.ActiveRuleNormalizer; -import org.sonar.server.qualityprofile.ws.*; -import org.sonar.server.rule.*; +import org.sonar.server.qualityprofile.ws.BulkRuleActivationActions; +import org.sonar.server.qualityprofile.ws.ProfilesWs; +import org.sonar.server.qualityprofile.ws.QProfileRestoreBuiltInAction; +import org.sonar.server.qualityprofile.ws.QProfilesWs; +import org.sonar.server.qualityprofile.ws.RuleActivationActions; +import org.sonar.server.rule.DefaultRuleFinder; +import org.sonar.server.rule.DeprecatedRulesDefinitionLoader; +import org.sonar.server.rule.RegisterRules; +import org.sonar.server.rule.RubyRuleService; +import org.sonar.server.rule.RuleCreator; +import org.sonar.server.rule.RuleDefinitionsLoader; +import org.sonar.server.rule.RuleDeleter; +import org.sonar.server.rule.RuleOperations; +import org.sonar.server.rule.RuleRepositories; +import org.sonar.server.rule.RuleService; +import org.sonar.server.rule.RuleUpdater; import org.sonar.server.rule.db.RuleDao; import org.sonar.server.rule.index.RuleIndex; import org.sonar.server.rule.index.RuleNormalizer; -import org.sonar.server.rule.ws.*; -import org.sonar.server.search.*; +import org.sonar.server.rule.ws.ActiveRuleCompleter; +import org.sonar.server.rule.ws.AppAction; +import org.sonar.server.rule.ws.DeleteAction; +import org.sonar.server.rule.ws.RuleMapping; +import org.sonar.server.rule.ws.RulesWebService; +import org.sonar.server.rule.ws.SearchAction; +import org.sonar.server.rule.ws.TagsAction; +import org.sonar.server.rule.ws.UpdateAction; +import org.sonar.server.search.IndexClient; +import org.sonar.server.search.IndexQueue; +import org.sonar.server.search.IndexSynchronizer; +import org.sonar.server.search.SearchClient; +import org.sonar.server.search.SearchHealth; import org.sonar.server.source.HtmlSourceDecorator; import org.sonar.server.source.IndexSourceLinesStep; import org.sonar.server.source.SourceService; import org.sonar.server.source.index.SourceLineIndex; import org.sonar.server.source.index.SourceLineIndexDefinition; import org.sonar.server.source.index.SourceLineIndexer; -import org.sonar.server.source.ws.*; +import org.sonar.server.source.ws.HashAction; +import org.sonar.server.source.ws.IndexAction; +import org.sonar.server.source.ws.LinesAction; +import org.sonar.server.source.ws.RawAction; +import org.sonar.server.source.ws.ScmAction; +import org.sonar.server.source.ws.ScmWriter; import org.sonar.server.source.ws.ShowAction; -import org.sonar.server.startup.*; +import org.sonar.server.source.ws.SourcesWs; +import org.sonar.server.startup.CleanPreviewAnalysisCache; +import org.sonar.server.startup.CopyRequirementsFromCharacteristicsToRules; +import org.sonar.server.startup.GeneratePluginIndex; +import org.sonar.server.startup.JdbcDriverDeployer; +import org.sonar.server.startup.LogServerId; +import org.sonar.server.startup.RegisterDashboards; +import org.sonar.server.startup.RegisterDebtModel; +import org.sonar.server.startup.RegisterMetrics; +import org.sonar.server.startup.RegisterNewMeasureFilters; +import org.sonar.server.startup.RegisterPermissionTemplates; +import org.sonar.server.startup.RegisterServletFilters; +import org.sonar.server.startup.RenameDeprecatedPropertyKeys; +import org.sonar.server.startup.ServerMetadataPersister; import org.sonar.server.test.CoverageService; -import org.sonar.server.test.ws.*; +import org.sonar.server.test.ws.CoverageShowAction; +import org.sonar.server.test.ws.CoverageWs; +import org.sonar.server.test.ws.TestsCoveredFilesAction; +import org.sonar.server.test.ws.TestsShowAction; +import org.sonar.server.test.ws.TestsTestCasesAction; +import org.sonar.server.test.ws.TestsWs; import org.sonar.server.text.MacroInterpreter; import org.sonar.server.text.RubyTextService; import org.sonar.server.ui.JRubyI18n; @@ -181,7 +319,14 @@ import org.sonar.server.ui.JRubyProfiling; import org.sonar.server.ui.PageDecorations; import org.sonar.server.ui.Views; import org.sonar.server.updatecenter.ws.UpdateCenterWs; -import org.sonar.server.user.*; +import org.sonar.server.user.DefaultUserService; +import org.sonar.server.user.DoPrivileged; +import org.sonar.server.user.GroupMembershipFinder; +import org.sonar.server.user.GroupMembershipService; +import org.sonar.server.user.NewUserNotifier; +import org.sonar.server.user.SecurityRealmFactory; +import org.sonar.server.user.UserService; +import org.sonar.server.user.UserUpdater; import org.sonar.server.user.db.GroupDao; import org.sonar.server.user.db.UserDao; import org.sonar.server.user.db.UserGroupDao; @@ -191,7 +336,13 @@ import org.sonar.server.user.index.UserIndexer; import org.sonar.server.user.ws.FavoritesWs; import org.sonar.server.user.ws.UserPropertiesWs; import org.sonar.server.user.ws.UsersWs; -import org.sonar.server.util.*; +import org.sonar.server.util.BooleanTypeValidation; +import org.sonar.server.util.FloatTypeValidation; +import org.sonar.server.util.IntegerTypeValidation; +import org.sonar.server.util.StringListTypeValidation; +import org.sonar.server.util.StringTypeValidation; +import org.sonar.server.util.TextTypeValidation; +import org.sonar.server.util.TypeValidations; import org.sonar.server.ws.ListingWs; import org.sonar.server.ws.WebServiceEngine; @@ -525,6 +676,7 @@ class ServerComponents { pico.addSingleton(org.sonar.server.issue.ws.SearchAction.class); pico.addSingleton(org.sonar.server.issue.ws.TagsAction.class); pico.addSingleton(SetTagsAction.class); + pico.addSingleton(ComponentTagsAction.class); pico.addSingleton(IssueService.class); pico.addSingleton(IssueActionsWriter.class); pico.addSingleton(IssueQueryService.class); diff --git a/server/sonar-server/src/main/resources/org/sonar/server/issue/ws/example-component-tags.json b/server/sonar-server/src/main/resources/org/sonar/server/issue/ws/example-component-tags.json new file mode 100644 index 00000000000..3e00535cb05 --- /dev/null +++ b/server/sonar-server/src/main/resources/org/sonar/server/issue/ws/example-component-tags.json @@ -0,0 +1,7 @@ +{ + "tags": [ + { key: "convention", value: 42 }, + { key: "cwe", value: 12 }, + { key: "security", value: 5 } + ] +}
\ No newline at end of file diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java index 9d9f0b25bfb..eccf43c8f4a 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java @@ -68,6 +68,7 @@ import java.util.Map; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; +import static org.fest.assertions.MapAssert.entry; public class IssueServiceMediumTest { @@ -488,4 +489,19 @@ public class IssueServiceMediumTest { service.setTags(issue.getKey(), ImmutableSet.<String>of()); assertThat(indexClient.get(IssueIndex.class).getByKey(issue.getKey()).tags()).isEmpty(); } + + @Test + public void list_component_tags() { + db.issueDao().insert(session, + IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "java8", "bug")), + IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention", "bug")), + IssueTesting.newDto(rule, file, project), + IssueTesting.newDto(rule, file, project).setTags(ImmutableSet.of("convention"))); + session.commit(); + index(); + + assertThat(service.listTagsForComponent(project.uuid(), 5)).includes(entry("convention", 3L), entry("bug", 2L), entry("java8", 1L)); + assertThat(service.listTagsForComponent(project.uuid(), 2)).includes(entry("convention", 3L), entry("bug", 2L)).excludes(entry("java8", 1L)); + assertThat(service.listTagsForComponent("other", 10)).isEmpty(); + } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/ComponentTagsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/ComponentTagsActionTest.java new file mode 100644 index 00000000000..1dd86e25218 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/ComponentTagsActionTest.java @@ -0,0 +1,98 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2014 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.server.issue.ws; + +import com.google.common.collect.ImmutableMap; +import org.junit.Before; +import org.junit.Test; +import org.junit.runner.RunWith; +import org.mockito.Mock; +import org.mockito.runners.MockitoJUnitRunner; +import org.sonar.api.server.ws.WebService.Action; +import org.sonar.api.server.ws.WebService.Param; +import org.sonar.server.issue.IssueService; +import org.sonar.server.ws.WsTester; + +import java.util.Map; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + +@RunWith(MockitoJUnitRunner.class) +public class ComponentTagsActionTest { + + @Mock + private IssueService service; + + private ComponentTagsAction componentTagsAction; + + private WsTester tester; + + @Before + public void setUp() { + componentTagsAction = new ComponentTagsAction(service); + tester = new WsTester( + new IssuesWs(new IssueShowAction(null, null, null, null, null, null, null, null, null, null, null), + new SearchAction(null, null, null, null, null, null, null, null, null, null,null), + new TagsAction(null), new SetTagsAction(null), componentTagsAction)); + } + + @Test + public void should_define() throws Exception { + Action action = tester.controller("api/issues").action("component_tags"); + assertThat(action.description()).isNotEmpty(); + assertThat(action.responseExampleAsString()).isNotEmpty(); + assertThat(action.isPost()).isFalse(); + assertThat(action.isInternal()).isTrue(); + assertThat(action.handler()).isEqualTo(componentTagsAction); + assertThat(action.params()).hasSize(2); + + Param query = action.param("componentUuid"); + assertThat(query.isRequired()).isTrue(); + assertThat(query.description()).isNotEmpty(); + assertThat(query.exampleValue()).isNotEmpty(); + Param pageSize = action.param("ps"); + assertThat(pageSize.isRequired()).isFalse(); + assertThat(pageSize.defaultValue()).isEqualTo("10"); + assertThat(pageSize.description()).isNotEmpty(); + assertThat(pageSize.exampleValue()).isNotEmpty(); + } + + @Test + public void should_return_empty_list() throws Exception { + tester.newGetRequest("api/issues", "component_tags").setParam("componentUuid", "polop").execute().assertJson("{tags:[]}"); + } + + @Test + public void should_return_tag_list() throws Exception { + Map<String, Long> tags = ImmutableMap.<String, Long>builder() + .put("convention", 2771L) + .put("brain-overload", 998L) + .put("cwe", 89L) + .put("bug", 32L) + .put("cert", 2L) + .build(); + when(service.listTagsForComponent("polop", 5)).thenReturn(tags); + tester.newGetRequest("api/issues", "component_tags").setParam("componentUuid", "polop").setParam("ps", "5").execute() + .assertJson(getClass(), "component-tags.json"); + verify(service).listTagsForComponent("polop", 5); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java index b791878ab8d..799c7f266a8 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java @@ -150,7 +150,7 @@ public class IssueShowActionTest { new SearchAction(mock(DbClient.class), mock(IssueChangeDao.class), mock(IssueService.class), mock(IssueActionsWriter.class), mock(IssueQueryService.class), mock(RuleService.class), mock(ActionPlanService.class), mock(UserFinder.class), mock(I18n.class), mock(Durations.class), mock(Languages.class)), - new TagsAction(null), new SetTagsAction(null) + new TagsAction(null), new SetTagsAction(null), new ComponentTagsAction(null) )); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueTagsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueTagsActionTest.java index 3e5cca639bb..dda5f3d4f81 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueTagsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueTagsActionTest.java @@ -50,7 +50,7 @@ public class IssueTagsActionTest { tester = new WsTester( new IssuesWs(new IssueShowAction(null, null, null, null, null, null, null, null, null, null, null), new SearchAction(null, null, null, null, null, null, null, null, null, null,null), - tagsAction, new SetTagsAction(null))); + tagsAction, new SetTagsAction(null), new ComponentTagsAction(null))); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java index 8c3f3d0e4ba..42d276ae99b 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java @@ -61,7 +61,7 @@ public class IssuesWsTest { SearchAction searchAction = new SearchAction(mock(DbClient.class), mock(IssueChangeDao.class), mock(IssueService.class), mock(IssueActionsWriter.class), mock(IssueQueryService.class), mock(RuleService.class), mock(ActionPlanService.class), mock(UserFinder.class), mock(I18n.class), mock(Durations.class), mock(Languages.class)); - tester = new WsTester(new IssuesWs(showAction, searchAction, new TagsAction(null), new SetTagsAction(null))); + tester = new WsTester(new IssuesWs(showAction, searchAction, new TagsAction(null), new SetTagsAction(null), new ComponentTagsAction(null))); } @Test @@ -70,7 +70,7 @@ public class IssuesWsTest { assertThat(controller).isNotNull(); assertThat(controller.description()).isNotEmpty(); assertThat(controller.since()).isEqualTo("3.6"); - assertThat(controller.actions()).hasSize(16); + assertThat(controller.actions()).hasSize(17); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SetTagsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SetTagsActionTest.java index f54e1f6adee..5c9c9abcb7c 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SetTagsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/issue/ws/SetTagsActionTest.java @@ -50,7 +50,7 @@ public class SetTagsActionTest { tester = new WsTester( new IssuesWs(new IssueShowAction(null, null, null, null, null, null, null, null, null, null, null), new SearchAction(null, null, null, null, null, null, null, null, null, null,null), - new TagsAction(null), setTagsAction)); + new TagsAction(null), setTagsAction, new ComponentTagsAction(null))); } @Test diff --git a/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ComponentTagsActionTest/component-tags.json b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ComponentTagsActionTest/component-tags.json new file mode 100644 index 00000000000..38e018c645b --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ComponentTagsActionTest/component-tags.json @@ -0,0 +1,9 @@ +{ + tags: [ + { key: "convention", value: 2771 }, + { key: "brain-overload", value: 998 }, + { key: "cwe", value: 89 }, + { key: "bug", value: 32 }, + { key: "cert", value: 2 } + ] +}
\ No newline at end of file |