-
Notifications
You must be signed in to change notification settings - Fork 1.9k
/
CreateAction.java
187 lines (167 loc) · 7.52 KB
/
CreateAction.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
/*
* SonarQube
* Copyright (C) 2009-2017 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.rule.ws;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Optional;
import org.sonar.api.rule.RuleKey;
import org.sonar.api.rule.RuleStatus;
import org.sonar.api.rule.Severity;
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.utils.KeyValueFormat;
import org.sonar.db.DbClient;
import org.sonar.db.DbSession;
import org.sonar.db.rule.RuleDefinitionDto;
import org.sonar.db.rule.RuleParamDto;
import org.sonar.server.organization.OrganizationFlags;
import org.sonar.server.rule.NewCustomRule;
import org.sonar.server.rule.ReactivationException;
import org.sonar.server.rule.RuleCreator;
import org.sonarqube.ws.Rules;
import static com.google.common.base.Strings.isNullOrEmpty;
import static java.net.HttpURLConnection.HTTP_CONFLICT;
import static java.util.Collections.singletonList;
import static org.sonar.server.ws.WsUtils.writeProtobuf;
/**
* @since 4.4
*/
public class CreateAction implements RulesWsAction {
public static final String PARAM_CUSTOM_KEY = "custom_key";
public static final String PARAM_NAME = "name";
public static final String PARAM_DESCRIPTION = "markdown_description";
public static final String PARAM_SEVERITY = "severity";
public static final String PARAM_STATUS = "status";
public static final String PARAM_TEMPLATE_KEY = "template_key";
public static final String PARAMS = "params";
public static final String PARAM_PREVENT_REACTIVATION = "prevent_reactivation";
private final DbClient dbClient;
private final RuleCreator ruleCreator;
private final RuleMapper ruleMapper;
private final OrganizationFlags organizationFlags;
private final RuleWsSupport ruleWsSupport;
public CreateAction(DbClient dbClient, RuleCreator ruleCreator, RuleMapper ruleMapper, OrganizationFlags organizationFlags, RuleWsSupport ruleWsSupport) {
this.dbClient = dbClient;
this.ruleCreator = ruleCreator;
this.ruleMapper = ruleMapper;
this.organizationFlags = organizationFlags;
this.ruleWsSupport = ruleWsSupport;
}
@Override
public void define(WebService.NewController controller) {
WebService.NewAction action = controller
.createAction("create")
.setDescription("Create a custom rule.<br>" +
"Requires the 'Administer Quality Profiles' permission")
.setSince("4.4")
.setChangelog(
new Change("5.5", "Creating manual rule is not more possible"),
new Change("6.4", "Creating custom rules are not supported if the organization feature is enabled. In that case, the webservice will fail"))
.setPost(true)
.setHandler(this);
action
.createParam(PARAM_CUSTOM_KEY)
.setDescription("Key of the custom rule")
.setExampleValue("Todo_should_not_be_used")
.setRequired(true);
action
.createParam("manual_key")
.setDescription("Manual rules are no more supported. This parameter is ignored")
.setExampleValue("Error_handling")
.setDeprecatedSince("5.5");
action
.createParam(PARAM_TEMPLATE_KEY)
.setDescription("Key of the template rule in order to create a custom rule (mandatory for custom rule)")
.setExampleValue("java:XPath");
action
.createParam(PARAM_NAME)
.setDescription("Rule name")
.setRequired(true)
.setExampleValue("My custom rule");
action
.createParam(PARAM_DESCRIPTION)
.setDescription("Rule description")
.setRequired(true)
.setExampleValue("Description of my custom rule");
action
.createParam(PARAM_SEVERITY)
.setDescription("Rule severity")
.setPossibleValues(Severity.ALL);
action
.createParam(PARAM_STATUS)
.setDescription("Rule status")
.setDefaultValue(RuleStatus.READY)
.setPossibleValues(RuleStatus.values());
action.createParam(PARAMS)
.setDescription("Parameters as semi-colon list of <key>=<value>, for example 'params=key1=v1;key2=v2' (Only for custom rule)");
action
.createParam(PARAM_PREVENT_REACTIVATION)
.setDescription("If set to true and if the rule has been deactivated (status 'REMOVED'), a status 409 will be returned")
.setDefaultValue(false)
.setBooleanPossibleValues();
}
@Override
public void handle(Request request, Response response) throws Exception {
ruleWsSupport.checkQProfileAdminPermission();
String customKey = request.mandatoryParam(PARAM_CUSTOM_KEY);
try (DbSession dbSession = dbClient.openSession(false)) {
organizationFlags.checkDisabled(dbSession);
try {
NewCustomRule newRule = NewCustomRule.createForCustomRule(customKey, RuleKey.parse(request.mandatoryParam(PARAM_TEMPLATE_KEY)))
.setName(request.mandatoryParam(PARAM_NAME))
.setMarkdownDescription(request.mandatoryParam(PARAM_DESCRIPTION))
.setSeverity(request.mandatoryParam(PARAM_SEVERITY))
.setStatus(RuleStatus.valueOf(request.mandatoryParam(PARAM_STATUS)))
.setPreventReactivation(request.mandatoryParamAsBoolean(PARAM_PREVENT_REACTIVATION));
String params = request.param(PARAMS);
if (!isNullOrEmpty(params)) {
newRule.setParameters(KeyValueFormat.parse(params));
}
writeResponse(dbSession, request, response, ruleCreator.create(dbSession, newRule));
} catch (ReactivationException e) {
response.stream().setStatus(HTTP_CONFLICT);
writeResponse(dbSession, request, response, e.ruleKey());
}
}
}
private void writeResponse(DbSession dbSession, Request request, Response response, RuleKey ruleKey) {
writeProtobuf(createResponse(dbSession, ruleKey), request, response);
}
private Rules.CreateResponse createResponse(DbSession dbSession, RuleKey ruleKey) {
RuleDefinitionDto rule = dbClient.ruleDao().selectDefinitionByKey(dbSession, ruleKey)
.orElseThrow(() -> new IllegalStateException(String.format("Cannot load rule, that has just been created '%s'", ruleKey)));
List<RuleDefinitionDto> templateRules = new ArrayList<>();
if (rule.isCustomRule()) {
Optional<RuleDefinitionDto> templateRule = dbClient.ruleDao().selectDefinitionById(rule.getTemplateId(), dbSession);
templateRule.ifPresent(templateRules::add);
}
List<RuleParamDto> ruleParameters = dbClient.ruleDao().selectRuleParamsByRuleIds(dbSession, singletonList(rule.getId()));
SearchAction.SearchResult searchResult = new SearchAction.SearchResult()
.setRuleParameters(ruleParameters)
.setTemplateRules(templateRules)
.setTotal(1L);
return Rules.CreateResponse.newBuilder()
.setRule(ruleMapper.toWsRule(rule, searchResult, Collections.emptySet()))
.build();
}
}