From: Teryk Bellahsene Date: Fri, 29 Jul 2016 09:08:56 +0000 (+0200) Subject: SONAR-7923 Create WS api/qualitygates/get_by_project X-Git-Tag: 6.1-RC1~482 X-Git-Url: https://source.dussan.org/?a=commitdiff_plain;h=3e3e4b1e16c0e5ebf8a485d3014cb7bd2577e192;p=sonarqube.git SONAR-7923 Create WS api/qualitygates/get_by_project --- diff --git a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java index f64df96c3e8..0a41ac2a4a2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java +++ b/server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java @@ -180,18 +180,7 @@ import org.sonar.server.plugins.ws.UpdatesAction; import org.sonar.server.project.ws.ProjectsWsModule; import org.sonar.server.projectlink.ws.ProjectLinksModule; import org.sonar.server.properties.ProjectSettingsFactory; -import org.sonar.server.qualitygate.QgateProjectFinder; -import org.sonar.server.qualitygate.QualityGates; -import org.sonar.server.qualitygate.ws.CreateConditionAction; -import org.sonar.server.qualitygate.ws.DeleteConditionAction; -import org.sonar.server.qualitygate.ws.DeselectAction; -import org.sonar.server.qualitygate.ws.DestroyAction; -import org.sonar.server.qualitygate.ws.ProjectStatusAction; -import org.sonar.server.qualitygate.ws.QualityGatesWs; -import org.sonar.server.qualitygate.ws.SelectAction; -import org.sonar.server.qualitygate.ws.SetAsDefaultAction; -import org.sonar.server.qualitygate.ws.UnsetDefaultAction; -import org.sonar.server.qualitygate.ws.UpdateConditionAction; +import org.sonar.server.qualitygate.QualityGateModule; import org.sonar.server.qualityprofile.BuiltInProfiles; import org.sonar.server.qualityprofile.QProfileBackuper; import org.sonar.server.qualityprofile.QProfileComparison; @@ -462,26 +451,7 @@ public class PlatformLevel4 extends PlatformLevel { DefaultMetricFinder.class, TimeMachineWs.class, - // quality gates - QualityGates.class, - QgateProjectFinder.class, - org.sonar.server.qualitygate.ws.ListAction.class, - org.sonar.server.qualitygate.ws.SearchAction.class, - org.sonar.server.qualitygate.ws.ShowAction.class, - org.sonar.server.qualitygate.ws.CreateAction.class, - org.sonar.server.qualitygate.ws.RenameAction.class, - org.sonar.server.qualitygate.ws.CopyAction.class, - DestroyAction.class, - SetAsDefaultAction.class, - UnsetDefaultAction.class, - SelectAction.class, - DeselectAction.class, - CreateConditionAction.class, - DeleteConditionAction.class, - UpdateConditionAction.class, - org.sonar.server.qualitygate.ws.AppAction.class, - ProjectStatusAction.class, - QualityGatesWs.class, + QualityGateModule.class, // web services WebServiceEngine.class, diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateModule.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateModule.java new file mode 100644 index 00000000000..4999167b855 --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateModule.java @@ -0,0 +1,69 @@ +/* + * 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.qualitygate; + +import org.sonar.core.platform.Module; +import org.sonar.server.qualitygate.ws.AppAction; +import org.sonar.server.qualitygate.ws.CopyAction; +import org.sonar.server.qualitygate.ws.CreateAction; +import org.sonar.server.qualitygate.ws.CreateConditionAction; +import org.sonar.server.qualitygate.ws.DeleteConditionAction; +import org.sonar.server.qualitygate.ws.DeselectAction; +import org.sonar.server.qualitygate.ws.DestroyAction; +import org.sonar.server.qualitygate.ws.GetByProjectAction; +import org.sonar.server.qualitygate.ws.ListAction; +import org.sonar.server.qualitygate.ws.ProjectStatusAction; +import org.sonar.server.qualitygate.ws.QualityGatesWs; +import org.sonar.server.qualitygate.ws.RenameAction; +import org.sonar.server.qualitygate.ws.SearchAction; +import org.sonar.server.qualitygate.ws.SelectAction; +import org.sonar.server.qualitygate.ws.SetAsDefaultAction; +import org.sonar.server.qualitygate.ws.ShowAction; +import org.sonar.server.qualitygate.ws.UnsetDefaultAction; +import org.sonar.server.qualitygate.ws.UpdateConditionAction; + +public class QualityGateModule extends Module { + @Override + protected void configureModule() { + add( + QualityGates.class, + QgateProjectFinder.class, + // WS + QualityGatesWs.class, + ListAction.class, + SearchAction.class, + ShowAction.class, + CreateAction.class, + RenameAction.class, + CopyAction.class, + DestroyAction.class, + SetAsDefaultAction.class, + UnsetDefaultAction.class, + SelectAction.class, + DeselectAction.class, + CreateConditionAction.class, + DeleteConditionAction.class, + UpdateConditionAction.class, + AppAction.class, + ProjectStatusAction.class, + GetByProjectAction.class); + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java index 9925fb6eb5e..786f38ed803 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java @@ -21,15 +21,14 @@ package org.sonar.server.qualitygate; import com.google.common.base.Predicate; import com.google.common.base.Strings; -import com.google.common.collect.Collections2; import java.util.Collection; +import java.util.stream.Collectors; import javax.annotation.CheckForNull; import javax.annotation.Nonnull; import javax.annotation.Nullable; import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.StringUtils; -import org.apache.ibatis.session.SqlSession; import org.sonar.api.config.Settings; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; @@ -37,6 +36,7 @@ import org.sonar.api.measures.Metric.ValueType; import org.sonar.api.measures.MetricFinder; import org.sonar.api.web.UserRole; import org.sonar.core.permission.GlobalPermissions; +import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.MyBatis; import org.sonar.db.component.ComponentDao; @@ -56,7 +56,6 @@ import org.sonar.server.exceptions.ServerException; import org.sonar.server.user.UserSession; import org.sonar.server.util.Validation; -import static com.google.common.collect.FluentIterable.from; import static java.lang.String.format; /** @@ -66,23 +65,22 @@ public class QualityGates { public static final String SONAR_QUALITYGATE_PROPERTY = "sonar.qualitygate"; + private final DbClient dbClient; private final QualityGateDao dao; private final QualityGateConditionDao conditionDao; private final MetricFinder metricFinder; private final PropertiesDao propertiesDao; private final ComponentDao componentDao; - private final MyBatis myBatis; private final UserSession userSession; private final Settings settings; - public QualityGates(QualityGateDao dao, QualityGateConditionDao conditionDao, MetricFinder metricFinder, PropertiesDao propertiesDao, ComponentDao componentDao, - MyBatis myBatis, UserSession userSession, Settings settings) { - this.dao = dao; - this.conditionDao = conditionDao; + public QualityGates(DbClient dbClient, MetricFinder metricFinder, UserSession userSession, Settings settings) { + this.dbClient = dbClient; + this.dao = dbClient.qualityGateDao(); + this.conditionDao = dbClient.gateConditionDao(); this.metricFinder = metricFinder; - this.propertiesDao = propertiesDao; - this.componentDao = componentDao; - this.myBatis = myBatis; + this.propertiesDao = dbClient.propertiesDao(); + this.componentDao = dbClient.componentDao(); this.userSession = userSession; this.settings = settings; } @@ -117,18 +115,18 @@ public class QualityGates { getNonNullQgate(sourceId); validateQualityGate(null, destinationName); QualityGateDto destinationGate = new QualityGateDto().setName(destinationName); - SqlSession session = myBatis.openSession(false); + DbSession dbSession = dbClient.openSession(false); try { - dao.insert(destinationGate, session); - for (QualityGateConditionDto sourceCondition : conditionDao.selectForQualityGate(sourceId, session)) { + dao.insert(dbSession, destinationGate); + for (QualityGateConditionDto sourceCondition : conditionDao.selectForQualityGate(sourceId, dbSession)) { conditionDao.insert(new QualityGateConditionDto().setQualityGateId(destinationGate.getId()) .setMetricId(sourceCondition.getMetricId()).setOperator(sourceCondition.getOperator()) .setWarningThreshold(sourceCondition.getWarningThreshold()).setErrorThreshold(sourceCondition.getErrorThreshold()).setPeriod(sourceCondition.getPeriod()), - session); + dbSession); } - session.commit(); + dbSession.commit(); } finally { - MyBatis.closeQuietly(session); + MyBatis.closeQuietly(dbSession); } return destinationGate; } @@ -140,7 +138,7 @@ public class QualityGates { public void delete(long idToDelete) { checkPermission(); QualityGateDto qGate = getNonNullQgate(idToDelete); - DbSession session = myBatis.openSession(false); + DbSession session = dbClient.openSession(false); try { if (isDefault(qGate)) { propertiesDao.deleteGlobalProperty(SONAR_QUALITYGATE_PROPERTY, session); @@ -228,7 +226,7 @@ public class QualityGates { } public void associateProject(Long qGateId, Long projectId) { - DbSession session = myBatis.openSession(false); + DbSession session = dbClient.openSession(false); try { getNonNullQgate(qGateId); checkPermission(projectId, session); @@ -239,7 +237,7 @@ public class QualityGates { } public void dissociateProject(Long qGateId, Long projectId) { - DbSession session = myBatis.openSession(false); + DbSession session = dbClient.openSession(false); try { getNonNullQgate(qGateId); checkPermission(projectId, session); @@ -250,12 +248,9 @@ public class QualityGates { } public Collection gateMetrics() { - return Collections2.filter(metricFinder.findAll(), new Predicate() { - @Override - public boolean apply(Metric metric) { - return isAvailableForInit(metric); - } - }); + return metricFinder.findAll().stream() + .filter(QualityGates::isAvailableForInit) + .collect(Collectors.toList()); } public boolean currentUserHasWritePermission() { @@ -274,7 +269,9 @@ public class QualityGates { if (conditionId == null) { return conditions; } - return from(conditionDao.selectForQualityGate(qGateId)).filter(new MatchConditionId(conditionId)).toList(); + return conditionDao.selectForQualityGate(qGateId).stream() + .filter(condition -> condition.getId() != conditionId) + .collect(Collectors.toList()); } private static void validateCondition(Metric metric, String operator, @Nullable String warningThreshold, @Nullable String errorThreshold, @Nullable Integer period) { @@ -293,7 +290,7 @@ public class QualityGates { return; } - boolean conditionExists = from(conditions).anyMatch(new MatchMetricAndPeriod(metric.getId(), period)); + boolean conditionExists = conditions.stream().anyMatch(new MatchMetricAndPeriod(metric.getId(), period)::apply); if (conditionExists) { String errorMessage = period == null ? format("Condition on metric '%s' already exists.", metric.getName()) @@ -421,18 +418,4 @@ public class QualityGates { ObjectUtils.equals(input.getPeriod(), period); } } - - private static class MatchConditionId implements Predicate { - private final long conditionId; - - private MatchConditionId(long conditionId) { - this.conditionId = conditionId; - } - - @Override - public boolean apply(@Nonnull QualityGateConditionDto input) { - return input.getId() != conditionId; - } - } - } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CopyAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CopyAction.java index 89e77f7998e..21e56bf8e37 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CopyAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CopyAction.java @@ -26,6 +26,9 @@ import org.sonar.api.utils.text.JsonWriter; import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.server.qualitygate.QualityGates; +import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_ID; +import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_NAME; + public class CopyAction implements QualityGatesWsAction { private final QualityGates qualityGates; @@ -42,12 +45,12 @@ public class CopyAction implements QualityGatesWsAction { .setSince("4.3") .setHandler(this); - action.createParam(QualityGatesWs.PARAM_ID) + action.createParam(PARAM_ID) .setDescription("The ID of the source quality gate") .setRequired(true) .setExampleValue("1"); - action.createParam(QualityGatesWs.PARAM_NAME) + action.createParam(PARAM_NAME) .setDescription("The name of the quality gate to create") .setRequired(true) .setExampleValue("My Quality Gate"); @@ -55,7 +58,7 @@ public class CopyAction implements QualityGatesWsAction { @Override public void handle(Request request, Response response) { - QualityGateDto newQualityGate = qualityGates.copy(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID), request.mandatoryParam(QualityGatesWs.PARAM_NAME)); + QualityGateDto newQualityGate = qualityGates.copy(QualityGatesWs.parseId(request, PARAM_ID), request.mandatoryParam(PARAM_NAME)); JsonWriter writer = response.newJsonWriter(); QualityGatesWs.writeQualityGate(newQualityGate, writer).close(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateAction.java index 5ddc735e02b..49b2e837d7c 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateAction.java @@ -25,6 +25,7 @@ import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.text.JsonWriter; import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.server.qualitygate.QualityGates; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; public class CreateAction implements QualityGatesWsAction { @@ -42,7 +43,7 @@ public class CreateAction implements QualityGatesWsAction { .setPost(true) .setHandler(this); - action.createParam(QualityGatesWs.PARAM_NAME) + action.createParam(QualityGatesWsParameters.PARAM_NAME) .setDescription("The name of the quality gate to create") .setRequired(true) .setExampleValue("My Quality Gate"); @@ -50,7 +51,7 @@ public class CreateAction implements QualityGatesWsAction { @Override public void handle(Request request, Response response) { - QualityGateDto newQualityGate = qualityGates.create(request.mandatoryParam(QualityGatesWs.PARAM_NAME)); + QualityGateDto newQualityGate = qualityGates.create(request.mandatoryParam(QualityGatesWsParameters.PARAM_NAME)); JsonWriter writer = response.newJsonWriter(); QualityGatesWs.writeQualityGate(newQualityGate, writer).close(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateConditionAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateConditionAction.java index aa572402040..fbaf599cea6 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateConditionAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateConditionAction.java @@ -23,6 +23,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.server.qualitygate.QualityGates; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; public class CreateConditionAction implements QualityGatesWsAction { @@ -41,7 +42,7 @@ public class CreateConditionAction implements QualityGatesWsAction { .setHandler(this); createCondition - .createParam(QualityGatesWs.PARAM_GATE_ID) + .createParam(QualityGatesWsParameters.PARAM_GATE_ID) .setDescription("ID of the quality gate") .setRequired(true) .setExampleValue("1"); @@ -53,12 +54,12 @@ public class CreateConditionAction implements QualityGatesWsAction { public void handle(Request request, Response response) { QualityGatesWs.writeQualityGateCondition( qualityGates.createCondition( - QualityGatesWs.parseId(request, QualityGatesWs.PARAM_GATE_ID), - request.mandatoryParam(QualityGatesWs.PARAM_METRIC), - request.mandatoryParam(QualityGatesWs.PARAM_OPERATOR), - request.param(QualityGatesWs.PARAM_WARNING), - request.param(QualityGatesWs.PARAM_ERROR), - request.paramAsInt(QualityGatesWs.PARAM_PERIOD) + QualityGatesWs.parseId(request, QualityGatesWsParameters.PARAM_GATE_ID), + request.mandatoryParam(QualityGatesWsParameters.PARAM_METRIC), + request.mandatoryParam(QualityGatesWsParameters.PARAM_OPERATOR), + request.param(QualityGatesWsParameters.PARAM_WARNING), + request.param(QualityGatesWsParameters.PARAM_ERROR), + request.paramAsInt(QualityGatesWsParameters.PARAM_PERIOD) ), response.newJsonWriter() ).close(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeleteConditionAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeleteConditionAction.java index cd1f94f0f9a..24510b91298 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeleteConditionAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeleteConditionAction.java @@ -23,6 +23,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.server.qualitygate.QualityGates; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; public class DeleteConditionAction implements QualityGatesWsAction { @@ -41,7 +42,7 @@ public class DeleteConditionAction implements QualityGatesWsAction { .setHandler(this); createCondition - .createParam(QualityGatesWs.PARAM_ID) + .createParam(QualityGatesWsParameters.PARAM_ID) .setRequired(true) .setDescription("Condition ID") .setExampleValue("2"); @@ -49,7 +50,7 @@ public class DeleteConditionAction implements QualityGatesWsAction { @Override public void handle(Request request, Response response) { - qualityGates.deleteCondition(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID)); + qualityGates.deleteCondition(QualityGatesWs.parseId(request, QualityGatesWsParameters.PARAM_ID)); response.noContent(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java index 1f1bfee0a47..0579676dfcb 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java @@ -23,6 +23,9 @@ import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.server.qualitygate.QualityGates; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; + +import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_PROJECT_ID; public class DeselectAction implements QualityGatesWsAction { @@ -40,12 +43,12 @@ public class DeselectAction implements QualityGatesWsAction { .setSince("4.3") .setHandler(this); - action.createParam(QualityGatesWs.PARAM_GATE_ID) + action.createParam(QualityGatesWsParameters.PARAM_GATE_ID) .setDescription("Quality Gate ID") .setRequired(true) .setExampleValue("1"); - action.createParam(QualityGatesWs.PARAM_PROJECT_ID) + action.createParam(PARAM_PROJECT_ID) .setDescription("Project ID") .setRequired(true) .setExampleValue("12"); @@ -53,7 +56,7 @@ public class DeselectAction implements QualityGatesWsAction { @Override public void handle(Request request, Response response) { - qualityGates.dissociateProject(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_GATE_ID), QualityGatesWs.parseId(request, QualityGatesWs.PARAM_PROJECT_ID)); + qualityGates.dissociateProject(QualityGatesWs.parseId(request, QualityGatesWsParameters.PARAM_GATE_ID), QualityGatesWs.parseId(request, PARAM_PROJECT_ID)); response.noContent(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java index 654a693e7f0..97e5e60080e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java @@ -23,6 +23,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.server.qualitygate.QualityGates; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; public class DestroyAction implements QualityGatesWsAction { @@ -40,7 +41,7 @@ public class DestroyAction implements QualityGatesWsAction { .setPost(true) .setHandler(this); - action.createParam(QualityGatesWs.PARAM_ID) + action.createParam(QualityGatesWsParameters.PARAM_ID) .setDescription("ID of the quality gate to delete") .setRequired(true) .setExampleValue("1"); @@ -48,7 +49,7 @@ public class DestroyAction implements QualityGatesWsAction { @Override public void handle(Request request, Response response) { - qualityGates.delete(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID)); + qualityGates.delete(QualityGatesWs.parseId(request, QualityGatesWsParameters.PARAM_ID)); response.noContent(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/GetByProjectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/GetByProjectAction.java new file mode 100644 index 00000000000..2fbb8d03f4b --- /dev/null +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/GetByProjectAction.java @@ -0,0 +1,134 @@ +/* + * 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.qualitygate.ws; + +import java.util.Optional; +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.web.UserRole; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.qualitygate.QualityGateDto; +import org.sonar.server.component.ComponentFinder; +import org.sonar.server.component.ComponentFinder.ParamNames; +import org.sonar.server.qualitygate.QualityGates; +import org.sonar.server.user.UserSession; +import org.sonarqube.ws.WsQualityGates.GetByProjectWsResponse; + +import static org.sonar.core.util.Uuids.UUID_EXAMPLE_01; +import static org.sonar.server.user.AbstractUserSession.insufficientPrivilegesException; +import static org.sonar.server.ws.KeyExamples.KEY_PROJECT_EXAMPLE_001; +import static org.sonar.server.ws.WsUtils.writeProtobuf; +import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_PROJECT_ID; +import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_PROJECT_KEY; + +public class GetByProjectAction implements QualityGatesWsAction { + private final UserSession userSession; + private final DbClient dbClient; + private final ComponentFinder componentFinder; + private final QualityGates qualityGates; + + public GetByProjectAction(UserSession userSession, DbClient dbClient, ComponentFinder componentFinder, QualityGates qualityGates) { + this.userSession = userSession; + this.dbClient = dbClient; + this.componentFinder = componentFinder; + this.qualityGates = qualityGates; + } + + @Override + public void define(WebService.NewController context) { + WebService.NewAction action = context.createAction("get_by_project") + .setInternal(true) + .setSince("6.1") + .setDescription("Get the quality gate of a project.
" + + "Either project id or project key must be provided, not both.") + .setResponseExample(getClass().getResource("get_by_project-example.json")) + .setHandler(this); + + action.createParam(PARAM_PROJECT_ID) + .setDescription("Project id") + .setExampleValue(UUID_EXAMPLE_01); + + action.createParam(PARAM_PROJECT_KEY) + .setDescription("Project key") + .setExampleValue(KEY_PROJECT_EXAMPLE_001); + } + + @Override + public void handle(Request request, Response response) throws Exception { + DbSession dbSession = dbClient.openSession(false); + try { + ComponentDto project = getProject(dbSession, request.param(PARAM_PROJECT_ID), request.param(PARAM_PROJECT_KEY)); + QualityGateData data = getQualityGate(dbSession, project.getId()); + + writeProtobuf(buildResponse(data), request, response); + } finally { + dbClient.closeSession(dbSession); + } + } + + private ComponentDto getProject(DbSession dbSession, String projectUuid, String projectKey) { + ComponentDto project = componentFinder.getByUuidOrKey(dbSession, projectUuid, projectKey, ParamNames.PROJECT_ID_AND_KEY); + + if (!userSession.hasComponentUuidPermission(UserRole.USER, projectUuid) && + !userSession.hasComponentUuidPermission(UserRole.ADMIN, projectUuid)) { + throw insufficientPrivilegesException(); + } + + return project; + } + + private static GetByProjectWsResponse buildResponse(QualityGateData data) { + if (!data.qualityGate.isPresent()) { + return GetByProjectWsResponse.getDefaultInstance(); + } + + QualityGateDto qualityGate = data.qualityGate.get(); + GetByProjectWsResponse.Builder response = GetByProjectWsResponse.newBuilder(); + + response.getQualityGateBuilder() + .setId(String.valueOf(qualityGate.getId())) + .setName(qualityGate.getName()) + .setDefault(data.isDefault); + + return response.build(); + } + + private QualityGateData getQualityGate(DbSession dbSession, long componentId) { + Optional qualityGateId = dbClient.projectQgateAssociationDao().selectQGateIdByComponentId(dbSession, componentId); + + return qualityGateId.isPresent() + ? new QualityGateData(Optional.ofNullable(dbClient.qualityGateDao().selectById(dbSession, qualityGateId.get())), false) + : new QualityGateData(Optional.ofNullable(qualityGates.getDefault()), true); + } + + private static class QualityGateData { + private final Optional qualityGate; + private final boolean isDefault; + + private QualityGateData(Optional qualityGate, boolean isDefault) { + this.qualityGate = qualityGate; + this.isDefault = isDefault; + } + } +} diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java index fc98402788a..8e103f8e235 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java @@ -25,22 +25,9 @@ import org.sonar.api.utils.text.JsonWriter; import org.sonar.db.qualitygate.QualityGateConditionDto; import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.server.exceptions.BadRequestException; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; public class QualityGatesWs implements WebService { - - static final String PARAM_PAGE_SIZE = "pageSize"; - static final String PARAM_PAGE = "page"; - static final String PARAM_QUERY = "query"; - static final String PARAM_NAME = "name"; - static final String PARAM_ERROR = "error"; - static final String PARAM_WARNING = "warning"; - static final String PARAM_PERIOD = "period"; - static final String PARAM_OPERATOR = "op"; - static final String PARAM_METRIC = "metric"; - static final String PARAM_GATE_ID = "gateId"; - static final String PARAM_PROJECT_ID = "projectId"; - static final String PARAM_ID = "id"; - private final QualityGatesWsAction[] actions; public QualityGatesWs(QualityGatesWsAction... actions) { @@ -62,12 +49,12 @@ public class QualityGatesWs implements WebService { static void addConditionParams(NewAction action) { action - .createParam(PARAM_METRIC) + .createParam(QualityGatesWsParameters.PARAM_METRIC) .setDescription("Condition metric") .setRequired(true) .setExampleValue("blocker_violations"); - action.createParam(PARAM_OPERATOR) + action.createParam(QualityGatesWsParameters.PARAM_OPERATOR) .setDescription("Condition operator:
" + "
    " + "
  • EQ = equals
  • " + @@ -78,15 +65,15 @@ public class QualityGatesWs implements WebService { .setExampleValue(QualityGateConditionDto.OPERATOR_EQUALS) .setPossibleValues(QualityGateConditionDto.ALL_OPERATORS); - action.createParam(PARAM_PERIOD) + action.createParam(QualityGatesWsParameters.PARAM_PERIOD) .setDescription("Condition period. If not set, the absolute value is considered.") .setPossibleValues("1"); - action.createParam(PARAM_WARNING) + action.createParam(QualityGatesWsParameters.PARAM_WARNING) .setDescription("Condition warning threshold") .setExampleValue("5"); - action.createParam(PARAM_ERROR) + action.createParam(QualityGatesWsParameters.PARAM_ERROR) .setDescription("Condition error threshold") .setExampleValue("10"); } @@ -101,24 +88,24 @@ public class QualityGatesWs implements WebService { static JsonWriter writeQualityGate(QualityGateDto qualityGate, JsonWriter writer) { return writer.beginObject() - .prop(PARAM_ID, qualityGate.getId()) - .prop(PARAM_NAME, qualityGate.getName()) + .prop(QualityGatesWsParameters.PARAM_ID, qualityGate.getId()) + .prop(QualityGatesWsParameters.PARAM_NAME, qualityGate.getName()) .endObject(); } static JsonWriter writeQualityGateCondition(QualityGateConditionDto condition, JsonWriter writer) { writer.beginObject() - .prop(PARAM_ID, condition.getId()) - .prop(PARAM_METRIC, condition.getMetricKey()) - .prop(PARAM_OPERATOR, condition.getOperator()); + .prop(QualityGatesWsParameters.PARAM_ID, condition.getId()) + .prop(QualityGatesWsParameters.PARAM_METRIC, condition.getMetricKey()) + .prop(QualityGatesWsParameters.PARAM_OPERATOR, condition.getOperator()); if (condition.getWarningThreshold() != null) { - writer.prop(PARAM_WARNING, condition.getWarningThreshold()); + writer.prop(QualityGatesWsParameters.PARAM_WARNING, condition.getWarningThreshold()); } if (condition.getErrorThreshold() != null) { - writer.prop(PARAM_ERROR, condition.getErrorThreshold()); + writer.prop(QualityGatesWsParameters.PARAM_ERROR, condition.getErrorThreshold()); } if (condition.getPeriod() != null) { - writer.prop(PARAM_PERIOD, condition.getPeriod()); + writer.prop(QualityGatesWsParameters.PARAM_PERIOD, condition.getPeriod()); } writer.endObject(); return writer; diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/RenameAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/RenameAction.java index ca685d7fb61..af0231d6e90 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/RenameAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/RenameAction.java @@ -25,6 +25,7 @@ import org.sonar.api.server.ws.WebService; import org.sonar.api.utils.text.JsonWriter; import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.server.qualitygate.QualityGates; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; public class RenameAction implements QualityGatesWsAction { @@ -42,12 +43,12 @@ public class RenameAction implements QualityGatesWsAction { .setPost(true) .setHandler(this); - action.createParam(QualityGatesWs.PARAM_ID) + action.createParam(QualityGatesWsParameters.PARAM_ID) .setDescription("ID of the quality gate to rename") .setRequired(true) .setExampleValue("1"); - action.createParam(QualityGatesWs.PARAM_NAME) + action.createParam(QualityGatesWsParameters.PARAM_NAME) .setDescription("New name of the quality gate") .setRequired(true) .setExampleValue("My Quality Gate"); @@ -55,8 +56,8 @@ public class RenameAction implements QualityGatesWsAction { @Override public void handle(Request request, Response response) { - long idToRename = QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID); - QualityGateDto renamedQualityGate = qualityGates.rename(idToRename, request.mandatoryParam(QualityGatesWs.PARAM_NAME)); + long idToRename = QualityGatesWs.parseId(request, QualityGatesWsParameters.PARAM_ID); + QualityGateDto renamedQualityGate = qualityGates.rename(idToRename, request.mandatoryParam(QualityGatesWsParameters.PARAM_NAME)); JsonWriter writer = response.newJsonWriter(); QualityGatesWs.writeQualityGate(renamedQualityGate, writer).close(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SearchAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SearchAction.java index 8f57e3bf59d..cfdc0004ad5 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SearchAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SearchAction.java @@ -28,6 +28,7 @@ import org.sonar.api.utils.text.JsonWriter; import org.sonar.db.qualitygate.ProjectQgateAssociation; import org.sonar.db.qualitygate.ProjectQgateAssociationQuery; import org.sonar.server.qualitygate.QgateProjectFinder; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; public class SearchAction implements QualityGatesWsAction { @@ -46,23 +47,23 @@ public class SearchAction implements QualityGatesWsAction { .setResponseExample(Resources.getResource(this.getClass(), "example-search.json")) .setHandler(this); - action.createParam(QualityGatesWs.PARAM_GATE_ID) + action.createParam(QualityGatesWsParameters.PARAM_GATE_ID) .setDescription("Quality Gate ID") .setRequired(true) .setExampleValue("1"); - action.createParam(QualityGatesWs.PARAM_QUERY) + action.createParam(QualityGatesWsParameters.PARAM_QUERY) .setDescription("To search for projects containing this string. If this parameter is set, \"selected\" is set to \"all\".") .setExampleValue("abc"); action.addSelectionModeParam(); - action.createParam(QualityGatesWs.PARAM_PAGE) + action.createParam(QualityGatesWsParameters.PARAM_PAGE) .setDescription("Page number") .setDefaultValue("1") .setExampleValue("2"); - action.createParam(QualityGatesWs.PARAM_PAGE_SIZE) + action.createParam(QualityGatesWsParameters.PARAM_PAGE_SIZE) .setDescription("Page size") .setExampleValue("10"); } @@ -70,11 +71,11 @@ public class SearchAction implements QualityGatesWsAction { @Override public void handle(Request request, Response response) { QgateProjectFinder.Association associations = projectFinder.find(ProjectQgateAssociationQuery.builder() - .gateId(request.mandatoryParam(QualityGatesWs.PARAM_GATE_ID)) - .membership(request.param(QualityGatesWs.PARAM_QUERY) == null ? request.param(Param.SELECTED) : ProjectQgateAssociationQuery.ANY) - .projectSearch(request.param(QualityGatesWs.PARAM_QUERY)) - .pageIndex(request.paramAsInt(QualityGatesWs.PARAM_PAGE)) - .pageSize(request.paramAsInt(QualityGatesWs.PARAM_PAGE_SIZE)) + .gateId(request.mandatoryParam(QualityGatesWsParameters.PARAM_GATE_ID)) + .membership(request.param(QualityGatesWsParameters.PARAM_QUERY) == null ? request.param(Param.SELECTED) : ProjectQgateAssociationQuery.ANY) + .projectSearch(request.param(QualityGatesWsParameters.PARAM_QUERY)) + .pageIndex(request.paramAsInt(QualityGatesWsParameters.PARAM_PAGE)) + .pageSize(request.paramAsInt(QualityGatesWsParameters.PARAM_PAGE_SIZE)) .build()); JsonWriter writer = response.newJsonWriter(); writer.beginObject().prop("more", associations.hasMoreResults()); diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java index 4afdc7ae8c5..8f55ba0d85e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java @@ -23,6 +23,9 @@ import org.sonar.api.server.ws.Request; import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.WebService; import org.sonar.server.qualitygate.QualityGates; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; + +import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_PROJECT_ID; public class SelectAction implements QualityGatesWsAction { @@ -40,12 +43,12 @@ public class SelectAction implements QualityGatesWsAction { .setSince("4.3") .setHandler(this); - action.createParam(QualityGatesWs.PARAM_GATE_ID) + action.createParam(QualityGatesWsParameters.PARAM_GATE_ID) .setDescription("Quality Gate ID") .setRequired(true) .setExampleValue("1"); - action.createParam(QualityGatesWs.PARAM_PROJECT_ID) + action.createParam(PARAM_PROJECT_ID) .setDescription("Project ID") .setRequired(true) .setExampleValue("12"); @@ -53,7 +56,7 @@ public class SelectAction implements QualityGatesWsAction { @Override public void handle(Request request, Response response) { - qualityGates.associateProject(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_GATE_ID), QualityGatesWs.parseId(request, QualityGatesWs.PARAM_PROJECT_ID)); + qualityGates.associateProject(QualityGatesWs.parseId(request, QualityGatesWsParameters.PARAM_GATE_ID), QualityGatesWs.parseId(request, PARAM_PROJECT_ID)); response.noContent(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SetAsDefaultAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SetAsDefaultAction.java index 38990131f9b..b9edc97e1e0 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SetAsDefaultAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SetAsDefaultAction.java @@ -23,6 +23,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.server.qualitygate.QualityGates; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; public class SetAsDefaultAction implements QualityGatesWsAction { @@ -40,7 +41,7 @@ public class SetAsDefaultAction implements QualityGatesWsAction { .setPost(true) .setHandler(this); - action.createParam(QualityGatesWs.PARAM_ID) + action.createParam(QualityGatesWsParameters.PARAM_ID) .setDescription("ID of the quality gate to set as default") .setRequired(true) .setExampleValue("1"); @@ -48,7 +49,7 @@ public class SetAsDefaultAction implements QualityGatesWsAction { @Override public void handle(Request request, Response response) { - qualityGates.setDefault(QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID)); + qualityGates.setDefault(QualityGatesWs.parseId(request, QualityGatesWsParameters.PARAM_ID)); response.noContent(); } diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ShowAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ShowAction.java index cb447eb653c..0709867d1f2 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ShowAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ShowAction.java @@ -30,6 +30,7 @@ import org.sonar.db.qualitygate.QualityGateConditionDto; import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.server.exceptions.BadRequestException; import org.sonar.server.qualitygate.QualityGates; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; public class ShowAction implements QualityGatesWsAction { @@ -47,27 +48,27 @@ public class ShowAction implements QualityGatesWsAction { .setResponseExample(Resources.getResource(this.getClass(), "example-show.json")) .setHandler(this); - action.createParam(QualityGatesWs.PARAM_ID) + action.createParam(QualityGatesWsParameters.PARAM_ID) .setDescription("ID of the quality gate. Either id or name must be set") .setExampleValue("1"); - action.createParam(QualityGatesWs.PARAM_NAME) + action.createParam(QualityGatesWsParameters.PARAM_NAME) .setDescription("Name of the quality gate. Either id or name must be set") .setExampleValue("My Quality Gate"); } @Override public void handle(Request request, Response response) { - Long qGateId = request.paramAsLong(QualityGatesWs.PARAM_ID); - String qGateName = request.param(QualityGatesWs.PARAM_NAME); + Long qGateId = request.paramAsLong(QualityGatesWsParameters.PARAM_ID); + String qGateName = request.param(QualityGatesWsParameters.PARAM_NAME); checkOneOfIdOrNamePresent(qGateId, qGateName); QualityGateDto qGate = qGateId == null ? qualityGates.get(qGateName) : qualityGates.get(qGateId); qGateId = qGate.getId(); JsonWriter writer = response.newJsonWriter().beginObject() - .prop(QualityGatesWs.PARAM_ID, qGate.getId()) - .prop(QualityGatesWs.PARAM_NAME, qGate.getName()); + .prop(QualityGatesWsParameters.PARAM_ID, qGate.getId()) + .prop(QualityGatesWsParameters.PARAM_NAME, qGate.getName()); Collection conditions = qualityGates.listConditions(qGateId); if (!conditions.isEmpty()) { writer.name("conditions").beginArray(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UnsetDefaultAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UnsetDefaultAction.java index 29e905000ba..5945255045b 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UnsetDefaultAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UnsetDefaultAction.java @@ -23,6 +23,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.server.qualitygate.QualityGates; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; public class UnsetDefaultAction implements QualityGatesWsAction { @@ -40,7 +41,7 @@ public class UnsetDefaultAction implements QualityGatesWsAction { .setPost(true) .setHandler(this); - action.createParam(QualityGatesWs.PARAM_ID) + action.createParam(QualityGatesWsParameters.PARAM_ID) .setDescription("ID of the quality gate to unset as default") .setRequired(true) .setExampleValue("1"); diff --git a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UpdateConditionAction.java b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UpdateConditionAction.java index 111d68fc5ce..1c9f637a59e 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UpdateConditionAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UpdateConditionAction.java @@ -23,6 +23,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.server.qualitygate.QualityGates; +import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters; public class UpdateConditionAction implements QualityGatesWsAction { @@ -41,7 +42,7 @@ public class UpdateConditionAction implements QualityGatesWsAction { .setHandler(this); createCondition - .createParam(QualityGatesWs.PARAM_ID) + .createParam(QualityGatesWsParameters.PARAM_ID) .setDescription("Condition ID") .setRequired(true) .setExampleValue("10"); @@ -53,12 +54,12 @@ public class UpdateConditionAction implements QualityGatesWsAction { public void handle(Request request, Response response) { QualityGatesWs.writeQualityGateCondition( qualityGates.updateCondition( - QualityGatesWs.parseId(request, QualityGatesWs.PARAM_ID), - request.mandatoryParam(QualityGatesWs.PARAM_METRIC), - request.mandatoryParam(QualityGatesWs.PARAM_OPERATOR), - request.param(QualityGatesWs.PARAM_WARNING), - request.param(QualityGatesWs.PARAM_ERROR), - request.paramAsInt(QualityGatesWs.PARAM_PERIOD) + QualityGatesWs.parseId(request, QualityGatesWsParameters.PARAM_ID), + request.mandatoryParam(QualityGatesWsParameters.PARAM_METRIC), + request.mandatoryParam(QualityGatesWsParameters.PARAM_OPERATOR), + request.param(QualityGatesWsParameters.PARAM_WARNING), + request.param(QualityGatesWsParameters.PARAM_ERROR), + request.paramAsInt(QualityGatesWsParameters.PARAM_PERIOD) ), response.newJsonWriter() ).close(); } diff --git a/server/sonar-server/src/main/resources/org/sonar/server/qualitygate/ws/get_by_project-example.json b/server/sonar-server/src/main/resources/org/sonar/server/qualitygate/ws/get_by_project-example.json new file mode 100644 index 00000000000..3cf49b85ded --- /dev/null +++ b/server/sonar-server/src/main/resources/org/sonar/server/qualitygate/ws/get_by_project-example.json @@ -0,0 +1,7 @@ +{ + "qualityGate": { + "id": "23", + "name": "My team QG", + "default": false + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QgateProjectFinderTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QgateProjectFinderTest.java index 66360314728..a35f3b095f8 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QgateProjectFinderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QgateProjectFinderTest.java @@ -83,7 +83,7 @@ public class QgateProjectFinderTest { dbClient.userDao().insert(dbSession, userDto); qGate = new QualityGateDto().setName("Default Quality Gate"); - dbClient.qualityGateDao().insert(qGate, dbSession); + dbClient.qualityGateDao().insert(dbSession, qGate); dbTester.commit(); } diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGateModuleTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGateModuleTest.java new file mode 100644 index 00000000000..0ea94b7f023 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGateModuleTest.java @@ -0,0 +1,35 @@ +/* + * 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.qualitygate; + +import org.junit.Test; +import org.sonar.core.platform.ComponentContainer; + +import static org.assertj.core.api.Assertions.assertThat; + +public class QualityGateModuleTest { + @Test + public void verify_count_of_added_components() { + ComponentContainer container = new ComponentContainer(); + new QualityGateModule().configure(container); + assertThat(container.size()).isEqualTo(20 + 2); + } +} diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java index 56f401ab687..ec9af1871e2 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java @@ -19,18 +19,6 @@ */ package org.sonar.server.qualitygate; -import static java.util.Arrays.asList; -import static java.util.Collections.singletonList; -import static org.assertj.core.api.Assertions.assertThat; -import static org.mockito.Matchers.any; -import static org.mockito.Matchers.anyLong; -import static org.mockito.Matchers.anyString; -import static org.mockito.Matchers.eq; -import static org.mockito.Mockito.mock; -import static org.mockito.Mockito.times; -import static org.mockito.Mockito.verify; -import static org.mockito.Mockito.when; - import com.google.common.collect.ImmutableList; import com.google.common.collect.Lists; import java.util.Collection; @@ -44,11 +32,8 @@ import org.junit.Test; import org.junit.rules.ExpectedException; import org.junit.runner.RunWith; import org.mockito.ArgumentCaptor; -import org.mockito.Mock; import org.mockito.Mockito; -import org.mockito.invocation.InvocationOnMock; import org.mockito.runners.MockitoJUnitRunner; -import org.mockito.stubbing.Answer; import org.sonar.api.config.Settings; import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.Metric; @@ -56,8 +41,8 @@ import org.sonar.api.measures.Metric.ValueType; import org.sonar.api.measures.MetricFinder; import org.sonar.api.web.UserRole; import org.sonar.core.permission.GlobalPermissions; +import org.sonar.db.DbClient; import org.sonar.db.DbSession; -import org.sonar.db.MyBatis; import org.sonar.db.component.ComponentDao; import org.sonar.db.component.ComponentDto; import org.sonar.db.property.PropertiesDao; @@ -74,6 +59,18 @@ import org.sonar.server.tester.MockUserSession; import org.sonar.server.tester.UserSessionRule; import org.sonar.server.user.UserSession; +import static java.util.Arrays.asList; +import static java.util.Collections.singletonList; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Matchers.any; +import static org.mockito.Matchers.anyLong; +import static org.mockito.Matchers.anyString; +import static org.mockito.Matchers.eq; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.times; +import static org.mockito.Mockito.verify; +import static org.mockito.Mockito.when; + @RunWith(MockitoJUnitRunner.class) public class QualityGatesTest { @@ -82,31 +79,16 @@ public class QualityGatesTest { @Rule public ExpectedException expectedException = ExpectedException.none(); - @Rule public UserSessionRule userSessionRule = UserSessionRule.standalone(); - @Mock - DbSession session; - - @Mock - QualityGateDao dao; - - @Mock - QualityGateConditionDao conditionDao; - - @Mock - MetricFinder metricFinder; - - @Mock - PropertiesDao propertiesDao; - - @Mock - ComponentDao componentDao; - - @Mock - MyBatis myBatis; - + DbSession dbSession = mock(DbSession.class); + DbClient dbClient = mock(DbClient.class); + QualityGateDao dao = mock(QualityGateDao.class); + QualityGateConditionDao conditionDao = mock(QualityGateConditionDao.class); + PropertiesDao propertiesDao = mock(PropertiesDao.class); + ComponentDao componentDao = mock(ComponentDao.class); + MetricFinder metricFinder = mock(MetricFinder.class); Settings settings = new Settings(); QualityGates underTest; @@ -122,10 +104,15 @@ public class QualityGatesTest { public void initialize() { settings.clear(); - when(componentDao.selectOrFailById(eq(session), anyLong())).thenReturn(new ComponentDto().setId(1L).setKey(PROJECT_KEY)); + when(dbClient.openSession(false)).thenReturn(dbSession); + when(dbClient.qualityGateDao()).thenReturn(dao); + when(dbClient.gateConditionDao()).thenReturn(conditionDao); + when(dbClient.propertiesDao()).thenReturn(propertiesDao); + when(dbClient.componentDao()).thenReturn(componentDao); + + when(componentDao.selectOrFailById(eq(dbSession), anyLong())).thenReturn(new ComponentDto().setId(1L).setKey(PROJECT_KEY)); - when(myBatis.openSession(false)).thenReturn(session); - underTest = new QualityGates(dao, conditionDao, metricFinder, propertiesDao, componentDao, myBatis, userSessionRule, settings); + underTest = new QualityGates(dbClient, metricFinder, userSessionRule, settings); userSessionRule.set(authorizedProfileAdminUserSession); } @@ -270,12 +257,11 @@ public class QualityGatesTest { String name = "To Delete"; QualityGateDto toDelete = new QualityGateDto().setId(idToDelete).setName(name); when(dao.selectById(idToDelete)).thenReturn(toDelete); - DbSession session = mock(DbSession.class); - when(myBatis.openSession(false)).thenReturn(session); + when(dbClient.openSession(false)).thenReturn(dbSession); underTest.delete(idToDelete); verify(dao).selectById(idToDelete); - verify(propertiesDao).deleteProjectProperties("sonar.qualitygate", "42", session); - verify(dao).delete(toDelete, session); + verify(propertiesDao).deleteProjectProperties("sonar.qualitygate", "42", dbSession); + verify(dao).delete(toDelete, dbSession); } @Test @@ -285,12 +271,11 @@ public class QualityGatesTest { QualityGateDto toDelete = new QualityGateDto().setId(idToDelete).setName(name); when(dao.selectById(idToDelete)).thenReturn(toDelete); when(propertiesDao.selectGlobalProperty("sonar.qualitygate")).thenReturn(new PropertyDto().setValue("666")); - DbSession session = mock(DbSession.class); - when(myBatis.openSession(false)).thenReturn(session); + when(dbClient.openSession(false)).thenReturn(dbSession); underTest.delete(idToDelete); verify(dao).selectById(idToDelete); - verify(propertiesDao).deleteProjectProperties("sonar.qualitygate", "42", session); - verify(dao).delete(toDelete, session); + verify(propertiesDao).deleteProjectProperties("sonar.qualitygate", "42", dbSession); + verify(dao).delete(toDelete, dbSession); } @Test @@ -300,13 +285,12 @@ public class QualityGatesTest { QualityGateDto toDelete = new QualityGateDto().setId(idToDelete).setName(name); when(dao.selectById(idToDelete)).thenReturn(toDelete); when(propertiesDao.selectGlobalProperty("sonar.qualitygate")).thenReturn(new PropertyDto().setValue("42")); - DbSession session = mock(DbSession.class); - when(myBatis.openSession(false)).thenReturn(session); + when(dbClient.openSession(false)).thenReturn(dbSession); underTest.delete(idToDelete); verify(dao).selectById(idToDelete); - verify(propertiesDao).deleteGlobalProperty("sonar.qualitygate", session); - verify(propertiesDao).deleteProjectProperties("sonar.qualitygate", "42", session); - verify(dao).delete(toDelete, session); + verify(propertiesDao).deleteGlobalProperty("sonar.qualitygate", dbSession); + verify(propertiesDao).deleteProjectProperties("sonar.qualitygate", "42", dbSession); + verify(dao).delete(toDelete, dbSession); } @Test @@ -637,22 +621,17 @@ public class QualityGatesTest { Collection conditions = ImmutableList.of(cond1, cond2); when(dao.selectById(sourceId)).thenReturn(new QualityGateDto().setId(sourceId).setName("SG-1")); - DbSession session = mock(DbSession.class); - when(myBatis.openSession(false)).thenReturn(session); - Mockito.doAnswer(new Answer() { - @Override - public Object answer(InvocationOnMock invocation) throws Throwable { - ((QualityGateDto) invocation.getArguments()[0]).setId(destId); - return null; - } - }).when(dao).insert(any(QualityGateDto.class), eq(session)); - when(conditionDao.selectForQualityGate(anyLong(), eq(session))).thenReturn(conditions); + Mockito.doAnswer(invocation -> { + ((QualityGateDto) invocation.getArguments()[1]).setId(destId); + return null; + }).when(dao).insert(eq(dbSession), any(QualityGateDto.class)); + when(conditionDao.selectForQualityGate(anyLong(), eq(dbSession))).thenReturn(conditions); QualityGateDto atlantis = underTest.copy(sourceId, name); assertThat(atlantis.getName()).isEqualTo(name); verify(dao).selectByName(name); - verify(dao).insert(atlantis, session); - verify(conditionDao).selectForQualityGate(anyLong(), eq(session)); - verify(conditionDao, times(conditions.size())).insert(any(QualityGateConditionDto.class), eq(session)); + verify(dao).insert(dbSession, atlantis); + verify(conditionDao).selectForQualityGate(anyLong(), eq(dbSession)); + verify(conditionDao, times(conditions.size())).insert(any(QualityGateConditionDto.class), eq(dbSession)); } @Test diff --git a/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/GetByProjectActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/GetByProjectActionTest.java new file mode 100644 index 00000000000..17c1b684a15 --- /dev/null +++ b/server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/GetByProjectActionTest.java @@ -0,0 +1,245 @@ +/* + * 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.qualitygate.ws; + +import java.io.IOException; +import java.io.InputStream; +import javax.annotation.Nullable; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.sonar.api.config.Settings; +import org.sonar.api.measures.MetricFinder; +import org.sonar.api.utils.System2; +import org.sonar.api.web.UserRole; +import org.sonar.core.permission.GlobalPermissions; +import org.sonar.db.DbClient; +import org.sonar.db.DbSession; +import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDbTester; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.property.PropertyDto; +import org.sonar.db.qualitygate.QualityGateDto; +import org.sonar.server.component.ComponentFinder; +import org.sonar.server.exceptions.ForbiddenException; +import org.sonar.server.exceptions.NotFoundException; +import org.sonar.server.qualitygate.QualityGates; +import org.sonar.server.tester.UserSessionRule; +import org.sonar.server.user.UserSession; +import org.sonar.server.ws.TestRequest; +import org.sonar.server.ws.WsActionTester; +import org.sonarqube.ws.MediaTypes; +import org.sonarqube.ws.WsQualityGates; +import org.sonarqube.ws.WsQualityGates.GetByProjectWsResponse; + +import static com.google.common.base.Throwables.propagate; +import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.sonar.db.component.ComponentTesting.newProjectDto; +import static org.sonar.test.JsonAssert.assertJson; +import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_PROJECT_ID; +import static org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters.PARAM_PROJECT_KEY; + +public class GetByProjectActionTest { + @Rule + public UserSessionRule userSession = UserSessionRule.standalone().setGlobalPermissions(GlobalPermissions.SYSTEM_ADMIN); + @Rule + public ExpectedException expectedException = ExpectedException.none(); + @Rule + public DbTester db = DbTester.create(System2.INSTANCE); + ComponentDbTester componentDb = new ComponentDbTester(db); + DbClient dbClient = db.getDbClient(); + DbSession dbSession = db.getSession(); + + private WsActionTester ws = new WsActionTester( + new GetByProjectAction(userSession, dbClient, new ComponentFinder(dbClient), + new QualityGates(dbClient, mock(MetricFinder.class), mock(UserSession.class), mock(Settings.class)))); + + @Test + public void json_example() { + ComponentDto project = componentDb.insertComponent(newProjectDto()); + QualityGateDto qualityGate = insertQualityGate("My team QG"); + associateProjectToQualityGate(project.getId(), qualityGate.getId()); + + String result = ws.newRequest().setParam(PARAM_PROJECT_ID, project.uuid()).execute().getInput(); + + assertJson(result) + .ignoreFields("id") + .isSimilarTo(getClass().getResource("get_by_project-example.json")); + } + + @Test + public void empty_response() { + ComponentDto project = componentDb.insertComponent(newProjectDto()); + insertQualityGate("Another QG"); + + String result = ws.newRequest().setParam(PARAM_PROJECT_ID, project.uuid()).execute().getInput(); + + assertThat(result).isEqualToIgnoringWhitespace("{}"); + } + + @Test + public void default_quality_gate() { + ComponentDto project = componentDb.insertComponent(newProjectDto()); + QualityGateDto dbQualityGate = insertQualityGate("Sonar way"); + setDefaultQualityGate(dbQualityGate.getId()); + + GetByProjectWsResponse result = callByUuid(project.uuid()); + + WsQualityGates.QualityGate qualityGate = result.getQualityGate(); + assertThat(Long.valueOf(qualityGate.getId())).isEqualTo(dbQualityGate.getId()); + assertThat(qualityGate.getName()).isEqualTo(dbQualityGate.getName()); + assertThat(qualityGate.getDefault()).isTrue(); + } + + @Test + public void project_quality_gate_over_default() { + ComponentDto project = componentDb.insertComponent(newProjectDto()); + QualityGateDto defaultDbQualityGate = insertQualityGate("Sonar way"); + QualityGateDto dbQualityGate = insertQualityGate("My team QG"); + setDefaultQualityGate(defaultDbQualityGate.getId()); + associateProjectToQualityGate(project.getId(), dbQualityGate.getId()); + + GetByProjectWsResponse result = callByUuid(project.uuid()); + + WsQualityGates.QualityGate qualityGate = result.getQualityGate(); + assertThat(qualityGate.getName()).isEqualTo(dbQualityGate.getName()); + assertThat(qualityGate.getDefault()).isFalse(); + } + + @Test + public void get_by_project_key() { + ComponentDto project = componentDb.insertComponent(newProjectDto()); + QualityGateDto dbQualityGate = insertQualityGate("My team QG"); + associateProjectToQualityGate(project.getId(), dbQualityGate.getId()); + + GetByProjectWsResponse result = callByKey(project.key()); + + assertThat(result.getQualityGate().getName()).isEqualTo(dbQualityGate.getName()); + } + + @Test + public void get_with_project_admin_permission() { + ComponentDto project = componentDb.insertComponent(newProjectDto()); + userSession.anonymous().addProjectUuidPermissions(UserRole.USER, project.uuid()); + QualityGateDto dbQualityGate = insertQualityGate("Sonar way"); + setDefaultQualityGate(dbQualityGate.getId()); + + GetByProjectWsResponse result = callByUuid(project.uuid()); + + assertThat(result.getQualityGate().getName()).isEqualTo(dbQualityGate.getName()); + } + + @Test + public void get_with_project_browse_permission() { + ComponentDto project = componentDb.insertComponent(newProjectDto()); + userSession.anonymous().addProjectUuidPermissions(UserRole.ADMIN, project.uuid()); + QualityGateDto dbQualityGate = insertQualityGate("Sonar way"); + setDefaultQualityGate(dbQualityGate.getId()); + + GetByProjectWsResponse result = callByUuid(project.uuid()); + + assertThat(result.getQualityGate().getName()).isEqualTo(dbQualityGate.getName()); + } + + @Test + public void fail_when_insufficient_permission() { + expectedException.expect(ForbiddenException.class); + + ComponentDto project = componentDb.insertComponent(newProjectDto()); + userSession.anonymous().setGlobalPermissions(GlobalPermissions.SCAN_EXECUTION); + QualityGateDto dbQualityGate = insertQualityGate("Sonar way"); + setDefaultQualityGate(dbQualityGate.getId()); + + callByUuid(project.uuid()); + } + + @Test + public void fail_when_project_does_not_exist() { + expectedException.expect(NotFoundException.class); + + callByUuid("Unknown"); + } + + @Test + public void fail_when_no_parameter() { + expectedException.expect(IllegalArgumentException.class); + + call(null, null); + } + + @Test + public void fail_when_project_uuid_and_key_provided() { + expectedException.expect(IllegalArgumentException.class); + + call("uuid", "key"); + } + + private GetByProjectWsResponse callByUuid(String projectUuid) { + return call(projectUuid, null); + } + + private GetByProjectWsResponse callByKey(String projectKey) { + return call(null, projectKey); + } + + private GetByProjectWsResponse call(@Nullable String projectUuid, @Nullable String projectKey) { + TestRequest request = ws.newRequest() + .setMediaType(MediaTypes.PROTOBUF); + + if (projectUuid != null) { + request.setParam(PARAM_PROJECT_ID, projectUuid); + } + + if (projectKey != null) { + request.setParam(PARAM_PROJECT_KEY, projectKey); + } + + InputStream response = request.execute().getInputStream(); + + try { + return GetByProjectWsResponse.parseFrom(response); + } catch (IOException e) { + throw propagate(e); + } + } + + private QualityGateDto insertQualityGate(String name) { + QualityGateDto qualityGate = dbClient.qualityGateDao().insert(dbSession, new QualityGateDto().setName(name)); + db.commit(); + return qualityGate; + } + + private void associateProjectToQualityGate(long componentId, long qualityGateId) { + dbClient.propertiesDao().insertProperty(dbSession, new PropertyDto() + .setKey("sonar.qualitygate") + .setResourceId(componentId) + .setValue(String.valueOf(qualityGateId))); + db.commit(); + } + + private void setDefaultQualityGate(long qualityGateId) { + dbClient.propertiesDao().insertProperty(dbSession, new PropertyDto() + .setKey("sonar.qualitygate") + .setValue(String.valueOf(qualityGateId))); + db.commit(); + } +} diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java index c984fbe315c..74544f980ec 100644 --- a/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java @@ -20,6 +20,7 @@ package org.sonar.db.qualitygate; import java.util.List; +import java.util.Optional; import org.apache.ibatis.session.SqlSession; import org.sonar.db.Dao; import org.sonar.db.DbSession; @@ -30,6 +31,16 @@ public class ProjectQgateAssociationDao implements Dao { return mapper(dbSession).selectProjects(query); } + /** + * @return quality gate id if a specific Quality Gate has been defined for the given component id.
    + * Returns {@link Optional#empty()} otherwise (ex: default quality gate applies) + */ + public Optional selectQGateIdByComponentId(DbSession dbSession, long componentId) { + String id = mapper(dbSession).selectQGateIdByComponentId(componentId); + + return id == null ? Optional.empty() : Optional.of(Long.valueOf(id)); + } + private static ProjectQgateAssociationMapper mapper(SqlSession session) { return session.getMapper(ProjectQgateAssociationMapper.class); } diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java index 5b9d9462d2a..c4d058c69f7 100644 --- a/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java @@ -20,10 +20,13 @@ package org.sonar.db.qualitygate; import java.util.List; +import javax.annotation.CheckForNull; import org.apache.ibatis.annotations.Param; public interface ProjectQgateAssociationMapper { List selectProjects(@Param("query") ProjectQgateAssociationQuery query); + @CheckForNull + String selectQGateIdByComponentId(long componentId); } diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java index 41cc46124ce..49982d7ed20 100644 --- a/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java @@ -24,6 +24,7 @@ import java.util.Date; import javax.annotation.CheckForNull; import org.apache.ibatis.session.SqlSession; import org.sonar.db.Dao; +import org.sonar.db.DbSession; import org.sonar.db.MyBatis; public class QualityGateDao implements Dao{ @@ -35,17 +36,19 @@ public class QualityGateDao implements Dao{ } public void insert(QualityGateDto newQualityGate) { - SqlSession session = myBatis.openSession(false); + DbSession session = myBatis.openSession(false); try { - insert(newQualityGate, session); + insert(session, newQualityGate); session.commit(); } finally { MyBatis.closeQuietly(session); } } - public void insert(QualityGateDto newQualityGate, SqlSession session) { + public QualityGateDto insert(DbSession session, QualityGateDto newQualityGate) { mapper(session).insert(newQualityGate.setCreatedAt(new Date())); + + return newQualityGate; } public Collection selectAll() { diff --git a/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java index 9a1d8e60720..f7fa21e4d0c 100644 --- a/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java +++ b/sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java @@ -42,7 +42,7 @@ import java.util.List; */ public interface QualityGateMapper { - void insert(QualityGateDto newQualityGate); + void insert(QualityGateDto qualityGate); List selectAll(); diff --git a/sonar-db/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml b/sonar-db/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml index fe6683b58db..01203faf49a 100644 --- a/sonar-db/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml +++ b/sonar-db/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml @@ -32,4 +32,13 @@ ORDER BY proj.name + + diff --git a/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java b/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java index fbf6e2812b0..5673fe776a3 100644 --- a/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java +++ b/sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java @@ -20,61 +20,67 @@ package org.sonar.db.qualitygate; import java.util.List; +import java.util.Optional; import org.junit.Rule; import org.junit.Test; import org.sonar.api.utils.System2; +import org.sonar.db.DbClient; import org.sonar.db.DbSession; import org.sonar.db.DbTester; +import org.sonar.db.component.ComponentDbTester; +import org.sonar.db.component.ComponentDto; +import org.sonar.db.property.PropertyDto; import static org.assertj.core.api.Assertions.assertThat; - +import static org.sonar.db.component.ComponentTesting.newProjectDto; public class ProjectQgateAssociationDaoTest { @Rule - public DbTester dbTester = DbTester.create(System2.INSTANCE); - - DbSession dbSession = dbTester.getSession(); + public DbTester db = DbTester.create(System2.INSTANCE); + ComponentDbTester componentDb = new ComponentDbTester(db); + DbClient dbClient = db.getDbClient(); + DbSession dbSession = db.getSession(); - ProjectQgateAssociationDao dao = dbTester.getDbClient().projectQgateAssociationDao(); + ProjectQgateAssociationDao underTest = db.getDbClient().projectQgateAssociationDao(); @Test public void select_all_projects_by_query() { - dbTester.prepareDbUnit(getClass(), "shared.xml"); + db.prepareDbUnit(getClass(), "shared.xml"); ProjectQgateAssociationQuery query = ProjectQgateAssociationQuery.builder().gateId("42").build(); - List result = dao.selectProjects(dbSession, query); + List result = underTest.selectProjects(dbSession, query); assertThat(result).hasSize(5); } @Test public void select_projects_by_query() { - dbTester.prepareDbUnit(getClass(), "shared.xml"); + db.prepareDbUnit(getClass(), "shared.xml"); - assertThat(dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.IN).build())).hasSize(3); - assertThat(dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.OUT).build())).hasSize(2); + assertThat(underTest.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.IN).build())).hasSize(3); + assertThat(underTest.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").membership(ProjectQgateAssociationQuery.OUT).build())).hasSize(2); } @Test public void search_by_project_name() { - dbTester.prepareDbUnit(getClass(), "shared.xml"); + db.prepareDbUnit(getClass(), "shared.xml"); - List result = dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build()); + List result = underTest.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build()); assertThat(result).hasSize(1); assertThat(result.get(0).getName()).isEqualTo("Project One"); - result = dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build()); + result = underTest.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build()); assertThat(result).hasSize(1); - result = dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("project").build()); + result = underTest.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("project").build()); assertThat(result).hasSize(2); } @Test public void should_be_sorted_by_project_name() { - dbTester.prepareDbUnit(getClass(), "shared.xml"); + db.prepareDbUnit(getClass(), "shared.xml"); - List result = dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").build()); + List result = underTest.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").build()); assertThat(result).hasSize(5); assertThat(result.get(0).getName()).isEqualTo("Project Five"); assertThat(result.get(1).getName()).isEqualTo("Project Four"); @@ -82,4 +88,31 @@ public class ProjectQgateAssociationDaoTest { assertThat(result.get(3).getName()).isEqualTo("Project Three"); assertThat(result.get(4).getName()).isEqualTo("Project Two"); } + + @Test + public void select_qgate_id_is_absent() { + ComponentDto project = componentDb.insertComponent(newProjectDto()); + + Optional result = underTest.selectQGateIdByComponentId(dbSession, project.getId()); + + assertThat(result.isPresent()).isFalse(); + } + + @Test + public void select_qgate_id() { + associateProjectToQualityGate(10L, 1L); + associateProjectToQualityGate(11L, 2L); + + Optional result = underTest.selectQGateIdByComponentId(dbSession, 10L); + + assertThat(result).contains(1L); + } + + private void associateProjectToQualityGate(long componentId, long qualityGateId) { + dbClient.propertiesDao().insertProperty(dbSession, new PropertyDto() + .setKey("sonar.qualitygate") + .setResourceId(componentId) + .setValue(String.valueOf(qualityGateId))); + db.commit(); + } } diff --git a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygate/QualityGatesWsParameters.java b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygate/QualityGatesWsParameters.java index 5ba885b3dd3..e01d58e7b70 100644 --- a/sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygate/QualityGatesWsParameters.java +++ b/sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygate/QualityGatesWsParameters.java @@ -24,6 +24,17 @@ public class QualityGatesWsParameters { public static final String PARAM_ANALYSIS_ID = "analysisId"; public static final String PARAM_PROJECT_ID = "projectId"; public static final String PARAM_PROJECT_KEY = "projectKey"; + public static final String PARAM_PAGE_SIZE = "pageSize"; + public static final String PARAM_PAGE = "page"; + public static final String PARAM_QUERY = "query"; + public static final String PARAM_NAME = "name"; + public static final String PARAM_ERROR = "error"; + public static final String PARAM_WARNING = "warning"; + public static final String PARAM_PERIOD = "period"; + public static final String PARAM_OPERATOR = "op"; + public static final String PARAM_METRIC = "metric"; + public static final String PARAM_GATE_ID = "gateId"; + public static final String PARAM_ID = "id"; private QualityGatesWsParameters() { // prevent instantiation diff --git a/sonar-ws/src/main/protobuf/ws-qualitygates.proto b/sonar-ws/src/main/protobuf/ws-qualitygates.proto index 57e867e767d..514a5341a37 100644 --- a/sonar-ws/src/main/protobuf/ws-qualitygates.proto +++ b/sonar-ws/src/main/protobuf/ws-qualitygates.proto @@ -65,3 +65,14 @@ message ProjectStatusWsResponse { NE = 4; } } + +// GET api/qualitygates/get_by_project +message GetByProjectWsResponse { + optional QualityGate qualityGate = 1; +} + +message QualityGate { + optional string id = 1; + optional string name = 2; + optional bool default = 3; +}