Browse Source

SONAR-5893 Add internal web service to list n most violated tags on a component

tags/latest-silver-master-#65
Jean-Baptiste Lievremont 9 years ago
parent
commit
31a84b4796

+ 4
- 0
server/sonar-server/src/main/java/org/sonar/server/issue/IssueService.java View File

@@ -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);
}
}

+ 41
- 13
server/sonar-server/src/main/java/org/sonar/server/issue/index/IssueIndex.java View File

@@ -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;
}
}

+ 78
- 0
server/sonar-server/src/main/java/org/sonar/server/issue/ws/ComponentTagsAction.java View File

@@ -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();
}

}

+ 4
- 1
server/sonar-server/src/main/java/org/sonar/server/issue/ws/IssuesWs.java View File

@@ -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);

+ 174
- 22
server/sonar-server/src/main/java/org/sonar/server/platform/ServerComponents.java View File

@@ -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);

+ 7
- 0
server/sonar-server/src/main/resources/org/sonar/server/issue/ws/example-component-tags.json View File

@@ -0,0 +1,7 @@
{
"tags": [
{ key: "convention", value: 42 },
{ key: "cwe", value: 12 },
{ key: "security", value: 5 }
]
}

+ 16
- 0
server/sonar-server/src/test/java/org/sonar/server/issue/IssueServiceMediumTest.java View File

@@ -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();
}
}

+ 98
- 0
server/sonar-server/src/test/java/org/sonar/server/issue/ws/ComponentTagsActionTest.java View File

@@ -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);
}
}

+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueShowActionTest.java View File

@@ -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)
));
}


+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssueTagsActionTest.java View File

@@ -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

+ 2
- 2
server/sonar-server/src/test/java/org/sonar/server/issue/ws/IssuesWsTest.java View File

@@ -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

+ 1
- 1
server/sonar-server/src/test/java/org/sonar/server/issue/ws/SetTagsActionTest.java View File

@@ -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

+ 9
- 0
server/sonar-server/src/test/resources/org/sonar/server/issue/ws/ComponentTagsActionTest/component-tags.json View File

@@ -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 }
]
}

Loading…
Cancel
Save