]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-7923 Create WS api/qualitygates/get_by_project 1128/head
authorTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Fri, 29 Jul 2016 09:08:56 +0000 (11:08 +0200)
committerTeryk Bellahsene <teryk.bellahsene@sonarsource.com>
Fri, 29 Jul 2016 12:53:13 +0000 (14:53 +0200)
31 files changed:
server/sonar-server/src/main/java/org/sonar/server/platform/platformlevel/PlatformLevel4.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGateModule.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/QualityGates.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CopyAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/CreateConditionAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeleteConditionAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DeselectAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/DestroyAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/GetByProjectAction.java [new file with mode: 0644]
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/QualityGatesWs.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/RenameAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SearchAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SelectAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/SetAsDefaultAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/ShowAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UnsetDefaultAction.java
server/sonar-server/src/main/java/org/sonar/server/qualitygate/ws/UpdateConditionAction.java
server/sonar-server/src/main/resources/org/sonar/server/qualitygate/ws/get_by_project-example.json [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualitygate/QgateProjectFinderTest.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGateModuleTest.java [new file with mode: 0644]
server/sonar-server/src/test/java/org/sonar/server/qualitygate/QualityGatesTest.java
server/sonar-server/src/test/java/org/sonar/server/qualitygate/ws/GetByProjectActionTest.java [new file with mode: 0644]
sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationDao.java
sonar-db/src/main/java/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.java
sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateDao.java
sonar-db/src/main/java/org/sonar/db/qualitygate/QualityGateMapper.java
sonar-db/src/main/resources/org/sonar/db/qualitygate/ProjectQgateAssociationMapper.xml
sonar-db/src/test/java/org/sonar/db/qualitygate/ProjectQgateAssociationDaoTest.java
sonar-ws/src/main/java/org/sonarqube/ws/client/qualitygate/QualityGatesWsParameters.java
sonar-ws/src/main/protobuf/ws-qualitygates.proto

index f64df96c3e82a27b778af16e4a7207a934157ed9..0a41ac2a4a299ecdff9fce0757963cff60cb8518 100644 (file)
@@ -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 (file)
index 0000000..4999167
--- /dev/null
@@ -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);
+  }
+}
index 9925fb6eb5e42d565c919a366397ef730ccb1cd0..786f38ed803ded084dd014ba4da20a35a4124f9d 100644 (file)
@@ -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<Metric> gateMetrics() {
-    return Collections2.filter(metricFinder.findAll(), new Predicate<Metric>() {
-      @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<QualityGateConditionDto> {
-    private final long conditionId;
-
-    private MatchConditionId(long conditionId) {
-      this.conditionId = conditionId;
-    }
-
-    @Override
-    public boolean apply(@Nonnull QualityGateConditionDto input) {
-      return input.getId() != conditionId;
-    }
-  }
-
 }
index 89e77f7998e41fdba83d0e0556aaa76c0f85ace6..21e56bf8e379c22072373dda65e6392ac44e06a6 100644 (file)
@@ -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();
   }
index 5ddc735e02bccd6afa5673b90b57f9bb560a22dd..49b2e837d7cf1226d932baab563c4e293ffa24b5 100644 (file)
@@ -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();
   }
index aa572402040bd2e45d54b4f796349175bb73d0cf..fbaf599cea639e5997e63b93aaaca2e433bbde6d 100644 (file)
@@ -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();
   }
index cd1f94f0f9a94bb64b17c59134f9b5cc9234c382..24510b91298dc36bcd3e0b28a018605d2a9c5412 100644 (file)
@@ -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();
   }
 
index 1f1bfee0a4713017d53fff56d019621094c42bc2..0579676dfcb236ae5ebfcfec2c91b60e966a8102 100644 (file)
@@ -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();
   }
 
index 654a693e7f07f8423e11d0815ee7128aa4c656ee..97e5e60080e60b43aaf7c23873b90447ac15ada6 100644 (file)
@@ -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 (file)
index 0000000..2fbb8d0
--- /dev/null
@@ -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.<br> " +
+        "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<Long> 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<QualityGateDto> qualityGate;
+    private final boolean isDefault;
+
+    private QualityGateData(Optional<QualityGateDto> qualityGate, boolean isDefault) {
+      this.qualityGate = qualityGate;
+      this.isDefault = isDefault;
+    }
+  }
+}
index fc98402788a396216e130b55e19dbfb997910d73..8e103f8e235fbce68b5194c838a5459f50f0a97c 100644 (file)
@@ -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:<br/>" +
         "<ul>" +
         "<li>EQ = equals</li>" +
@@ -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;
index ca685d7fb618ec8bb04fab0cb67ff10257fea669..af0231d6e9081bee4c0eb72aa48513e10ba4817d 100644 (file)
@@ -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();
   }
index 8f57e3bf59d4fdda02945451dad3415166a683ba..cfdc0004ad5bcf522d8a88bff5ef18d5c633a4d2 100644 (file)
@@ -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());
index 4afdc7ae8c586bb8dc7b62e732aaf8022cb0e91e..8f55ba0d85efdfe8fee2825c641fb176a7ca9ea2 100644 (file)
@@ -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();
   }
 
index 38990131f9be654294fc7aa69721205e203b087e..b9edc97e1e0d7942a4d36dbd33097ac0cca4fb95 100644 (file)
@@ -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();
   }
 
index cb447eb653c4ed4919ca6ba5d3fbfe62ff88ee26..0709867d1f25afcdb02b1b8acbcc053d5cdf5906 100644 (file)
@@ -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<QualityGateConditionDto> conditions = qualityGates.listConditions(qGateId);
     if (!conditions.isEmpty()) {
       writer.name("conditions").beginArray();
index 29e905000ba1d49551ec33aeaaa066dc2afc3ec3..5945255045b0f00e7ea44139dcb89ea19c38598d 100644 (file)
@@ -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");
index 111d68fc5ce95d14576d425da7e83203f98e7135..1c9f637a59ec9ae8531288f9ddc6e6c3de4944b1 100644 (file)
@@ -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 (file)
index 0000000..3cf49b8
--- /dev/null
@@ -0,0 +1,7 @@
+{
+  "qualityGate": {
+    "id": "23",
+    "name": "My team QG",
+    "default": false
+  }
+}
index 663603147281e8f2ca74d4b34605e48e55eef8ec..a35f3b095f86487d436d268d54925de2cd62af8f 100644 (file)
@@ -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 (file)
index 0000000..0ea94b7
--- /dev/null
@@ -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);
+  }
+}
index 56f401ab687e6fb5226a090240313ef95ae811ff..ec9af1871e25d7591723ec5a8d85ae0e4997532a 100644 (file)
  */
 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<QualityGateConditionDto> 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<Object>() {
-      @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 (file)
index 0000000..17c1b68
--- /dev/null
@@ -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();
+  }
+}
index c984fbe315cae322c3c3041f5e1b2bf2abe51e1e..74544f980ecc8a61a5cdba9d9e21631c693aa096 100644 (file)
@@ -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. <br>
+   * Returns <code>{@link Optional#empty()}</code> otherwise (ex: default quality gate applies)
+   */
+  public Optional<Long> 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);
   }
index 5b9d9462d2a4d79a7ce540be708fdf532d589284..c4d058c69f7b0e9f7471cecdfd0c5cb133c6cb58 100644 (file)
 package org.sonar.db.qualitygate;
 
 import java.util.List;
+import javax.annotation.CheckForNull;
 import org.apache.ibatis.annotations.Param;
 
 public interface ProjectQgateAssociationMapper {
 
   List<ProjectQgateAssociationDto> selectProjects(@Param("query") ProjectQgateAssociationQuery query);
 
+  @CheckForNull
+  String selectQGateIdByComponentId(long componentId);
 }
index 41cc46124ce29dc50fda49c76cd79ecc9c26f7f7..49982d7ed204dd5d634509d398550af2f392e77f 100644 (file)
@@ -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<QualityGateDto> selectAll() {
index 9a1d8e6072013d0ff1771e986bfd87d7ed3d02f9..f7fa21e4d0cc1fb58c6a38b08a8c8983f4d6e576 100644 (file)
@@ -42,7 +42,7 @@ import java.util.List;
  */
 public interface QualityGateMapper {
 
-  void insert(QualityGateDto newQualityGate);
+  void insert(QualityGateDto qualityGate);
 
   List<QualityGateDto> selectAll();
 
index fe6683b58db3103ee8436075740ad209754d550e..01203faf49ac98fd0d4b10d43ebc322752f09eca 100644 (file)
     ORDER BY proj.name
   </select>
 
+  <select id="selectQGateIdByComponentId" parameterType="long" resultType="string">
+    SELECT text_value
+    FROM properties
+    <where>
+      AND resource_id=#{componentId}
+      AND prop_key='sonar.qualitygate'
+    </where>
+  </select>
+
 </mapper>
index fbf6e2812b02111cca1ecfe0ef78522cc901f64f..5673fe776a3c7190cdd444e2ff4517effae0aa62 100644 (file)
 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<ProjectQgateAssociationDto> result = dao.selectProjects(dbSession, query);
+    List<ProjectQgateAssociationDto> 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<ProjectQgateAssociationDto> result = dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").projectSearch("one").build());
+    List<ProjectQgateAssociationDto> 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<ProjectQgateAssociationDto> result = dao.selectProjects(dbSession, ProjectQgateAssociationQuery.builder().gateId("42").build());
+    List<ProjectQgateAssociationDto> 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<Long> result = underTest.selectQGateIdByComponentId(dbSession, project.getId());
+
+    assertThat(result.isPresent()).isFalse();
+  }
+
+  @Test
+  public void select_qgate_id() {
+    associateProjectToQualityGate(10L, 1L);
+    associateProjectToQualityGate(11L, 2L);
+
+    Optional<Long> 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();
+  }
 }
index 5ba885b3dd34eca2bd3b6a7a3d9fedc32668c3f6..e01d58e7b70705a53a8e46f0d205b705cd24c16a 100644 (file)
@@ -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
index 57e867e767d418b1431e97d6676a9c928b1c0a49..514a5341a37a23de8fa5c99810928cdfc1c314b7 100644 (file)
@@ -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;
+}