From 93dc9770902dc7e168869d88b5ad731bfc0bedd9 Mon Sep 17 00:00:00 2001
From: Duarte Meneses <duarte.meneses@sonarsource.com>
Date: Wed, 19 Jun 2019 13:56:51 -0500
Subject: Extract implementation from plugin API and create new module
 sonar-plugin-api-impl

---
 .../org/sonar/api/batch/fs/internal/Metadata.java  |  71 ------
 .../sonar/api/batch/fs/internal/PathPattern.java   | 136 ------------
 .../api/batch/fs/internal/SensorStrategy.java      |  41 ----
 .../sonar/api/batch/fs/internal/package-info.java  |  24 --
 .../org/sonar/api/batch/rule/LoadedActiveRule.java | 111 ++++++++++
 .../org/sonar/api/batch/rule/NewActiveRule.java    | 134 ++++++++++++
 .../java/org/sonar/api/batch/rule/NewRule.java     |  92 ++++++++
 .../org/sonar/api/batch/rule/NewRuleParam.java     |  36 +++
 .../java/org/sonar/api/config/Configuration.java   |   4 +-
 .../api/config/internal/ConfigurationBridge.java   |  52 -----
 .../org/sonar/api/config/internal/MapSettings.java | 112 ----------
 .../api/config/internal/MultivalueProperty.java    | 208 ------------------
 .../sonar/api/config/internal/package-info.java    |  23 --
 .../org/sonar/api/internal/MetadataLoader.java     |  79 -------
 .../org/sonar/api/internal/PluginContextImpl.java  |  89 --------
 .../org/sonar/api/internal/SonarRuntimeImpl.java   |  94 --------
 .../java/org/sonar/api/internal/package-info.java  |  24 --
 .../src/main/java/org/sonar/api/rules/Rule.java    |   2 +-
 .../org/sonar/api/server/rule/RulesDefinition.java |  90 ++++----
 .../org/sonar/api/server/ws/internal/PartImpl.java |  44 ----
 .../api/server/ws/internal/SimpleGetRequest.java   | 148 -------------
 .../api/server/ws/internal/ValidatingRequest.java  | 242 ---------------------
 .../sonar/api/server/ws/internal/package-info.java |  23 --
 .../java/org/sonar/api/utils/Preconditions.java    |   4 +
 .../utils/internal/AlwaysIncreasingSystem2.java    |  71 ------
 .../api/utils/internal/DefaultTempFolder.java      | 126 -----------
 .../sonar/api/utils/internal/JUnitTempFolder.java  | 108 ---------
 .../api/utils/internal/TempFolderCleaner.java      |  52 -----
 .../org/sonar/api/utils/internal/TestSystem2.java  |  52 -----
 .../org/sonar/api/utils/internal/WorkDuration.java | 194 -----------------
 .../org/sonar/api/utils/internal/package-info.java |  24 --
 31 files changed, 423 insertions(+), 2087 deletions(-)
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/Metadata.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java
 create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/LoadedActiveRule.java
 create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewActiveRule.java
 create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRule.java
 create mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRuleParam.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MapSettings.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MultivalueProperty.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/config/internal/package-info.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/internal/MetadataLoader.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/internal/PluginContextImpl.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/internal/package-info.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/PartImpl.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/SimpleGetRequest.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/package-info.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/AlwaysIncreasingSystem2.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/DefaultTempFolder.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TempFolderCleaner.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TestSystem2.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/WorkDuration.java
 delete mode 100644 sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/package-info.java

(limited to 'sonar-plugin-api/src/main')

diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/Metadata.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/Metadata.java
deleted file mode 100644
index 50c0d753bcd..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/Metadata.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.batch.fs.internal;
-
-import java.util.Arrays;
-
-import javax.annotation.concurrent.Immutable;
-
-@Immutable
-public class Metadata {
-  private final int lines;
-  private final int nonBlankLines;
-  private final String hash;
-  private final int[] originalLineStartOffsets;
-  private final int[] originalLineEndOffsets;
-  private final int lastValidOffset;
-
-  public Metadata(int lines, int nonBlankLines, String hash, int[] originalLineStartOffsets, int[] originalLineEndOffsets, int lastValidOffset) {
-    this.lines = lines;
-    this.nonBlankLines = nonBlankLines;
-    this.hash = hash;
-    this.originalLineStartOffsets = Arrays.copyOf(originalLineStartOffsets, originalLineStartOffsets.length);
-    this.originalLineEndOffsets = Arrays.copyOf(originalLineEndOffsets, originalLineEndOffsets.length);
-    this.lastValidOffset = lastValidOffset;
-  }
-
-  public int lines() {
-    return lines;
-  }
-
-  public int nonBlankLines() {
-    return nonBlankLines;
-  }
-
-  public String hash() {
-    return hash;
-  }
-
-  public int[] originalLineStartOffsets() {
-    return originalLineStartOffsets;
-  }
-
-  public int[] originalLineEndOffsets() {
-    return originalLineEndOffsets;
-  }
-
-  public int lastValidOffset() {
-    return lastValidOffset;
-  }
-
-  public boolean isEmpty() {
-    return lastValidOffset == 0;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java
deleted file mode 100644
index 41287d42011..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/PathPattern.java
+++ /dev/null
@@ -1,136 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.batch.fs.internal;
-
-import java.nio.file.Path;
-import javax.annotation.concurrent.ThreadSafe;
-import org.apache.commons.io.FilenameUtils;
-import org.apache.commons.lang.StringUtils;
-import org.sonar.api.utils.PathUtils;
-import org.sonar.api.utils.WildcardPattern;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-@ThreadSafe
-public abstract class PathPattern {
-
-  private static final Logger LOG = Loggers.get(PathPattern.class);
-
-  /**
-   * @deprecated since 6.6
-   */
-  @Deprecated
-  private static final String ABSOLUTE_PATH_PATTERN_PREFIX = "file:";
-  final WildcardPattern pattern;
-
-  PathPattern(String pattern) {
-    this.pattern = WildcardPattern.create(pattern);
-  }
-
-  public abstract boolean match(Path absolutePath, Path relativePath);
-
-  public abstract boolean match(Path absolutePath, Path relativePath, boolean caseSensitiveFileExtension);
-
-  public static PathPattern create(String s) {
-    String trimmed = StringUtils.trim(s);
-    if (StringUtils.startsWithIgnoreCase(trimmed, ABSOLUTE_PATH_PATTERN_PREFIX)) {
-      LOG.warn("Using absolute path pattern is deprecated. Please use relative path instead of '" + trimmed + "'");
-      return new AbsolutePathPattern(StringUtils.substring(trimmed, ABSOLUTE_PATH_PATTERN_PREFIX.length()));
-    }
-    return new RelativePathPattern(trimmed);
-  }
-
-  public static PathPattern[] create(String[] s) {
-    PathPattern[] result = new PathPattern[s.length];
-    for (int i = 0; i < s.length; i++) {
-      result[i] = create(s[i]);
-    }
-    return result;
-  }
-
-  /**
-   * @deprecated since 6.6
-   */
-  @Deprecated
-  private static class AbsolutePathPattern extends PathPattern {
-    private AbsolutePathPattern(String pattern) {
-      super(pattern);
-    }
-
-    @Override
-    public boolean match(Path absolutePath, Path relativePath) {
-      return match(absolutePath, relativePath, true);
-    }
-
-    @Override
-    public boolean match(Path absolutePath, Path relativePath, boolean caseSensitiveFileExtension) {
-      String path = PathUtils.sanitize(absolutePath.toString());
-      if (!caseSensitiveFileExtension) {
-        String extension = sanitizeExtension(FilenameUtils.getExtension(path));
-        if (StringUtils.isNotBlank(extension)) {
-          path = StringUtils.removeEndIgnoreCase(path, extension);
-          path = path + extension;
-        }
-      }
-      return pattern.match(path);
-    }
-
-    @Override
-    public String toString() {
-      return ABSOLUTE_PATH_PATTERN_PREFIX + pattern.toString();
-    }
-  }
-
-  /**
-   * Path relative to module basedir
-   */
-  private static class RelativePathPattern extends PathPattern {
-    private RelativePathPattern(String pattern) {
-      super(pattern);
-    }
-
-    @Override
-    public boolean match(Path absolutePath, Path relativePath) {
-      return match(absolutePath, relativePath, true);
-    }
-
-    @Override
-    public boolean match(Path absolutePath, Path relativePath, boolean caseSensitiveFileExtension) {
-      String path = PathUtils.sanitize(relativePath.toString());
-      if (!caseSensitiveFileExtension) {
-        String extension = sanitizeExtension(FilenameUtils.getExtension(path));
-        if (StringUtils.isNotBlank(extension)) {
-          path = StringUtils.removeEndIgnoreCase(path, extension);
-          path = path + extension;
-        }
-      }
-      return path != null && pattern.match(path);
-    }
-
-    @Override
-    public String toString() {
-      return pattern.toString();
-    }
-  }
-
-  static String sanitizeExtension(String suffix) {
-    return StringUtils.lowerCase(StringUtils.removeStart(suffix, "."));
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java
deleted file mode 100644
index adde73809f6..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/SensorStrategy.java
+++ /dev/null
@@ -1,41 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.batch.fs.internal;
-
-import org.sonar.api.batch.fs.InputFile;
-
-/**
- * A shared, mutable object in the project container.
- * It's used during the execution of sensors to decide whether
- * sensors should be executed once for the entire project, or per-module.
- * It is also injected into each InputFile to change the behavior of {@link InputFile#relativePath()}
- */
-public class SensorStrategy {
-
-  private boolean global = true;
-
-  public boolean isGlobal() {
-    return global;
-  }
-
-  public void setGlobal(boolean global) {
-    this.global = global;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java
deleted file mode 100644
index 4af8d775684..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/fs/internal/package-info.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.batch.fs.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/LoadedActiveRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/LoadedActiveRule.java
new file mode 100644
index 00000000000..fa22fb46f13
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/LoadedActiveRule.java
@@ -0,0 +1,111 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.batch.rule;
+
+import java.util.Map;
+import javax.annotation.CheckForNull;
+import javax.annotation.Nullable;
+import org.sonar.api.rule.RuleKey;
+
+public class LoadedActiveRule {
+  private RuleKey ruleKey;
+  private String severity;
+  private String name;
+  private String language;
+  private Map<String, String> params;
+  private long createdAt;
+  private long updatedAt;
+  private String templateRuleKey;
+  private String internalKey;
+
+  public RuleKey getRuleKey() {
+    return ruleKey;
+  }
+
+  public void setRuleKey(RuleKey ruleKey) {
+    this.ruleKey = ruleKey;
+  }
+
+  public String getName() {
+    return name;
+  }
+
+  public void setName(String name) {
+    this.name = name;
+  }
+
+  public String getSeverity() {
+    return severity;
+  }
+
+  public void setSeverity(String severity) {
+    this.severity = severity;
+  }
+
+  public String getLanguage() {
+    return language;
+  }
+
+  public void setLanguage(String language) {
+    this.language = language;
+  }
+
+  public Map<String, String> getParams() {
+    return params;
+  }
+
+  public void setParams(Map<String, String> params) {
+    this.params = params;
+  }
+
+  public long getCreatedAt() {
+    return createdAt;
+  }
+
+  public void setCreatedAt(long createdAt) {
+    this.createdAt = createdAt;
+  }
+
+  public long getUpdatedAt() {
+    return updatedAt;
+  }
+
+  public void setUpdatedAt(long updatedAt) {
+    this.updatedAt = updatedAt;
+  }
+
+  @CheckForNull
+  public String getTemplateRuleKey() {
+    return templateRuleKey;
+  }
+
+  public void setTemplateRuleKey(@Nullable String templateRuleKey) {
+    this.templateRuleKey = templateRuleKey;
+  }
+
+  public String getInternalKey() {
+    return internalKey;
+  }
+
+  public void setInternalKey(String internalKey) {
+    this.internalKey = internalKey;
+  }
+
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewActiveRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewActiveRule.java
new file mode 100644
index 00000000000..6f14a13a990
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewActiveRule.java
@@ -0,0 +1,134 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.batch.rule;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Nullable;
+import javax.annotation.concurrent.Immutable;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.Severity;
+
+/**
+ * @since 4.2
+ */
+@Immutable
+public class NewActiveRule {
+  final RuleKey ruleKey;
+  final String name;
+  final String severity;
+  final Map<String, String> params;
+  final long createdAt;
+  final long updatedAt;
+  final String internalKey;
+  final String language;
+  final String templateRuleKey;
+  final String qProfileKey;
+
+  NewActiveRule(Builder builder) {
+    this.ruleKey = builder.ruleKey;
+    this.name = builder.name;
+    this.severity = builder.severity;
+    this.params = builder.params;
+    this.createdAt = builder.createdAt;
+    this.updatedAt = builder.updatedAt;
+    this.internalKey = builder.internalKey;
+    this.language = builder.language;
+    this.templateRuleKey = builder.templateRuleKey;
+    this.qProfileKey = builder.qProfileKey;
+  }
+
+  public RuleKey ruleKey() {
+    return this.ruleKey;
+  }
+
+  public static class Builder {
+    private RuleKey ruleKey;
+    private String name;
+    private String severity = Severity.defaultSeverity();
+    private Map<String, String> params = new HashMap<>();
+    private long createdAt;
+    private long updatedAt;
+    private String internalKey;
+    private String language;
+    private String templateRuleKey;
+    private String qProfileKey;
+
+    public Builder setRuleKey(RuleKey ruleKey) {
+      this.ruleKey = ruleKey;
+      return this;
+    }
+
+    public Builder setName(String name) {
+      this.name = name;
+      return this;
+    }
+
+    public Builder setSeverity(@Nullable String severity) {
+      this.severity = StringUtils.defaultIfBlank(severity, Severity.defaultSeverity());
+      return this;
+    }
+
+    public Builder setParam(String key, @Nullable String value) {
+      // possible improvement : check that the param key exists in rule definition
+      if (value == null) {
+        params.remove(key);
+      } else {
+        params.put(key, value);
+      }
+      return this;
+    }
+
+    public Builder setCreatedAt(long createdAt) {
+      this.createdAt = createdAt;
+      return this;
+    }
+
+    public Builder setUpdatedAt(long updatedAt) {
+      this.updatedAt = updatedAt;
+      return this;
+    }
+
+    public Builder setInternalKey(@Nullable String internalKey) {
+      this.internalKey = internalKey;
+      return this;
+    }
+
+    public Builder setLanguage(@Nullable String language) {
+      this.language = language;
+      return this;
+    }
+
+    public Builder setTemplateRuleKey(@Nullable String templateRuleKey) {
+      this.templateRuleKey = templateRuleKey;
+      return this;
+    }
+
+    public Builder setQProfileKey(String qProfileKey) {
+      this.qProfileKey = qProfileKey;
+      return this;
+    }
+
+    public NewActiveRule build() {
+      return new NewActiveRule(this);
+    }
+  }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRule.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRule.java
new file mode 100644
index 00000000000..edcf70f8ce6
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRule.java
@@ -0,0 +1,92 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.batch.rule;
+
+import java.util.HashMap;
+import java.util.Map;
+import javax.annotation.Nullable;
+import org.apache.commons.lang.ObjectUtils;
+import org.apache.commons.lang.StringUtils;
+import org.sonar.api.rule.RuleKey;
+import org.sonar.api.rule.RuleStatus;
+import org.sonar.api.rule.Severity;
+
+public class NewRule {
+
+  private static final String DEFAULT_SEVERITY = Severity.defaultSeverity();
+
+  final RuleKey key;
+  Integer id;
+  String name;
+  String description;
+  String severity = DEFAULT_SEVERITY;
+  String type;
+  String internalKey;
+  RuleStatus status = RuleStatus.defaultStatus();
+  Map<String, NewRuleParam> params = new HashMap<>();
+
+  public NewRule(RuleKey key) {
+    this.key = key;
+  }
+
+  public NewRule setId(@Nullable Integer id) {
+    this.id = id;
+    return this;
+  }
+
+  public NewRule setDescription(@Nullable String description) {
+    this.description = description;
+    return this;
+  }
+
+  public NewRule setName(@Nullable String s) {
+    this.name = s;
+    return this;
+  }
+
+  public NewRule setSeverity(@Nullable String severity) {
+    this.severity = StringUtils.defaultIfBlank(severity, DEFAULT_SEVERITY);
+    return this;
+  }
+  
+  public NewRule setType(@Nullable String type) {
+    this.type = type;
+    return this;
+  }
+
+  public NewRule setStatus(@Nullable RuleStatus s) {
+    this.status = (RuleStatus) ObjectUtils.defaultIfNull(s, RuleStatus.defaultStatus());
+    return this;
+  }
+
+  public NewRule setInternalKey(@Nullable String s) {
+    this.internalKey = s;
+    return this;
+  }
+
+  public NewRuleParam addParam(String paramKey) {
+    if (params.containsKey(paramKey)) {
+      throw new IllegalStateException(String.format("Parameter '%s' already exists on rule '%s'", paramKey, key));
+    }
+    NewRuleParam param = new NewRuleParam(paramKey);
+    params.put(paramKey, param);
+    return param;
+  }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRuleParam.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRuleParam.java
new file mode 100644
index 00000000000..f06830d9245
--- /dev/null
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/rule/NewRuleParam.java
@@ -0,0 +1,36 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2019 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.batch.rule;
+
+import javax.annotation.Nullable;
+
+public class NewRuleParam {
+  final String key;
+  String description;
+
+  NewRuleParam(String key) {
+    this.key = key;
+  }
+
+  public NewRuleParam setDescription(@Nullable String s) {
+    description = s;
+    return this;
+  }
+}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/Configuration.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/Configuration.java
index 2a1ee512bc0..3afb8c8608e 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/config/Configuration.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/config/Configuration.java
@@ -22,7 +22,6 @@ package org.sonar.api.config;
 import java.util.Optional;
 import org.sonar.api.scanner.ScannerSide;
 import org.sonar.api.ce.ComputeEngineSide;
-import org.sonar.api.config.internal.MapSettings;
 import org.sonar.api.server.ServerSide;
 import org.sonarsource.api.sonarlint.SonarLintSide;
 
@@ -65,7 +64,7 @@ import org.sonarsource.api.sonarlint.SonarLintSide;
  * </pre>
  *
  * <p>
- * For testing, and only for testing, the in-memory implementation {@link MapSettings} can be used.
+ * For testing, and only for testing, the in-memory implementation MapSettings can be used.
  * <pre>
  * {@literal @}Test
  * public void my_test() {
@@ -76,7 +75,6 @@ import org.sonarsource.api.sonarlint.SonarLintSide;
  * }
  * </pre>
  *
- * @see MapSettings
  * @see PropertyDefinition
  * @since 6.5
  */
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java
deleted file mode 100644
index 5455cf03191..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/ConfigurationBridge.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.config.internal;
-
-import java.util.Optional;
-import org.sonar.api.config.Settings;
-import org.sonar.api.config.Configuration;
-
-/**
- * Used to help migration from {@link Settings} to {@link Configuration}
- */
-public class ConfigurationBridge implements Configuration {
-
-  private final Settings settings;
-
-  public ConfigurationBridge(Settings settings) {
-    this.settings = settings;
-  }
-
-  @Override
-  public Optional<String> get(String key) {
-    return Optional.ofNullable(settings.getString(key));
-  }
-
-  @Override
-  public boolean hasKey(String key) {
-    return settings.hasKey(key);
-  }
-
-  @Override
-  public String[] getStringArray(String key) {
-    return settings.getStringArray(key);
-  }
-
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MapSettings.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MapSettings.java
deleted file mode 100644
index 5d07d607923..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MapSettings.java
+++ /dev/null
@@ -1,112 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.config.internal;
-
-import java.util.HashMap;
-import java.util.Map;
-import java.util.Optional;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.config.Encryption;
-import org.sonar.api.config.PropertyDefinitions;
-import org.sonar.api.config.Settings;
-
-import static java.util.Collections.unmodifiableMap;
-import static java.util.Objects.requireNonNull;
-
-/**
- * In-memory map-based implementation of {@link Settings}. It must be used
- * <b>only for unit tests</b>. This is not the implementation
- * deployed at runtime, so non-test code must never cast
- * {@link Settings} to {@link MapSettings}.
- *
- * @since 6.1
- */
-public class MapSettings extends Settings {
-
-  private final Map<String, String> props = new HashMap<>();
-  private final ConfigurationBridge configurationBridge;
-
-  public MapSettings() {
-    this(new PropertyDefinitions());
-  }
-
-  public MapSettings(PropertyDefinitions definitions) {
-    super(definitions, new Encryption(null));
-    configurationBridge = new ConfigurationBridge(this);
-  }
-
-  @Override
-  protected Optional<String> get(String key) {
-    return Optional.ofNullable(props.get(key));
-  }
-
-  @Override
-  protected void set(String key, String value) {
-    props.put(
-      requireNonNull(key, "key can't be null"),
-      requireNonNull(value, "value can't be null").trim());
-  }
-
-  @Override
-  protected void remove(String key) {
-    props.remove(key);
-  }
-
-  @Override
-  public Map<String, String> getProperties() {
-    return unmodifiableMap(props);
-  }
-
-  /**
-   * Delete all properties
-   */
-  public MapSettings clear() {
-    props.clear();
-    return this;
-  }
-
-  @Override
-  public MapSettings setProperty(String key, String value) {
-    return (MapSettings) super.setProperty(key, value);
-  }
-
-  @Override
-  public MapSettings setProperty(String key, Integer value) {
-    return (MapSettings) super.setProperty(key, value);
-  }
-
-  @Override
-  public MapSettings setProperty(String key, Boolean value) {
-    return (MapSettings) super.setProperty(key, value);
-  }
-
-  @Override
-  public MapSettings setProperty(String key, Long value) {
-    return (MapSettings) super.setProperty(key, value);
-  }
-
-  /**
-   * @return a {@link Configuration} proxy on top of this existing {@link Settings} implementation. Changes are reflected in the {@link Configuration} object.
-   * @since 6.5
-   */
-  public Configuration asConfig() {
-    return configurationBridge;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MultivalueProperty.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MultivalueProperty.java
deleted file mode 100644
index dab98c55781..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/MultivalueProperty.java
+++ /dev/null
@@ -1,208 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.config.internal;
-
-import java.io.IOException;
-import java.io.StringReader;
-import java.util.ArrayList;
-import java.util.Iterator;
-import java.util.List;
-import java.util.function.Function;
-import org.apache.commons.csv.CSVFormat;
-import org.apache.commons.csv.CSVParser;
-import org.apache.commons.csv.CSVRecord;
-import org.apache.commons.lang.ArrayUtils;
-
-public class MultivalueProperty {
-  private MultivalueProperty() {
-    // prevents instantiation
-  }
-
-  public static String[] parseAsCsv(String key, String value) {
-    return parseAsCsv(key, value, Function.identity());
-  }
-
-  public static String[] parseAsCsv(String key, String value, Function<String, String> valueProcessor) {
-    String cleanValue = MultivalueProperty.trimFieldsAndRemoveEmptyFields(value);
-    List<String> result = new ArrayList<>();
-    try (CSVParser csvParser = CSVFormat.RFC4180
-      .withHeader((String) null)
-      .withIgnoreEmptyLines()
-      .withIgnoreSurroundingSpaces()
-      .parse(new StringReader(cleanValue))) {
-      List<CSVRecord> records = csvParser.getRecords();
-      if (records.isEmpty()) {
-        return ArrayUtils.EMPTY_STRING_ARRAY;
-      }
-      processRecords(result, records, valueProcessor);
-      return result.toArray(new String[result.size()]);
-    } catch (IOException e) {
-      throw new IllegalStateException("Property: '" + key + "' doesn't contain a valid CSV value: '" + value + "'", e);
-    }
-  }
-
-  /**
-   * In most cases we expect a single record. <br>Having multiple records means the input value was splitted over multiple lines (this is common in Maven).
-   * For example:
-   * <pre>
-   *   &lt;sonar.exclusions&gt;
-   *     src/foo,
-   *     src/bar,
-   *     src/biz
-   *   &lt;sonar.exclusions&gt;
-   * </pre>
-   * In this case records will be merged to form a single list of items. Last item of a record is appended to first item of next record.
-   * <p>
-   * This is a very curious case, but we try to preserve line break in the middle of an item:
-   * <pre>
-   *   &lt;sonar.exclusions&gt;
-   *     a
-   *     b,
-   *     c
-   *   &lt;sonar.exclusions&gt;
-   * </pre>
-   * will produce ['a\nb', 'c']
-   */
-  private static void processRecords(List<String> result, List<CSVRecord> records, Function<String, String> valueProcessor) {
-    for (CSVRecord csvRecord : records) {
-      Iterator<String> it = csvRecord.iterator();
-      if (!result.isEmpty()) {
-        String next = it.next();
-        if (!next.isEmpty()) {
-          int lastItemIdx = result.size() - 1;
-          String previous = result.get(lastItemIdx);
-          if (previous.isEmpty()) {
-            result.set(lastItemIdx, valueProcessor.apply(next));
-          } else {
-            result.set(lastItemIdx, valueProcessor.apply(previous + "\n" + next));
-          }
-        }
-      }
-      it.forEachRemaining(s -> {
-        String apply = valueProcessor.apply(s);
-        result.add(apply);
-      });
-    }
-  }
-
-  /**
-   * Removes the empty fields from the value of a multi-value property from empty fields, including trimming each field.
-   * <p>
-   * Quotes can be used to prevent an empty field to be removed (as it is used to preserve empty spaces).
-   * <ul>
-   *    <li>{@code "" => ""}</li>
-   *    <li>{@code " " => ""}</li>
-   *    <li>{@code "," => ""}</li>
-   *    <li>{@code ",," => ""}</li>
-   *    <li>{@code ",,," => ""}</li>
-   *    <li>{@code ",a" => "a"}</li>
-   *    <li>{@code "a," => "a"}</li>
-   *    <li>{@code ",a," => "a"}</li>
-   *    <li>{@code "a,,b" => "a,b"}</li>
-   *    <li>{@code "a,   ,b" => "a,b"}</li>
-   *    <li>{@code "a,\"\",b" => "a,b"}</li>
-   *    <li>{@code "\"a\",\"b\"" => "\"a\",\"b\""}</li>
-   *    <li>{@code "\"  a  \",\"b \"" => "\"  a  \",\"b \""}</li>
-   *    <li>{@code "\"a\",\"\",\"b\"" => "\"a\",\"\",\"b\""}</li>
-   *    <li>{@code "\"a\",\"  \",\"b\"" => "\"a\",\"  \",\"b\""}</li>
-   *    <li>{@code "\"  a,,b,c  \",\"d \"" => "\"  a,,b,c  \",\"d \""}</li>
-   *    <li>{@code "a,\"  \",b" => "ab"]}</li>
-   * </ul>
-   */
-  static String trimFieldsAndRemoveEmptyFields(String str) {
-    char[] chars = str.toCharArray();
-    char[] res = new char[chars.length];
-    /*
-     * set when reading the first non trimmable char after a separator char (or the beginning of the string)
-     * unset when reading a separator
-     */
-    boolean inField = false;
-    boolean inQuotes = false;
-    int i = 0;
-    int resI = 0;
-    for (; i < chars.length; i++) {
-      boolean isSeparator = chars[i] == ',';
-      if (!inQuotes && isSeparator) {
-        // exiting field (may already be unset)
-        inField = false;
-        if (resI > 0) {
-          resI = retroTrim(res, resI);
-        }
-      } else {
-        boolean isTrimmed = !inQuotes && istrimmable(chars[i]);
-        if (isTrimmed && !inField) {
-          // we haven't meet any non trimmable char since the last separator yet
-          continue;
-        }
-
-        boolean isEscape = isEscapeChar(chars[i]);
-        if (isEscape) {
-          inQuotes = !inQuotes;
-        }
-
-        // add separator as we already had one field
-        if (!inField && resI > 0) {
-          res[resI] = ',';
-          resI++;
-        }
-
-        // register in field (may already be set)
-        inField = true;
-        // copy current char
-        res[resI] = chars[i];
-        resI++;
-      }
-    }
-    // inQuotes can only be true at this point if quotes are unbalanced
-    if (!inQuotes) {
-      // trim end of str
-      resI = retroTrim(res, resI);
-    }
-    return new String(res, 0, resI);
-  }
-
-  private static boolean isEscapeChar(char aChar) {
-    return aChar == '"';
-  }
-
-  private static boolean istrimmable(char aChar) {
-    return aChar <= ' ';
-  }
-
-  /**
-   * Reads from index {@code resI} to the beginning into {@code res} looking up the location of the trimmable char with
-   * the lowest index before encountering a non-trimmable char.
-   * <p>
-   * This basically trims {@code res} from any trimmable char at its end.
-   *
-   * @return index of next location to put new char in res
-   */
-  private static int retroTrim(char[] res, int resI) {
-    int i = resI;
-    while (i >= 1) {
-      if (!istrimmable(res[i - 1])) {
-        return i;
-      }
-      i--;
-    }
-    return i;
-  }
-
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/package-info.java
deleted file mode 100644
index f6774798046..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/config/internal/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.config.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/internal/MetadataLoader.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/MetadataLoader.java
deleted file mode 100644
index bb155753d55..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/internal/MetadataLoader.java
+++ /dev/null
@@ -1,79 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.internal;
-
-import java.io.IOException;
-import java.net.URL;
-import java.nio.charset.StandardCharsets;
-import java.util.Scanner;
-import org.sonar.api.SonarEdition;
-import org.sonar.api.utils.System2;
-import org.sonar.api.utils.Version;
-
-import static org.apache.commons.lang.StringUtils.trimToEmpty;
-
-/**
- * For internal use
- *
- * @since 7.8
- */
-public class MetadataLoader {
-
-  private static final String VERSION_FILE_PATH = "/sonar-api-version.txt";
-  private static final String EDITION_FILE_PATH = "/sonar-edition.txt";
-
-  private MetadataLoader() {
-    // only static methods
-  }
-
-  public static Version loadVersion(System2 system) {
-    try {
-      URL url = system.getResource(VERSION_FILE_PATH);
-      Scanner scanner = new Scanner(url.openStream(), StandardCharsets.UTF_8.name());
-      String versionInFile = scanner.nextLine();
-      return Version.parse(versionInFile);
-    } catch (IOException e) {
-      throw new IllegalStateException("Can not load " + VERSION_FILE_PATH + " from classpath ", e);
-    }
-  }
-
-  public static SonarEdition loadEdition(System2 system) {
-    try {
-      URL url = system.getResource(EDITION_FILE_PATH);
-      if (url == null) {
-        return SonarEdition.COMMUNITY;
-      }
-      Scanner scanner = new Scanner(url.openStream(), StandardCharsets.UTF_8.name());
-      String editionInFile = scanner.nextLine();
-      return parseEdition(editionInFile);
-    } catch (IOException e) {
-      throw new IllegalStateException("Can not load " + EDITION_FILE_PATH + " from classpath", e);
-    }
-  }
-
-  static SonarEdition parseEdition(String edition) {
-    String str = trimToEmpty(edition.toUpperCase());
-    try {
-      return SonarEdition.valueOf(str);
-    } catch (IllegalArgumentException e) {
-      throw new IllegalStateException(String.format("Invalid edition found in '%s': '%s'", EDITION_FILE_PATH, str));
-    }
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/internal/PluginContextImpl.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/PluginContextImpl.java
deleted file mode 100644
index 3fccb4c59cc..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/internal/PluginContextImpl.java
+++ /dev/null
@@ -1,89 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.internal;
-
-import org.sonar.api.Plugin;
-import org.sonar.api.SonarRuntime;
-import org.sonar.api.config.Configuration;
-import org.sonar.api.config.internal.MapSettings;
-
-/**
- * Implementation of {@link Plugin.Context} that plugins could use in their unit tests.
- *
- * Example:
- *
- * <pre>
- *   import org.sonar.api.internal.SonarRuntimeImpl;
- *   import org.sonar.api.config.internal.MapSettings;
- *
- *   ...
- *
- *   SonarRuntime runtime = SonarRuntimeImpl.forSonarQube(Version.create(7, 1), SonarQubeSide.SCANNER);
- *   MapSettings settings = new MapSettings().setProperty("foo", "bar");
- *   Plugin.Context context = new PluginContextImpl.Builder()
- *     .setSonarRuntime(runtime)
- *     .setBootConfiguration(settings.asConfig());
- *     .build();
- * </pre>
- *
- * @since 7.1
- */
-public class PluginContextImpl extends Plugin.Context {
-
-  private final Configuration bootConfiguration;
-
-  private PluginContextImpl(Builder builder) {
-    super(builder.sonarRuntime);
-    this.bootConfiguration = builder.bootConfiguration != null ? builder.bootConfiguration : new MapSettings().asConfig();
-  }
-
-  @Override
-  public Configuration getBootConfiguration() {
-    return bootConfiguration;
-  }
-
-  public static class Builder {
-    private SonarRuntime sonarRuntime;
-    private Configuration bootConfiguration;
-
-    /**
-     * Required.
-     * @see SonarRuntimeImpl
-     * @return this
-     */
-    public Builder setSonarRuntime(SonarRuntime r) {
-      this.sonarRuntime = r;
-      return this;
-    }
-
-    /**
-     * If not set, then an empty configuration is used.
-     * @return this
-     */
-    public Builder setBootConfiguration(Configuration c) {
-      this.bootConfiguration = c;
-      return this;
-    }
-
-    public Plugin.Context build() {
-      return new PluginContextImpl(this);
-    }
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java
deleted file mode 100644
index 3f69f36bb4e..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/internal/SonarRuntimeImpl.java
+++ /dev/null
@@ -1,94 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.internal;
-
-import javax.annotation.Nullable;
-import javax.annotation.concurrent.Immutable;
-import org.sonar.api.SonarEdition;
-import org.sonar.api.SonarProduct;
-import org.sonar.api.SonarQubeSide;
-import org.sonar.api.SonarRuntime;
-import org.sonar.api.utils.Version;
-
-import static java.util.Objects.requireNonNull;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-
-/**
- * @since 6.0
- */
-@Immutable
-public class SonarRuntimeImpl implements SonarRuntime {
-
-  private final Version version;
-  private final SonarProduct product;
-  private final SonarQubeSide sonarQubeSide;
-  private final SonarEdition edition;
-
-  private SonarRuntimeImpl(Version version, SonarProduct product, @Nullable SonarQubeSide sonarQubeSide, @Nullable SonarEdition edition) {
-    this.edition = edition;
-    requireNonNull(product);
-    checkArgument((product == SonarProduct.SONARQUBE) == (sonarQubeSide != null), "sonarQubeSide should be provided only for SonarQube product");
-    checkArgument((product == SonarProduct.SONARQUBE) == (edition != null), "edition should be provided only for SonarQube product");
-    this.version = requireNonNull(version);
-    this.product = product;
-    this.sonarQubeSide = sonarQubeSide;
-  }
-
-  @Override
-  public Version getApiVersion() {
-    return version;
-  }
-
-  @Override
-  public SonarProduct getProduct() {
-    return product;
-  }
-
-  @Override
-  public SonarQubeSide getSonarQubeSide() {
-    if (sonarQubeSide == null) {
-      throw new UnsupportedOperationException("Can only be called in SonarQube");
-    }
-    return sonarQubeSide;
-  }
-
-  @Override
-  public SonarEdition getEdition() {
-    if (sonarQubeSide == null) {
-      throw new UnsupportedOperationException("Can only be called in SonarQube");
-    }
-    return edition;
-  }
-
-  /**
-   * Create an instance for SonarQube runtime environment.
-   */
-  public static SonarRuntime forSonarQube(Version version, SonarQubeSide side, SonarEdition edition) {
-    return new SonarRuntimeImpl(version, SonarProduct.SONARQUBE, side, edition);
-  }
-
-  /**
-   * Create an instance for SonarLint runtime environment.
-   */
-  public static SonarRuntime forSonarLint(Version version) {
-    return new SonarRuntimeImpl(version, SonarProduct.SONARLINT, null, null);
-  }
-
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/internal/package-info.java
deleted file mode 100644
index 17dc1220665..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/internal/package-info.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/rules/Rule.java b/sonar-plugin-api/src/main/java/org/sonar/api/rules/Rule.java
index 2eb4d07f57d..6f8452a8bd4 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/rules/Rule.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/rules/Rule.java
@@ -324,7 +324,7 @@ public class Rule {
    */
   public Rule setStatus(String status) {
     if (!STATUS_LIST.contains(status)) {
-      throw new SonarException("The status of a rule can only contain : " + String.join(", ", STATUS_LIST));
+      throw new IllegalStateException("The status of a rule can only contain : " + String.join(", ", STATUS_LIST));
     }
     this.status = status;
     return this;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
index 6ad36f5998e..d249ac0bda8 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/rule/RulesDefinition.java
@@ -347,7 +347,7 @@ public interface RulesDefinition {
   /**
    * Instantiated by core but not by plugins, except for their tests.
    */
-  interface Context {
+  abstract class Context {
     /*
      * New builder for {@link org.sonar.api.server.rule.RulesDefinition.Repository}.
      * <br>
@@ -355,7 +355,7 @@ public interface RulesDefinition {
      * the FbContrib plugin contributes to the Findbugs plugin rules. In this case no need
      * to execute {@link org.sonar.api.server.rule.RulesDefinition.NewRepository#setName(String)}
      */
-    NewRepository createRepository(String key, String language);
+    public abstract NewRepository createRepository(String key, String language);
 
     /**
      * Creates a repository of rules from external rule engines.
@@ -363,34 +363,34 @@ public interface RulesDefinition {
      *
      * @since 7.2
      */
-    NewRepository createExternalRepository(String engineId, String language);
+    public abstract NewRepository createExternalRepository(String engineId, String language);
 
     /**
      * @deprecated since 5.2. Simply use {@link #createRepository(String, String)}
      */
     @Deprecated
-    NewRepository extendRepository(String key, String language);
+    public abstract NewRepository extendRepository(String key, String language);
 
     @CheckForNull
-    Repository repository(String key);
+    public abstract Repository repository(String key);
 
-    List<Repository> repositories();
+    public abstract List<Repository> repositories();
 
     /**
      * @deprecated returns empty list since 5.2. Concept of "extended repository" was misleading and not valuable. Simply declare
      * repositories and use {@link #repositories()}. See http://jira.sonarsource.com/browse/SONAR-6709
      */
     @Deprecated
-    List<ExtendedRepository> extendedRepositories(String repositoryKey);
+    public abstract List<ExtendedRepository> extendedRepositories(String repositoryKey);
 
     /**
      * @deprecated returns empty list since 5.2. Concept of "extended repository" was misleading and not valuable. Simply declare
      * repositories and use {@link #repositories()}. See http://jira.sonarsource.com/browse/SONAR-6709
      */
     @Deprecated
-    List<ExtendedRepository> extendedRepositories();
+    public abstract List<ExtendedRepository> extendedRepositories();
 
-    void setCurrentPluginKey(@Nullable String pluginKey);
+    public abstract void setCurrentPluginKey(@Nullable String pluginKey);
   }
 
   interface NewExtendedRepository {
@@ -484,36 +484,36 @@ public interface RulesDefinition {
     DebtRemediationFunction create(DebtRemediationFunction.Type type, @Nullable String gapMultiplier, @Nullable String baseEffort);
   }
 
-  interface NewRule {
+  abstract class NewRule {
 
-    String key();
+    public abstract String key();
 
     /**
      * @since 7.1
      */
     @CheckForNull
-    RuleScope scope();
+    public abstract RuleScope scope();
 
     /**
      * @since 7.1
      */
-    NewRule setScope(RuleScope scope);
+    public abstract NewRule setScope(RuleScope scope);
 
     /**
      * Required rule name
      */
-    NewRule setName(String s);
+    public abstract NewRule setName(String s);
 
-    NewRule setTemplate(boolean template);
+    public abstract NewRule setTemplate(boolean template);
 
     /**
      * Should this rule be enabled by default. For example in SonarLint standalone.
      *
      * @since 6.0
      */
-    NewRule setActivatedByDefault(boolean activatedByDefault);
+    public abstract NewRule setActivatedByDefault(boolean activatedByDefault);
 
-    NewRule setSeverity(String s);
+    public abstract NewRule setSeverity(String s);
 
     /**
      * The type as defined by the SonarQube Quality Model.
@@ -531,36 +531,36 @@ public interface RulesDefinition {
      *
      * @since 5.5
      */
-    NewRule setType(RuleType t);
+    public abstract NewRule setType(RuleType t);
 
     /**
      * The optional description, in HTML format, has no max length. It's exclusive with markdown description
      * (see {@link #setMarkdownDescription(String)})
      */
-    NewRule setHtmlDescription(@Nullable String s);
+    public abstract NewRule setHtmlDescription(@Nullable String s);
 
     /**
      * Load description from a file available in classpath. Example : <code>setHtmlDescription(getClass().getResource("/myrepo/Rule1234.html")</code>
      */
-    NewRule setHtmlDescription(@Nullable URL classpathUrl);
+    public abstract NewRule setHtmlDescription(@Nullable URL classpathUrl);
 
     /**
      * The optional description, in a restricted Markdown format, has no max length. It's exclusive with HTML description
      * (see {@link #setHtmlDescription(String)})
      */
-    NewRule setMarkdownDescription(@Nullable String s);
+    public abstract NewRule setMarkdownDescription(@Nullable String s);
 
     /**
      * Load description from a file available in classpath. Example : {@code setMarkdownDescription(getClass().getResource("/myrepo/Rule1234.md")}
      */
-    NewRule setMarkdownDescription(@Nullable URL classpathUrl);
+    public abstract NewRule setMarkdownDescription(@Nullable URL classpathUrl);
 
     /**
      * Default value is {@link org.sonar.api.rule.RuleStatus#READY}. The value
      * {@link org.sonar.api.rule.RuleStatus#REMOVED} is not accepted and raises an
      * {@link java.lang.IllegalArgumentException}.
      */
-    NewRule setStatus(RuleStatus status);
+    public abstract NewRule setStatus(RuleStatus status);
 
     /**
      * SQALE sub-characteristic. See http://www.sqale.org
@@ -570,23 +570,24 @@ public interface RulesDefinition {
      * @deprecated in 5.5. SQALE Quality Model is replaced by SonarQube Quality Model. This method does nothing.
      * See https://jira.sonarsource.com/browse/MMF-184
      */
-    NewRule setDebtSubCharacteristic(@Nullable String s);
+    @Deprecated
+    public abstract NewRule setDebtSubCharacteristic(@Nullable String s);
 
     /**
      * Factory of {@link org.sonar.api.server.debt.DebtRemediationFunction}
      */
-    DebtRemediationFunctions debtRemediationFunctions();
+    public abstract DebtRemediationFunctions debtRemediationFunctions();
 
     /**
      * @see #debtRemediationFunctions()
      */
-    NewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction fn);
+    public abstract NewRule setDebtRemediationFunction(@Nullable DebtRemediationFunction fn);
 
     /**
      * @deprecated since 5.5, replaced by {@link #setGapDescription(String)}
      */
     @Deprecated
-    NewRule setEffortToFixDescription(@Nullable String s);
+    public abstract NewRule setEffortToFixDescription(@Nullable String s);
 
     /**
      * For rules that use LINEAR or LINEAR_OFFSET remediation functions, the meaning
@@ -597,44 +598,44 @@ public interface RulesDefinition {
      * remediation function gap multiplier/base effort would be something like
      * "Effort to test one uncovered condition".
      */
-    NewRule setGapDescription(@Nullable String s);
+    public abstract NewRule setGapDescription(@Nullable String s);
 
     /**
      * Create a parameter with given unique key. Max length of key is 128 characters.
      */
-    NewParam createParam(String paramKey);
+    public abstract NewParam createParam(String paramKey);
 
     @CheckForNull
-    NewParam param(String paramKey);
+    public abstract NewParam param(String paramKey);
 
-    Collection<NewParam> params();
+    public abstract Collection<NewParam> params();
 
     /**
      * @see RuleTagFormat
      */
-    NewRule addTags(String... list);
+    public abstract NewRule addTags(String... list);
 
     /**
      * @see RuleTagFormat
      */
-    NewRule setTags(String... list);
+    public abstract NewRule setTags(String... list);
 
     /**
      * @since 7.3
      */
-    NewRule addOwaspTop10(OwaspTop10... standards);
+    public abstract NewRule addOwaspTop10(OwaspTop10... standards);
 
     /**
      * @since 7.3
      */
-    NewRule addCwe(int... nums);
+    public abstract NewRule addCwe(int... nums);
 
     /**
      * Optional key that can be used by the rule engine. Not displayed
      * in webapp. For example the Java Checkstyle plugin feeds this field
      * with the internal path ("Checker/TreeWalker/AnnotationUseStyle").
      */
-    NewRule setInternalKey(@Nullable String s);
+    public abstract NewRule setInternalKey(@Nullable String s);
 
     /**
      * Register a repository and key under which this rule used to be known
@@ -646,10 +647,7 @@ public interface RulesDefinition {
      * @see Rule#deprecatedRuleKeys
      * @since 7.1
      */
-    NewRule addDeprecatedRuleKey(String repository, String key);
-
-    @Override
-    String toString();
+    public abstract NewRule addDeprecatedRuleKey(String repository, String key);
   }
 
   @Immutable
@@ -796,22 +794,22 @@ public interface RulesDefinition {
 
   }
 
-  interface NewParam {
-    String key();
+  abstract class NewParam {
+    public abstract String key();
 
-    NewParam setName(@Nullable String s);
+    public abstract NewParam setName(@Nullable String s);
 
-    NewParam setType(RuleParamType t);
+    public abstract NewParam setType(RuleParamType t);
 
     /**
      * Plain-text description. Can be null. Max length is 4000 characters.
      */
-    NewParam setDescription(@Nullable String s);
+    public abstract NewParam setDescription(@Nullable String s);
 
     /**
      * Empty default value will be converted to null. Max length is 4000 characters.
      */
-    NewParam setDefaultValue(@Nullable String s);
+    public abstract NewParam setDefaultValue(@Nullable String s);
   }
 
   @Immutable
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/PartImpl.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/PartImpl.java
deleted file mode 100644
index 0aca8b452d5..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/PartImpl.java
+++ /dev/null
@@ -1,44 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.ws.internal;
-
-import java.io.InputStream;
-import org.sonar.api.server.ws.Request;
-
-public class PartImpl implements Request.Part {
-
-  private final InputStream inputStream;
-  private final String fileName;
-
-  public PartImpl(InputStream inputStream, String fileName) {
-    this.inputStream = inputStream;
-    this.fileName = fileName;
-  }
-
-  @Override
-  public InputStream getInputStream() {
-    return inputStream;
-  }
-
-  @Override
-  public String getFileName() {
-    return fileName;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/SimpleGetRequest.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/SimpleGetRequest.java
deleted file mode 100644
index 757f8ea932c..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/SimpleGetRequest.java
+++ /dev/null
@@ -1,148 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.ws.internal;
-
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.HashMap;
-import java.util.List;
-import java.util.Map;
-import java.util.Optional;
-import java.util.stream.Collectors;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.apache.commons.io.IOUtils;
-import org.sonar.api.server.ws.LocalConnector;
-import org.sonar.api.server.ws.Request;
-
-import static java.nio.charset.StandardCharsets.UTF_8;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
-import static java.util.Objects.requireNonNull;
-
-/**
- * Fake implementation of {@link org.sonar.api.server.ws.Request} used
- * for testing. Call the method {@link #setParam(String, String)} to
- * emulate some parameter values.
- */
-public class SimpleGetRequest extends Request {
-
-  private final Map<String, String[]> params = new HashMap<>();
-  private final Map<String, Part> parts = new HashMap<>();
-  private final Map<String, String> headers = new HashMap<>();
-  private String mediaType = "application/json";
-  private String path;
-
-  @Override
-  public String method() {
-    return "GET";
-  }
-
-  @Override
-  public String getMediaType() {
-    return mediaType;
-  }
-
-  public SimpleGetRequest setMediaType(String mediaType) {
-    requireNonNull(mediaType);
-    this.mediaType = mediaType;
-    return this;
-  }
-
-  @Override
-  public boolean hasParam(String key) {
-    return params.keySet().contains(key);
-  }
-
-  @Override
-  public String param(String key) {
-    String[] strings = params.get(key);
-    return strings == null || strings.length == 0 ? null : strings[0];
-  }
-
-  @Override
-  public List<String> multiParam(String key) {
-    String value = param(key);
-    return value == null ? emptyList() : singletonList(value);
-  }
-
-  @Override
-  @CheckForNull
-  public List<String> paramAsStrings(String key) {
-    String value = param(key);
-    if (value == null) {
-      return null;
-    }
-
-    return Arrays.stream(value.split(",")).map(String::trim).filter(x -> !x.isEmpty()).collect(Collectors.toList());
-  }
-
-  @Override
-  public InputStream paramAsInputStream(String key) {
-    return IOUtils.toInputStream(param(key), UTF_8);
-  }
-
-  public SimpleGetRequest setParam(String key, @Nullable String value) {
-    if (value != null) {
-      params.put(key, new String[] {value});
-    }
-    return this;
-  }
-
-  @Override
-  public Map<String, String[]> getParams() {
-    return params;
-  }
-
-  @Override
-  public Part paramAsPart(String key) {
-    return parts.get(key);
-  }
-
-  public SimpleGetRequest setPart(String key, InputStream input, String fileName) {
-    parts.put(key, new PartImpl(input, fileName));
-    return this;
-  }
-
-  @Override
-  public LocalConnector localConnector() {
-    throw new UnsupportedOperationException();
-  }
-
-  @Override
-  public String getPath() {
-    return path;
-  }
-
-  public SimpleGetRequest setPath(String path) {
-    this.path = path;
-    return this;
-  }
-
-  @Override
-  public Optional<String> header(String name) {
-    return Optional.ofNullable(headers.get(name));
-  }
-
-  public SimpleGetRequest setHeader(String name, String value) {
-    headers.put(name, value);
-    return this;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java
deleted file mode 100644
index 5a9ee977497..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/ValidatingRequest.java
+++ /dev/null
@@ -1,242 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.ws.internal;
-
-import java.io.InputStream;
-import java.util.Arrays;
-import java.util.List;
-import java.util.Set;
-import java.util.stream.Collectors;
-import javax.annotation.CheckForNull;
-import javax.annotation.Nullable;
-import org.sonar.api.server.ws.LocalConnector;
-import org.sonar.api.server.ws.Request;
-import org.sonar.api.server.ws.WebService;
-
-import static java.lang.String.format;
-import static java.util.Collections.emptyList;
-import static java.util.Collections.singletonList;
-import static java.util.Objects.requireNonNull;
-import static org.apache.commons.lang.StringUtils.defaultString;
-import static org.sonar.api.utils.Preconditions.checkArgument;
-
-/**
- * @since 4.2
- */
-public abstract class ValidatingRequest extends Request {
-
-  private static final String COMMA_SPLITTER = ",";
-  private WebService.Action action;
-  private LocalConnector localConnector;
-
-  public void setAction(WebService.Action action) {
-    this.action = action;
-  }
-
-  public WebService.Action action() {
-    return action;
-  }
-
-  @Override
-  public LocalConnector localConnector() {
-    requireNonNull(localConnector, "Local connector has not been set");
-    return localConnector;
-  }
-
-  public void setLocalConnector(LocalConnector lc) {
-    this.localConnector = lc;
-  }
-
-  @Override
-  @CheckForNull
-  public String param(String key) {
-    WebService.Param definition = action.param(key);
-    String rawValue = readParam(key, definition);
-    String rawValueOrDefault = defaultString(rawValue, definition.defaultValue());
-    String value = rawValueOrDefault == null ? null : trim(rawValueOrDefault);
-    validateRequiredValue(key, definition, rawValue);
-    if (value == null) {
-      return null;
-    }
-    validatePossibleValues(key, value, definition);
-    validateMaximumLength(key, definition, rawValueOrDefault);
-    validateMinimumLength(key, definition, rawValueOrDefault);
-    validateMaximumValue(key, definition, value);
-    return value;
-  }
-
-  @Override
-  public List<String> multiParam(String key) {
-    WebService.Param definition = action.param(key);
-    List<String> values = readMultiParamOrDefaultValue(key, definition);
-    return validateValues(values, definition);
-  }
-
-  private static String trim(String s) {
-    int begin;
-    for (begin = 0; begin < s.length(); begin++) {
-      if (!Character.isWhitespace(s.charAt(begin))) {
-        break;
-      }
-    }
-
-    int end;
-    for (end = s.length(); end > begin; end--) {
-      if (!Character.isWhitespace(s.charAt(end - 1))) {
-        break;
-      }
-    }
-    return s.substring(begin, end);
-  }
-
-  @Override
-  @CheckForNull
-  public InputStream paramAsInputStream(String key) {
-    return readInputStreamParam(key);
-  }
-
-  @Override
-  @CheckForNull
-  public Part paramAsPart(String key) {
-    return readPart(key);
-  }
-
-  @CheckForNull
-  @Override
-  public List<String> paramAsStrings(String key) {
-    WebService.Param definition = action.param(key);
-    String value = defaultString(readParam(key, definition), definition.defaultValue());
-    if (value == null) {
-      return null;
-    }
-    List<String> values = Arrays.stream(value.split(COMMA_SPLITTER))
-      .map(String::trim)
-      .filter(s -> !s.isEmpty())
-      .collect(Collectors.toList());
-    return validateValues(values, definition);
-  }
-
-  @CheckForNull
-  @Override
-  public <E extends Enum<E>> List<E> paramAsEnums(String key, Class<E> enumClass) {
-    List<String> values = paramAsStrings(key);
-    if (values == null) {
-      return null;
-    }
-    return values.stream()
-      .filter(s -> !s.isEmpty())
-      .map(value -> Enum.valueOf(enumClass, value))
-      .collect(Collectors.toList());
-  }
-
-  @CheckForNull
-  private String readParam(String key, @Nullable WebService.Param definition) {
-    checkArgument(definition != null, "BUG - parameter '%s' is undefined for action '%s'", key, action.key());
-    String deprecatedKey = definition.deprecatedKey();
-    return deprecatedKey != null ? defaultString(readParam(deprecatedKey), readParam(key)) : readParam(key);
-  }
-
-  private List<String> readMultiParamOrDefaultValue(String key, @Nullable WebService.Param definition) {
-    checkArgument(definition != null, "BUG - parameter '%s' is undefined for action '%s'", key, action.key());
-
-    List<String> keyValues = readMultiParam(key);
-    if (!keyValues.isEmpty()) {
-      return keyValues;
-    }
-
-    String deprecatedKey = definition.deprecatedKey();
-    List<String> deprecatedKeyValues = deprecatedKey == null ? emptyList() : readMultiParam(deprecatedKey);
-    if (!deprecatedKeyValues.isEmpty()) {
-      return deprecatedKeyValues;
-    }
-
-    String defaultValue = definition.defaultValue();
-    return defaultValue == null ? emptyList() : singletonList(defaultValue);
-  }
-
-  @CheckForNull
-  protected abstract String readParam(String key);
-
-  protected abstract List<String> readMultiParam(String key);
-
-  @CheckForNull
-  protected abstract InputStream readInputStreamParam(String key);
-
-  @CheckForNull
-  protected abstract Part readPart(String key);
-
-  private static List<String> validateValues(List<String> values, WebService.Param definition) {
-    Integer maximumValues = definition.maxValuesAllowed();
-    checkArgument(maximumValues == null || values.size() <= maximumValues, "'%s' can contains only %s values, got %s", definition.key(), maximumValues, values.size());
-    values.forEach(value -> validatePossibleValues(definition.key(), value, definition));
-    return values;
-  }
-
-  private static void validatePossibleValues(String key, String value, WebService.Param definition) {
-    Set<String> possibleValues = definition.possibleValues();
-    if (possibleValues == null) {
-      return;
-    }
-    checkArgument(possibleValues.contains(value), "Value of parameter '%s' (%s) must be one of: %s", key, value, possibleValues);
-  }
-
-  private static void validateMaximumLength(String key, WebService.Param definition, String valueOrDefault) {
-    Integer maximumLength = definition.maximumLength();
-    if (maximumLength == null) {
-      return;
-    }
-    int valueLength = valueOrDefault.length();
-    checkArgument(valueLength <= maximumLength, "'%s' length (%s) is longer than the maximum authorized (%s)", key, valueLength, maximumLength);
-  }
-
-  private static void validateMinimumLength(String key, WebService.Param definition, String valueOrDefault) {
-    Integer minimumLength = definition.minimumLength();
-    if (minimumLength == null) {
-      return;
-    }
-    int valueLength = valueOrDefault.length();
-    checkArgument(valueLength >= minimumLength, "'%s' length (%s) is shorter than the minimum authorized (%s)", key, valueLength, minimumLength);
-  }
-
-  private static void validateMaximumValue(String key, WebService.Param definition, String value) {
-    Integer maximumValue = definition.maximumValue();
-    if (maximumValue == null) {
-      return;
-    }
-    int valueAsInt = validateAsNumeric(key, value);
-    checkArgument(valueAsInt <= maximumValue, "'%s' value (%s) must be less than %s", key, valueAsInt, maximumValue);
-  }
-
-  private static void validateRequiredValue(String key, WebService.Param definition, String value) {
-    boolean required = definition.isRequired();
-    if (required) {
-      checkArgument(value != null, format(MSG_PARAMETER_MISSING, key));
-    }
-  }
-
-  private static int validateAsNumeric(String key, String value) {
-    try {
-      return Integer.parseInt(value);
-    } catch (NumberFormatException exception) {
-      throw new IllegalArgumentException(format("'%s' value '%s' cannot be parsed as an integer", key, value), exception);
-    }
-  }
-
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/package-info.java
deleted file mode 100644
index 1dc6d3eda19..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/server/ws/internal/package-info.java
+++ /dev/null
@@ -1,23 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.server.ws.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/Preconditions.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/Preconditions.java
index 1a70241d869..a67dd38eb84 100644
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/Preconditions.java
+++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/Preconditions.java
@@ -20,6 +20,10 @@
 package org.sonar.api.utils;
 
 public class Preconditions {
+  private Preconditions() {
+    // static only
+  }
+
   public static void checkArgument(boolean condition, String message) {
     if (!condition) {
       throw new IllegalArgumentException(message);
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/AlwaysIncreasingSystem2.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/AlwaysIncreasingSystem2.java
deleted file mode 100644
index 35334080778..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/AlwaysIncreasingSystem2.java
+++ /dev/null
@@ -1,71 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.utils.internal;
-
-import java.util.Random;
-import java.util.concurrent.atomic.AtomicLong;
-import java.util.function.Supplier;
-import org.sonar.api.utils.System2;
-
-import static org.sonar.api.utils.Preconditions.checkArgument;
-
-/**
- * A subclass of {@link System2} which implementation of {@link System2#now()} always return a bigger value than the
- * previous returned value.
- * <p>
- * This class is intended to be used in Unit tests.
- * </p>
- */
-public class AlwaysIncreasingSystem2 extends System2 {
-  private final AtomicLong now;
-  private final long increment;
-
-  private AlwaysIncreasingSystem2(Supplier<Long> initialValueSupplier, long increment) {
-    checkArgument(increment > 0, "increment must be > 0");
-    long initialValue = initialValueSupplier.get();
-    checkArgument(initialValue >= 0, "Initial value must be >= 0");
-    this.now = new AtomicLong(initialValue);
-    this.increment = increment;
-  }
-
-  public AlwaysIncreasingSystem2(long increment) {
-    this(AlwaysIncreasingSystem2::randomInitialValue, increment);
-  }
-
-  public AlwaysIncreasingSystem2(long initialValue, int increment) {
-    this(() -> initialValue, increment);
-  }
-
-  /**
-   * Values returned by {@link #now()} will start with a random value and increment by 100.
-   */
-  public AlwaysIncreasingSystem2() {
-    this(AlwaysIncreasingSystem2::randomInitialValue, 100);
-  }
-
-  @Override
-  public long now() {
-    return now.getAndAdd(increment);
-  }
-
-  private static long randomInitialValue() {
-    return (long) Math.abs(new Random().nextInt(2_000_000));
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/DefaultTempFolder.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/DefaultTempFolder.java
deleted file mode 100644
index bedee39b7d0..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/DefaultTempFolder.java
+++ /dev/null
@@ -1,126 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.utils.internal;
-
-import java.nio.file.FileVisitResult;
-import java.nio.file.SimpleFileVisitor;
-import java.nio.file.attribute.BasicFileAttributes;
-import org.apache.commons.io.FileUtils;
-import org.sonar.api.utils.TempFolder;
-
-import javax.annotation.Nullable;
-
-import java.io.File;
-import java.io.IOException;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import org.sonar.api.utils.log.Logger;
-import org.sonar.api.utils.log.Loggers;
-
-public class DefaultTempFolder implements TempFolder {
-  private static final Logger LOG = Loggers.get(DefaultTempFolder.class);
-
-  private final File tempDir;
-  private final boolean deleteOnExit;
-
-  public DefaultTempFolder(File tempDir) {
-    this(tempDir, false);
-  }
-
-  public DefaultTempFolder(File tempDir, boolean deleteOnExit) {
-    this.tempDir = tempDir;
-    this.deleteOnExit = deleteOnExit;
-  }
-
-  @Override
-  public File newDir() {
-    return createTempDir(tempDir.toPath()).toFile();
-  }
-
-  private static Path createTempDir(Path baseDir) {
-    try {
-      return Files.createTempDirectory(baseDir, null);
-    } catch (IOException e) {
-      throw new IllegalStateException("Failed to create temp directory", e);
-    }
-  }
-
-  @Override
-  public File newDir(String name) {
-    File dir = new File(tempDir, name);
-    try {
-      FileUtils.forceMkdir(dir);
-    } catch (IOException e) {
-      throw new IllegalStateException("Failed to create temp directory - " + dir, e);
-    }
-    return dir;
-  }
-
-  @Override
-  public File newFile() {
-    return newFile(null, null);
-  }
-
-  @Override
-  public File newFile(@Nullable String prefix, @Nullable String suffix) {
-    return createTempFile(tempDir.toPath(), prefix, suffix).toFile();
-  }
-
-  private static Path createTempFile(Path baseDir, String prefix, String suffix) {
-    try {
-      return Files.createTempFile(baseDir, prefix, suffix);
-    } catch (IOException e) {
-      throw new IllegalStateException("Failed to create temp file", e);
-    }
-  }
-
-  public void clean() {
-    try {
-      if (tempDir.exists()) {
-        Files.walkFileTree(tempDir.toPath(), DeleteRecursivelyFileVisitor.INSTANCE);
-      }
-    } catch (IOException e) {
-      LOG.error("Failed to delete temp folder", e);
-    }
-  }
-
-  public void stop() {
-    if (deleteOnExit) {
-      clean();
-    }
-  }
-
-  private static final class DeleteRecursivelyFileVisitor extends SimpleFileVisitor<Path> {
-    public static final DeleteRecursivelyFileVisitor INSTANCE = new DeleteRecursivelyFileVisitor();
-
-    @Override
-    public FileVisitResult visitFile(Path file, BasicFileAttributes attrs) throws IOException {
-      Files.deleteIfExists(file);
-      return FileVisitResult.CONTINUE;
-    }
-
-    @Override
-    public FileVisitResult postVisitDirectory(Path dir, IOException exc) throws IOException {
-      Files.deleteIfExists(dir);
-      return FileVisitResult.CONTINUE;
-    }
-  }
-
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java
deleted file mode 100644
index 5c323f23f7d..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/JUnitTempFolder.java
+++ /dev/null
@@ -1,108 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.utils.internal;
-
-import org.apache.commons.lang.StringUtils;
-import org.junit.rules.ExternalResource;
-import org.junit.rules.TemporaryFolder;
-import org.junit.runner.Description;
-import org.junit.runners.model.Statement;
-import org.sonar.api.utils.TempFolder;
-
-import javax.annotation.Nullable;
-
-import java.io.File;
-import java.io.IOException;
-
-/**
- * Implementation of {@link org.sonar.api.utils.TempFolder} to be used
- * only in JUnit tests. It wraps {@link org.junit.rules.TemporaryFolder}.
- * <br>
- * Example:
- * <pre>
- * public class MyTest {
- *   &#064;@org.junit.Rule
- *   public JUnitTempFolder temp = new JUnitTempFolder();
- *
- *   &#064;@org.junit.Test
- *   public void myTest() throws Exception {
- *     File dir = temp.newDir();
- *     // ...
- *   }
- * }
- * </pre>
- *
- * @since 5.1
- */
-public class JUnitTempFolder extends ExternalResource implements TempFolder {
-
-  private final TemporaryFolder junit = new TemporaryFolder();
-
-  @Override
-  public Statement apply(Statement base, Description description) {
-    return junit.apply(base, description);
-  }
-
-  @Override
-  protected void before() throws Throwable {
-    junit.create();
-  }
-
-  @Override
-  protected void after() {
-    junit.delete();
-  }
-
-  @Override
-  public File newDir() {
-    try {
-      return junit.newFolder();
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to create temp dir", e);
-    }
-  }
-
-  @Override
-  public File newDir(String name) {
-    try {
-      return junit.newFolder(name);
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to create temp dir", e);
-    }
-  }
-
-  @Override
-  public File newFile() {
-    try {
-      return junit.newFile();
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to create temp file", e);
-    }
-  }
-
-  @Override
-  public File newFile(@Nullable String prefix, @Nullable String suffix) {
-    try {
-      return junit.newFile(StringUtils.defaultString(prefix) + "-" + StringUtils.defaultString(suffix));
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to create temp file", e);
-    }
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TempFolderCleaner.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TempFolderCleaner.java
deleted file mode 100644
index 3a7836cff4f..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TempFolderCleaner.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.utils.internal;
-
-import org.sonar.api.Startable;
-import org.sonar.api.server.ServerSide;
-import org.sonar.api.utils.TempFolder;
-
-@ServerSide
-public class TempFolderCleaner implements Startable {
-
-  private TempFolder defaultTempFolder;
-
-  public TempFolderCleaner(TempFolder defaultTempFolder) {
-    this.defaultTempFolder = defaultTempFolder;
-  }
-
-  /**
-   * This method should not be renamed. It follows the naming convention
-   * defined by IoC container.
-   */
-  @Override
-  public void start() {
-    // Nothing to do
-  }
-
-  /**
-   * This method should not be renamed. It follows the naming convention
-   * defined by IoC container.
-   */
-  @Override
-  public void stop() {
-    ((DefaultTempFolder) defaultTempFolder).clean();
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TestSystem2.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TestSystem2.java
deleted file mode 100644
index 37d2ed5d719..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/TestSystem2.java
+++ /dev/null
@@ -1,52 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.utils.internal;
-
-import java.util.TimeZone;
-import org.sonar.api.utils.System2;
-
-public class TestSystem2 extends System2 {
-
-  private long now = 0L;
-  private TimeZone defaultTimeZone = getDefaultTimeZone();
-
-  public TestSystem2 setNow(long l) {
-    this.now = l;
-    return this;
-  }
-
-  @Override
-  public long now() {
-    if (now <= 0L) {
-      throw new IllegalStateException("Method setNow() was not called by test");
-    }
-    return now;
-  }
-
-  public TestSystem2 setDefaultTimeZone(TimeZone defaultTimeZone) {
-    this.defaultTimeZone = defaultTimeZone;
-    return this;
-  }
-
-  @Override
-  public TimeZone getDefaultTimeZone() {
-    return defaultTimeZone;
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/WorkDuration.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/WorkDuration.java
deleted file mode 100644
index fc4de0037bc..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/WorkDuration.java
+++ /dev/null
@@ -1,194 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.utils.internal;
-
-import java.io.Serializable;
-import javax.annotation.Nullable;
-import org.apache.commons.lang.builder.ToStringBuilder;
-import org.apache.commons.lang.builder.ToStringStyle;
-
-/**
- * @since 4.2
- */
-public class WorkDuration implements Serializable {
-
-  static final int DAY_POSITION_IN_LONG = 10_000;
-  static final int HOUR_POSITION_IN_LONG = 100;
-  static final int MINUTE_POSITION_IN_LONG = 1;
-
-  public enum UNIT {
-    DAYS, HOURS, MINUTES
-  }
-
-  private int hoursInDay;
-
-  private long durationInMinutes;
-  private int days;
-  private int hours;
-  private int minutes;
-
-  private WorkDuration(long durationInMinutes, int days, int hours, int minutes, int hoursInDay) {
-    this.durationInMinutes = durationInMinutes;
-    this.days = days;
-    this.hours = hours;
-    this.minutes = minutes;
-    this.hoursInDay = hoursInDay;
-  }
-
-  public static WorkDuration create(int days, int hours, int minutes, int hoursInDay) {
-    long durationInSeconds = 60L * days * hoursInDay;
-    durationInSeconds += 60L * hours;
-    durationInSeconds += minutes;
-    return new WorkDuration(durationInSeconds, days, hours, minutes, hoursInDay);
-  }
-
-  public static WorkDuration createFromValueAndUnit(int value, UNIT unit, int hoursInDay) {
-    switch (unit) {
-      case DAYS:
-        return create(value, 0, 0, hoursInDay);
-      case HOURS:
-        return create(0, value, 0, hoursInDay);
-      case MINUTES:
-        return create(0, 0, value, hoursInDay);
-      default:
-        throw new IllegalStateException("Cannot create work duration");
-    }
-  }
-
-  static WorkDuration createFromLong(long duration, int hoursInDay) {
-    int days = 0;
-    int hours = 0;
-    int minutes = 0;
-
-    long time = duration;
-    Long currentTime = time / WorkDuration.DAY_POSITION_IN_LONG;
-    if (currentTime > 0) {
-      days = currentTime.intValue();
-      time = time - (currentTime * WorkDuration.DAY_POSITION_IN_LONG);
-    }
-
-    currentTime = time / WorkDuration.HOUR_POSITION_IN_LONG;
-    if (currentTime > 0) {
-      hours = currentTime.intValue();
-      time = time - (currentTime * WorkDuration.HOUR_POSITION_IN_LONG);
-    }
-
-    currentTime = time / WorkDuration.MINUTE_POSITION_IN_LONG;
-    if (currentTime > 0) {
-      minutes = currentTime.intValue();
-    }
-    return WorkDuration.create(days, hours, minutes, hoursInDay);
-  }
-
-  static WorkDuration createFromMinutes(long duration, int hoursInDay) {
-    int days = (int)(duration / (double)hoursInDay / 60.0);
-    Long currentDurationInMinutes = duration - (60L * days * hoursInDay);
-    int hours = (int)(currentDurationInMinutes / 60.0);
-    currentDurationInMinutes = currentDurationInMinutes - (60L * hours);
-    return new WorkDuration(duration, days, hours, currentDurationInMinutes.intValue(), hoursInDay);
-  }
-
-  /**
-   * Return the duration in number of working days.
-   * For instance, 3 days and 4 hours will return 3.5 days (if hoursIndDay is 8).
-   */
-  public double toWorkingDays() {
-    return durationInMinutes / 60d / hoursInDay;
-  }
-
-  /**
-   * Return the duration using the following format DDHHMM, where DD is the number of days, HH is the number of months, and MM the number of minutes.
-   * For instance, 3 days and 4 hours will return 030400 (if hoursIndDay is 8).
-   */
-  public long toLong() {
-    int workingDays = days;
-    int workingHours = hours;
-    if (hours >= hoursInDay) {
-      int nbAdditionalDays = hours / hoursInDay;
-      workingDays += nbAdditionalDays;
-      workingHours = hours - (nbAdditionalDays * hoursInDay);
-    }
-    return 1L * workingDays * DAY_POSITION_IN_LONG + workingHours * HOUR_POSITION_IN_LONG + minutes * MINUTE_POSITION_IN_LONG;
-  }
-
-  public long toMinutes() {
-    return durationInMinutes;
-  }
-
-  public WorkDuration add(@Nullable WorkDuration with) {
-    if (with != null) {
-      return WorkDuration.createFromMinutes(this.toMinutes() + with.toMinutes(), this.hoursInDay);
-    } else {
-      return this;
-    }
-  }
-
-  public WorkDuration subtract(@Nullable WorkDuration with) {
-    if (with != null) {
-      return WorkDuration.createFromMinutes(this.toMinutes() - with.toMinutes(), this.hoursInDay);
-    } else {
-      return this;
-    }
-  }
-
-  public WorkDuration multiply(int factor) {
-    return WorkDuration.createFromMinutes(this.toMinutes() * factor, this.hoursInDay);
-  }
-
-  public int days() {
-    return days;
-  }
-
-  public int hours() {
-    return hours;
-  }
-
-  public int minutes() {
-    return minutes;
-  }
-
-  int hoursInDay() {
-    return hoursInDay;
-  }
-
-  @Override
-  public boolean equals(Object o) {
-    if (this == o) {
-      return true;
-    }
-    if (o == null || getClass() != o.getClass()) {
-      return false;
-    }
-
-    WorkDuration that = (WorkDuration) o;
-    return durationInMinutes == that.durationInMinutes;
-
-  }
-
-  @Override
-  public int hashCode() {
-    return (int) (durationInMinutes ^ (durationInMinutes >>> 32));
-  }
-
-  @Override
-  public String toString() {
-    return ToStringBuilder.reflectionToString(this, ToStringStyle.SHORT_PREFIX_STYLE);
-  }
-}
diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/package-info.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/package-info.java
deleted file mode 100644
index f3fea3220e9..00000000000
--- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/internal/package-info.java
+++ /dev/null
@@ -1,24 +0,0 @@
-/*
- * SonarQube
- * Copyright (C) 2009-2019 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.
- */
-@ParametersAreNonnullByDefault
-package org.sonar.api.utils.internal;
-
-import javax.annotation.ParametersAreNonnullByDefault;
-
-- 
cgit v1.2.3