--- /dev/null
+/*
+ * 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.collect.Collections2;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
+import org.sonar.core.util.NonNullInputFunction;
+
+import java.util.Arrays;
+import java.util.Collection;
+
+public class LanguageParamUtils {
+
+ private LanguageParamUtils() {
+ // Utility class
+ }
+
+ public static String getExampleValue(Languages languages) {
+ Language[] languageArray = languages.all();
+ if (languageArray.length > 0) {
+ return languageArray[0].getKey();
+ } else {
+ return "";
+ }
+ }
+
+ public static Collection<String> getLanguageKeys(Languages languages) {
+ return Collections2.transform(Arrays.asList(languages.all()), new NonNullInputFunction<Language, String>() {
+ @Override
+ public String doApply(Language input) {
+ return input.getKey();
+ }
+ });
+ }
+}
import java.util.Set;
import javax.annotation.Nonnull;
import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.Languages;
import org.sonar.api.resources.Qualifiers;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.server.ws.Request;
import static org.sonar.server.component.ResourceTypeFunctions.RESOURCE_TYPE_TO_QUALIFIER;
import static org.sonar.server.ws.WsUtils.checkRequest;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
+import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_LANGUAGE;
import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS;
import static org.sonarqube.ws.client.permission.PermissionsWsParameters.PARAM_QUALIFIER;
private final ResourceTypes resourceTypes;
private final I18n i18n;
private final UserSession userSession;
+ private final Languages languages;
- public SearchAction(DbClient dbClient, ResourceTypes resourceTypes, I18n i18n, UserSession userSession) {
+ public SearchAction(DbClient dbClient, ResourceTypes resourceTypes, I18n i18n, UserSession userSession, Languages languages) {
this.dbClient = dbClient;
this.resourceTypes = resourceTypes;
this.i18n = i18n;
this.userSession = userSession;
+ this.languages = languages;
}
@Override
.setRequired(true)
.setExampleValue(format("%s,%s", Qualifiers.PROJECT, Qualifiers.MODULE))
.setDescription("Comma-separated list of component qualifiers. Possible values are " + buildQualifiersDescription());
+
+ action
+ .createParam(PARAM_LANGUAGE)
+ .setDescription("Language key. If provided, only components for the given language are returned.")
+ .setExampleValue(LanguageParamUtils.getExampleValue(languages))
+ .setPossibleValues(LanguageParamUtils.getLanguageKeys(languages))
+ .setSince("5.4");
}
@Override
private static SearchWsRequest toSearchWsRequest(Request request) {
return new SearchWsRequest()
.setQualifiers(request.mandatoryParamAsStrings(PARAM_QUALIFIERS))
+ .setLanguage(request.param(PARAM_LANGUAGE))
.setQuery(request.param(Param.TEXT_QUERY))
.setPage(request.mandatoryParamAsInt(Param.PAGE))
.setPageSize(request.mandatoryParamAsInt(Param.PAGE_SIZE));
private ComponentQuery buildQuery(SearchWsRequest request, List<String> qualifiers) {
return new ComponentQuery(
request.getQuery(),
+ request.getLanguage(),
qualifiers.toArray(new String[qualifiers.size()]));
}
@Override
public WsComponents.Component apply(@Nonnull ComponentDto dto) {
- return WsComponents.Component.newBuilder()
+ WsComponents.Component.Builder builder = WsComponents.Component.newBuilder()
.setId(dto.uuid())
.setKey(dto.key())
.setName(dto.name())
- .setQualifier(dto.qualifier())
- .build();
+ .setQualifier(dto.qualifier());
+ if (dto.language() != null) {
+ builder.setLanguage(dto.language());
+ }
+
+ return builder.build();
}
}
}
query.setComponentUuid(componentUuid);
}
if (componentQuery != null) {
- ComponentQuery componentDtoQuery = new ComponentQuery(componentQuery, Qualifiers.PROJECT, Qualifiers.VIEW);
+ ComponentQuery componentDtoQuery = new ComponentQuery(componentQuery, null, Qualifiers.PROJECT, Qualifiers.VIEW);
List<ComponentDto> componentDtos = dbClient.componentDao().selectByQuery(dbSession, componentDtoQuery, 0, CeActivityQuery.MAX_COMPONENT_UUIDS);
query.setComponentUuids(Lists.transform(componentDtos, ComponentDtoFunctions.toUuid()));
}
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.component.ws.LanguageParamUtils;
import org.sonarqube.ws.MediaTypes;
import org.sonar.server.qualityprofile.QProfileExporters;
import org.sonar.server.qualityprofile.QProfileFactory;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.component.ws.LanguageParamUtils;
import org.sonar.server.exceptions.NotFoundException;
import org.sonarqube.ws.MediaTypes;
import org.sonar.server.qualityprofile.QProfileBackuper;
+++ /dev/null
-/*
- * 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.qualityprofile.ws;
-
-import com.google.common.collect.Collections2;
-import org.sonar.api.resources.Language;
-import org.sonar.api.resources.Languages;
-import org.sonar.core.util.NonNullInputFunction;
-
-import java.util.Arrays;
-import java.util.Collection;
-
-class LanguageParamUtils {
-
- private LanguageParamUtils() {
- // Utility class
- }
-
- static String getExampleValue(Languages languages) {
- Language[] languageArray = languages.all();
- if (languageArray.length > 0) {
- return languageArray[0].getKey();
- } else {
- return "";
- }
- }
-
- static Collection<String> getLanguageKeys(Languages languages) {
- return Collections2.transform(Arrays.asList(languages.all()), new NonNullInputFunction<Language, String>() {
- @Override
- public String doApply(Language input) {
- return input.getKey();
- }
- });
- }
-}
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.NewAction;
import org.sonar.server.component.ComponentService;
+import org.sonar.server.component.ws.LanguageParamUtils;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.qualityprofile.QProfile;
import org.sonar.server.qualityprofile.QProfileLookup;
import org.sonar.api.server.ws.WebService.NewAction;
import org.sonar.db.DbSession;
import org.sonar.db.qualityprofile.QualityProfileDto;
+import org.sonar.server.component.ws.LanguageParamUtils;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.qualityprofile.QProfileFactory;
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.server.component.ws.LanguageParamUtils;
import org.sonar.server.qualityprofile.QProfile;
import org.sonarqube.ws.QualityProfiles;
import org.sonarqube.ws.QualityProfiles.SearchWsResponse;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.NewAction;
import org.sonar.core.permission.GlobalPermissions;
+import org.sonar.server.component.ws.LanguageParamUtils;
import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.qualityprofile.QProfile;
import org.sonar.server.qualityprofile.QProfileFactory;
"id": "file-uuid",
"key": "file-key",
"qualifier": "FIL",
- "name": "File Name"
+ "name": "File Name",
+ "language": "java"
},
{
"id": "module-uuid",
import org.junit.Rule;
import org.junit.Test;
import org.sonar.api.i18n.I18n;
+import org.sonar.api.resources.Language;
+import org.sonar.api.resources.Languages;
import org.sonar.api.resources.ResourceTypes;
import org.sonar.api.server.ws.RailsHandler;
import org.sonar.api.server.ws.WebService;
import org.sonar.server.ws.WsTester;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.mockito.Mockito.RETURNS_DEEP_STUBS;
import static org.mockito.Mockito.mock;
+import static org.mockito.Mockito.when;
public class ComponentsWsTest {
@Rule
@Before
public void setUp() {
+ Languages languages = mock(Languages.class, RETURNS_DEEP_STUBS);
+ when(languages.all()).thenReturn(new Language[0]);
+
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 SearchAction(mock(org.sonar.db.DbClient.class), mock(ResourceTypes.class), mock(I18n.class), userSessionRule)
+ new SearchAction(mock(org.sonar.db.DbClient.class), mock(ResourceTypes.class), mock(I18n.class), userSessionRule, languages)
));
controller = tester.controller("api/components");
}
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.Language;
+import org.sonar.api.resources.Languages;
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.db.component.ResourceTypesRule;
import org.sonar.server.exceptions.BadRequestException;
import org.sonar.server.exceptions.ForbiddenException;
import org.sonar.server.exceptions.UnauthorizedException;
import org.sonarqube.ws.MediaTypes;
import org.sonarqube.ws.WsComponents.SearchWsResponse;
-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.newModuleDto;
import static org.sonar.db.component.ComponentTesting.newProjectDto;
import static org.sonar.db.component.ComponentTesting.newView;
-import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS;
import static org.sonar.test.JsonAssert.assertJson;
+import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_LANGUAGE;
+import static org.sonarqube.ws.client.component.ComponentsWsParameters.PARAM_QUALIFIERS;
public class SearchActionTest {
@Rule
I18nRule i18n = new I18nRule();
WsActionTester ws;
- ResourceTypes resourceTypes;
+ ResourceTypesRule resourceTypes = new ResourceTypesRule();
+ Languages languages;
@Before
public void setUp() {
userSession.login().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN);
- resourceTypes = mock(ResourceTypes.class);
- when(resourceTypes.getAll()).thenReturn(resourceTypes());
+ resourceTypes.setAllQualifiers(Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.DIRECTORY, Qualifiers.FILE);
+ languages = mock(Languages.class);
+ when(languages.all()).thenReturn(javaLanguage());
- ws = new WsActionTester(new SearchAction(db.getDbClient(), resourceTypes, i18n, userSession));
+ ws = new WsActionTester(new SearchAction(db.getDbClient(), resourceTypes, i18n, userSession, languages));
}
ComponentDto project = componentDb.insertComponent(
newProjectDto("project-uuid")
.setName("Project Name")
- .setKey("project-key")
- );
+ .setKey("project-key"));
ComponentDto module = componentDb.insertComponent(
newModuleDto("module-uuid", project)
.setName("Module Name")
- .setKey("module-key")
- );
+ .setKey("module-key"));
componentDb.insertComponent(
newDirectory(module, "path/to/directoy")
.setUuid("directory-uuid")
.setKey("directory-key")
- .setName("Directory Name")
- );
+ .setName("Directory Name"));
componentDb.insertComponent(
newFileDto(module, "file-uuid")
.setKey("file-key")
- .setName("File Name")
- );
+ .setLanguage("java")
+ .setName("File Name"));
db.commit();
String response = newRequest(Qualifiers.PROJECT, Qualifiers.MODULE, Qualifiers.DIRECTORY, Qualifiers.FILE)
assertThat(response.getComponentsList()).extracting("key").containsExactly("project-_%-key");
}
+ @Test
+ public void search_with_language() throws IOException {
+ componentDb.insertComponent(newProjectDto().setKey("java-project").setLanguage("java"));
+ componentDb.insertComponent(newProjectDto().setKey("cpp-project").setLanguage("cpp"));
+ db.commit();
+
+ InputStream responseStream = newRequest(Qualifiers.PROJECT)
+ .setParam(PARAM_LANGUAGE, "java")
+ .execute().getInputStream();
+ SearchWsResponse response = SearchWsResponse.parseFrom(responseStream);
+
+ assertThat(response.getComponentsCount()).isEqualTo(1);
+ assertThat(response.getComponentsList().get(0).getKey()).isEqualTo("java-project");
+ }
+
@Test
public void fail_if_unknown_qualifier_provided() {
expectedException.expect(BadRequestException.class);
.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());
+ private static Language[] javaLanguage() {
+ return new Language[] {new Language() {
+ @Override
+ public String getKey() {
+ return "java";
+ }
+
+ @Override
+ public String getName() {
+ return "Java";
+ }
+
+ @Override
+ public String[] getFileSuffixes() {
+ return new String[0];
+ }
+ }};
}
}
public class ComponentQuery {
private final String nameOrKeyQuery;
private final String[] qualifiers;
+ private final String language;
- public ComponentQuery(@Nullable String nameOrKeyQuery, String... qualifiers) {
+ public ComponentQuery(@Nullable String nameOrKeyQuery, String language, String... qualifiers) {
+ this.language = language;
checkArgument(qualifiers.length > 0, "At least one qualifier must be provided");
this.nameOrKeyQuery = nameOrKeyQuery;
public String getNameOrKeyQueryToSqlForProjectKey() {
return buildLikeValue(nameOrKeyQuery, AFTER);
}
+
+ @CheckForNull
+ public String getLanguage() {
+ return language;
+ }
}
<foreach collection="query.qualifiers" item="qualifier" open="(" close=")" separator=",">
#{qualifier}
</foreach>
+ <if test="query.language!=null">
+ AND p.language = #{query.language}
+ </if>
<if test="query.nameOrKeyQuery!=null">
AND (exists (
select 1
db.commit();
componentDb.indexProjects();
- ComponentQuery query = new ComponentQuery("oJect", Qualifiers.PROJECT);
+ ComponentQuery query = new ComponentQuery("oJect", null, Qualifiers.PROJECT);
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 1, 3);
assertThat(result).hasSize(3);
db.commit();
componentDb.indexProjects();
- ComponentQuery query = new ComponentQuery("-\\_%/-", Qualifiers.PROJECT);
+ ComponentQuery query = new ComponentQuery("-\\_%/-", null, Qualifiers.PROJECT);
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
assertThat(result).hasSize(1);
db.commit();
componentDb.indexProjects();
- ComponentQuery query = new ComponentQuery("project-_%-", Qualifiers.PROJECT);
+ ComponentQuery query = new ComponentQuery("project-_%-", null, Qualifiers.PROJECT);
List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
assertThat(result).hasSize(1);
assertThat(result.get(0).key()).isEqualTo("project-_%-key");
}
+ @Test
+ public void select_by_query_filter_on_language() {
+ componentDb.insertComponent(newProjectDto().setKey("java-project-key").setLanguage("java"));
+ componentDb.insertComponent(newProjectDto().setKey("cpp-project-key").setLanguage("cpp"));
+ db.commit();
+
+ ComponentQuery query = new ComponentQuery(null, "java", Qualifiers.PROJECT);
+ List<ComponentDto> result = underTest.selectByQuery(dbSession, query, 0, 10);
+
+ assertThat(result).hasSize(1);
+ assertThat(result.get(0).key()).isEqualTo("java-project-key");
+ }
+
@Test
public void select_direct_children_of_a_project() {
ComponentDto project = newProjectDto().setKey("project-key").setUuid("project-uuid");
expectedException.expect(IllegalArgumentException.class);
expectedException.expectMessage("At least one qualifier must be provided");
- underTest = new ComponentQuery(null);
+ underTest = new ComponentQuery(null, "java");
}
}
// parameters
public static final String PARAM_QUALIFIERS = "qualifiers";
+ public static final String PARAM_LANGUAGE = "language";
public static final String PARAM_BASE_COMPONENT_ID = "baseComponentId";
public static final String PARAM_BASE_COMPONENT_KEY = "baseComponentKey";
public static final String PARAM_STRATEGY = "strategy";
private Integer page;
private Integer pageSize;
private String query;
+ private String language;
public List<String> getQualifiers() {
return qualifiers;
this.query = query;
return this;
}
+
+ @CheckForNull
+ public String getLanguage() {
+ return language;
+ }
+
+ public SearchWsRequest setLanguage(@Nullable String language) {
+ this.language = language;
+ return this;
+ }
}
optional string description = 5;
optional string qualifier = 6;
optional string path = 7;
+ optional string language = 8;
}