From: Teryk Bellahsene Date: Fri, 8 May 2015 10:05:06 +0000 (+0200) Subject: WS api/projects/projects/provisioned list the provisioned projects - SONAR-6526 X-Git-Tag: 5.2-RC1~1989 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=c41df8617792d56e035fdc82db61242fc0f113b0;p=sonarqube.git WS api/projects/projects/provisioned list the provisioned projects - SONAR-6526 --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java b/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java index bd85204aaa6..96d3eb0ab44 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/db/ComponentDao.java @@ -21,6 +21,8 @@ package org.sonar.server.component.db; import com.google.common.base.Function; +import org.apache.ibatis.session.RowBounds; +import org.sonar.api.ServerComponent; import org.sonar.api.ServerSide; import org.sonar.api.resources.Qualifiers; import org.sonar.api.resources.Scopes; @@ -33,13 +35,17 @@ import org.sonar.core.persistence.DaoComponent; import org.sonar.core.persistence.DaoUtils; import org.sonar.core.persistence.DbSession; import org.sonar.server.db.BaseDao; +import org.sonar.server.es.SearchOptions; import org.sonar.server.exceptions.NotFoundException; import javax.annotation.CheckForNull; +import javax.annotation.Nullable; import java.util.Collection; import java.util.Collections; +import java.util.HashMap; import java.util.List; +import java.util.Map; /** * @since 4.3 @@ -173,4 +179,21 @@ public class ComponentDao extends BaseDao return mapper(session).selectProjectsFromView("%." + viewUuid + ".%", projectViewUuid); } + public List selectProvisionedProjects(DbSession session, SearchOptions searchOptions, @Nullable String query) { + Map parameters = new HashMap<>(); + parameters.put("qualifier", Qualifiers.PROJECT); + if (query != null) { + parameters.put("query", "%" + query + "%"); + } + return mapper(session).selectProvisionedProjects(parameters, new RowBounds(searchOptions.getOffset(), searchOptions.getLimit())); + } + + public int countProvisionedProjects(DbSession session, @Nullable String query) { + Map parameters = new HashMap<>(); + parameters.put("qualifier", Qualifiers.PROJECT); + if (query != null) { + parameters.put("query", "%" + query + "%"); + } + return mapper(session).countProvisionedProjects(parameters); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsAction.java new file mode 100644 index 00000000000..ddbe535b745 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsAction.java @@ -0,0 +1,27 @@ +/* + * 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.server.ws.WsAction; + +public interface ProjectsAction extends WsAction { + // marker interface +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsWs.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsWs.java index a4a06570cf2..4b99a290d58 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsWs.java +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProjectsWs.java @@ -25,6 +25,11 @@ import org.sonar.api.server.ws.RailsHandler; import org.sonar.api.server.ws.WebService; public class ProjectsWs implements WebService { + private final ProjectsAction[] actions; + + public ProjectsWs(ProjectsAction... actions) { + this.actions = actions; + } @Override public void define(Context context) { @@ -36,6 +41,10 @@ public class ProjectsWs implements WebService { defineCreateAction(controller); defineDestroyAction(controller); + for (ProjectsAction action : actions) { + action.define(controller); + } + controller.done(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProvisionedProjectsAction.java b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProvisionedProjectsAction.java new file mode 100644 index 00000000000..cbc15b86377 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/component/ws/ProvisionedProjectsAction.java @@ -0,0 +1,126 @@ +/* + * 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.io.Resources; +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.text.JsonWriter; +import org.sonar.api.web.UserRole; +import org.sonar.core.component.ComponentDto; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.MyBatis; +import org.sonar.server.db.DbClient; +import org.sonar.server.es.SearchOptions; +import org.sonar.server.user.UserSession; + +import java.util.Arrays; +import java.util.Date; +import java.util.List; + +public class ProvisionedProjectsAction implements ProjectsAction { + private final DbClient dbClient; + + private static final List POSSIBLE_FIELDS = Arrays.asList("uuid", "key", "name", "creationDate"); + + public ProvisionedProjectsAction(DbClient dbClient) { + this.dbClient = dbClient; + } + + @Override + public void define(WebService.NewController controller) { + WebService.NewAction action = controller + .createAction("provisioned") + .setDescription( + "Get the list of provisioned projects.
" + + "Require admin role.") + .setSince("5.2") + .setResponseExample(Resources.getResource(getClass(), "projects-example-provisioned.json")) + .setHandler(this) + .addPagingParams(100) + .addFieldsParam(POSSIBLE_FIELDS); + + action + .createParam(Param.TEXT_QUERY) + .setDescription("UTF-8 search query") + .setExampleValue("sonar"); + } + + @Override + public void handle(Request request, Response response) throws Exception { + UserSession.get().checkGlobalPermission(UserRole.ADMIN, "You need admin rights."); + SearchOptions options = new SearchOptions().setPage( + request.mandatoryParamAsInt(Param.PAGE), + request.mandatoryParamAsInt(Param.PAGE_SIZE) + ); + List desiredFields = desiredFields(request); + String query = request.param(Param.TEXT_QUERY); + + DbSession dbSession = dbClient.openSession(false); + try { + List projects = dbClient.componentDao().selectProvisionedProjects(dbSession, options, query); + int nbOfProjects = dbClient.componentDao().countProvisionedProjects(dbSession, query); + JsonWriter json = response.newJsonWriter().beginObject(); + writeProjects(projects, json, desiredFields); + options.writeJson(json, nbOfProjects); + json.endObject().close(); + } finally { + MyBatis.closeQuietly(dbSession); + } + } + + private void writeProjects(List projects, JsonWriter json, List desiredFields) { + json.name("projects"); + json.beginArray(); + for (ComponentDto project : projects) { + json.beginObject(); + json.prop("uuid", project.uuid()); + writeIfNeeded(json, "key", project.key(), desiredFields); + writeIfNeeded(json, "name", project.name(), desiredFields); + writeIfNeeded(json, "creationDate", project.getCreatedAt(), desiredFields); + json.endObject(); + } + json.endArray(); + } + + private void writeIfNeeded(JsonWriter json, String fieldName, String value, List desiredFields) { + if (desiredFields.contains(fieldName)) { + json.prop(fieldName, value); + } + } + + private void writeIfNeeded(JsonWriter json, String fieldName, Date date, List desiredFields) { + if (desiredFields.contains(fieldName)) { + json.propDateTime(fieldName, date); + } + } + + private List desiredFields(Request request) { + List desiredFields = request.paramAsStrings(Param.FIELDS); + if (desiredFields == null) { + desiredFields = POSSIBLE_FIELDS; + } + + return desiredFields; + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/AuthorsAction.java b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/AuthorsAction.java index 8096dc5dd62..880d8ac9e8a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/issue/ws/AuthorsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/issue/ws/AuthorsAction.java @@ -24,6 +24,7 @@ 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.NewAction; +import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.text.JsonWriter; import org.sonar.server.issue.IssueService; @@ -37,8 +38,8 @@ public class AuthorsAction implements BaseIssuesWsAction { @Override public void handle(Request request, Response response) throws Exception { - String query = request.param(WebService.Param.TEXT_QUERY); - int pageSize = request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE); + String query = request.param(Param.TEXT_QUERY); + int pageSize = request.mandatoryParamAsInt(Param.PAGE_SIZE); JsonWriter json = response.newJsonWriter() .beginObject() @@ -60,10 +61,10 @@ public class AuthorsAction implements BaseIssuesWsAction { .setResponseExample(Resources.getResource(this.getClass(), "example-authors.json")) .setHandler(this); - action.createParam(WebService.Param.TEXT_QUERY) + action.createParam(Param.TEXT_QUERY) .setDescription("A pattern to match SCM accounts against") .setExampleValue("luke"); - action.createParam(WebService.Param.PAGE_SIZE) + action.createParam(Param.PAGE_SIZE) .setDescription("The size of the list to return") .setExampleValue("25") .setDefaultValue("10"); diff --git a/server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java b/server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java index fcd4326e48c..d8c80e868fe 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/language/ws/ListAction.java @@ -29,6 +29,7 @@ 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.server.ws.WebService.Param; import org.sonar.api.utils.text.JsonWriter; import javax.annotation.Nullable; @@ -52,7 +53,7 @@ public class ListAction implements RequestHandler { @Override public void handle(Request request, Response response) throws Exception { - String query = request.param("q"); + String query = request.param(Param.TEXT_QUERY); int pageSize = request.mandatoryParamAsInt("ps"); JsonWriter json = response.newJsonWriter().beginObject().name("languages").beginArray(); @@ -84,7 +85,7 @@ public class ListAction implements RequestHandler { .setHandler(this) .setResponseExample(Resources.getResource(getClass(), "example-list.json")); - action.createParam("q") + action.createParam(Param.TEXT_QUERY) .setDescription("A pattern to match language keys/names against") .setExampleValue("java"); action.createParam("ps") 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 4c76a9e1fef..4fb3c1fbf8a 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 @@ -104,6 +104,7 @@ 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.ProvisionedProjectsAction; import org.sonar.server.component.ws.ResourcesWs; import org.sonar.server.computation.ComputationThreadLauncher; import org.sonar.server.computation.ReportQueue; @@ -795,6 +796,7 @@ class ServerComponents { pico.addSingleton(org.sonar.server.component.ws.SearchAction.class); pico.addSingleton(EventsWs.class); pico.addSingleton(ComponentCleanerService.class); + pico.addSingleton(ProvisionedProjectsAction.class); // views pico.addSingleton(ViewIndexDefinition.class); diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java index 8a2adbbd562..87f2b89e755 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/RepositoriesAction.java @@ -27,6 +27,7 @@ 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.NewAction; +import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.text.JsonWriter; import org.sonar.server.rule.RuleRepositories; import org.sonar.server.rule.RuleRepositories.Repository; @@ -53,7 +54,7 @@ public class RepositoriesAction implements RulesAction { @Override public void handle(Request request, Response response) throws Exception { - String query = request.param("q"); + String query = request.param(Param.TEXT_QUERY); String languageKey = request.param(LANGUAGE); int pageSize = request.mandatoryParamAsInt("ps"); @@ -102,7 +103,7 @@ public class RepositoriesAction implements RulesAction { .setHandler(this) .setResponseExample(Resources.getResource(getClass(), "example-repositories.json")); - action.createParam("q") + action.createParam(Param.TEXT_QUERY) .setDescription("A pattern to match repository keys/names against") .setExampleValue("squid"); action.createParam(LANGUAGE) diff --git a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/TagsAction.java b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/TagsAction.java index 4d20919f6ad..cec16771671 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/rule/ws/TagsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/rule/ws/TagsAction.java @@ -24,6 +24,7 @@ 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.NewAction; +import org.sonar.api.server.ws.WebService.Param; import org.sonar.api.utils.text.JsonWriter; import org.sonar.server.rule.RuleService; @@ -46,7 +47,7 @@ public class TagsAction implements RulesAction { .setHandler(this) .setResponseExample(Resources.getResource(getClass(), "example-tags.json")); - action.createParam("q") + action.createParam(Param.TEXT_QUERY) .setDescription("A pattern to match tags against") .setExampleValue("misra"); action.createParam("ps") @@ -57,7 +58,7 @@ public class TagsAction implements RulesAction { @Override public void handle(Request request, Response response) { - String query = request.param("q"); + String query = request.param(Param.TEXT_QUERY); int pageSize = request.mandatoryParamAsInt("ps"); Set tags = service.listTags(query, pageSize); JsonWriter json = response.newJsonWriter().beginObject(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsListAction.java b/server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsListAction.java index ffd502d92a4..0a65137ecf7 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsListAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/test/ws/TestsListAction.java @@ -114,7 +114,7 @@ public class TestsListAction implements TestAction { SearchOptions searchOptions = new SearchOptions().setPage( request.mandatoryParamAsInt(WebService.Param.PAGE), request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE) - ); + ); DbSession dbSession = dbClient.openSession(false); SearchResult tests; diff --git a/server/sonar-server/src/main/java/org/sonar/server/user/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/user/ws/SearchAction.java index 7030d7363ba..996488ec57d 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/user/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/user/ws/SearchAction.java @@ -24,6 +24,7 @@ import com.google.common.collect.ImmutableSet; 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.text.JsonWriter; import org.sonar.server.es.SearchOptions; import org.sonar.server.es.SearchResult; @@ -37,8 +38,6 @@ import java.util.Set; public class SearchAction implements BaseUsersWsAction { - private static final String PARAM_QUERY = "q"; - private static final String FIELD_LOGIN = "login"; private static final String FIELD_NAME = "name"; private static final String FIELD_EMAIL = "email"; @@ -61,16 +60,16 @@ public class SearchAction implements BaseUsersWsAction { action.addFieldsParam(FIELDS); action.addPagingParams(50); - action.createParam(PARAM_QUERY) + action.createParam(Param.TEXT_QUERY) .setDescription("Filter on login or name."); } @Override public void handle(Request request, Response response) throws Exception { SearchOptions options = new SearchOptions() - .setPage(request.mandatoryParamAsInt(WebService.Param.PAGE), request.mandatoryParamAsInt(WebService.Param.PAGE_SIZE)); - List fields = request.paramAsStrings(WebService.Param.FIELDS); - SearchResult result = userIndex.search(request.param(PARAM_QUERY), options); + .setPage(request.mandatoryParamAsInt(Param.PAGE), request.mandatoryParamAsInt(Param.PAGE_SIZE)); + List fields = request.paramAsStrings(Param.FIELDS); + SearchResult result = userIndex.search(request.param(Param.TEXT_QUERY), options); JsonWriter json = response.newJsonWriter().beginObject(); options.writeJson(json, result.getTotal()); diff --git a/server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-provisioned.json b/server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-provisioned.json new file mode 100644 index 00000000000..4bb9f843654 --- /dev/null +++ b/server/sonar-server/src/main/resources/org/sonar/server/component/ws/projects-example-provisioned.json @@ -0,0 +1,19 @@ +{ + "projects": [ + { + "uuid": "ce4c03d6-430f-40a9-b777-ad877c00aa4d", + "key": "org.apache.hbas:hbase", + "name": "HBase", + "creationDate": "2015-03-04T23:03:44+0100" + }, + { + "uuid": "c526ef20-131b-4486-9357-063fa64b5079", + "key": "com.microsoft.roslyn:roslyn", + "name": "Roslyn", + "creationDate": "2013-03-04T23:03:44+0100" + } + ], + "total": 2, + "p": 1, + "ps": 100 +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java index a7b643f7905..ff3d0b1fecb 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/component/db/ComponentDaoTest.java @@ -23,13 +23,15 @@ package org.sonar.server.component.db; import org.apache.ibatis.exceptions.PersistenceException; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; import org.sonar.api.utils.DateUtils; import org.sonar.api.utils.System2; import org.sonar.core.component.ComponentDto; import org.sonar.core.component.FilePathWithHashDto; -import org.sonar.core.persistence.AbstractDaoTestCase; import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.DbTester; +import org.sonar.server.es.SearchOptions; import org.sonar.server.exceptions.NotFoundException; import java.util.Collections; @@ -41,19 +43,21 @@ import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.when; -public class ComponentDaoTest extends AbstractDaoTestCase { +public class ComponentDaoTest { - DbSession session; - - ComponentDao dao; + ComponentDao sut; + @ClassRule + public static DbTester db = new DbTester(); + DbSession session; System2 system2; + @Before public void createDao() { - session = getMyBatis().openSession(false); + session = db.myBatis().openSession(false); system2 = mock(System2.class); - dao = new ComponentDao(system2); + sut = new ComponentDao(system2); } @After @@ -63,9 +67,9 @@ public class ComponentDaoTest extends AbstractDaoTestCase { @Test public void get_by_uuid() { - setupData("shared"); + loadBasicDataInDatabase(); - ComponentDto result = dao.getNullableByUuid(session, "KLMN"); + ComponentDto result = sut.getNullableByUuid(session, "KLMN"); assertThat(result).isNotNull(); assertThat(result.uuid()).isEqualTo("KLMN"); assertThat(result.moduleUuid()).isEqualTo("EFGH"); @@ -82,11 +86,15 @@ public class ComponentDaoTest extends AbstractDaoTestCase { assertThat(result.getCopyResourceId()).isNull(); } + private void loadBasicDataInDatabase() { + db.prepareDbUnit(getClass(), "shared.xml"); + } + @Test public void get_by_uuid_on_technical_project_copy() { - setupData("shared"); + loadBasicDataInDatabase(); - ComponentDto result = dao.getNullableByUuid(session, "STUV"); + ComponentDto result = sut.getNullableByUuid(session, "STUV"); assertThat(result).isNotNull(); assertThat(result.uuid()).isEqualTo("STUV"); assertThat(result.moduleUuid()).isEqualTo("OPQR"); @@ -105,25 +113,25 @@ public class ComponentDaoTest extends AbstractDaoTestCase { @Test public void get_by_uuid_on_disabled_component() { - setupData("shared"); + loadBasicDataInDatabase(); - ComponentDto result = dao.getNullableByUuid(session, "DCBA"); + ComponentDto result = sut.getNullableByUuid(session, "DCBA"); assertThat(result).isNotNull(); assertThat(result.isEnabled()).isFalse(); } @Test(expected = NotFoundException.class) public void fail_to_get_by_uuid_when_component_not_found() { - setupData("shared"); + loadBasicDataInDatabase(); - dao.getByUuid(session, "unknown"); + sut.getByUuid(session, "unknown"); } @Test public void get_by_key() { - setupData("shared"); + loadBasicDataInDatabase(); - ComponentDto result = dao.getNullableByKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java"); + ComponentDto result = sut.getNullableByKey(session, "org.struts:struts-core:src/org/struts/RequestContext.java"); assertThat(result).isNotNull(); assertThat(result.key()).isEqualTo("org.struts:struts-core:src/org/struts/RequestContext.java"); assertThat(result.path()).isEqualTo("src/org/struts/RequestContext.java"); @@ -134,23 +142,23 @@ public class ComponentDaoTest extends AbstractDaoTestCase { assertThat(result.language()).isEqualTo("java"); assertThat(result.parentProjectId()).isEqualTo(2); - assertThat(dao.getNullableByKey(session, "unknown")).isNull(); + assertThat(sut.getNullableByKey(session, "unknown")).isNull(); } @Test public void get_by_key_on_disabled_component() { - setupData("shared"); + loadBasicDataInDatabase(); - ComponentDto result = dao.getNullableByKey(session, "org.disabled.project"); + ComponentDto result = sut.getNullableByKey(session, "org.disabled.project"); assertThat(result).isNotNull(); assertThat(result.isEnabled()).isFalse(); } @Test public void get_by_key_on_a_root_project() { - setupData("shared"); + loadBasicDataInDatabase(); - ComponentDto result = dao.getNullableByKey(session, "org.struts:struts"); + ComponentDto result = sut.getNullableByKey(session, "org.struts:struts"); assertThat(result).isNotNull(); assertThat(result.key()).isEqualTo("org.struts:struts"); assertThat(result.deprecatedKey()).isEqualTo("org.struts:struts"); @@ -166,9 +174,9 @@ public class ComponentDaoTest extends AbstractDaoTestCase { @Test public void get_by_keys() { - setupData("shared"); + loadBasicDataInDatabase(); - List results = dao.getByKeys(session, "org.struts:struts-core:src/org/struts/RequestContext.java"); + List results = sut.getByKeys(session, "org.struts:struts-core:src/org/struts/RequestContext.java"); assertThat(results).hasSize(1); ComponentDto result = results.get(0); @@ -182,14 +190,14 @@ public class ComponentDaoTest extends AbstractDaoTestCase { assertThat(result.language()).isEqualTo("java"); assertThat(result.parentProjectId()).isEqualTo(2); - assertThat(dao.getByKeys(session, "unknown")).isEmpty(); + assertThat(sut.getByKeys(session, "unknown")).isEmpty(); } @Test public void get_by_ids() { - setupData("shared"); + loadBasicDataInDatabase(); - List results = dao.getByIds(session, newArrayList(4L)); + List results = sut.getByIds(session, newArrayList(4L)); assertThat(results).hasSize(1); ComponentDto result = results.get(0); @@ -203,14 +211,14 @@ public class ComponentDaoTest extends AbstractDaoTestCase { assertThat(result.language()).isEqualTo("java"); assertThat(result.parentProjectId()).isEqualTo(2); - assertThat(dao.getByIds(session, newArrayList(555L))).isEmpty(); + assertThat(sut.getByIds(session, newArrayList(555L))).isEmpty(); } @Test public void get_by_uuids() { - setupData("shared"); + loadBasicDataInDatabase(); - List results = dao.getByUuids(session, newArrayList("KLMN")); + List results = sut.getByUuids(session, newArrayList("KLMN")); assertThat(results).hasSize(1); ComponentDto result = results.get(0); @@ -228,14 +236,14 @@ public class ComponentDaoTest extends AbstractDaoTestCase { assertThat(result.scope()).isEqualTo("FIL"); assertThat(result.language()).isEqualTo("java"); - assertThat(dao.getByUuids(session, newArrayList("unknown"))).isEmpty(); + assertThat(sut.getByUuids(session, newArrayList("unknown"))).isEmpty(); } @Test public void get_by_uuids_on_removed_components() { - setupData("shared"); + loadBasicDataInDatabase(); - List results = dao.getByUuids(session, newArrayList("DCBA")); + List results = sut.getByUuids(session, newArrayList("DCBA")); assertThat(results).hasSize(1); ComponentDto result = results.get(0); @@ -245,201 +253,201 @@ public class ComponentDaoTest extends AbstractDaoTestCase { @Test public void select_existing_uuids() { - setupData("shared"); + loadBasicDataInDatabase(); - List results = dao.selectExistingUuids(session, newArrayList("KLMN")); + List results = sut.selectExistingUuids(session, newArrayList("KLMN")); assertThat(results).containsOnly("KLMN"); - assertThat(dao.selectExistingUuids(session, newArrayList("KLMN", "unknown"))).hasSize(1); - assertThat(dao.selectExistingUuids(session, newArrayList("unknown"))).isEmpty(); + assertThat(sut.selectExistingUuids(session, newArrayList("KLMN", "unknown"))).hasSize(1); + assertThat(sut.selectExistingUuids(session, newArrayList("unknown"))).isEmpty(); } @Test public void get_by_id() { - setupData("shared"); + loadBasicDataInDatabase(); - assertThat(dao.getById(4L, session)).isNotNull(); + assertThat(sut.getById(4L, session)).isNotNull(); } @Test public void get_by_id_on_disabled_component() { - setupData("shared"); + loadBasicDataInDatabase(); - ComponentDto result = dao.getNullableById(10L, session); + ComponentDto result = sut.getNullableById(10L, session); assertThat(result).isNotNull(); assertThat(result.isEnabled()).isFalse(); } @Test(expected = NotFoundException.class) public void fail_to_get_by_id_when_project_not_found() { - setupData("shared"); + loadBasicDataInDatabase(); - dao.getById(111L, session); + sut.getById(111L, session); } @Test public void get_nullable_by_id() { - setupData("shared"); + loadBasicDataInDatabase(); - assertThat(dao.getNullableById(4L, session)).isNotNull(); - assertThat(dao.getNullableById(111L, session)).isNull(); + assertThat(sut.getNullableById(4L, session)).isNotNull(); + assertThat(sut.getNullableById(111L, session)).isNull(); } @Test public void count_by_id() { - setupData("shared"); + loadBasicDataInDatabase(); - assertThat(dao.existsById(4L, session)).isTrue(); - assertThat(dao.existsById(111L, session)).isFalse(); + assertThat(sut.existsById(4L, session)).isTrue(); + assertThat(sut.existsById(111L, session)).isFalse(); } @Test public void find_modules_by_project() { - setupData("multi-modules"); + db.prepareDbUnit(getClass(), "multi-modules.xml"); - List results = dao.findModulesByProject("org.struts:struts", session); + List results = sut.findModulesByProject("org.struts:struts", session); assertThat(results).hasSize(1); assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts-core"); - results = dao.findModulesByProject("org.struts:struts-core", session); + results = sut.findModulesByProject("org.struts:struts-core", session); assertThat(results).hasSize(1); assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts-data"); - assertThat(dao.findModulesByProject("org.struts:struts-data", session)).isEmpty(); + assertThat(sut.findModulesByProject("org.struts:struts-data", session)).isEmpty(); - assertThat(dao.findModulesByProject("unknown", session)).isEmpty(); + assertThat(sut.findModulesByProject("unknown", session)).isEmpty(); } @Test public void find_sub_projects_by_component_keys() { - setupData("multi-modules"); + db.prepareDbUnit(getClass(), "multi-modules.xml"); // Sub project of a file - List results = dao.findSubProjectsByComponentUuids(session, newArrayList("HIJK")); + List results = sut.findSubProjectsByComponentUuids(session, newArrayList("HIJK")); assertThat(results).hasSize(1); assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts-data"); // Sub project of a directory - results = dao.findSubProjectsByComponentUuids(session, newArrayList("GHIJ")); + results = sut.findSubProjectsByComponentUuids(session, newArrayList("GHIJ")); assertThat(results).hasSize(1); assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts-data"); // Sub project of a sub module - results = dao.findSubProjectsByComponentUuids(session, newArrayList("FGHI")); + results = sut.findSubProjectsByComponentUuids(session, newArrayList("FGHI")); assertThat(results).hasSize(1); assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts"); // Sub project of a module - results = dao.findSubProjectsByComponentUuids(session, newArrayList("EFGH")); + results = sut.findSubProjectsByComponentUuids(session, newArrayList("EFGH")); assertThat(results).hasSize(1); assertThat(results.get(0).getKey()).isEqualTo("org.struts:struts"); // Sub project of a project - assertThat(dao.findSubProjectsByComponentUuids(session, newArrayList("ABCD"))).isEmpty(); + assertThat(sut.findSubProjectsByComponentUuids(session, newArrayList("ABCD"))).isEmpty(); // SUb projects of a component and a sub module - assertThat(dao.findSubProjectsByComponentUuids(session, newArrayList("HIJK", "FGHI"))).hasSize(2); + assertThat(sut.findSubProjectsByComponentUuids(session, newArrayList("HIJK", "FGHI"))).hasSize(2); - assertThat(dao.findSubProjectsByComponentUuids(session, newArrayList("unknown"))).isEmpty(); + assertThat(sut.findSubProjectsByComponentUuids(session, newArrayList("unknown"))).isEmpty(); - assertThat(dao.findSubProjectsByComponentUuids(session, Collections.emptyList())).isEmpty(); + assertThat(sut.findSubProjectsByComponentUuids(session, Collections.emptyList())).isEmpty(); } @Test public void select_enabled_modules_tree() { - setupData("multi-modules"); + db.prepareDbUnit(getClass(), "multi-modules.xml"); // From root project - List modules = dao.selectEnabledDescendantModules(session, "ABCD"); + List modules = sut.selectEnabledDescendantModules(session, "ABCD"); assertThat(modules).extracting("uuid").containsOnly("ABCD", "EFGH", "FGHI"); // From module - modules = dao.selectEnabledDescendantModules(session, "EFGH"); + modules = sut.selectEnabledDescendantModules(session, "EFGH"); assertThat(modules).extracting("uuid").containsOnly("EFGH", "FGHI"); // From sub module - modules = dao.selectEnabledDescendantModules(session, "FGHI"); + modules = sut.selectEnabledDescendantModules(session, "FGHI"); assertThat(modules).extracting("uuid").containsOnly("FGHI"); // Folder - assertThat(dao.selectEnabledDescendantModules(session, "GHIJ")).isEmpty(); - assertThat(dao.selectEnabledDescendantModules(session, "unknown")).isEmpty(); + assertThat(sut.selectEnabledDescendantModules(session, "GHIJ")).isEmpty(); + assertThat(sut.selectEnabledDescendantModules(session, "unknown")).isEmpty(); } @Test public void select_all_modules_tree() { - setupData("multi-modules"); + db.prepareDbUnit(getClass(), "multi-modules.xml"); // From root project, disabled sub module is returned - List modules = dao.selectDescendantModules(session, "ABCD"); + List modules = sut.selectDescendantModules(session, "ABCD"); assertThat(modules).extracting("uuid").containsOnly("ABCD", "EFGH", "FGHI", "IHGF"); // From module, disabled sub module is returned - modules = dao.selectDescendantModules(session, "EFGH"); + modules = sut.selectDescendantModules(session, "EFGH"); assertThat(modules).extracting("uuid").containsOnly("EFGH", "FGHI", "IHGF"); // From removed sub module -> should not be returned - assertThat(dao.selectDescendantModules(session, "IHGF")).isEmpty(); + assertThat(sut.selectDescendantModules(session, "IHGF")).isEmpty(); } @Test public void select_enabled_module_files_tree_from_module() { - setupData("select_module_files_tree"); + db.prepareDbUnit(getClass(), "select_module_files_tree.xml"); // From root project - List files = dao.selectEnabledDescendantFiles(session, "ABCD"); + List files = sut.selectEnabledDescendantFiles(session, "ABCD"); assertThat(files).extracting("uuid").containsOnly("EFGHI", "HIJK"); assertThat(files).extracting("moduleUuid").containsOnly("EFGH", "FGHI"); assertThat(files).extracting("srcHash").containsOnly("srcEFGHI", "srcHIJK"); assertThat(files).extracting("path").containsOnly("src/org/struts/pom.xml", "src/org/struts/RequestContext.java"); // From module - files = dao.selectEnabledDescendantFiles(session, "EFGH"); + files = sut.selectEnabledDescendantFiles(session, "EFGH"); assertThat(files).extracting("uuid").containsOnly("EFGHI", "HIJK"); assertThat(files).extracting("moduleUuid").containsOnly("EFGH", "FGHI"); assertThat(files).extracting("srcHash").containsOnly("srcEFGHI", "srcHIJK"); assertThat(files).extracting("path").containsOnly("src/org/struts/pom.xml", "src/org/struts/RequestContext.java"); // From sub module - files = dao.selectEnabledDescendantFiles(session, "FGHI"); + files = sut.selectEnabledDescendantFiles(session, "FGHI"); assertThat(files).extracting("uuid").containsOnly("HIJK"); assertThat(files).extracting("moduleUuid").containsOnly("FGHI"); assertThat(files).extracting("srcHash").containsOnly("srcHIJK"); assertThat(files).extracting("path").containsOnly("src/org/struts/RequestContext.java"); // From directory - assertThat(dao.selectEnabledDescendantFiles(session, "GHIJ")).isEmpty(); + assertThat(sut.selectEnabledDescendantFiles(session, "GHIJ")).isEmpty(); - assertThat(dao.selectEnabledDescendantFiles(session, "unknown")).isEmpty(); + assertThat(sut.selectEnabledDescendantFiles(session, "unknown")).isEmpty(); } @Test public void select_enabled_module_files_tree_from_project() { - setupData("select_module_files_tree"); + db.prepareDbUnit(getClass(), "select_module_files_tree.xml"); // From root project - List files = dao.selectEnabledFilesFromProject(session, "ABCD"); + List files = sut.selectEnabledFilesFromProject(session, "ABCD"); assertThat(files).extracting("uuid").containsOnly("EFGHI", "HIJK"); assertThat(files).extracting("moduleUuid").containsOnly("EFGH", "FGHI"); assertThat(files).extracting("srcHash").containsOnly("srcEFGHI", "srcHIJK"); assertThat(files).extracting("path").containsOnly("src/org/struts/pom.xml", "src/org/struts/RequestContext.java"); // From module - assertThat(dao.selectEnabledFilesFromProject(session, "EFGH")).isEmpty(); + assertThat(sut.selectEnabledFilesFromProject(session, "EFGH")).isEmpty(); // From sub module - assertThat(dao.selectEnabledFilesFromProject(session, "FGHI")).isEmpty(); + assertThat(sut.selectEnabledFilesFromProject(session, "FGHI")).isEmpty(); // From directory - assertThat(dao.selectEnabledFilesFromProject(session, "GHIJ")).isEmpty(); + assertThat(sut.selectEnabledFilesFromProject(session, "GHIJ")).isEmpty(); - assertThat(dao.selectEnabledFilesFromProject(session, "unknown")).isEmpty(); + assertThat(sut.selectEnabledFilesFromProject(session, "unknown")).isEmpty(); } @Test public void insert() { when(system2.now()).thenReturn(DateUtils.parseDate("2014-06-18").getTime()); - setupData("empty"); + db.prepareDbUnit(getClass(), "empty.xml"); ComponentDto componentDto = new ComponentDto() .setId(1L) @@ -460,17 +468,17 @@ public class ComponentDaoTest extends AbstractDaoTestCase { .setEnabled(true) .setAuthorizationUpdatedAt(123456789L); - dao.insert(session, componentDto); + sut.insert(session, componentDto); session.commit(); assertThat(componentDto.getId()).isNotNull(); - checkTables("insert", "projects"); + db.assertDbUnit(getClass(), "insert-result.xml", "projects"); } @Test public void insert_disabled_component() { when(system2.now()).thenReturn(DateUtils.parseDate("2014-06-18").getTime()); - setupData("empty"); + db.prepareDbUnit(getClass(), "empty.xml"); ComponentDto componentDto = new ComponentDto() .setId(1L) @@ -489,62 +497,82 @@ public class ComponentDaoTest extends AbstractDaoTestCase { .setEnabled(false) .setAuthorizationUpdatedAt(123456789L); - dao.insert(session, componentDto); + sut.insert(session, componentDto); session.commit(); assertThat(componentDto.getId()).isNotNull(); - checkTables("insert_disabled_component", "projects"); + db.assertDbUnit(getClass(), "insert_disabled_component-result.xml", "projects"); } @Test(expected = IllegalStateException.class) public void update() { - dao.update(session, new ComponentDto() - .setId(1L) - .setKey("org.struts:struts-core:src/org/struts/RequestContext.java") - ); + sut.update(session, new ComponentDto() + .setId(1L) + .setKey("org.struts:struts-core:src/org/struts/RequestContext.java") + ); } @Test public void delete() { - setupData("shared"); + loadBasicDataInDatabase(); - dao.delete(session, new ComponentDto() - .setId(1L) - .setKey("org.struts:struts-core:src/org/struts/RequestContext.java") - ); + sut.delete(session, new ComponentDto() + .setId(1L) + .setKey("org.struts:struts-core:src/org/struts/RequestContext.java") + ); session.commit(); - checkTable("delete", "projects"); + db.assertDbUnit(getClass(), "delete-result.xml", "projects"); } @Test public void find_project_uuids() { - setupData("find_project_uuids"); + db.prepareDbUnit(getClass(), "find_project_uuids.xml"); - assertThat(dao.findProjectUuids(session)).containsExactly("ABCD"); + assertThat(sut.findProjectUuids(session)).containsExactly("ABCD"); } @Test(expected = PersistenceException.class) public void synchronize_after() { - dao.synchronizeAfter(session, new Date(0L)); + sut.synchronizeAfter(session, new Date(0L)); } @Test public void select_views_and_sub_views() { - setupData("shared_views"); + db.prepareDbUnit(getClass(), "shared_views.xml"); - assertThat(dao.selectAllViewsAndSubViews(session)).extracting("uuid").containsOnly("ABCD", "EFGH", "FGHI", "IJKL"); - assertThat(dao.selectAllViewsAndSubViews(session)).extracting("projectUuid").containsOnly("ABCD", "EFGH", "IJKL"); + assertThat(sut.selectAllViewsAndSubViews(session)).extracting("uuid").containsOnly("ABCD", "EFGH", "FGHI", "IJKL"); + assertThat(sut.selectAllViewsAndSubViews(session)).extracting("projectUuid").containsOnly("ABCD", "EFGH", "IJKL"); } @Test public void select_projects_from_view() { - setupData("shared_views"); + db.prepareDbUnit(getClass(), "shared_views.xml"); + + assertThat(sut.selectProjectsFromView(session, "ABCD", "ABCD")).containsOnly("JKLM"); + assertThat(sut.selectProjectsFromView(session, "EFGH", "EFGH")).containsOnly("KLMN", "JKLM"); + assertThat(sut.selectProjectsFromView(session, "FGHI", "EFGH")).containsOnly("JKLM"); + assertThat(sut.selectProjectsFromView(session, "IJKL", "IJKL")).isEmpty(); + assertThat(sut.selectProjectsFromView(session, "Unknown", "Unknown")).isEmpty(); + } + + @Test + public void select_provisioned_projects() { + db.prepareDbUnit(getClass(), "select_provisioned_projects.xml"); + + List result = sut.selectProvisionedProjects(session, new SearchOptions(), null); + ComponentDto project = result.get(0); + + assertThat(result).hasSize(1); + assertThat(project.getKey()).isEqualTo("org.provisioned.project"); + } + + @Test + public void count_provisioned_projects() { + db.prepareDbUnit(getClass(), "select_provisioned_projects.xml"); + + int numberOfProjects = sut.countProvisionedProjects(session, null); - assertThat(dao.selectProjectsFromView(session, "ABCD", "ABCD")).containsOnly("JKLM"); - assertThat(dao.selectProjectsFromView(session, "EFGH", "EFGH")).containsOnly("KLMN", "JKLM"); - assertThat(dao.selectProjectsFromView(session, "FGHI", "EFGH")).containsOnly("JKLM"); - assertThat(dao.selectProjectsFromView(session, "IJKL", "IJKL")).isEmpty(); - assertThat(dao.selectProjectsFromView(session, "Unknown", "Unknown")).isEmpty(); + assertThat(numberOfProjects).isEqualTo(1); } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProvisionedProjectsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProvisionedProjectsActionTest.java new file mode 100644 index 00000000000..27070552002 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/component/ws/ProvisionedProjectsActionTest.java @@ -0,0 +1,162 @@ +/* + * 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.io.Resources; +import org.apache.commons.lang.StringUtils; +import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; +import org.junit.Test; +import org.sonar.api.server.ws.WebService.Param; +import org.sonar.api.utils.DateUtils; +import org.sonar.api.utils.System2; +import org.sonar.api.web.UserRole; +import org.sonar.core.component.ComponentDto; +import org.sonar.core.component.SnapshotDto; +import org.sonar.core.persistence.DbSession; +import org.sonar.core.persistence.DbTester; +import org.sonar.server.component.ComponentTesting; +import org.sonar.server.component.SnapshotTesting; +import org.sonar.server.component.db.ComponentDao; +import org.sonar.server.component.db.SnapshotDao; +import org.sonar.server.db.DbClient; +import org.sonar.server.user.MockUserSession; +import org.sonar.server.ws.WsTester; +import org.sonar.test.JsonAssert; + +import static org.assertj.core.api.Assertions.assertThat; + +public class ProvisionedProjectsActionTest { + + @ClassRule + public static DbTester db = new DbTester(); + + WsTester ws; + DbClient dbClient; + DbSession dbSession; + ComponentDao componentDao; + + @After + public void tearDown() throws Exception { + dbSession.close(); + } + + @Before + public void setUp() throws Exception { + dbClient = new DbClient(db.database(), db.myBatis(), new ComponentDao(), new SnapshotDao(System2.INSTANCE)); + dbSession = dbClient.openSession(false); + componentDao = dbClient.componentDao(); + db.truncateTables(); + ws = new WsTester(new ProjectsWs(new ProvisionedProjectsAction(dbClient))); + } + + @Test + public void all_provisioned_projects_without_analyzed_projects() throws Exception { + MockUserSession.set().setGlobalPermissions(UserRole.ADMIN); + ComponentDto analyzedProject = ComponentTesting.newProjectDto("analyzed-uuid-1"); + componentDao.insert(dbSession, newProvisionedProject("1"), newProvisionedProject("2")); + analyzedProject = componentDao.insert(dbSession, analyzedProject); + SnapshotDto snapshot = SnapshotTesting.createForProject(analyzedProject); + dbClient.snapshotDao().insert(dbSession, snapshot); + dbSession.commit(); + + WsTester.TestRequest request = ws.newGetRequest("api/projects", "provisioned"); + + request.execute().assertJson(getClass(), "all-projects.json"); + } + + @Test + public void provisioned_projects_with_correct_paginated() throws Exception { + MockUserSession.set().setGlobalPermissions(UserRole.ADMIN); + for (int i = 1; i <= 10; i++) { + componentDao.insert(dbSession, newProvisionedProject(String.valueOf(i))); + } + dbSession.commit(); + + WsTester.TestRequest request = ws.newGetRequest("api/projects", "provisioned") + .setParam(Param.PAGE, "3") + .setParam(Param.PAGE_SIZE, "4"); + + String jsonOutput = request.execute().outputAsString(); + + assertThat(StringUtils.countMatches(jsonOutput, "provisioned-uuid-")).isEqualTo(2); + } + + @Test + public void provisioned_projects_with_desired_fields() throws Exception { + MockUserSession.set().setGlobalPermissions(UserRole.ADMIN); + componentDao.insert(dbSession, newProvisionedProject("1")); + dbSession.commit(); + + String jsonOutput = ws.newGetRequest("api/projects", "provisioned") + .setParam(Param.FIELDS, "key") + .execute().outputAsString(); + + assertThat(jsonOutput).contains("uuid", "key") + .doesNotContain("name") + .doesNotContain("creationDate"); + } + + @Test + public void provisioned_projects_with_query() throws Exception { + MockUserSession.set().setGlobalPermissions(UserRole.ADMIN); + componentDao.insert(dbSession, newProvisionedProject("1"), newProvisionedProject("2")); + dbSession.commit(); + + String jsonOutput = ws.newGetRequest("api/projects", "provisioned") + .setParam(Param.TEXT_QUERY, "provisioned-name-2") + .execute().outputAsString(); + + assertThat(jsonOutput) + .contains("provisioned-name-2", "provisioned-uuid-2") + .doesNotContain("provisioned-uuid-1"); + assertThat(componentDao.countProvisionedProjects(dbSession, "name-2")).isEqualTo(1); + assertThat(componentDao.countProvisionedProjects(dbSession, "key-2")).isEqualTo(1); + assertThat(componentDao.countProvisionedProjects(dbSession, "visioned-name-")).isEqualTo(2); + } + + private static ComponentDto newProvisionedProject(String id) { + return ComponentTesting + .newProjectDto("provisioned-uuid-" + id) + .setName("provisioned-name-" + id) + .setKey("provisioned-key-" + id); + } + + @Test + public void provisioned_projects_as_defined_in_the_example() throws Exception { + MockUserSession.set().setGlobalPermissions(UserRole.ADMIN); + ComponentDto hBaseProject = ComponentTesting.newProjectDto("ce4c03d6-430f-40a9-b777-ad877c00aa4d") + .setKey("org.apache.hbas:hbase") + .setName("HBase") + .setCreatedAt(DateUtils.parseDateTime("2015-03-04T23:03:44+0100")); + ComponentDto roslynProject = ComponentTesting.newProjectDto("c526ef20-131b-4486-9357-063fa64b5079") + .setKey("com.microsoft.roslyn:roslyn") + .setName("Roslyn") + .setCreatedAt(DateUtils.parseDateTime("2013-03-04T23:03:44+0100")); + componentDao.insert(dbSession, hBaseProject, roslynProject); + dbSession.commit(); + + WsTester.Result result = ws.newGetRequest("api/projects", "provisioned").execute(); + + JsonAssert.assertJson(result.outputAsString()).isSimilarTo(Resources.getResource(getClass(), "projects-example-provisioned.json")); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/computation/step/BaseStepTest.java b/server/sonar-server/src/test/java/org/sonar/server/computation/step/BaseStepTest.java index adc3e316086..224a8316a39 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/computation/step/BaseStepTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/computation/step/BaseStepTest.java @@ -36,6 +36,5 @@ public abstract class BaseStepTest { assertThat(step().toString()).isNotEmpty(); assertThat(step().getDescription()).isNotEmpty(); assertThat(step().supportedProjectQualifiers().length).isGreaterThan(0); - } } diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/delete-result.xml b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/delete-result.xml index 2547c1eb707..45814a6cbe7 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/delete-result.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/delete-result.xml @@ -86,7 +86,7 @@ uuid="OPQR" project_uuid="OPQR" module_uuid="[null]" module_uuid_path=".OPQR." description="the description" long_name="Anakin Skywalker" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="123456789" /> - diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/select_provisioned_projects.xml b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/select_provisioned_projects.xml new file mode 100644 index 00000000000..7d13578796a --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/select_provisioned_projects.xml @@ -0,0 +1,100 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/shared.xml b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/shared.xml index 70b0af093df..91b28bfa466 100644 --- a/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/shared.xml +++ b/server/sonar-server/src/test/resources/org/sonar/server/component/db/ComponentDaoTest/shared.xml @@ -87,7 +87,7 @@ uuid="OPQR" project_uuid="OPQR" module_uuid="[null]" module_uuid_path=".OPQR." description="the description" long_name="Anakin Skywalker" enabled="[true]" language="[null]" copy_resource_id="[null]" person_id="[null]" path="[null]" authorization_updated_at="123456789" /> - diff --git a/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProvisionedProjectsActionTest/all-projects.json b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProvisionedProjectsActionTest/all-projects.json new file mode 100644 index 00000000000..3fc3e56b540 --- /dev/null +++ b/server/sonar-server/src/test/resources/org/sonar/server/component/ws/ProvisionedProjectsActionTest/all-projects.json @@ -0,0 +1,14 @@ +{ + "projects":[ + { + "uuid":"provisioned-uuid-1", + "key":"provisioned-key-1", + "name":"provisioned-name-1" + }, + { + "uuid":"provisioned-uuid-2", + "key":"provisioned-key-2", + "name":"provisioned-name-2" + } + ] +} diff --git a/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java index cfbfb4291b3..6ed690b97d6 100644 --- a/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java +++ b/sonar-core/src/main/java/org/sonar/core/component/db/ComponentMapper.java @@ -21,6 +21,7 @@ package org.sonar.core.component.db; import org.apache.ibatis.annotations.Param; +import org.apache.ibatis.session.RowBounds; import org.sonar.core.component.ComponentDto; import org.sonar.core.component.FilePathWithHashDto; import org.sonar.core.component.UuidWithProjectUuidDto; @@ -29,6 +30,7 @@ import javax.annotation.CheckForNull; import java.util.Collection; import java.util.List; +import java.util.Map; /** * @since 4.3 @@ -101,4 +103,8 @@ public interface ComponentMapper { void insert(ComponentDto rule); void deleteByKey(String key); + + List selectProvisionedProjects(Map parameters, RowBounds rowBounds); + + int countProvisionedProjects(Map parameters); } diff --git a/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml b/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml index 7c5430038ec..84c011c08f2 100644 --- a/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml +++ b/sonar-core/src/main/resources/org/sonar/core/component/db/ComponentMapper.xml @@ -227,5 +227,30 @@ delete from projects where kee=#{key} - + + + + + left join snapshots s on s.project_id=p.id + where + s.id is null + and p.enabled=${_true} + and p.qualifier=#{qualifier} + and p.copy_resource_id is null + + and ( + p.name like #{query} + or p.kee like #{query} + ) + + +