diff options
author | Jenkins CI <ci@sonarsource.com> | 2016-04-14 22:26:08 +0200 |
---|---|---|
committer | Jenkins CI <ci@sonarsource.com> | 2016-04-14 22:26:08 +0200 |
commit | 8a49482fc8b942ea75ddab4fee58d75a5c6eee9a (patch) | |
tree | ef347ae401089ec4c09f21287c7e605a21058634 | |
parent | bf79ed11bd311395aaf01a0d17f72a835ef0d7fb (diff) | |
parent | ec0c9c265fed27964480ce51edc8a191b5234be7 (diff) | |
download | sonarqube-8a49482fc8b942ea75ddab4fee58d75a5c6eee9a.tar.gz sonarqube-8a49482fc8b942ea75ddab4fee58d75a5c6eee9a.zip |
Automatic merge from branch-5.5
* origin/branch-5.5:
SONAR-7429 defaults of HTTPS proxy are values of HTTP proxy
Add context when failing to map a db measure to a ws measure
SONAR-7187 Fix perf issue in selectByQuery
Add support of WS api/ce/task to sonar-ws
Add partial support of api/projects to sonar-ws
SONAR-7427 Remove "effort_to_reach_reliability_rating_a" and "effort_to_reach_security_rating_a" from js
19 files changed, 539 insertions, 29 deletions
diff --git a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java index bf9156fc46f..85019fac7d6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java +++ b/server/sonar-server/src/main/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasure.java @@ -33,24 +33,28 @@ class MeasureDtoToWsMeasure { } static WsMeasures.Measure measureDtoToWsMeasure(MetricDto metricDto, MeasureDto measureDto) { - WsMeasures.Measure.Builder measure = WsMeasures.Measure.newBuilder(); - measure.setMetric(metricDto.getKey()); - // a measure value can be null, new_violations metric for example - if (measureDto.getValue() != null - || measureDto.getData() != null) { - measure.setValue(formatMeasureValue(measureDto, metricDto)); - } + try { + WsMeasures.Measure.Builder measure = WsMeasures.Measure.newBuilder(); + measure.setMetric(metricDto.getKey()); + // a measure value can be null, new_violations metric for example + if (measureDto.getValue() != null + || measureDto.getData() != null) { + measure.setValue(formatMeasureValue(measureDto, metricDto)); + } - WsMeasures.PeriodValue.Builder periodBuilder = WsMeasures.PeriodValue.newBuilder(); - for (int i = 1; i <= 5; i++) { - if (measureDto.getVariation(i) != null) { - measure.getPeriodsBuilder().addPeriodsValue(periodBuilder - .clear() - .setIndex(i) - .setValue(formatNumericalValue(measureDto.getVariation(i), metricDto))); + WsMeasures.PeriodValue.Builder periodBuilder = WsMeasures.PeriodValue.newBuilder(); + for (int i = 1; i <= 5; i++) { + if (measureDto.getVariation(i) != null) { + measure.getPeriodsBuilder().addPeriodsValue(periodBuilder + .clear() + .setIndex(i) + .setValue(formatNumericalValue(measureDto.getVariation(i), metricDto))); + } } - } - return measure.build(); + return measure.build(); + } catch (Exception e) { + throw new IllegalStateException(String.format("Error while mapping a measure of metric key '%s' and parameters %s", metricDto.getKey(), measureDto.toString()), e); + } } } diff --git a/server/sonar-server/src/test/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasureTest.java b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasureTest.java new file mode 100644 index 00000000000..5b29ea233bf --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/measure/ws/MeasureDtoToWsMeasureTest.java @@ -0,0 +1,53 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.measure.ws; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.db.metric.MetricDto; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.spy; +import static org.mockito.Mockito.when; +import static org.sonar.db.measure.MeasureTesting.newMeasureDto; +import static org.sonar.db.metric.MetricTesting.newMetricDto; +import static org.sonar.test.TestUtils.hasOnlyPrivateConstructors; + +public class MeasureDtoToWsMeasureTest { + @Rule + public ExpectedException expectedException = ExpectedException.none(); + + @Test + public void fail_when_mapping_fails() { + MetricDto metric = spy(newMetricDto().setKey("metric-key")); + when(metric.getValueType()).thenThrow(NullPointerException.class); + expectedException.expect(IllegalStateException.class); + expectedException.expectMessage("Error while mapping a measure of metric key 'metric-key' and parameters "); + + MeasureDtoToWsMeasure.measureDtoToWsMeasure(metric, newMeasureDto(metric, 1L).setValue(5.5d).setData("data")); + } + + @Test + public void utility_class() { + assertThat(hasOnlyPrivateConstructors(MeasureDtoToWsMeasure.class)).isTrue(); + } +} diff --git a/server/sonar-web/src/main/js/apps/component-measures/config/domains.js b/server/sonar-web/src/main/js/apps/component-measures/config/domains.js index 08d97febd27..d7e52100202 100644 --- a/server/sonar-web/src/main/js/apps/component-measures/config/domains.js +++ b/server/sonar-web/src/main/js/apps/component-measures/config/domains.js @@ -24,8 +24,7 @@ export const domains = { 'new_bugs', 'reliability_rating', 'reliability_remediation_effort', - 'new_reliability_remediation_effort', - 'effort_to_reach_reliability_rating_a' + 'new_reliability_remediation_effort' ] }, @@ -35,8 +34,7 @@ export const domains = { 'new_vulnerabilities', 'security_rating', 'security_remediation_effort', - 'new_security_remediation_effort', - 'effort_to_reach_security_rating_a' + 'new_security_remediation_effort' ] }, diff --git a/sonar-application/src/main/assembly/conf/sonar.properties b/sonar-application/src/main/assembly/conf/sonar.properties index 1d700de0695..c4118f20895 100644 --- a/sonar-application/src/main/assembly/conf/sonar.properties +++ b/sonar-application/src/main/assembly/conf/sonar.properties @@ -188,8 +188,7 @@ # HTTP proxy (default none) #http.proxyHost= #http.proxyPort= - -# HTTPS proxy (default none) +# HTTPS proxy (defaults are values of http.proxyHost and http.proxyPort) #https.proxyHost= #https.proxyPort= diff --git a/sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java b/sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java index 9d7b87e1bd6..d7b343787ad 100644 --- a/sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java +++ b/sonar-core/src/main/java/org/sonar/core/util/DefaultHttpDownloader.java @@ -177,10 +177,14 @@ public class DefaultHttpDownloader extends HttpDownloader { private static final String GET = "GET"; private static final String HTTP_PROXY_USER = "http.proxyUser"; private static final String HTTP_PROXY_PASSWORD = "http.proxyPassword"; + private static final String HTTP_PROXY_HOST = "http.proxyHost"; + private static final String HTTPS_PROXY_HOST = "https.proxyHost"; + private static final String HTTP_PROXY_PORT = "http.proxyPort"; + private static final String HTTPS_PROXY_PORT = "https.proxyPort"; private static final List<String> PROXY_SETTINGS = ImmutableList.of( - "http.proxyHost", "http.proxyPort", "http.nonProxyHosts", - "https.proxyHost", "https.proxyPort", + HTTP_PROXY_HOST, HTTP_PROXY_PORT, "http.nonProxyHosts", + HTTPS_PROXY_HOST, HTTPS_PROXY_PORT, "http.auth.ntlm.domain", "socksProxyHost", "socksProxyPort"); private String userAgent; @@ -197,6 +201,10 @@ public class DefaultHttpDownloader extends HttpDownloader { system.setProperty(key, settings.getString(key)); } } + // defaults of HTTPS properties are the values of HTTP properties + setSystemPropertyToDefaultIfNotSet(system, settings, HTTPS_PROXY_HOST, HTTP_PROXY_HOST); + setSystemPropertyToDefaultIfNotSet(system, settings, HTTPS_PROXY_PORT, HTTP_PROXY_PORT); + // register credentials String login = settings.getString(HTTP_PROXY_USER); if (isNotEmpty(login)) { @@ -204,6 +212,12 @@ public class DefaultHttpDownloader extends HttpDownloader { } } + private static void setSystemPropertyToDefaultIfNotSet(SystemFacade system, Settings settings, String httpsProperty, String httpProperty) { + if (!settings.hasKey(httpsProperty) && settings.hasKey(httpProperty)) { + system.setProperty(httpsProperty, settings.getString(httpProperty)); + } + } + private void initUserAgent(@Nullable String sonarVersion) { userAgent = sonarVersion == null ? "SonarQube" : String.format("SonarQube %s", sonarVersion); System.setProperty("http.agent", userAgent); diff --git a/sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java b/sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java index 906c96a2013..f9296bcd139 100644 --- a/sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java +++ b/sonar-core/src/test/java/org/sonar/core/util/DefaultHttpDownloaderTest.java @@ -57,7 +57,9 @@ import org.sonar.api.utils.SonarException; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyString; import static org.mockito.Matchers.argThat; +import static org.mockito.Matchers.eq; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; @@ -273,6 +275,21 @@ public class DefaultHttpDownloaderTest { } @Test + public void https_defaults_are_http_properties() { + DefaultHttpDownloader.SystemFacade system = mock(DefaultHttpDownloader.SystemFacade.class); + Settings settings = new Settings(); + settings.setProperty("http.proxyHost", "1.2.3.4"); + settings.setProperty("http.proxyPort", "80"); + + new DefaultHttpDownloader.BaseHttpDownloader(system, settings, null); + + verify(system).setProperty("http.proxyHost", "1.2.3.4"); + verify(system).setProperty("http.proxyPort", "80"); + verify(system).setProperty("https.proxyHost", "1.2.3.4"); + verify(system).setProperty("https.proxyPort", "80"); + } + + @Test public void configure_http_proxy_credentials() { DefaultHttpDownloader.SystemFacade system = mock(DefaultHttpDownloader.SystemFacade.class); Settings settings = new Settings(); @@ -297,6 +314,19 @@ public class DefaultHttpDownloaderTest { })); } + @Test + public void no_http_proxy_settings_by_default() { + DefaultHttpDownloader.SystemFacade system = mock(DefaultHttpDownloader.SystemFacade.class); + Settings settings = new Settings(); + new DefaultHttpDownloader.BaseHttpDownloader(system, settings, null); + + verify(system, never()).setProperty(eq("http.proxyHost"), anyString()); + verify(system, never()).setProperty(eq("https.proxyHost"), anyString()); + verify(system, never()).setProperty(eq("http.proxyPort"), anyString()); + verify(system, never()).setProperty(eq("https.proxyPort"), anyString()); + verify(system, never()).setDefaultAuthenticator(any(Authenticator.class)); + } + } class FakeProxy extends Proxy { diff --git a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java index 050389c8858..e32a1be1535 100644 --- a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java +++ b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityDao.java @@ -69,7 +69,7 @@ public class CeActivityDao implements Dao { return Collections.emptyList(); } - return mapper(dbSession).selectByQuery(query, new RowBounds(offset, pageSize)); + return mapper(dbSession).selectByQuery(query, offset, pageSize); } public int countByQuery(DbSession dbSession, CeTaskQuery query) { diff --git a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java index a59254827ed..ea4652d4185 100644 --- a/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/ce/CeActivityMapper.java @@ -33,7 +33,7 @@ public interface CeActivityMapper { List<CeActivityDto> selectByComponentUuid(@Param("componentUuid") String componentUuid); - List<CeActivityDto> selectByQuery(@Param("query") CeTaskQuery query, RowBounds rowBounds); + List<CeActivityDto> selectByQuery(@Param("query") CeTaskQuery query, @Param("offset") int offset, @Param("pageSize") int pageSize); List<CeActivityDto> selectOlderThan(@Param("beforeDate") long beforeDate); diff --git a/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml b/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml index d86c8f73212..08247b4faa1 100644 --- a/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/ce/CeActivityMapper.xml @@ -4,6 +4,7 @@ <mapper namespace="org.sonar.db.ce.CeActivityMapper"> <sql id="columns"> + ca.id, ca.uuid, ca.task_type as taskType, ca.component_uuid as componentUuid, @@ -44,10 +45,33 @@ </select> <select id="selectByQuery" parameterType="map" resultType="org.sonar.db.ce.CeActivityDto"> - select + SELECT <include refid="columns"/> <include refid="sqlSelectByQuery" /> - order by ca.submitted_at desc, ca.id desc + ORDER BY ca.id desc + LIMIT #{pageSize} OFFSET #{offset} + </select> + + <select id="selectByQuery" parameterType="map" resultType="org.sonar.db.ce.CeActivityDto" databaseId="mssql"> + SELECT * FROM ( + SELECT ROW_NUMBER() OVER(ORDER BY id desc) AS NUMBER, + <include refid="columns"/> + <include refid="sqlSelectByQuery" /> + ) AS QUERY + WHERE NUMBER BETWEEN (#{offset} * #{pageSize} + 1) AND ((#{offset} + 1) * #{pageSize}) + ORDER BY id desc + </select> + + <select id="selectByQuery" parameterType="map" resultType="org.sonar.db.ce.CeActivityDto" databaseId="oracle"> + SELECT * FROM ( + SELECT ROWNUM AS rn, t.* FROM ( + SELECT + <include refid="columns"/> + <include refid="sqlSelectByQuery" /> + ORDER BY ca.id desc + ) t + ) t + WHERE rn BETWEEN (#{offset} * #{pageSize} + 1) AND ((#{offset} + 1) * #{pageSize}) </select> <select id="countByQuery" parameterType="map" resultType="int"> diff --git a/sonar-db/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java b/sonar-db/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java index 8b2b03adde9..bb92b76097b 100644 --- a/sonar-db/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java +++ b/sonar-db/src/test/java/org/sonar/db/ce/CeActivityDaoTest.java @@ -19,9 +19,12 @@ */ package org.sonar.db.ce; +import com.google.common.base.Function; import com.google.common.base.Optional; +import com.google.common.collect.FluentIterable; import java.util.Collections; import java.util.List; +import javax.annotation.Nonnull; import org.junit.Rule; import org.junit.Test; import org.sonar.api.utils.internal.TestSystem2; @@ -31,7 +34,6 @@ import static java.util.Collections.singletonList; import static org.assertj.core.api.Assertions.assertThat; import static org.sonar.db.ce.CeTaskTypes.REPORT; - public class CeActivityDaoTest { TestSystem2 system2 = new TestSystem2().setNow(1_450_000_000_000L); @@ -123,6 +125,22 @@ public class CeActivityDaoTest { } @Test + public void selectByQuery_is_paginated_and_return_results_sorted_from_last_to_first() { + insert("TASK_1", REPORT, "PROJECT_1", CeActivityDto.Status.SUCCESS); + insert("TASK_2", REPORT, "PROJECT_1", CeActivityDto.Status.FAILED); + insert("TASK_3", REPORT, "PROJECT_2", CeActivityDto.Status.SUCCESS); + insert("TASK_4", "views", null, CeActivityDto.Status.SUCCESS); + + assertThat(selectPageOfUuids(0, 1)).containsExactly("TASK_4"); + assertThat(selectPageOfUuids(1, 1)).containsExactly("TASK_3"); + assertThat(selectPageOfUuids(0, 3)).containsExactly("TASK_4", "TASK_3", "TASK_2"); + assertThat(selectPageOfUuids(0, 4)).containsExactly("TASK_4", "TASK_3", "TASK_2", "TASK_1"); + assertThat(selectPageOfUuids(0, 100)).containsExactly("TASK_4", "TASK_3", "TASK_2", "TASK_1"); + assertThat(selectPageOfUuids(0, 0)).isEmpty(); + assertThat(selectPageOfUuids(10, 2)).isEmpty(); + } + + @Test public void test_countByQuery() { insert("TASK_1", REPORT, "PROJECT_1", CeActivityDto.Status.SUCCESS); insert("TASK_2", REPORT, "PROJECT_1", CeActivityDto.Status.FAILED); @@ -262,4 +280,17 @@ public class CeActivityDaoTest { system2.setNow(date); underTest.insert(db.getSession(), dto); } + + private List<String> selectPageOfUuids(int offset, int pageSize) { + return FluentIterable.from(underTest.selectByQuery(db.getSession(), new CeTaskQuery(), offset, pageSize)).transform(CeActivityToUuid.INSTANCE).toList(); + } + + private enum CeActivityToUuid implements Function<CeActivityDto, String> { + INSTANCE; + + @Override + public String apply(@Nonnull CeActivityDto input) { + return input.getUuid(); + } + } } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java index 1c0d8278ee9..110c8d0377a 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/DefaultWsClient.java @@ -24,6 +24,7 @@ import org.sonarqube.ws.client.component.ComponentsService; import org.sonarqube.ws.client.issue.IssuesService; import org.sonarqube.ws.client.measure.MeasuresService; import org.sonarqube.ws.client.permission.PermissionsService; +import org.sonarqube.ws.client.project.ProjectsService; import org.sonarqube.ws.client.qualitygate.QualityGatesService; import org.sonarqube.ws.client.qualityprofile.QualityProfilesService; import org.sonarqube.ws.client.rule.RulesService; @@ -49,6 +50,7 @@ class DefaultWsClient implements WsClient { private final SystemService systemService; private final CeService ceService; private final RulesService rulesService; + private final ProjectsService projectsService; DefaultWsClient(WsConnector wsConnector) { this.wsConnector = wsConnector; @@ -62,6 +64,7 @@ class DefaultWsClient implements WsClient { this.systemService = new SystemService(wsConnector); this.ceService = new CeService(wsConnector); this.rulesService = new RulesService(wsConnector); + this.projectsService = new ProjectsService(wsConnector); } @Override @@ -118,4 +121,9 @@ class DefaultWsClient implements WsClient { public RulesService rules() { return rulesService; } + + @Override + public ProjectsService projects() { + return projectsService; + } } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java index fc79d58e695..36369c45e5c 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/WsClient.java @@ -24,6 +24,7 @@ import org.sonarqube.ws.client.component.ComponentsService; import org.sonarqube.ws.client.issue.IssuesService; import org.sonarqube.ws.client.measure.MeasuresService; import org.sonarqube.ws.client.permission.PermissionsService; +import org.sonarqube.ws.client.project.ProjectsService; import org.sonarqube.ws.client.qualitygate.QualityGatesService; import org.sonarqube.ws.client.qualityprofile.QualityProfilesService; import org.sonarqube.ws.client.rule.RulesService; @@ -70,4 +71,9 @@ public interface WsClient { RulesService rules(); WsConnector wsConnector(); + + /** + * @since 5.5 + */ + ProjectsService projects(); } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/ce/CeService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/ce/CeService.java index a05d383c67d..1871cd800d9 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/ce/CeService.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/ce/CeService.java @@ -20,6 +20,7 @@ package org.sonarqube.ws.client.ce; +import org.sonarqube.ws.WsCe; import org.sonarqube.ws.WsCe.ActivityResponse; import org.sonarqube.ws.WsCe.TaskTypesWsResponse; import org.sonarqube.ws.client.BaseService; @@ -33,6 +34,9 @@ import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_ONLY_CURRENTS; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_STATUS; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_TYPE; +/** + * Maps web service {@code api/ce} (Compute Engine). + */ public class CeService extends BaseService { public CeService(WsConnector wsConnector) { @@ -58,4 +62,13 @@ public class CeService extends BaseService { return call(new GetRequest(path("task_types")), TaskTypesWsResponse.parser()); } + /** + * Gets details of a Compute Engine task. + * + * @throws org.sonarqube.ws.client.HttpException if HTTP status code is not 2xx. + * @since 5.5 + */ + public WsCe.TaskResponse task(String id) { + return call(new GetRequest(path("task")).setParam("id", id), WsCe.TaskResponse.parser()); + } } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/CreateRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/CreateRequest.java new file mode 100644 index 00000000000..698d7666904 --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/CreateRequest.java @@ -0,0 +1,84 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.sonarqube.ws.client.project; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +/** + * @since 5.5 + */ +public class CreateRequest { + + private final String key; + private final String name; + private final String branch; + + private CreateRequest(Builder builder) { + this.key = builder.key; + this.name = builder.name; + this.branch = builder.branch; + } + + public String getKey() { + return key; + } + + public String getName() { + return name; + } + + @CheckForNull + public String getBranch() { + return branch; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String key; + private String name; + private String branch; + + private Builder() { + } + + public Builder setKey(String key) { + this.key = key; + return this; + } + + public Builder setName(String name) { + this.name = name; + return this; + } + + public Builder setBranch(@Nullable String branch) { + this.branch = branch; + return this; + } + + public CreateRequest build() { + return new CreateRequest(this); + } + } +} diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/DeleteRequest.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/DeleteRequest.java new file mode 100644 index 00000000000..5a0df28686a --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/DeleteRequest.java @@ -0,0 +1,73 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.sonarqube.ws.client.project; + +import javax.annotation.CheckForNull; +import javax.annotation.Nullable; + +/** + * @since 5.5 + */ +public class DeleteRequest { + + private final String id; + private final String key; + + private DeleteRequest(Builder builder) { + this.id = builder.id; + this.key = builder.key; + } + + @CheckForNull + public String getKey() { + return key; + } + + @CheckForNull + public String getId() { + return id; + } + + public static Builder builder() { + return new Builder(); + } + + public static class Builder { + private String id; + private String key; + + private Builder() { + } + + public Builder setId(@Nullable String id) { + this.id = id; + return this; + } + + public Builder setKey(@Nullable String key) { + this.key = key; + return this; + } + + public DeleteRequest build() { + return new DeleteRequest(this); + } + } +} diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsService.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsService.java new file mode 100644 index 00000000000..2eb5ae1af0b --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/ProjectsService.java @@ -0,0 +1,58 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.sonarqube.ws.client.project; + +import org.sonarqube.ws.client.BaseService; +import org.sonarqube.ws.client.PostRequest; +import org.sonarqube.ws.client.WsConnector; + +/** + * Maps web service {@code api/projects}. + * @since 5.5 + */ +public class ProjectsService extends BaseService { + + public ProjectsService(WsConnector wsConnector) { + super(wsConnector, "api/projects"); + } + + /** + * Provisions a new project. + * + * @throws org.sonarqube.ws.client.HttpException if HTTP status code is not 2xx. + */ + public void create(CreateRequest project) { + PostRequest request = new PostRequest(path("create")) + .setParam("key", project.getKey()) + .setParam("name", project.getName()) + .setParam("branch", project.getBranch()); + call(request); + } + + /** + * @throws org.sonarqube.ws.client.HttpException if HTTP status code is not 2xx. + */ + public void delete(DeleteRequest request) { + call(new PostRequest(path("delete")) + .setParam("id", request.getId()) + .setParam("key", request.getKey())); + } +} diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/project/package-info.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/package-info.java new file mode 100644 index 00000000000..041d5d4da2f --- /dev/null +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/project/package-info.java @@ -0,0 +1,25 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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. + */ + +@ParametersAreNonnullByDefault +package org.sonarqube.ws.client.project; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/ce/CeServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/ce/CeServiceTest.java index 1125072b933..51cc5293bc6 100644 --- a/sonar-ws/src/test/java/org/sonarqube/ws/client/ce/CeServiceTest.java +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/ce/CeServiceTest.java @@ -30,6 +30,7 @@ import org.sonarqube.ws.client.ServiceTester; import org.sonarqube.ws.client.WsConnector; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.data.MapEntry.entry; import static org.mockito.Mockito.mock; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_COMPONENT_ID; import static org.sonarqube.ws.client.ce.CeWsParameters.PARAM_MAX_EXECUTED_AT; @@ -94,4 +95,12 @@ public class CeServiceTest { assertThat(serviceTester.getGetParser()).isSameAs(WsCe.TaskTypesWsResponse.parser()); } + + @Test + public void task() { + underTest.task("task_id"); + + assertThat(serviceTester.getGetRequest().getPath()).isEqualTo("api/ce/task"); + assertThat(serviceTester.getGetRequest().getParams()).containsOnly(entry("id", "task_id")); + } } diff --git a/sonar-ws/src/test/java/org/sonarqube/ws/client/project/ProjectsServiceTest.java b/sonar-ws/src/test/java/org/sonarqube/ws/client/project/ProjectsServiceTest.java new file mode 100644 index 00000000000..ccb720b00fd --- /dev/null +++ b/sonar-ws/src/test/java/org/sonarqube/ws/client/project/ProjectsServiceTest.java @@ -0,0 +1,81 @@ +/* + * SonarQube + * Copyright (C) 2009-2016 SonarSource SA + * mailto:contact AT sonarsource DOT com + * + * This program 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. + * + * This program 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.sonarqube.ws.client.project; + +import org.junit.Rule; +import org.junit.Test; +import org.sonarqube.ws.client.ServiceTester; +import org.sonarqube.ws.client.WsConnector; + +import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.data.MapEntry.entry; +import static org.mockito.Mockito.mock; + +public class ProjectsServiceTest { + + @Rule + public ServiceTester<ProjectsService> serviceTester = new ServiceTester<>(new ProjectsService(mock(WsConnector.class))); + + private ProjectsService underTest = serviceTester.getInstanceUnderTest(); + + @Test + public void creates_project() { + underTest.create(CreateRequest.builder() + .setKey("project_key") + .setName("Project Name") + .build()); + + assertThat(serviceTester.getPostRequest().getPath()).isEqualTo("api/projects/create"); + assertThat(serviceTester.getPostRequest().getParams()).containsOnly( + entry("key", "project_key"), + entry("name", "Project Name")); + } + + @Test + public void creates_project_on_branch() { + underTest.create(CreateRequest.builder() + .setKey("project_key") + .setName("Project Name") + .setBranch("the_branch") + .build()); + + assertThat(serviceTester.getPostRequest().getPath()).isEqualTo("api/projects/create"); + assertThat(serviceTester.getPostRequest().getParams()).containsOnly( + entry("key", "project_key"), + entry("name", "Project Name"), + entry("branch", "the_branch")); + } + + @Test + public void deletes_project_by_id() { + underTest.delete(DeleteRequest.builder().setId("abc").build()); + + assertThat(serviceTester.getPostRequest().getPath()).isEqualTo("api/projects/delete"); + assertThat(serviceTester.getPostRequest().getParams()).containsOnly(entry("id", "abc")); + } + + @Test + public void deletes_project_by_key() { + underTest.delete(DeleteRequest.builder().setKey("project_key").build()); + + assertThat(serviceTester.getPostRequest().getPath()).isEqualTo("api/projects/delete"); + assertThat(serviceTester.getPostRequest().getParams()).containsOnly(entry("key", "project_key")); + } +} |