Skip to content

Commit

Permalink
SONAR-7923 Create WS api/qualitygates/get_by_project
Browse files Browse the repository at this point in the history
  • Loading branch information
teryk committed Jul 29, 2016
1 parent 88c26b4 commit 3e3e4b1
Show file tree
Hide file tree
Showing 31 changed files with 749 additions and 240 deletions.
Expand Up @@ -180,18 +180,7 @@
import org.sonar.server.project.ws.ProjectsWsModule; import org.sonar.server.project.ws.ProjectsWsModule;
import org.sonar.server.projectlink.ws.ProjectLinksModule; import org.sonar.server.projectlink.ws.ProjectLinksModule;
import org.sonar.server.properties.ProjectSettingsFactory; import org.sonar.server.properties.ProjectSettingsFactory;
import org.sonar.server.qualitygate.QgateProjectFinder; import org.sonar.server.qualitygate.QualityGateModule;
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.qualityprofile.BuiltInProfiles; import org.sonar.server.qualityprofile.BuiltInProfiles;
import org.sonar.server.qualityprofile.QProfileBackuper; import org.sonar.server.qualityprofile.QProfileBackuper;
import org.sonar.server.qualityprofile.QProfileComparison; import org.sonar.server.qualityprofile.QProfileComparison;
Expand Down Expand Up @@ -462,26 +451,7 @@ protected void configureLevel() {
DefaultMetricFinder.class, DefaultMetricFinder.class,
TimeMachineWs.class, TimeMachineWs.class,


// quality gates QualityGateModule.class,
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,


// web services // web services
WebServiceEngine.class, WebServiceEngine.class,
Expand Down
@@ -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);
}
}
Expand Up @@ -21,22 +21,22 @@


import com.google.common.base.Predicate; import com.google.common.base.Predicate;
import com.google.common.base.Strings; import com.google.common.base.Strings;
import com.google.common.collect.Collections2;
import java.util.Collection; import java.util.Collection;
import java.util.stream.Collectors;
import javax.annotation.CheckForNull; import javax.annotation.CheckForNull;
import javax.annotation.Nonnull; import javax.annotation.Nonnull;
import javax.annotation.Nullable; import javax.annotation.Nullable;
import org.apache.commons.lang.BooleanUtils; import org.apache.commons.lang.BooleanUtils;
import org.apache.commons.lang.ObjectUtils; import org.apache.commons.lang.ObjectUtils;
import org.apache.commons.lang.StringUtils; import org.apache.commons.lang.StringUtils;
import org.apache.ibatis.session.SqlSession;
import org.sonar.api.config.Settings; import org.sonar.api.config.Settings;
import org.sonar.api.measures.CoreMetrics; import org.sonar.api.measures.CoreMetrics;
import org.sonar.api.measures.Metric; import org.sonar.api.measures.Metric;
import org.sonar.api.measures.Metric.ValueType; import org.sonar.api.measures.Metric.ValueType;
import org.sonar.api.measures.MetricFinder; import org.sonar.api.measures.MetricFinder;
import org.sonar.api.web.UserRole; import org.sonar.api.web.UserRole;
import org.sonar.core.permission.GlobalPermissions; import org.sonar.core.permission.GlobalPermissions;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession; import org.sonar.db.DbSession;
import org.sonar.db.MyBatis; import org.sonar.db.MyBatis;
import org.sonar.db.component.ComponentDao; import org.sonar.db.component.ComponentDao;
Expand All @@ -56,7 +56,6 @@
import org.sonar.server.user.UserSession; import org.sonar.server.user.UserSession;
import org.sonar.server.util.Validation; import org.sonar.server.util.Validation;


import static com.google.common.collect.FluentIterable.from;
import static java.lang.String.format; import static java.lang.String.format;


/** /**
Expand All @@ -66,23 +65,22 @@ public class QualityGates {


public static final String SONAR_QUALITYGATE_PROPERTY = "sonar.qualitygate"; public static final String SONAR_QUALITYGATE_PROPERTY = "sonar.qualitygate";


private final DbClient dbClient;
private final QualityGateDao dao; private final QualityGateDao dao;
private final QualityGateConditionDao conditionDao; private final QualityGateConditionDao conditionDao;
private final MetricFinder metricFinder; private final MetricFinder metricFinder;
private final PropertiesDao propertiesDao; private final PropertiesDao propertiesDao;
private final ComponentDao componentDao; private final ComponentDao componentDao;
private final MyBatis myBatis;
private final UserSession userSession; private final UserSession userSession;
private final Settings settings; private final Settings settings;


public QualityGates(QualityGateDao dao, QualityGateConditionDao conditionDao, MetricFinder metricFinder, PropertiesDao propertiesDao, ComponentDao componentDao, public QualityGates(DbClient dbClient, MetricFinder metricFinder, UserSession userSession, Settings settings) {
MyBatis myBatis, UserSession userSession, Settings settings) { this.dbClient = dbClient;
this.dao = dao; this.dao = dbClient.qualityGateDao();
this.conditionDao = conditionDao; this.conditionDao = dbClient.gateConditionDao();
this.metricFinder = metricFinder; this.metricFinder = metricFinder;
this.propertiesDao = propertiesDao; this.propertiesDao = dbClient.propertiesDao();
this.componentDao = componentDao; this.componentDao = dbClient.componentDao();
this.myBatis = myBatis;
this.userSession = userSession; this.userSession = userSession;
this.settings = settings; this.settings = settings;
} }
Expand Down Expand Up @@ -117,18 +115,18 @@ public QualityGateDto copy(long sourceId, String destinationName) {
getNonNullQgate(sourceId); getNonNullQgate(sourceId);
validateQualityGate(null, destinationName); validateQualityGate(null, destinationName);
QualityGateDto destinationGate = new QualityGateDto().setName(destinationName); QualityGateDto destinationGate = new QualityGateDto().setName(destinationName);
SqlSession session = myBatis.openSession(false); DbSession dbSession = dbClient.openSession(false);
try { try {
dao.insert(destinationGate, session); dao.insert(dbSession, destinationGate);
for (QualityGateConditionDto sourceCondition : conditionDao.selectForQualityGate(sourceId, session)) { for (QualityGateConditionDto sourceCondition : conditionDao.selectForQualityGate(sourceId, dbSession)) {
conditionDao.insert(new QualityGateConditionDto().setQualityGateId(destinationGate.getId()) conditionDao.insert(new QualityGateConditionDto().setQualityGateId(destinationGate.getId())
.setMetricId(sourceCondition.getMetricId()).setOperator(sourceCondition.getOperator()) .setMetricId(sourceCondition.getMetricId()).setOperator(sourceCondition.getOperator())
.setWarningThreshold(sourceCondition.getWarningThreshold()).setErrorThreshold(sourceCondition.getErrorThreshold()).setPeriod(sourceCondition.getPeriod()), .setWarningThreshold(sourceCondition.getWarningThreshold()).setErrorThreshold(sourceCondition.getErrorThreshold()).setPeriod(sourceCondition.getPeriod()),
session); dbSession);
} }
session.commit(); dbSession.commit();
} finally { } finally {
MyBatis.closeQuietly(session); MyBatis.closeQuietly(dbSession);
} }
return destinationGate; return destinationGate;
} }
Expand All @@ -140,7 +138,7 @@ public Collection<QualityGateDto> list() {
public void delete(long idToDelete) { public void delete(long idToDelete) {
checkPermission(); checkPermission();
QualityGateDto qGate = getNonNullQgate(idToDelete); QualityGateDto qGate = getNonNullQgate(idToDelete);
DbSession session = myBatis.openSession(false); DbSession session = dbClient.openSession(false);
try { try {
if (isDefault(qGate)) { if (isDefault(qGate)) {
propertiesDao.deleteGlobalProperty(SONAR_QUALITYGATE_PROPERTY, session); propertiesDao.deleteGlobalProperty(SONAR_QUALITYGATE_PROPERTY, session);
Expand Down Expand Up @@ -228,7 +226,7 @@ public void deleteCondition(Long condId) {
} }


public void associateProject(Long qGateId, Long projectId) { public void associateProject(Long qGateId, Long projectId) {
DbSession session = myBatis.openSession(false); DbSession session = dbClient.openSession(false);
try { try {
getNonNullQgate(qGateId); getNonNullQgate(qGateId);
checkPermission(projectId, session); checkPermission(projectId, session);
Expand All @@ -239,7 +237,7 @@ public void associateProject(Long qGateId, Long projectId) {
} }


public void dissociateProject(Long qGateId, Long projectId) { public void dissociateProject(Long qGateId, Long projectId) {
DbSession session = myBatis.openSession(false); DbSession session = dbClient.openSession(false);
try { try {
getNonNullQgate(qGateId); getNonNullQgate(qGateId);
checkPermission(projectId, session); checkPermission(projectId, session);
Expand All @@ -250,12 +248,9 @@ public void dissociateProject(Long qGateId, Long projectId) {
} }


public Collection<Metric> gateMetrics() { public Collection<Metric> gateMetrics() {
return Collections2.filter(metricFinder.findAll(), new Predicate<Metric>() { return metricFinder.findAll().stream()
@Override .filter(QualityGates::isAvailableForInit)
public boolean apply(Metric metric) { .collect(Collectors.toList());
return isAvailableForInit(metric);
}
});
} }


public boolean currentUserHasWritePermission() { public boolean currentUserHasWritePermission() {
Expand All @@ -274,7 +269,9 @@ private Collection<QualityGateConditionDto> getConditions(long qGateId, @Nullabl
if (conditionId == null) { if (conditionId == null) {
return conditions; 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) { private static void validateCondition(Metric metric, String operator, @Nullable String warningThreshold, @Nullable String errorThreshold, @Nullable Integer period) {
Expand All @@ -293,7 +290,7 @@ private static void checkConditionDoesNotAlreadyExistOnSameMetricAndPeriod(Colle
return; return;
} }


boolean conditionExists = from(conditions).anyMatch(new MatchMetricAndPeriod(metric.getId(), period)); boolean conditionExists = conditions.stream().anyMatch(new MatchMetricAndPeriod(metric.getId(), period)::apply);
if (conditionExists) { if (conditionExists) {
String errorMessage = period == null String errorMessage = period == null
? format("Condition on metric '%s' already exists.", metric.getName()) ? format("Condition on metric '%s' already exists.", metric.getName())
Expand Down Expand Up @@ -421,18 +418,4 @@ public boolean apply(@Nonnull QualityGateConditionDto input) {
ObjectUtils.equals(input.getPeriod(), period); 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;
}
}

} }
Expand Up @@ -26,6 +26,9 @@
import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.server.qualitygate.QualityGates; 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 { public class CopyAction implements QualityGatesWsAction {


private final QualityGates qualityGates; private final QualityGates qualityGates;
Expand All @@ -42,20 +45,20 @@ public void define(WebService.NewController controller) {
.setSince("4.3") .setSince("4.3")
.setHandler(this); .setHandler(this);


action.createParam(QualityGatesWs.PARAM_ID) action.createParam(PARAM_ID)
.setDescription("The ID of the source quality gate") .setDescription("The ID of the source quality gate")
.setRequired(true) .setRequired(true)
.setExampleValue("1"); .setExampleValue("1");


action.createParam(QualityGatesWs.PARAM_NAME) action.createParam(PARAM_NAME)
.setDescription("The name of the quality gate to create") .setDescription("The name of the quality gate to create")
.setRequired(true) .setRequired(true)
.setExampleValue("My Quality Gate"); .setExampleValue("My Quality Gate");
} }


@Override @Override
public void handle(Request request, Response response) { 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(); JsonWriter writer = response.newJsonWriter();
QualityGatesWs.writeQualityGate(newQualityGate, writer).close(); QualityGatesWs.writeQualityGate(newQualityGate, writer).close();
} }
Expand Down
Expand Up @@ -25,6 +25,7 @@
import org.sonar.api.utils.text.JsonWriter; import org.sonar.api.utils.text.JsonWriter;
import org.sonar.db.qualitygate.QualityGateDto; import org.sonar.db.qualitygate.QualityGateDto;
import org.sonar.server.qualitygate.QualityGates; import org.sonar.server.qualitygate.QualityGates;
import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters;


public class CreateAction implements QualityGatesWsAction { public class CreateAction implements QualityGatesWsAction {


Expand All @@ -42,15 +43,15 @@ public void define(WebService.NewController controller) {
.setPost(true) .setPost(true)
.setHandler(this); .setHandler(this);


action.createParam(QualityGatesWs.PARAM_NAME) action.createParam(QualityGatesWsParameters.PARAM_NAME)
.setDescription("The name of the quality gate to create") .setDescription("The name of the quality gate to create")
.setRequired(true) .setRequired(true)
.setExampleValue("My Quality Gate"); .setExampleValue("My Quality Gate");
} }


@Override @Override
public void handle(Request request, Response response) { 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(); JsonWriter writer = response.newJsonWriter();
QualityGatesWs.writeQualityGate(newQualityGate, writer).close(); QualityGatesWs.writeQualityGate(newQualityGate, writer).close();
} }
Expand Down
Expand Up @@ -23,6 +23,7 @@
import org.sonar.api.server.ws.Response; import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService; import org.sonar.api.server.ws.WebService;
import org.sonar.server.qualitygate.QualityGates; import org.sonar.server.qualitygate.QualityGates;
import org.sonarqube.ws.client.qualitygate.QualityGatesWsParameters;


public class CreateConditionAction implements QualityGatesWsAction { public class CreateConditionAction implements QualityGatesWsAction {


Expand All @@ -41,7 +42,7 @@ public void define(WebService.NewController controller) {
.setHandler(this); .setHandler(this);


createCondition createCondition
.createParam(QualityGatesWs.PARAM_GATE_ID) .createParam(QualityGatesWsParameters.PARAM_GATE_ID)
.setDescription("ID of the quality gate") .setDescription("ID of the quality gate")
.setRequired(true) .setRequired(true)
.setExampleValue("1"); .setExampleValue("1");
Expand All @@ -53,12 +54,12 @@ public void define(WebService.NewController controller) {
public void handle(Request request, Response response) { public void handle(Request request, Response response) {
QualityGatesWs.writeQualityGateCondition( QualityGatesWs.writeQualityGateCondition(
qualityGates.createCondition( qualityGates.createCondition(
QualityGatesWs.parseId(request, QualityGatesWs.PARAM_GATE_ID), QualityGatesWs.parseId(request, QualityGatesWsParameters.PARAM_GATE_ID),
request.mandatoryParam(QualityGatesWs.PARAM_METRIC), request.mandatoryParam(QualityGatesWsParameters.PARAM_METRIC),
request.mandatoryParam(QualityGatesWs.PARAM_OPERATOR), request.mandatoryParam(QualityGatesWsParameters.PARAM_OPERATOR),
request.param(QualityGatesWs.PARAM_WARNING), request.param(QualityGatesWsParameters.PARAM_WARNING),
request.param(QualityGatesWs.PARAM_ERROR), request.param(QualityGatesWsParameters.PARAM_ERROR),
request.paramAsInt(QualityGatesWs.PARAM_PERIOD) request.paramAsInt(QualityGatesWsParameters.PARAM_PERIOD)
), response.newJsonWriter() ), response.newJsonWriter()
).close(); ).close();
} }
Expand Down

0 comments on commit 3e3e4b1

Please sign in to comment.