Pārlūkot izejas kodu

SONAR-6857 WS components/search search for components

tags/5.2-RC1
Teryk Bellahsene pirms 8 gadiem
vecāks
revīzija
c9eccbdea6

server/sonar-server/src/main/java/org/sonar/server/permission/ws/ResourceTypeToQualifier.java → server/sonar-server/src/main/java/org/sonar/server/component/ResourceTypeFunctions.java Parādīt failu

@@ -18,17 +18,17 @@
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*/

package org.sonar.server.permission.ws;
package org.sonar.server.component;

import com.google.common.base.Function;
import javax.annotation.Nonnull;
import org.sonar.api.resources.ResourceType;

public class ResourceTypeToQualifier {
public class ResourceTypeFunctions {

public static final Function<ResourceType, String> RESOURCE_TYPE_TO_QUALIFIER = Singleton.INSTANCE;
public static final Function<ResourceType, String> RESOURCE_TYPE_TO_QUALIFIER = ResourceTypeToQualifier.INSTANCE;

private enum Singleton implements Function<ResourceType, String> {
private enum ResourceTypeToQualifier implements Function<ResourceType, String> {
INSTANCE;

@Override

+ 37
- 0
server/sonar-server/src/main/java/org/sonar/server/component/ws/ComponentsWsModule.java Parādīt failu

@@ -0,0 +1,37 @@
/*
* 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.component.ws;

import org.sonar.core.platform.Module;

public class ComponentsWsModule extends Module {
@Override
protected void configureModule() {
add(
ResourcesWs.class,
ComponentsWs.class,
EventsWs.class,
// actions
AppAction.class,
SearchAction.class,
SearchViewComponentsAction.class);
}
}

+ 142
- 2
server/sonar-server/src/main/java/org/sonar/server/component/ws/SearchAction.java Parādīt failu

@@ -20,24 +20,164 @@

package org.sonar.server.component.ws;

import com.google.common.base.Function;
import java.util.List;
import java.util.Set;
import javax.annotation.Nonnull;
import org.sonar.api.i18n.I18n;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.server.ws.Request;
import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.Param;
import org.sonar.api.utils.Paging;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.ComponentDto;
import org.sonar.db.component.ComponentQuery;
import org.sonar.server.user.UserSession;
import org.sonarqube.ws.WsComponents.WsSearchResponse;

import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.Ordering.natural;
import static java.lang.String.format;
import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER;
import static org.sonar.server.component.ws.WsComponentsParameters.PARAM_QUALIFIERS;
import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_QUALIFIER;
import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonar.server.ws.WsUtils.writeProtobuf;

public class SearchAction implements ComponentsWsAction {
private static final String QUALIFIER_PROPERTY_PREFIX = "qualifiers.";

private final DbClient dbClient;
private final ResourceTypes resourceTypes;
private final I18n i18n;
private final UserSession userSession;

public SearchAction(DbClient dbClient, ResourceTypes resourceTypes, I18n i18n, UserSession userSession) {
this.dbClient = dbClient;
this.resourceTypes = resourceTypes;
this.i18n = i18n;
this.userSession = userSession;
}

@Override
public void define(WebService.NewController context) {
WebService.NewAction action = context.createAction("search")
.setSince("5.2")
.setInternal(true)
.setDescription("Search for components")
.addPagingParams(100)
.addSearchQuery("sona", "project names")
.setResponseExample(getClass().getResource("search-example.json"))
.addSearchQuery("sona", "component names", "component keys")
.setResponseExample(getClass().getResource("search-components-example.json"))
.setHandler(this);

action.createParam(PARAM_QUALIFIERS)
.setRequired(true)
.setExampleValue(format("%s,%s", Qualifiers.PROJECT, Qualifiers.MODULE))
.setDescription("Comma-separated list of component qualifiers. Possible values are " + buildQualifiersDescription());
}

@Override
public void handle(Request wsRequest, Response wsResponse) throws Exception {
userSession.checkLoggedIn().checkGlobalPermission(GlobalPermissions.SYSTEM_ADMIN);

List<String> qualifiers = wsRequest.mandatoryParamAsStrings(PARAM_QUALIFIERS);
validateQualifiers(qualifiers);

DbSession dbSession = dbClient.openSession(false);
try {
ComponentQuery query = buildQuery(wsRequest, qualifiers);
Paging paging = buildPaging(dbSession, wsRequest, query);
List<ComponentDto> components = searchComponents(dbSession, query, paging);
WsSearchResponse response = buildResponse(components, paging);
writeProtobuf(response, wsRequest, wsResponse);
} finally {
dbClient.closeSession(dbSession);
}
}

private List<ComponentDto> searchComponents(DbSession dbSession, ComponentQuery query, Paging paging) {
return dbClient.componentDao().selectByQuery(
dbSession,
query,
paging.offset(),
paging.pageSize());
}

private WsSearchResponse buildResponse(List<ComponentDto> components, Paging paging) {
WsSearchResponse.Builder responseBuilder = WsSearchResponse.newBuilder();
responseBuilder.getPagingBuilder()
.setPageIndex(paging.pageIndex())
.setPageSize(paging.pageSize())
.setTotal(paging.total())
.build();

responseBuilder.addAllComponents(
from(components)
.transform(ComponentDToComponentResponseFunction.INSTANCE));

return responseBuilder.build();
}

private Paging buildPaging(DbSession dbSession, Request wsRequest, ComponentQuery query) {
int total = dbClient.componentDao().countByQuery(dbSession, query);
return Paging.forPageIndex(wsRequest.mandatoryParamAsInt(Param.PAGE))
.withPageSize(wsRequest.mandatoryParamAsInt(Param.PAGE_SIZE))
.andTotal(total);
}

private ComponentQuery buildQuery(Request wsRequest, List<String> qualifiers) {
return new ComponentQuery(
dbClient.getDatabase(),
wsRequest.param(Param.TEXT_QUERY),
qualifiers.toArray(new String[qualifiers.size()]));
}

private void validateQualifiers(List<String> qualifiers) {
Set<String> possibleQualifiers = allQualifiers();
for (String qualifier : qualifiers) {
checkRequest(possibleQualifiers.contains(qualifier),
format("The '%s' parameter must be one of %s. '%s' was passed.", PARAM_QUALIFIER, possibleQualifiers, qualifier));
}
}

private Set<String> allQualifiers() {
return from(resourceTypes.getAll())
.transform(RESOURCE_TYPE_TO_QUALIFIER)
.toSortedSet(natural());
}

private String buildQualifiersDescription() {
StringBuilder description = new StringBuilder();
description.append("<ul>");
String qualifierPattern = "<li>%s - %s</li>";
for (String qualifier : allQualifiers()) {
description.append(format(qualifierPattern, qualifier, i18n(qualifier)));
}
description.append("</ul>");

return description.toString();
}

private String i18n(String qualifier) {
return i18n.message(userSession.locale(), QUALIFIER_PROPERTY_PREFIX + qualifier, "");
}

private enum ComponentDToComponentResponseFunction implements Function<ComponentDto, WsSearchResponse.Component> {
INSTANCE;

@Override
public WsSearchResponse.Component apply(@Nonnull ComponentDto dto) {
return WsSearchResponse.Component.newBuilder()
.setId(dto.uuid())
.setKey(dto.key())
.setName(dto.name())
.setQualifier(dto.qualifier())
.build();
}
}
}

+ 29
- 0
server/sonar-server/src/main/java/org/sonar/server/component/ws/WsComponentsParameters.java Parādīt failu

@@ -0,0 +1,29 @@
/*
* 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.component.ws;

class WsComponentsParameters {
private WsComponentsParameters() {
// static utility class
}

static final String PARAM_QUALIFIERS = "qualifiers";
}

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/permission/ws/SearchProjectPermissionsDataLoader.java Parādīt failu

@@ -44,7 +44,7 @@ import static org.sonar.api.server.ws.WebService.Param.PAGE;
import static org.sonar.api.server.ws.WebService.Param.PAGE_SIZE;
import static org.sonar.api.server.ws.WebService.Param.TEXT_QUERY;
import static org.sonar.api.utils.Paging.forPageIndex;
import static org.sonar.server.permission.ws.ResourceTypeToQualifier.RESOURCE_TYPE_TO_QUALIFIER;
import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER;
import static org.sonar.server.permission.ws.SearchProjectPermissionsData.newBuilder;

public class SearchProjectPermissionsDataLoader {

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/DefaultPermissionTemplateFinder.java Parādīt failu

@@ -32,7 +32,7 @@ import static com.google.common.collect.FluentIterable.from;
import static com.google.common.collect.Ordering.natural;
import static org.sonar.server.permission.DefaultPermissionTemplates.DEFAULT_TEMPLATE_PROPERTY;
import static org.sonar.server.permission.DefaultPermissionTemplates.defaultRootQualifierTemplateProperty;
import static org.sonar.server.permission.ws.ResourceTypeToQualifier.RESOURCE_TYPE_TO_QUALIFIER;
import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER;

public class DefaultPermissionTemplateFinder {
private final Settings settings;

+ 1
- 1
server/sonar-server/src/main/java/org/sonar/server/permission/ws/template/SetDefaultTemplateAction.java Parādīt failu

@@ -44,7 +44,7 @@ import static org.sonar.server.permission.PermissionPrivilegeChecker.checkGlobal
import static org.sonar.server.permission.ws.WsPermissionParameters.PARAM_QUALIFIER;
import static org.sonar.server.permission.ws.WsPermissionParameters.createTemplateParameters;
import static org.sonar.server.permission.ws.PermissionRequestValidator.validateQualifier;
import static org.sonar.server.permission.ws.ResourceTypeToQualifier.RESOURCE_TYPE_TO_QUALIFIER;
import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER;

public class SetDefaultTemplateAction implements PermissionsWsAction {
private final DbClient dbClient;

+ 38
- 45
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java Parādīt failu

@@ -58,10 +58,7 @@ import org.sonar.server.component.ComponentFinder;
import org.sonar.server.component.ComponentService;
import org.sonar.server.component.DefaultComponentFinder;
import org.sonar.server.component.DefaultRubyComponentService;
import org.sonar.server.component.ws.ComponentsWs;
import org.sonar.server.component.ws.EventsWs;
import org.sonar.server.component.ws.ResourcesWs;
import org.sonar.server.component.ws.SearchViewComponentsAction;
import org.sonar.server.component.ws.ComponentsWsModule;
import org.sonar.server.computation.CeModule;
import org.sonar.server.computation.container.ReportProcessingModule;
import org.sonar.server.computation.queue.CeQueueModule;
@@ -338,16 +335,16 @@ public class PlatformLevel4 extends PlatformLevel {
IndexDefinitions.class,
IndexCreator.class,

// Activity
// Activity
ActivityService.class,
ActivityIndexDefinition.class,
ActivityIndexer.class,
ActivityIndex.class,

// batch
// batch
BatchWsModule.class,

// Dashboard
// Dashboard
DashboardsWs.class,
org.sonar.server.dashboard.ws.ShowAction.class,
ProjectDefaultDashboard.class,
@@ -385,12 +382,12 @@ public class PlatformLevel4 extends PlatformLevel {
ProjectIssueFilterWidget.class,
IssueTagCloudWidget.class,

// update center
// update center
UpdateCenterClient.class,
UpdateCenterMatrixFactory.class,
UpdateCenterWs.class,

// quality profile
// quality profile
XMLProfileParser.class,
XMLProfileSerializer.class,
AnnotationProfileParser.class,
@@ -434,7 +431,7 @@ public class PlatformLevel4 extends PlatformLevel {
QProfileReset.class,
RubyQProfileActivityService.class,

// rule
// rule
AnnotationRuleParser.class,
XMLRuleParser.class,
DefaultRuleFinder.class,
@@ -462,17 +459,17 @@ public class PlatformLevel4 extends PlatformLevel {
RepositoriesAction.class,
org.sonar.server.rule.ws.AppAction.class,

// languages
// languages
Languages.class,
LanguageWs.class,
org.sonar.server.language.ws.ListAction.class,

// activity
// activity
ActivitiesWs.class,
org.sonar.server.activity.ws.SearchAction.class,
ActivityMapping.class,

// measure
// measure
MeasureFilterFactory.class,
MeasureFilterExecutor.class,
MeasureFilterEngine.class,
@@ -484,14 +481,14 @@ public class PlatformLevel4 extends PlatformLevel {
DefaultMetricFinder.class,
TimeMachineWs.class,

// quality gates
// quality gates
QualityGateDao.class,
QualityGateConditionDao.class,
QualityGates.class,
ProjectQgateAssociationDao.class,
QgateProjectFinder.class,

org.sonar.server.qualitygate.ws.ListAction.class,
org.sonar.server.qualitygate.ws.ListAction.class,
org.sonar.server.qualitygate.ws.SearchAction.class,
org.sonar.server.qualitygate.ws.ShowAction.class,
org.sonar.server.qualitygate.ws.CreateAction.class,
@@ -508,17 +505,17 @@ public class PlatformLevel4 extends PlatformLevel {
org.sonar.server.qualitygate.ws.AppAction.class,
QGatesWs.class,

// web services
// web services
WebServiceEngine.class,
ListingWs.class,

// localization
// localization
L10nWs.class,

// authentication
// authentication
AuthenticationWs.class,

// users
// users
SecurityRealmFactory.class,
DeprecatedUserFinder.class,
NewUserNotifier.class,
@@ -540,39 +537,35 @@ public class PlatformLevel4 extends PlatformLevel {
UserIndex.class,
UserUpdater.class,

// groups
// groups
GroupMembershipService.class,
GroupMembershipFinder.class,
UserGroupsModule.class,

// permissions
// permissions
PermissionRepository.class,
PermissionService.class,
PermissionUpdater.class,
PermissionFinder.class,
PermissionsWsModule.class,

// components
// components
ProjectsWsModule.class,
ComponentsWsModule.class,
DefaultComponentFinder.class,
DefaultRubyComponentService.class,
ComponentService.class,
ComponentFinder.class,
ResourcesWs.class,
ComponentsWs.class,
org.sonar.server.component.ws.AppAction.class,
SearchViewComponentsAction.class,
EventsWs.class,
NewAlerts.class,
NewAlerts.newMetadata(),
ComponentCleanerService.class,

// views
// views
ViewIndexDefinition.class,
ViewIndexer.class,
ViewIndex.class,

// issues
// issues
IssueIndexDefinition.class,
IssueIndexer.class,
IssueAuthorizationIndexer.class,
@@ -606,13 +599,13 @@ public class PlatformLevel4 extends PlatformLevel {
EmailNotificationChannel.class,
AlertsEmailTemplate.class,

IssueFilterWsModule.class,
IssueFilterWsModule.class,

// action plan
// action plan
ActionPlanWs.class,
ActionPlanService.class,

// issues actions
// issues actions
AssignAction.class,
PlanAction.class,
SetSeverityAction.class,
@@ -621,7 +614,7 @@ public class PlatformLevel4 extends PlatformLevel {
AddTagsAction.class,
RemoveTagsAction.class,

// technical debt
// technical debt
DebtModelService.class,
DebtModelOperations.class,
DebtModelLookup.class,
@@ -631,7 +624,7 @@ public class PlatformLevel4 extends PlatformLevel {
DebtRulesXMLImporter.class,
DebtCharacteristicsXMLImporter.class,

// source
// source
HtmlSourceDecorator.class,
SourceService.class,
SourcesWs.class,
@@ -642,23 +635,23 @@ public class PlatformLevel4 extends PlatformLevel {
IndexAction.class,
ScmAction.class,

// Duplications
// Duplications
DuplicationsParser.class,
DuplicationsWs.class,
DuplicationsJsonWriter.class,
org.sonar.server.duplication.ws.ShowAction.class,

// text
// text
MacroInterpreter.class,
RubyTextService.class,

// Notifications
// Notifications
EmailSettings.class,
NotificationService.class,
NotificationCenter.class,
DefaultNotificationManager.class,

// Tests
// Tests
CoverageService.class,
TestsWs.class,
CoveredFilesAction.class,
@@ -667,12 +660,12 @@ public class PlatformLevel4 extends PlatformLevel {
TestIndex.class,
TestIndexer.class,

// Properties
// Properties
PropertiesWs.class,

TypeValidationModule.class,
TypeValidationModule.class,

// System
// System
RestartAction.class,
InfoAction.class,
UpgradesAction.class,
@@ -687,7 +680,7 @@ public class PlatformLevel4 extends PlatformLevel {
MigrateDbAction.class,
DbMigrationStatusAction.class,

// Plugins WS
// Plugins WS
PluginWSCommons.class,
PluginUpdateAggregator.class,
InstalledAction.class,
@@ -700,18 +693,18 @@ public class PlatformLevel4 extends PlatformLevel {
CancelAllAction.class,
PluginsWs.class,

// Compute engine
// Compute engine
CeModule.class,
CeQueueModule.class,
CeTaskProcessorModule.class,
CeWsModule.class,
ReportProcessingModule.class,

// Views plugin
// Views plugin
ViewsBootstrap.class,
ViewsStopper.class,

// UI
// UI
GlobalNavigationAction.class,
SettingsNavigationAction.class,
ComponentNavigationAction.class,

+ 33
- 0
server/sonar-server/src/main/resources/org/sonar/server/component/ws/search-components-example.json Parādīt failu

@@ -0,0 +1,33 @@
{
"paging": {
"pageIndex": 1,
"pageSize": 100,
"total": 4
},
"components": [
{
"id": "directory-uuid",
"key": "directory-key",
"qualifier": "DIR",
"name": "Directory Name"
},
{
"id": "file-uuid",
"key": "file-key",
"qualifier": "FIL",
"name": "File Name"
},
{
"id": "module-uuid",
"key": "module-key",
"qualifier": "BRC",
"name": "Module Name"
},
{
"id": "project-uuid",
"key": "project-key",
"qualifier": "TRK",
"name": "Project Name"
}
]
}

+ 35
- 0
server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsModuleTest.java Parādīt failu

@@ -0,0 +1,35 @@
/*
* 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.component.ws;

import org.junit.Test;
import org.sonar.core.platform.ComponentContainer;

import static org.assertj.core.api.Assertions.assertThat;

public class ComponentsWsModuleTest {
@Test
public void verify_count_of_added_components() {
ComponentContainer container = new ComponentContainer();
new ComponentsWsModule().configure(container);
assertThat(container.size()).isEqualTo(8);
}
}

+ 19
- 4
server/sonar-server/src/test/java/org/sonar/server/component/ws/ComponentsWsTest.java Parādīt failu

@@ -24,6 +24,7 @@ import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.i18n.I18n;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.server.ws.RailsHandler;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.utils.Durations;
@@ -45,8 +46,9 @@ public class ComponentsWsTest {
public void setUp() {
WsTester tester = new WsTester(new ComponentsWs(
new AppAction(mock(DbClient.class), mock(Durations.class), mock(I18n.class), userSessionRule, mock(ComponentFinder.class)),
new SearchViewComponentsAction(mock(DbClient.class), userSessionRule, mock(ComponentFinder.class)))
);
new SearchViewComponentsAction(mock(DbClient.class), userSessionRule, mock(ComponentFinder.class)),
new SearchAction(mock(org.sonar.db.DbClient.class), mock(ResourceTypes.class), mock(I18n.class), userSessionRule)
));
controller = tester.controller("api/components");
}

@@ -55,7 +57,7 @@ public class ComponentsWsTest {
assertThat(controller).isNotNull();
assertThat(controller.description()).isNotEmpty();
assertThat(controller.since()).isEqualTo("4.2");
assertThat(controller.actions()).hasSize(3);
assertThat(controller.actions()).hasSize(4);
}

@Test
@@ -80,8 +82,9 @@ public class ComponentsWsTest {
}

@Test
public void define_search_action() {
public void define_search_view_components_action() {
WebService.Action action = controller.action("search_view_components");

assertThat(action).isNotNull();
assertThat(action.isInternal()).isTrue();
assertThat(action.isPost()).isFalse();
@@ -89,4 +92,16 @@ public class ComponentsWsTest {
assertThat(action.params()).hasSize(4);
}

@Test
public void define_search_action() {
WebService.Action action = controller.action("search");

assertThat(action).isNotNull();
assertThat(action.param("qualifiers").isRequired()).isTrue();
assertThat(action.responseExampleAsString()).isNotEmpty();
assertThat(action.description()).isNotEmpty();
assertThat(action.isInternal()).isTrue();
assertThat(action.isPost()).isFalse();
assertThat(action.since()).isEqualTo("5.2");
}
}

+ 191
- 0
server/sonar-server/src/test/java/org/sonar/server/component/ws/SearchActionTest.java Parādīt failu

@@ -0,0 +1,191 @@
/*
* 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.component.ws;

import com.google.common.base.Joiner;
import java.io.IOException;
import java.io.InputStream;
import java.util.List;
import org.junit.Before;
import org.junit.Rule;
import org.junit.Test;
import org.junit.rules.ExpectedException;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.ResourceType;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.server.ws.WebService.Param;
import org.sonar.api.utils.System2;
import org.sonar.core.permission.GlobalPermissions;
import org.sonar.db.DbTester;
import org.sonar.db.component.ComponentDbTester;
import org.sonar.db.component.ComponentDto;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.UnauthorizedException;
import org.sonar.server.i18n.I18nRule;
import org.sonar.server.plugins.MimeTypes;
import org.sonar.server.tester.UserSessionRule;
import org.sonar.server.ws.TestRequest;
import org.sonar.server.ws.WsActionTester;
import org.sonarqube.ws.WsComponents.WsSearchResponse;

import static java.util.Arrays.asList;
import static org.assertj.core.api.Assertions.assertThat;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
import static org.sonar.db.component.ComponentTesting.newDirectory;
import static org.sonar.db.component.ComponentTesting.newFileDto;
import static org.sonar.db.component.ComponentTesting.newModuleDto;
import static org.sonar.db.component.ComponentTesting.newProjectDto;
import static org.sonar.db.component.ComponentTesting.newView;
import static org.sonar.server.component.ws.WsComponentsParameters.PARAM_QUALIFIERS;
import static org.sonar.test.JsonAssert.assertJson;

public class SearchActionTest {
@Rule
public ExpectedException expectedException = ExpectedException.none();
@Rule
public UserSessionRule userSession = UserSessionRule.standalone();
@Rule
public DbTester db = DbTester.create(System2.INSTANCE);
ComponentDbTester componentDb = new ComponentDbTester(db);
I18nRule i18n = new I18nRule();

WsActionTester ws;
ResourceTypes resourceTypes;

@Before
public void setUp() {
userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
resourceTypes = mock(ResourceTypes.class);
when(resourceTypes.getAll()).thenReturn(resourceTypes());

ws = new WsActionTester(new SearchAction(db.getDbClient(), resourceTypes, i18n, userSession));

}

@Test
public void search_json_example() {
componentDb.insertComponent(newView());
ComponentDto project = componentDb.insertComponent(
newProjectDto("project-uuid")
.setName("Project Name")
.setKey("project-key")
);
ComponentDto module = componentDb.insertComponent(
newModuleDto("module-uuid", project)
.setName("Module Name")
.setKey("module-key")
);
componentDb.insertComponent(
newDirectory(module, "path/to/directoy")
.setUuid("directory-uuid")
.setKey("directory-key")
.setName("Directory Name")
);
componentDb.insertComponent(
newFileDto(module, "file-uuid")
.setKey("file-key")
.setName("File Name")
);
db.commit();

String response = newRequest(Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.DIRECTORY, Qualifiers.FILE)
.setMediaType(MimeTypes.JSON)
.execute()
.getInput();

assertJson(response).isSimilarTo(getClass().getResource("search-components-example.json"));
}

@Test
public void search_with_pagination() throws IOException {
for (int i = 1; i <= 9; i++) {
componentDb.insertComponent(
newProjectDto("project-uuid-" + i)
.setName("Project Name " + i));
}
db.commit();

InputStream responseStream = newRequest(Qualifiers.PROJECT)
.setParam(Param.PAGE, "2")
.setParam(Param.PAGE_SIZE, "3")
.execute()
.getInputStream();
WsSearchResponse response = WsSearchResponse.parseFrom(responseStream);

assertThat(response.getComponentsCount()).isEqualTo(3);
assertThat(response.getComponentsList()).extracting("id").containsExactly("project-uuid-4", "project-uuid-5", "project-uuid-6");
}

@Test
public void search_with_key_query() throws IOException {
componentDb.insertComponent(newProjectDto().setKey("project-_%-key"));
componentDb.insertComponent(newProjectDto().setKey("project-key-without-escaped-characters"));
db.commit();

InputStream responseStream = newRequest(Qualifiers.PROJECT)
.setParam(Param.TEXT_QUERY, "project-_%")
.execute().getInputStream();
WsSearchResponse response = WsSearchResponse.parseFrom(responseStream);

assertThat(response.getComponentsCount()).isEqualTo(1);
assertThat(response.getComponentsList()).extracting("key").containsExactly("project-_%-key");
}

@Test
public void fail_if_unknown_qualifier_provided() {
expectedException.expect(BadRequestException.class);
expectedException.expectMessage("The 'qualifier' parameter must be one of [BRC, DIR, FIL, TRK]. 'Unknown-Qualifier' was passed.");

newRequest("Unknown-Qualifier").execute();
}

@Test
public void fail_if_not_logged_in() {
expectedException.expect(UnauthorizedException.class);
userSession.anonymous();

newRequest(Qualifiers.PROJECT).execute();
}

@Test
public void fail_if_insufficient_privileges() {
expectedException.expect(ForbiddenException.class);
userSession.login().setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION);

newRequest(Qualifiers.PROJECT).execute();
}

private TestRequest newRequest(String... qualifiers) {
return ws.newRequest()
.setMediaType(MimeTypes.PROTOBUF)
.setParam(PARAM_QUALIFIERS, Joiner.on(",").join(qualifiers));
}

private static List<ResourceType> resourceTypes() {
return asList(
ResourceType.builder(Qualifiers.PROJECT).build(),
ResourceType.builder(Qualifiers.MODULE).build(),
ResourceType.builder(Qualifiers.DIRECTORY).build(),
ResourceType.builder(Qualifiers.FILE).build());
}
}

+ 1884
- 0
sonar-ws/src/main/gen-java/org/sonarqube/ws/WsComponents.java
Failā izmaiņas netiks attēlotas, jo tās ir par lielu
Parādīt failu


+ 40
- 0
sonar-ws/src/main/protobuf/ws-components.proto Parādīt failu

@@ -0,0 +1,40 @@
// SonarQube, open source software quality management tool.
// Copyright (C) 2008-2015 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.

syntax = "proto2";

package sonarqube.ws.component;

import "ws-commons.proto";

option java_package = "org.sonarqube.ws";
option java_outer_classname = "WsComponents";
option optimize_for = SPEED;

// WS api/components/search
message WsSearchResponse {
message Component {
optional string id = 1;
optional string key = 2;
optional string qualifier = 3;
optional string name = 4;
}

optional sonarqube.ws.commons.Paging paging = 1;
repeated Component components = 2;
}

Notiek ielāde…
Atcelt
Saglabāt