123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339 |
- /*
- * SonarQube
- * Copyright (C) 2009-2021 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.api.server.rule.internal;
-
- import java.io.IOException;
- import java.net.URL;
- import java.util.Collection;
- import java.util.HashMap;
- import java.util.Locale;
- import java.util.Map;
- import java.util.Set;
- import java.util.TreeSet;
- import javax.annotation.CheckForNull;
- import javax.annotation.Nullable;
- import org.apache.commons.io.IOUtils;
- import org.sonar.api.rule.RuleKey;
- import org.sonar.api.rule.RuleScope;
- import org.sonar.api.rule.RuleStatus;
- import org.sonar.api.rule.Severity;
- import org.sonar.api.rules.RuleType;
- import org.sonar.api.server.debt.DebtRemediationFunction;
- import org.sonar.api.server.rule.RuleTagFormat;
- import org.sonar.api.server.rule.RulesDefinition;
-
- import static java.lang.String.format;
- import static java.nio.charset.StandardCharsets.UTF_8;
- import static org.apache.commons.lang.StringUtils.isEmpty;
- import static org.apache.commons.lang.StringUtils.trimToNull;
- import static org.sonar.api.utils.Preconditions.checkArgument;
- import static org.sonar.api.utils.Preconditions.checkState;
-
- class DefaultNewRule extends RulesDefinition.NewRule {
- private final String pluginKey;
- private final String repoKey;
- private final String key;
- private RuleType type;
- private String name;
- private String htmlDescription;
- private String markdownDescription;
- private String internalKey;
- private String severity = Severity.MAJOR;
- private boolean template;
- private RuleStatus status = RuleStatus.defaultStatus();
- private DebtRemediationFunction debtRemediationFunction;
- private String gapDescription;
- private final Set<String> tags = new TreeSet<>();
- private final Set<String> securityStandards = new TreeSet<>();
- private final Map<String, RulesDefinition.NewParam> paramsByKey = new HashMap<>();
- private final RulesDefinition.DebtRemediationFunctions functions;
- private boolean activatedByDefault;
- private RuleScope scope;
- private final Set<RuleKey> deprecatedRuleKeys = new TreeSet<>();
-
- DefaultNewRule(@Nullable String pluginKey, String repoKey, String key) {
- this.pluginKey = pluginKey;
- this.repoKey = repoKey;
- this.key = key;
- this.functions = new DefaultDebtRemediationFunctions(repoKey, key);
- }
-
- @Override
- public String key() {
- return this.key;
- }
-
- @CheckForNull
- @Override
- public RuleScope scope() {
- return this.scope;
- }
-
- @Override
- public DefaultNewRule setScope(RuleScope scope) {
- this.scope = scope;
- return this;
- }
-
- @Override
- public DefaultNewRule setName(String s) {
- this.name = trimToNull(s);
- return this;
- }
-
- @Override
- public DefaultNewRule setTemplate(boolean template) {
- this.template = template;
- return this;
- }
-
- @Override
- public DefaultNewRule setActivatedByDefault(boolean activatedByDefault) {
- this.activatedByDefault = activatedByDefault;
- return this;
- }
-
- @Override
- public DefaultNewRule setSeverity(String s) {
- checkArgument(Severity.ALL.contains(s), "Severity of rule %s is not correct: %s", this, s);
- this.severity = s;
- return this;
- }
-
- @Override
- public DefaultNewRule setType(RuleType t) {
- this.type = t;
- return this;
- }
-
- @Override
- public DefaultNewRule setHtmlDescription(@Nullable String s) {
- checkState(markdownDescription == null, "Rule '%s' already has a Markdown description", this);
- this.htmlDescription = trimToNull(s);
- return this;
- }
-
- @Override
- public DefaultNewRule setHtmlDescription(@Nullable URL classpathUrl) {
- if (classpathUrl != null) {
- try {
- setHtmlDescription(IOUtils.toString(classpathUrl, UTF_8));
- } catch (IOException e) {
- throw new IllegalStateException("Fail to read: " + classpathUrl, e);
- }
- } else {
- this.htmlDescription = null;
- }
- return this;
- }
-
- @Override
- public DefaultNewRule setMarkdownDescription(@Nullable String s) {
- checkState(htmlDescription == null, "Rule '%s' already has an HTML description", this);
- this.markdownDescription = trimToNull(s);
- return this;
- }
-
- @Override
- public DefaultNewRule setMarkdownDescription(@Nullable URL classpathUrl) {
- if (classpathUrl != null) {
- try {
- setMarkdownDescription(IOUtils.toString(classpathUrl, UTF_8));
- } catch (IOException e) {
- throw new IllegalStateException("Fail to read: " + classpathUrl, e);
- }
- } else {
- this.markdownDescription = null;
- }
- return this;
- }
-
- @Override
- public DefaultNewRule setStatus(RuleStatus status) {
- checkArgument(RuleStatus.REMOVED != status, "Status 'REMOVED' is not accepted on rule '%s'", this);
- this.status = status;
- return this;
- }
-
- @Override
- public RulesDefinition.DebtRemediationFunctions debtRemediationFunctions() {
- return functions;
- }
-
- @Override
- public DefaultNewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction fn) {
- this.debtRemediationFunction = fn;
- return this;
- }
-
- @Override
- public DefaultNewRule setGapDescription(@Nullable String s) {
- this.gapDescription = s;
- return this;
- }
-
- @Override
- public RulesDefinition.NewParam createParam(String paramKey) {
- checkArgument(!paramsByKey.containsKey(paramKey), "The parameter '%s' is declared several times on the rule %s", paramKey, this);
- DefaultNewParam param = new DefaultNewParam(paramKey);
- paramsByKey.put(paramKey, param);
- return param;
- }
-
- @CheckForNull
- @Override
- public RulesDefinition.NewParam param(String paramKey) {
- return paramsByKey.get(paramKey);
- }
-
- @Override
- public Collection<RulesDefinition.NewParam> params() {
- return paramsByKey.values();
- }
-
- @Override
- public DefaultNewRule addTags(String... list) {
- for (String tag : list) {
- RuleTagFormat.validate(tag);
- tags.add(tag);
- }
- return this;
- }
-
- @Override
- public DefaultNewRule setTags(String... list) {
- tags.clear();
- addTags(list);
- return this;
- }
-
- @Override
- public DefaultNewRule addOwaspTop10(RulesDefinition.OwaspTop10... standards) {
- for (RulesDefinition.OwaspTop10 owaspTop10 : standards) {
- String standard = "owaspTop10:" + owaspTop10.name().toLowerCase(Locale.ENGLISH);
- securityStandards.add(standard);
- }
- return this;
- }
-
- @Override
- public DefaultNewRule addCwe(int... nums) {
- for (int num : nums) {
- String standard = "cwe:" + num;
- securityStandards.add(standard);
- }
- return this;
- }
-
- @Override
- public DefaultNewRule setInternalKey(@Nullable String s) {
- this.internalKey = s;
- return this;
- }
-
- void validate() {
- if (isEmpty(name)) {
- throw new IllegalStateException(format("Name of rule %s is empty", this));
- }
- if (isEmpty(htmlDescription) && isEmpty(markdownDescription)) {
- throw new IllegalStateException(format("One of HTML description or Markdown description must be defined for rule %s", this));
- }
- }
-
- @Override
- public DefaultNewRule addDeprecatedRuleKey(String repository, String key) {
- deprecatedRuleKeys.add(RuleKey.of(repository, key));
- return this;
- }
-
- String pluginKey() {
- return pluginKey;
- }
-
- String repoKey() {
- return repoKey;
- }
-
- RuleType type() {
- return type;
- }
-
- String name() {
- return name;
- }
-
- String htmlDescription() {
- return htmlDescription;
- }
-
- String markdownDescription() {
- return markdownDescription;
- }
-
- @CheckForNull
- String internalKey() {
- return internalKey;
- }
-
- String severity() {
- return severity;
- }
-
- boolean template() {
- return template;
- }
-
- RuleStatus status() {
- return status;
- }
-
- DebtRemediationFunction debtRemediationFunction() {
- return debtRemediationFunction;
- }
-
- String gapDescription() {
- return gapDescription;
- }
-
- Set<String> tags() {
- return tags;
- }
-
- Set<String> securityStandards() {
- return securityStandards;
- }
-
- Map<String, RulesDefinition.NewParam> paramsByKey() {
- return paramsByKey;
- }
-
- boolean activatedByDefault() {
- return activatedByDefault;
- }
-
- Set<RuleKey> deprecatedRuleKeys() {
- return deprecatedRuleKeys;
- }
-
- @Override
- public String toString() {
- return format("[repository=%s, key=%s]", repoKey, key);
- }
- }
|