aboutsummaryrefslogtreecommitdiffstats
path: root/server/sonar-webserver-webapi
diff options
context:
space:
mode:
authorAnita Stanisz <106669481+anita-stanisz-sonarsource@users.noreply.github.com>2024-09-23 09:39:40 +0200
committersonartech <sonartech@sonarsource.com>2024-09-25 20:02:53 +0000
commit7a57a3ad0f517f598a5bc4d38620ec3a517425e8 (patch)
treeba78ed44c1a8896ee8ef3d732ba3231398d6cd70 /server/sonar-webserver-webapi
parentab63cf091138cfca9d823f3cd131569e3868a422 (diff)
downloadsonarqube-7a57a3ad0f517f598a5bc4d38620ec3a517425e8.tar.gz
sonarqube-7a57a3ad0f517f598a5bc4d38620ec3a517425e8.zip
SONAR-23008 Add AI Code Assurance badge endpoint (#11794)
Diffstat (limited to 'server/sonar-webserver-webapi')
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/AbstractProjectBadgesWsAction.java71
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java44
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/ProjectBadgesSupport.java20
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/ProjectBadgesWsAction.java2
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java39
-rw-r--r--server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/SvgGenerator.java14
6 files changed, 106 insertions, 84 deletions
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/AbstractProjectBadgesWsAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/AbstractProjectBadgesWsAction.java
new file mode 100644
index 00000000000..88328940e49
--- /dev/null
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/AbstractProjectBadgesWsAction.java
@@ -0,0 +1,71 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2024 SonarSource SA
+ * mailto:info 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.badge.ws;
+
+import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
+import java.util.Locale;
+import java.util.Optional;
+import org.sonar.api.server.ws.Request;
+import org.sonar.api.server.ws.Response;
+import org.sonar.server.exceptions.ForbiddenException;
+import org.sonar.server.exceptions.NotFoundException;
+
+import static java.nio.charset.StandardCharsets.UTF_8;
+import static org.apache.commons.io.IOUtils.write;
+import static org.sonar.server.badge.ws.ETagUtils.RFC1123_DATE;
+import static org.sonar.server.badge.ws.ETagUtils.getETag;
+import static org.sonarqube.ws.MediaTypes.SVG;
+
+public abstract class AbstractProjectBadgesWsAction implements ProjectBadgesWsAction {
+ protected final ProjectBadgesSupport support;
+ protected final SvgGenerator svgGenerator;
+
+ protected AbstractProjectBadgesWsAction(ProjectBadgesSupport support, SvgGenerator svgGenerator) {
+ this.support = support;
+ this.svgGenerator = svgGenerator;
+ }
+
+ @Override
+ public void handle(Request request, Response response) throws IOException {
+ response.setHeader("Cache-Control", "no-cache");
+ response.stream().setMediaType(SVG);
+ try {
+ support.validateToken(request);
+ String result = getBadge(request);
+ String eTag = getETag(result);
+ Optional<String> requestedETag = request.header("If-None-Match");
+ if (requestedETag.filter(eTag::equals).isPresent()) {
+ response.stream().setStatus(304);
+ return;
+ }
+ response.setHeader("ETag", eTag);
+ write(result, response.stream().output(), UTF_8);
+ } catch (ProjectBadgesException | ForbiddenException | NotFoundException e) {
+ // There is an issue, so do not return any ETag but make this response expire now
+ SimpleDateFormat sdf = new SimpleDateFormat(RFC1123_DATE, Locale.US);
+ response.setHeader("Expires", sdf.format(new Date()));
+ write(svgGenerator.generateError(e.getMessage()), response.stream().output(), UTF_8);
+ }
+ }
+
+ protected abstract String getBadge(Request request);
+}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java
index baecd8df161..bf604a531db 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/MeasureAction.java
@@ -21,16 +21,11 @@ package org.sonar.server.badge.ws;
import com.google.common.collect.ImmutableMap;
import com.google.common.io.Resources;
-import java.text.SimpleDateFormat;
-import java.util.Date;
import java.util.EnumMap;
-import java.util.Locale;
import java.util.Map;
-import java.util.Optional;
import java.util.function.Function;
import org.sonar.api.server.ws.Change;
import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.NewAction;
import org.sonar.db.DbClient;
@@ -39,14 +34,10 @@ import org.sonar.db.component.BranchDto;
import org.sonar.db.measure.LiveMeasureDto;
import org.sonar.db.metric.MetricDto;
import org.sonar.server.badge.ws.SvgGenerator.Color;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
import org.sonar.server.measure.Rating;
import static com.google.common.base.Preconditions.checkState;
import static java.lang.String.format;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.commons.io.IOUtils.write;
import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
import static org.sonar.api.measures.CoreMetrics.BUGS_KEY;
import static org.sonar.api.measures.CoreMetrics.CODE_SMELLS_KEY;
@@ -63,8 +54,6 @@ import static org.sonar.api.measures.Metric.Level;
import static org.sonar.api.measures.Metric.Level.ERROR;
import static org.sonar.api.measures.Metric.Level.OK;
import static org.sonar.api.measures.Metric.ValueType;
-import static org.sonar.server.badge.ws.ETagUtils.RFC1123_DATE;
-import static org.sonar.server.badge.ws.ETagUtils.getETag;
import static org.sonar.server.badge.ws.SvgFormatter.formatDuration;
import static org.sonar.server.badge.ws.SvgFormatter.formatNumeric;
import static org.sonar.server.badge.ws.SvgFormatter.formatPercent;
@@ -74,9 +63,8 @@ import static org.sonar.server.measure.Rating.C;
import static org.sonar.server.measure.Rating.D;
import static org.sonar.server.measure.Rating.E;
import static org.sonar.server.measure.Rating.valueOf;
-import static org.sonarqube.ws.MediaTypes.SVG;
-public class MeasureAction implements ProjectBadgesWsAction {
+public class MeasureAction extends AbstractProjectBadgesWsAction {
private static final String PARAM_METRIC = "metric";
@@ -113,13 +101,10 @@ public class MeasureAction implements ProjectBadgesWsAction {
E, Color.RATING_E));
private final DbClient dbClient;
- private final ProjectBadgesSupport support;
- private final SvgGenerator svgGenerator;
public MeasureAction(DbClient dbClient, ProjectBadgesSupport support, SvgGenerator svgGenerator) {
+ super(support, svgGenerator);
this.dbClient = dbClient;
- this.support = support;
- this.svgGenerator = svgGenerator;
}
@Override
@@ -129,7 +114,8 @@ public class MeasureAction implements ProjectBadgesWsAction {
.setDescription("Generate badge for project's measure as an SVG.<br/>" +
"Requires 'Browse' permission on the specified project.")
.setSince("7.1")
- .setChangelog(new Change("10.4", String.format("The following metric keys are now deprecated: %s", String.join(", ", DEPRECATED_METRIC_KEYS))))
+ .setChangelog(new Change("10.4", String.format("The following metric keys are now deprecated: %s", String.join(", ",
+ DEPRECATED_METRIC_KEYS))))
.setResponseExample(Resources.getResource(getClass(), "measure-example.svg"));
support.addProjectAndBranchParams(action);
action.createParam(PARAM_METRIC)
@@ -139,30 +125,14 @@ public class MeasureAction implements ProjectBadgesWsAction {
}
@Override
- public void handle(Request request, Response response) throws Exception {
- response.setHeader("Cache-Control", "no-cache");
- response.stream().setMediaType(SVG);
- String metricKey = request.mandatoryParam(PARAM_METRIC);
+ protected String getBadge(Request request) {
try (DbSession dbSession = dbClient.openSession(false)) {
- support.validateToken(request);
+ String metricKey = request.mandatoryParam(PARAM_METRIC);
BranchDto branch = support.getBranch(dbSession, request);
MetricDto metric = dbClient.metricDao().selectByKey(dbSession, metricKey);
checkState(metric != null && metric.isEnabled(), "Metric '%s' hasn't been found", metricKey);
LiveMeasureDto measure = getMeasure(dbSession, branch, metricKey);
- String result = generateSvg(metric, measure);
- String eTag = getETag(result);
- Optional<String> requestedETag = request.header("If-None-Match");
- if (requestedETag.filter(eTag::equals).isPresent()) {
- response.stream().setStatus(304);
- return;
- }
- response.setHeader("ETag", eTag);
- write(result, response.stream().output(), UTF_8);
- } catch (ProjectBadgesException | ForbiddenException | NotFoundException e) {
- // There is an issue, so do not return any ETag but make this response expire now
- SimpleDateFormat sdf = new SimpleDateFormat(RFC1123_DATE, Locale.US);
- response.setHeader("Expires", sdf.format(new Date()));
- write(svgGenerator.generateError(e.getMessage()), response.stream().output(), UTF_8);
+ return generateSvg(metric, measure);
}
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/ProjectBadgesSupport.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/ProjectBadgesSupport.java
index cec59de51d6..a6f23e7dc91 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/ProjectBadgesSupport.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/ProjectBadgesSupport.java
@@ -56,14 +56,18 @@ public class ProjectBadgesSupport {
}
void addProjectAndBranchParams(WebService.NewAction action) {
- action.createParam(PARAM_PROJECT)
- .setDescription("Project or application key")
- .setRequired(true)
- .setExampleValue(KEY_PROJECT_EXAMPLE_001);
+ addProjectAndTokenParams(action);
action
.createParam(PARAM_BRANCH)
.setDescription("Branch key")
.setExampleValue(KEY_BRANCH_EXAMPLE_001);
+ }
+
+ public void addProjectAndTokenParams(WebService.NewAction action) {
+ action.createParam(PARAM_PROJECT)
+ .setDescription("Project or application key")
+ .setRequired(true)
+ .setExampleValue(KEY_PROJECT_EXAMPLE_001);
action
.createParam(PARAM_TOKEN)
.setDescription("Project badge token")
@@ -72,9 +76,8 @@ public class ProjectBadgesSupport {
BranchDto getBranch(DbSession dbSession, Request request) {
try {
- String projectKey = request.mandatoryParam(PARAM_PROJECT);
String branchName = request.param(PARAM_BRANCH);
- ProjectDto project = componentFinder.getProjectOrApplicationByKey(dbSession, projectKey);
+ ProjectDto project = getProject(dbSession, request);
BranchDto branch = componentFinder.getBranchOrPullRequest(dbSession, project, branchName, null);
@@ -88,6 +91,11 @@ public class ProjectBadgesSupport {
}
}
+ public ProjectDto getProject(DbSession dbSession, Request request) {
+ String projectKey = request.mandatoryParam(PARAM_PROJECT);
+ return componentFinder.getProjectOrApplicationByKey(dbSession, projectKey);
+ }
+
private static ProjectBadgesException generateInvalidProjectException() {
return new ProjectBadgesException("Project is invalid");
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/ProjectBadgesWsAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/ProjectBadgesWsAction.java
index bbdba2441da..ea6457604ef 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/ProjectBadgesWsAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/ProjectBadgesWsAction.java
@@ -21,6 +21,6 @@ package org.sonar.server.badge.ws;
import org.sonar.server.ws.WsAction;
-interface ProjectBadgesWsAction extends WsAction {
+public interface ProjectBadgesWsAction extends WsAction {
// Marker interface
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java
index ed71caff49d..a4d03563852 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/QualityGateAction.java
@@ -20,39 +20,24 @@
package org.sonar.server.badge.ws;
import com.google.common.io.Resources;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.Locale;
-import java.util.Optional;
import org.sonar.api.measures.Metric.Level;
import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.Response;
import org.sonar.api.server.ws.WebService;
import org.sonar.api.server.ws.WebService.NewAction;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.component.BranchDto;
import org.sonar.db.measure.LiveMeasureDto;
-import org.sonar.server.exceptions.ForbiddenException;
-import org.sonar.server.exceptions.NotFoundException;
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static org.apache.commons.io.IOUtils.write;
import static org.sonar.api.measures.CoreMetrics.ALERT_STATUS_KEY;
-import static org.sonar.server.badge.ws.ETagUtils.RFC1123_DATE;
-import static org.sonar.server.badge.ws.ETagUtils.getETag;
-import static org.sonarqube.ws.MediaTypes.SVG;
-public class QualityGateAction implements ProjectBadgesWsAction {
+public class QualityGateAction extends AbstractProjectBadgesWsAction {
private final DbClient dbClient;
- private final ProjectBadgesSupport support;
- private final SvgGenerator svgGenerator;
public QualityGateAction(DbClient dbClient, ProjectBadgesSupport support, SvgGenerator svgGenerator) {
+ super(support, svgGenerator);
this.dbClient = dbClient;
- this.support = support;
- this.svgGenerator = svgGenerator;
}
@Override
@@ -67,27 +52,11 @@ public class QualityGateAction implements ProjectBadgesWsAction {
}
@Override
- public void handle(Request request, Response response) throws Exception {
- response.setHeader("Cache-Control", "no-cache");
- response.stream().setMediaType(SVG);
+ protected String getBadge(Request request) {
try (DbSession dbSession = dbClient.openSession(false)) {
- support.validateToken(request);
BranchDto branch = support.getBranch(dbSession, request);
Level qualityGateStatus = getQualityGate(dbSession, branch);
- String result = svgGenerator.generateQualityGate(qualityGateStatus);
- String eTag = getETag(result);
- Optional<String> requestedETag = request.header("If-None-Match");
- if (requestedETag.filter(eTag::equals).isPresent()) {
- response.stream().setStatus(304);
- return;
- }
- response.setHeader("ETag", eTag);
- write(result, response.stream().output(), UTF_8);
- } catch (ProjectBadgesException | ForbiddenException | NotFoundException e) {
- // There is an issue, so do not return any ETag but make this response expire now
- SimpleDateFormat sdf = new SimpleDateFormat(RFC1123_DATE, Locale.US);
- response.setHeader("Expires", sdf.format(new Date()));
- write(svgGenerator.generateError(e.getMessage()), response.stream().output(), UTF_8);
+ return svgGenerator.generateQualityGate(qualityGateStatus);
}
}
diff --git a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/SvgGenerator.java b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/SvgGenerator.java
index 47d241556b1..b5ed8ab09d3 100644
--- a/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/SvgGenerator.java
+++ b/server/sonar-webserver-webapi/src/main/java/org/sonar/server/badge/ws/SvgGenerator.java
@@ -166,6 +166,14 @@ public class SvgGenerator {
return strSubstitutor.replace(errorTemplate);
}
+ public static String readTemplate(String template, Class<?> clazz) {
+ try {
+ return IOUtils.toString(clazz.getResource(template), UTF_8);
+ } catch (IOException e) {
+ throw new IllegalStateException(String.format("Can't read svg template '%s'", template), e);
+ }
+ }
+
private static int computeWidth(String text) {
return text.chars()
.mapToObj(i -> (char) i)
@@ -178,11 +186,7 @@ public class SvgGenerator {
}
private String readTemplate(String template) {
- try {
- return IOUtils.toString(getClass().getResource(template), UTF_8);
- } catch (IOException e) {
- throw new IllegalStateException(String.format("Can't read svg template '%s'", template), e);
- }
+ return readTemplate(template, getClass());
}
static class Color {