3 * Copyright (C) 2009-2019 SonarSource SA
4 * mailto:info AT sonarsource DOT com
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 3 of the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public License
17 * along with this program; if not, write to the Free Software Foundation,
18 * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
20 package org.sonar.server.projectanalysis.ws;
22 import com.google.protobuf.Empty;
23 import javax.annotation.Nullable;
24 import org.sonar.api.server.ws.Request;
25 import org.sonar.api.server.ws.Response;
26 import org.sonar.api.server.ws.WebService;
27 import org.sonar.api.web.UserRole;
28 import org.sonar.core.util.Uuids;
29 import org.sonar.db.DbClient;
30 import org.sonar.db.DbSession;
31 import org.sonar.db.component.BranchDto;
32 import org.sonar.db.component.BranchType;
33 import org.sonar.db.component.ComponentDto;
34 import org.sonar.db.component.SnapshotDto;
35 import org.sonar.db.newcodeperiod.NewCodePeriodDto;
36 import org.sonar.db.newcodeperiod.NewCodePeriodType;
37 import org.sonar.server.component.ComponentFinder;
38 import org.sonar.server.exceptions.NotFoundException;
39 import org.sonar.server.user.UserSession;
41 import static com.google.common.base.Preconditions.checkArgument;
42 import static java.lang.String.format;
43 import static org.apache.commons.lang.StringUtils.trimToNull;
44 import static org.sonar.server.component.ComponentFinder.ParamNames.PROJECT_ID_AND_KEY;
45 import static org.sonar.server.projectanalysis.ws.ProjectAnalysesWsParameters.PARAM_ANALYSIS;
46 import static org.sonar.server.projectanalysis.ws.ProjectAnalysesWsParameters.PARAM_BRANCH;
47 import static org.sonar.server.projectanalysis.ws.ProjectAnalysesWsParameters.PARAM_PROJECT;
48 import static org.sonar.server.ws.WsUtils.writeProtobuf;
50 public class SetBaselineAction implements ProjectAnalysesWsAction {
51 private final DbClient dbClient;
52 private final UserSession userSession;
53 private final ComponentFinder componentFinder;
55 public SetBaselineAction(DbClient dbClient, UserSession userSession, ComponentFinder componentFinder) {
56 this.dbClient = dbClient;
57 this.userSession = userSession;
58 this.componentFinder = componentFinder;
62 public void define(WebService.NewController context) {
63 WebService.NewAction action = context.createAction("set_baseline")
64 .setDescription("Set an analysis as the baseline of the New Code Period on a project or a long-lived branch.<br/>" +
65 "This manually set baseline overrides the `sonar.leak.period` setting.<br/>" +
66 "Requires one of the following permissions:" +
68 " <li>'Administer System'</li>" +
69 " <li>'Administer' rights on the specified project</li>" +
72 .setDeprecatedSince("8.0")
76 action.createParam(PARAM_PROJECT)
77 .setDescription("Project key")
80 action.createParam(PARAM_BRANCH)
81 .setDescription("Branch key");
83 action.createParam(PARAM_ANALYSIS)
84 .setDescription("Analysis key")
85 .setExampleValue(Uuids.UUID_EXAMPLE_01)
90 public void handle(Request httpRequest, Response httpResponse) throws Exception {
91 doHandle(httpRequest);
93 writeProtobuf(Empty.newBuilder().build(), httpRequest, httpResponse);
96 private void doHandle(Request request) {
97 String projectKey = request.mandatoryParam(PARAM_PROJECT);
98 String branchKey = trimToNull(request.param(PARAM_BRANCH));
99 String analysisUuid = request.mandatoryParam(PARAM_ANALYSIS);
101 try (DbSession dbSession = dbClient.openSession(false)) {
102 ComponentDto projectBranch = getProjectBranch(dbSession, projectKey, branchKey);
103 SnapshotDto analysis = getAnalysis(dbSession, analysisUuid);
104 checkRequest(dbSession, projectBranch, branchKey, analysis);
106 dbClient.newCodePeriodDao().upsert(dbSession, new NewCodePeriodDto()
107 .setProjectUuid(projectBranch.getMainBranchProjectUuid() != null ? projectBranch.getMainBranchProjectUuid() : projectBranch.uuid())
108 .setBranchUuid(branchKey != null ? projectBranch.uuid() : null)
109 .setType(NewCodePeriodType.SPECIFIC_ANALYSIS)
110 .setValue(analysisUuid)
116 private ComponentDto getProjectBranch(DbSession dbSession, String projectKey, @Nullable String branchKey) {
117 if (branchKey == null) {
118 return componentFinder.getByUuidOrKey(dbSession, null, projectKey, PROJECT_ID_AND_KEY);
120 ComponentDto project = componentFinder.getByKeyAndBranch(dbSession, projectKey, branchKey);
122 BranchDto branchDto = dbClient.branchDao().selectByUuid(dbSession, project.uuid())
123 .orElseThrow(() -> new NotFoundException(format("Branch '%s' is not found", branchKey)));
125 checkArgument(branchDto.getBranchType() == BranchType.LONG,
126 "Not a long-living branch: '%s'", branchKey);
131 private SnapshotDto getAnalysis(DbSession dbSession, String analysisUuid) {
132 return dbClient.snapshotDao().selectByUuid(dbSession, analysisUuid)
133 .orElseThrow(() -> new NotFoundException(format("Analysis '%s' is not found", analysisUuid)));
136 private void checkRequest(DbSession dbSession, ComponentDto projectBranch, @Nullable String branchKey, SnapshotDto analysis) {
137 userSession.checkComponentPermission(UserRole.ADMIN, projectBranch);
138 ComponentDto project = dbClient.componentDao().selectByUuid(dbSession, analysis.getComponentUuid()).orElse(null);
140 boolean analysisMatchesProjectBranch = project != null && projectBranch.uuid().equals(project.uuid());
141 if (branchKey != null) {
142 checkArgument(analysisMatchesProjectBranch,
143 "Analysis '%s' does not belong to branch '%s' of project '%s'",
144 analysis.getUuid(), branchKey, projectBranch.getKey());
146 checkArgument(analysisMatchesProjectBranch,
147 "Analysis '%s' does not belong to project '%s'",
148 analysis.getUuid(), projectBranch.getKey());