From fdf0f2f89300342c932ab23b71c895866c7d4834 Mon Sep 17 00:00:00 2001 From: Julien HENRY Date: Thu, 5 Jul 2018 11:51:17 +0200 Subject: [PATCH] SONAR-10541, SONAR-10331 Drop compatibility mode and clean plugin classloader --- .../build.gradle | 3 +- .../ComputeEngineContainerImplTest.java | 2 + .../server/platform/ServerFileSystemImpl.java | 16 ++++-- server/sonar-server/build.gradle | 6 +-- settings.gradle | 1 - sonar-application/build.gradle | 4 +- sonar-core/build.gradle | 14 ----- .../core/platform/PluginClassLoaderDef.java | 13 ----- .../platform/PluginClassloaderFactory.java | 47 +++-------------- .../org/sonar/core/platform/PluginLoader.java | 9 ++-- .../PluginClassloaderFactoryTest.java | 21 +------- .../sonar/core/platform/PluginLoaderTest.java | 52 +++++++------------ sonar-duplications/build.gradle | 1 + .../org/sonar/duplications/CodeFragment.java | 44 ---------------- .../org/sonar/duplications/block/Block.java | 6 +-- .../sonar/duplications/index/ClonePart.java | 6 +-- .../internal/pmd/PmdBlockChunker.java | 3 +- .../internal/pmd/TokenizerBridge.java | 1 + .../duplications/statement/Statement.java | 5 +- .../internal/pmd/PmdBlockChunkerTest.java | 6 +-- .../internal/pmd/TokenizerBridgeTest.java | 1 + sonar-plugin-api-deps/build.gradle | 42 --------------- sonar-plugin-api/build.gradle | 3 -- .../sensor/cpd/internal/DefaultCpdTokens.java | 3 +- .../sensor/cpd/internal}/TokensLine.java | 8 +-- .../sensor/internal/SensorContextTester.java | 2 +- .../authentication/IdentityProvider.java | 2 + sonar-scanner-engine/build.gradle | 1 + 28 files changed, 69 insertions(+), 253 deletions(-) delete mode 100644 sonar-duplications/src/main/java/org/sonar/duplications/CodeFragment.java delete mode 100644 sonar-plugin-api-deps/build.gradle rename {sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd => sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal}/TokensLine.java (91%) diff --git a/server/sonar-ce-task-projectanalysis/build.gradle b/server/sonar-ce-task-projectanalysis/build.gradle index 8b52c4232f2..b73d4b2e72b 100644 --- a/server/sonar-ce-task-projectanalysis/build.gradle +++ b/server/sonar-ce-task-projectanalysis/build.gradle @@ -42,7 +42,8 @@ dependencies { compileOnly project(':server:sonar-db-dao') compileOnly project(':server:sonar-process') compileOnly project(':server:sonar-server-common') - compileOnly project(path: ':sonar-plugin-api') + compileOnly project(':sonar-plugin-api') + compileOnly project(':sonar-duplications') testCompile 'com.google.code.findbugs:jsr305' testCompile 'com.h2database:h2' diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java index bc7a95804b5..81fe42adca6 100644 --- a/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java +++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/ComputeEngineContainerImplTest.java @@ -150,7 +150,9 @@ public class ComputeEngineContainerImplTest { Properties properties = ProcessProperties.defaults(); File homeDir = tempFolder.newFolder(); File dataDir = new File(homeDir, "data"); + dataDir.mkdirs(); File tmpDir = new File(homeDir, "tmp"); + tmpDir.mkdirs(); properties.setProperty(PATH_HOME.getKey(), homeDir.getAbsolutePath()); properties.setProperty(PATH_DATA.getKey(), dataDir.getAbsolutePath()); properties.setProperty(PATH_TEMP.getKey(), tmpDir.getAbsolutePath()); diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystemImpl.java b/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystemImpl.java index 9818d98584f..d596044e8e3 100644 --- a/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystemImpl.java +++ b/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystemImpl.java @@ -20,6 +20,8 @@ package org.sonar.server.platform; import java.io.File; +import java.io.IOException; +import org.apache.commons.io.FileUtils; import org.picocontainer.Startable; import org.sonar.api.config.Configuration; import org.sonar.api.utils.log.Logger; @@ -39,9 +41,9 @@ public class ServerFileSystemImpl implements ServerFileSystem, org.sonar.api.pla private final File uninstallDir; public ServerFileSystemImpl(Configuration config) { - this.homeDir = new File(config.get(PATH_HOME.getKey()).get()); - this.tempDir = new File(config.get(PATH_TEMP.getKey()).get()); - File dataDir = new File(config.get(PATH_DATA.getKey()).get()); + this.homeDir = createDir(new File(config.get(PATH_HOME.getKey()).get())); + this.tempDir = createDir(new File(config.get(PATH_TEMP.getKey()).get())); + File dataDir = createDir(new File(config.get(PATH_DATA.getKey()).get())); this.deployDir = new File(dataDir, "web/deploy"); this.uninstallDir = new File(getTempDir(), "uninstalled-plugins"); } @@ -91,4 +93,12 @@ public class ServerFileSystemImpl implements ServerFileSystem, org.sonar.api.pla return uninstallDir; } + private static File createDir(File dir) { + try { + FileUtils.forceMkdir(dir); + return dir; + } catch (IOException e) { + throw new IllegalStateException("Fail to create directory " + dir, e); + } + } } diff --git a/server/sonar-server/build.gradle b/server/sonar-server/build.gradle index 19d0f661aa4..15111dfb774 100644 --- a/server/sonar-server/build.gradle +++ b/server/sonar-server/build.gradle @@ -55,10 +55,8 @@ dependencies { compile project(':server:sonar-server-common') compile project(':sonar-core') compile project(':sonar-scanner-protocol') - compile(project(':sonar-markdown')) { - // already shaded with sonar-plugin-api - exclude group: 'org.codehaus.sonar', module: 'sonar-channel' - } + compile project(':sonar-markdown') + compile project(':sonar-duplications') runtime project(path: ':sonar-plugin-api', configuration: 'shadow') compileOnly project(path: ':sonar-plugin-api') compile project(':sonar-ws') diff --git a/settings.gradle b/settings.gradle index 38a3b8713d5..9ab4a914693 100644 --- a/settings.gradle +++ b/settings.gradle @@ -24,7 +24,6 @@ include 'sonar-core' include 'sonar-duplications' include 'sonar-markdown' include 'sonar-plugin-api' -include 'sonar-plugin-api-deps' include 'sonar-scanner-engine' include 'sonar-scanner-engine-shaded' include 'sonar-scanner-protocol' diff --git a/sonar-application/build.gradle b/sonar-application/build.gradle index 07929229da8..41cd8d85b18 100644 --- a/sonar-application/build.gradle +++ b/sonar-application/build.gradle @@ -131,8 +131,8 @@ zip.doFirst { } // Check the size of the archive zip.doLast { - def minLength = 160000000 - def maxLength = 175000000 + def minLength = 150000000 + def maxLength = 165000000 def length = new File(distsDir, archiveName).length() if (length < minLength) throw new GradleException("$archiveName size ($length) too small. Min is $minLength") diff --git a/sonar-core/build.gradle b/sonar-core/build.gradle index a2d0f1bb189..aad84e6dbfe 100644 --- a/sonar-core/build.gradle +++ b/sonar-core/build.gradle @@ -4,10 +4,6 @@ sonarqube { } } -configurations { - includeInResources -} - dependencies { // please keep list ordered @@ -24,8 +20,6 @@ dependencies { compileOnly 'com.google.code.findbugs:jsr305' - includeInResources project(path: ':sonar-plugin-api-deps', configuration: 'shadow') - testCompile 'com.tngtech.java:junit-dataprovider' testCompile 'junit:junit' testCompile 'org.assertj:assertj-core' @@ -36,14 +30,6 @@ dependencies { testCompileOnly 'com.google.code.findbugs:jsr305' } -// sonar-plugin-api.jar is copied into target JAR file -processResources { - into('/') { - from configurations.includeInResources - rename '(.*)-' + project.version + '-all.jar', '$1.jar' - } -} - // Used by sonar-db-core to run DB Unit Tests artifactoryPublish.skip = false publishing { diff --git a/sonar-core/src/main/java/org/sonar/core/platform/PluginClassLoaderDef.java b/sonar-core/src/main/java/org/sonar/core/platform/PluginClassLoaderDef.java index c1c3584b58a..d228ee088bd 100644 --- a/sonar-core/src/main/java/org/sonar/core/platform/PluginClassLoaderDef.java +++ b/sonar-core/src/main/java/org/sonar/core/platform/PluginClassLoaderDef.java @@ -41,11 +41,6 @@ class PluginClassLoaderDef { private final Mask mask = new Mask(); private boolean selfFirstStrategy = false; - /** - * Compatibility with API classloader as defined before version 5.2 - */ - private boolean compatibilityMode = false; - PluginClassLoaderDef(String basePluginKey) { Preconditions.checkArgument(!Strings.isNullOrEmpty(basePluginKey)); this.basePluginKey = basePluginKey; @@ -85,14 +80,6 @@ class PluginClassLoaderDef { } } - boolean isCompatibilityMode() { - return compatibilityMode; - } - - void setCompatibilityMode(boolean b) { - this.compatibilityMode = b; - } - @Override public boolean equals(@Nullable Object o) { if (this == o) { diff --git a/sonar-core/src/main/java/org/sonar/core/platform/PluginClassloaderFactory.java b/sonar-core/src/main/java/org/sonar/core/platform/PluginClassloaderFactory.java index 0c69f978a09..bc584778d68 100644 --- a/sonar-core/src/main/java/org/sonar/core/platform/PluginClassloaderFactory.java +++ b/sonar-core/src/main/java/org/sonar/core/platform/PluginClassloaderFactory.java @@ -25,11 +25,9 @@ import java.net.URL; import java.util.Collection; import java.util.HashMap; import java.util.Map; -import org.apache.commons.io.FileUtils; import org.sonar.api.batch.ScannerSide; import org.sonar.api.ce.ComputeEngineSide; import org.sonar.api.server.ServerSide; -import org.sonar.api.utils.TempFolder; import org.sonar.classloader.ClassloaderBuilder; import org.sonar.classloader.Mask; @@ -40,8 +38,6 @@ import static org.sonar.classloader.ClassloaderBuilder.LoadingOrder.SELF_FIRST; * Builds the graph of classloaders to be used to instantiate plugins. It deals with: * @@ -54,13 +50,6 @@ public class PluginClassloaderFactory { // underscores are used to not conflict with plugin keys (if someday a plugin key is "api") private static final String API_CLASSLOADER_KEY = "_api_"; - private final TempFolder temp; - private URL compatibilityModeJar; - - public PluginClassloaderFactory(TempFolder temp) { - this.temp = temp; - } - /** * Creates as many classloaders as requested by the input parameter. */ @@ -78,9 +67,6 @@ public class PluginClassloaderFactory { for (File jar : def.getFiles()) { builder.addURL(def.getBasePluginKey(), fileToUrl(jar)); } - if (def.isCompatibilityMode()) { - builder.addURL(def.getBasePluginKey(), extractCompatibilityModeJar()); - } exportResources(def, builder, defs); } @@ -120,19 +106,6 @@ public class PluginClassloaderFactory { return getClass().getClassLoader(); } - private URL extractCompatibilityModeJar() { - if (compatibilityModeJar == null) { - File jar = temp.newFile("sonar-plugin-api-deps", "jar"); - try { - FileUtils.copyURLToFile(getClass().getResource("/sonar-plugin-api-deps.jar"), jar); - compatibilityModeJar = jar.toURI().toURL(); - } catch (Exception e) { - throw new IllegalStateException("Can not extract sonar-plugin-api-deps.jar to " + jar.getAbsolutePath(), e); - } - } - return compatibilityModeJar; - } - private static URL fileToUrl(File file) { try { return file.toURI().toURL(); @@ -149,31 +122,25 @@ public class PluginClassloaderFactory { */ private static Mask apiMask() { return new Mask() - .addInclusion("org/sonar/api/") - .addInclusion("org/sonar/channel/") + .addInclusion("org/sonar/api/") .addInclusion("org/sonar/check/") - .addInclusion("org/sonar/colorizer/") - .addInclusion("org/sonar/duplications/") - .addInclusion("org/sonar/graph/") - .addInclusion("org/sonar/plugins/emailnotifications/api/") - .addInclusion("net/sourceforge/pmd/") - .addInclusion("org/apache/maven/") .addInclusion("org/codehaus/stax2/") .addInclusion("org/codehaus/staxmate/") .addInclusion("com/ctc/wstx/") .addInclusion("org/slf4j/") - .addInclusion("javax/servlet/") // SLF4J bridges. Do not let plugins re-initialize and configure their logging system .addInclusion("org/apache/commons/logging/") .addInclusion("org/apache/log4j/") .addInclusion("ch/qos/logback/") - // required for internal libs at SonarSource + // Exposed by org.sonar.api.server.authentication.IdentityProvider + .addInclusion("javax/servlet/") + + // required for some internal SonarSource plugins (billing, orchestrator, ...) .addInclusion("org/sonar/server/platform/") - .addInclusion("org/sonar/core/persistence/") - .addInclusion("org/sonar/core/properties/") - .addInclusion("org/sonar/server/views/") + + // required for commercial plugins at SonarSource .addInclusion("com/sonarsource/plugins/license/api/") // API exclusions diff --git a/sonar-core/src/main/java/org/sonar/core/platform/PluginLoader.java b/sonar-core/src/main/java/org/sonar/core/platform/PluginLoader.java index f44a346336e..7b045fe6961 100644 --- a/sonar-core/src/main/java/org/sonar/core/platform/PluginLoader.java +++ b/sonar-core/src/main/java/org/sonar/core/platform/PluginLoader.java @@ -50,7 +50,7 @@ public class PluginLoader { private static final String[] DEFAULT_SHARED_RESOURCES = {"org/sonar/plugins", "com/sonar/plugins", "com/sonarsource/plugins"}; - public static final Version COMPATIBILITY_MODE_MAX_VERSION = Version.create("5.2"); + private static final Version COMPATIBILITY_MODE_MAX_VERSION = Version.create("5.2"); private final PluginJarExploder jarExploder; private final PluginClassloaderFactory classloaderFactory; @@ -96,15 +96,14 @@ public class PluginLoader { def.setSelfFirstStrategy(info.isUseChildFirstClassLoader()); Version minSqVersion = info.getMinimalSqVersion(); boolean compatibilityMode = minSqVersion != null && minSqVersion.compareToIgnoreQualifier(COMPATIBILITY_MODE_MAX_VERSION) < 0; - def.setCompatibilityMode(compatibilityMode); if (compatibilityMode) { - Loggers.get(getClass()).debug("API compatibility mode is enabled on plugin {} [{}] " + - "(built with API lower than {})", - info.getName(), info.getKey(), COMPATIBILITY_MODE_MAX_VERSION); + Loggers.get(getClass()).warn("API compatibility mode is no longer supported. In case of error, plugin {} [{}] should package its dependencies.", + info.getName(), info.getKey()); } } } return classloadersByBasePlugin.values(); + } /** diff --git a/sonar-core/src/test/java/org/sonar/core/platform/PluginClassloaderFactoryTest.java b/sonar-core/src/test/java/org/sonar/core/platform/PluginClassloaderFactoryTest.java index 9d825b758af..329a5431d7a 100644 --- a/sonar-core/src/test/java/org/sonar/core/platform/PluginClassloaderFactoryTest.java +++ b/sonar-core/src/test/java/org/sonar/core/platform/PluginClassloaderFactoryTest.java @@ -23,10 +23,8 @@ import com.sonarsource.plugins.license.api.FooBar; import java.io.File; import java.util.Map; import org.apache.commons.lang.StringUtils; -import org.junit.Rule; import org.junit.Test; import org.sonar.api.server.rule.RulesDefinition; -import org.sonar.api.utils.internal.JUnitTempFolder; import static java.util.Arrays.asList; import static org.assertj.core.api.Assertions.assertThat; @@ -38,10 +36,7 @@ public class PluginClassloaderFactoryTest { static final String BASE_PLUGIN_KEY = "base"; static final String DEPENDENT_PLUGIN_KEY = "dependent"; - @Rule - public JUnitTempFolder temp = new JUnitTempFolder(); - - PluginClassloaderFactory factory = new PluginClassloaderFactory(temp); + PluginClassloaderFactory factory = new PluginClassloaderFactory(); @Test public void create_isolated_classloader() { @@ -61,20 +56,6 @@ public class PluginClassloaderFactoryTest { assertThat(canLoadClass(classLoader, StringUtils.class.getCanonicalName())).isFalse(); } - @Test - public void create_classloader_compatible_with_with_old_api_dependencies() { - PluginClassLoaderDef def = basePluginDef(); - def.setCompatibilityMode(true); - ClassLoader classLoader = factory.create(asList(def)).get(def); - - // Plugin can access to API and its transitive dependencies as defined in version 5.1. - // It can not access to core classes though, even if it was possible in previous versions. - assertThat(canLoadClass(classLoader, RulesDefinition.class.getCanonicalName())).isTrue(); - assertThat(canLoadClass(classLoader, StringUtils.class.getCanonicalName())).isTrue(); - assertThat(canLoadClass(classLoader, BASE_PLUGIN_CLASSNAME)).isTrue(); - assertThat(canLoadClass(classLoader, PluginClassloaderFactory.class.getCanonicalName())).isFalse(); - } - @Test public void classloader_exports_resources_to_other_classloaders() { PluginClassLoaderDef baseDef = basePluginDef(); diff --git a/sonar-core/src/test/java/org/sonar/core/platform/PluginLoaderTest.java b/sonar-core/src/test/java/org/sonar/core/platform/PluginLoaderTest.java index 76a1268f933..2a2ae2c3575 100644 --- a/sonar-core/src/test/java/org/sonar/core/platform/PluginLoaderTest.java +++ b/sonar-core/src/test/java/org/sonar/core/platform/PluginLoaderTest.java @@ -21,13 +21,15 @@ package org.sonar.core.platform; import com.google.common.collect.ImmutableMap; import java.io.File; -import java.io.IOException; import java.util.Collection; import java.util.Collections; +import java.util.List; import org.assertj.core.data.MapEntry; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; +import org.sonar.api.utils.log.LogTester; +import org.sonar.api.utils.log.LoggerLevel; import org.sonar.updatecenter.common.Version; import static org.assertj.core.api.Assertions.assertThat; @@ -39,8 +41,11 @@ public class PluginLoaderTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); + @Rule + public LogTester logTester = new LogTester(); + private PluginClassloaderFactory classloaderFactory = mock(PluginClassloaderFactory.class); - private PluginLoader loader = new PluginLoader(new FakePluginExploder(), classloaderFactory); + private PluginLoader underTest = new PluginLoader(new FakePluginExploder(), classloaderFactory); @Test public void define_classloader() throws Exception { @@ -50,7 +55,7 @@ public class PluginLoaderTest { .setMainClass("org.foo.FooPlugin") .setMinimalSqVersion(Version.create("5.2")); - Collection defs = loader.defineClassloaders(ImmutableMap.of("foo", info)); + Collection defs = underTest.defineClassloaders(ImmutableMap.of("foo", info)); assertThat(defs).hasSize(1); PluginClassLoaderDef def = defs.iterator().next(); @@ -59,21 +64,6 @@ public class PluginLoaderTest { assertThat(def.getFiles()).containsOnly(jarFile); assertThat(def.getMainClassesByPluginKey()).containsOnly(MapEntry.entry("foo", "org.foo.FooPlugin")); // TODO test mask - require change in sonar-classloader - - // built with SQ 5.2+ -> does not need API compatibility mode - assertThat(def.isCompatibilityMode()).isFalse(); - } - - @Test - public void enable_compatibility_mode_if_plugin_is_built_before_5_2() throws Exception { - File jarFile = temp.newFile(); - PluginInfo info = new PluginInfo("foo") - .setJarFile(jarFile) - .setMainClass("org.foo.FooPlugin") - .setMinimalSqVersion(Version.create("4.5.2")); - - Collection defs = loader.defineClassloaders(ImmutableMap.of("foo", info)); - assertThat(defs.iterator().next().isCompatibilityMode()).isTrue(); } /** @@ -104,7 +94,7 @@ public class PluginLoaderTest { .setBasePlugin("foo") .setUseChildFirstClassLoader(true); - Collection defs = loader.defineClassloaders(ImmutableMap.of( + Collection defs = underTest.defineClassloaders(ImmutableMap.of( base.getKey(), base, extension1.getKey(), extension1, extension2.getKey(), extension2)); assertThat(defs).hasSize(1); @@ -120,22 +110,18 @@ public class PluginLoaderTest { } @Test - public void plugin_is_not_recognised_as_system_extension_if_key_is_governance_and_extends_another_plugin() throws IOException { - PluginInfo foo = createPluginInfo("foo"); - PluginInfo governance = createPluginInfo("governance") - .setBasePlugin("foo"); - - Collection defs = loader.defineClassloaders(ImmutableMap.of("foo", foo, "governance", governance)); - - assertThat(defs).extracting("compatibilityMode").containsOnly(false, false); - } - - private PluginInfo createPluginInfo(String pluginKey) throws IOException { + public void log_warning_if_plugin_is_built_with_api_5_2_or_lower() throws Exception { File jarFile = temp.newFile(); - return new PluginInfo(pluginKey) + PluginInfo info = new PluginInfo("foo") .setJarFile(jarFile) - .setMainClass("org.foo." + pluginKey + "Plugin") - .setMinimalSqVersion(Version.create("6.6")); + .setMainClass("org.foo.FooPlugin") + .setMinimalSqVersion(Version.create("4.5.2")); + + Collection defs = underTest.defineClassloaders(ImmutableMap.of("foo", info)); + assertThat(defs).extracting(PluginClassLoaderDef::getBasePluginKey).containsExactly("foo"); + + List warnings = logTester.logs(LoggerLevel.WARN); + assertThat(warnings).contains("API compatibility mode is no longer supported. In case of error, plugin foo [foo] should package its dependencies."); } /** diff --git a/sonar-duplications/build.gradle b/sonar-duplications/build.gradle index a45feb6dca7..79e4b224640 100644 --- a/sonar-duplications/build.gradle +++ b/sonar-duplications/build.gradle @@ -8,6 +8,7 @@ dependencies { // please keep list ordered compile 'org.codehaus.sonar:sonar-channel' + compile project(':sonar-plugin-api') compileOnly 'com.google.code.findbugs:jsr305' diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/CodeFragment.java b/sonar-duplications/src/main/java/org/sonar/duplications/CodeFragment.java deleted file mode 100644 index 450259c72e6..00000000000 --- a/sonar-duplications/src/main/java/org/sonar/duplications/CodeFragment.java +++ /dev/null @@ -1,44 +0,0 @@ -/* - * SonarQube - * Copyright (C) 2009-2018 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.duplications; - - -/** - * TODO Enforce contracts of this interface in concrete classes by using preconditions, currently this leads to failures of tests. - * - *

This interface is not intended to be implemented by clients.

- * - * @since 2.14 - */ -public interface CodeFragment { - - /** - * Number of line where fragment starts. - * Numbering starts from 1. - */ - int getStartLine(); - - /** - * Number of line where fragment ends. - * Numbering starts from 1. - */ - int getEndLine(); - -} diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/block/Block.java b/sonar-duplications/src/main/java/org/sonar/duplications/block/Block.java index 7b2e5fe3dce..76b8bbc4b36 100644 --- a/sonar-duplications/src/main/java/org/sonar/duplications/block/Block.java +++ b/sonar-duplications/src/main/java/org/sonar/duplications/block/Block.java @@ -19,13 +19,11 @@ */ package org.sonar.duplications.block; -import org.sonar.duplications.CodeFragment; - /** * Represents part of source code between two lines. * If two blocks have the same {@link #getBlockHash() hash}, then we assume that there is a duplication in a code, which they represent. */ -public final class Block implements CodeFragment { +public final class Block { private final String resourceId; private final ByteArray blockHash; @@ -127,12 +125,10 @@ public final class Block implements CodeFragment { return indexInFile; } - @Override public int getStartLine() { return startLine; } - @Override public int getEndLine() { return endLine; } diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/index/ClonePart.java b/sonar-duplications/src/main/java/org/sonar/duplications/index/ClonePart.java index da8cd64c543..5b62937268a 100644 --- a/sonar-duplications/src/main/java/org/sonar/duplications/index/ClonePart.java +++ b/sonar-duplications/src/main/java/org/sonar/duplications/index/ClonePart.java @@ -19,9 +19,7 @@ */ package org.sonar.duplications.index; -import org.sonar.duplications.CodeFragment; - -public class ClonePart implements CodeFragment { +public class ClonePart { private final String resourceId; private final int startUnit; @@ -48,12 +46,10 @@ public class ClonePart implements CodeFragment { return startUnit; } - @Override public int getStartLine() { return startLine; } - @Override public int getEndLine() { return endLine; } diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/PmdBlockChunker.java b/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/PmdBlockChunker.java index 50a32621f0a..1e11b40dc9c 100644 --- a/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/PmdBlockChunker.java +++ b/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/PmdBlockChunker.java @@ -21,9 +21,8 @@ package org.sonar.duplications.internal.pmd; import java.util.ArrayList; import java.util.List; - import javax.annotation.concurrent.Immutable; - +import org.sonar.api.batch.sensor.cpd.internal.TokensLine; import org.sonar.duplications.block.Block; import org.sonar.duplications.block.ByteArray; diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/TokenizerBridge.java b/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/TokenizerBridge.java index 44f1576dc75..e98f30e9e00 100644 --- a/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/TokenizerBridge.java +++ b/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/TokenizerBridge.java @@ -26,6 +26,7 @@ import net.sourceforge.pmd.cpd.SourceCode; import net.sourceforge.pmd.cpd.TokenEntry; import net.sourceforge.pmd.cpd.Tokenizer; import net.sourceforge.pmd.cpd.Tokens; +import org.sonar.api.batch.sensor.cpd.internal.TokensLine; import org.sonar.duplications.block.Block; import org.sonar.duplications.cpd.FileCodeLoaderWithoutCache; diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/statement/Statement.java b/sonar-duplications/src/main/java/org/sonar/duplications/statement/Statement.java index a18c6635381..c6a84d59a7b 100644 --- a/sonar-duplications/src/main/java/org/sonar/duplications/statement/Statement.java +++ b/sonar-duplications/src/main/java/org/sonar/duplications/statement/Statement.java @@ -21,10 +21,9 @@ package org.sonar.duplications.statement; import java.util.List; import javax.annotation.Nullable; -import org.sonar.duplications.CodeFragment; import org.sonar.duplications.token.Token; -public class Statement implements CodeFragment { +public class Statement { private final int startLine; private final int endLine; @@ -54,12 +53,10 @@ public class Statement implements CodeFragment { this.endLine = tokens.get(tokens.size() - 1).getLine(); } - @Override public int getStartLine() { return startLine; } - @Override public int getEndLine() { return endLine; } diff --git a/sonar-duplications/src/test/java/org/sonar/duplications/internal/pmd/PmdBlockChunkerTest.java b/sonar-duplications/src/test/java/org/sonar/duplications/internal/pmd/PmdBlockChunkerTest.java index 4335be00567..99d895c0b9b 100644 --- a/sonar-duplications/src/test/java/org/sonar/duplications/internal/pmd/PmdBlockChunkerTest.java +++ b/sonar-duplications/src/test/java/org/sonar/duplications/internal/pmd/PmdBlockChunkerTest.java @@ -19,13 +19,13 @@ */ package org.sonar.duplications.internal.pmd; +import java.util.Arrays; +import java.util.List; import org.junit.Test; +import org.sonar.api.batch.sensor.cpd.internal.TokensLine; import org.sonar.duplications.block.Block; import org.sonar.duplications.block.ByteArray; -import java.util.Arrays; -import java.util.List; - import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; diff --git a/sonar-duplications/src/test/java/org/sonar/duplications/internal/pmd/TokenizerBridgeTest.java b/sonar-duplications/src/test/java/org/sonar/duplications/internal/pmd/TokenizerBridgeTest.java index 7ff5dbe30d4..12f58bd8c9a 100644 --- a/sonar-duplications/src/test/java/org/sonar/duplications/internal/pmd/TokenizerBridgeTest.java +++ b/sonar-duplications/src/test/java/org/sonar/duplications/internal/pmd/TokenizerBridgeTest.java @@ -30,6 +30,7 @@ import net.sourceforge.pmd.cpd.Tokenizer; import net.sourceforge.pmd.cpd.Tokens; import org.junit.Before; import org.junit.Test; +import org.sonar.api.batch.sensor.cpd.internal.TokensLine; import static org.hamcrest.CoreMatchers.is; import static org.junit.Assert.assertThat; diff --git a/sonar-plugin-api-deps/build.gradle b/sonar-plugin-api-deps/build.gradle deleted file mode 100644 index e8620ce371a..00000000000 --- a/sonar-plugin-api-deps/build.gradle +++ /dev/null @@ -1,42 +0,0 @@ -sonarqube { - properties { - property 'sonar.projectName', "${projectTitle} :: Plugin API Dependencies" - } -} - -apply plugin: 'com.github.johnrengelman.shadow' - -dependencies { - // Versions must not be changed and overridden from root build.gradle (see dependencyManagement section). - // These are the versions defined in SQ 5.1 - compile 'com.google.code.gson:gson:2.3.1' - compile 'com.google.guava:guava:10.0.1' - compile 'commons-beanutils:commons-beanutils:1.9.3' - compile 'commons-codec:commons-codec:1.8' - compile 'commons-collections:commons-collections:3.2.2' - compile 'org.apache.commons:commons-email:1.3.2' - compile 'commons-io:commons-io:2.4' - compile 'commons-lang:commons-lang:2.6' - compile('dom4j:dom4j:1.6.1') { - exclude group: 'xml-apis' - } - compile 'org.picocontainer:picocontainer:2.14.3' - compile 'org.slf4j:slf4j-api:1.7.10' - compile 'ch.qos.logback:logback-classic:1.1.2' - compile 'ch.qos.logback:logback-core:1.1.2' - compile('org.apache.maven:maven-core:3.0.5') { - exclude group: 'classworlds', module: 'classworlds' - exclude group: 'org.sonatype.sisu', module: 'sisu-guava' - } - compile 'org.apache.maven:maven-artifact:3.0.5' - compile('org.codehaus.sonar:sonar-squid:4.1') { - exclude group: 'org.codehaus.sonar', module: 'sonar-check-api' - } - compile('org.codehaus.sonar:sonar-java-api:5.1') { - exclude group: 'org.codehaus.sonar', module: 'sonar-deprecated' - exclude group: 'org.codehaus.sonar', module: 'sonar-plugin-api' - } -} - -// This JAR is cached because used as a resource in sonar-core: -shadowJar.outputs.cacheIf { true } diff --git a/sonar-plugin-api/build.gradle b/sonar-plugin-api/build.gradle index 047cf35b695..e9c781e7e47 100644 --- a/sonar-plugin-api/build.gradle +++ b/sonar-plugin-api/build.gradle @@ -17,9 +17,6 @@ dependencies { // shaded, but not relocated compile project(':sonar-check-api') - compile(project(':sonar-duplications')) { - exclude group: 'org.slf4', module: 'slf4j-api' - } shadow 'org.codehaus.staxmate:staxmate' shadow 'org.codehaus.woodstox:stax2-api' diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java index 16ac7816508..06c5e30c0dd 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/DefaultCpdTokens.java @@ -30,7 +30,6 @@ import org.sonar.api.batch.sensor.cpd.NewCpdTokens; import org.sonar.api.batch.sensor.internal.DefaultStorable; import org.sonar.api.batch.sensor.internal.SensorStorage; import org.sonar.api.config.Configuration; -import org.sonar.duplications.internal.pmd.TokensLine; import static com.google.common.base.Preconditions.checkState; import static java.util.Collections.unmodifiableList; @@ -39,7 +38,7 @@ import static java.util.Objects.requireNonNull; public class DefaultCpdTokens extends DefaultStorable implements NewCpdTokens { private final Configuration config; - private final ArrayList result = new ArrayList<>(); + private final List result = new ArrayList<>(); private InputFile inputFile; private int startLine = Integer.MIN_VALUE; private int startIndex = 0; diff --git a/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/TokensLine.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/TokensLine.java similarity index 91% rename from sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/TokensLine.java rename to sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/TokensLine.java index 62f3059b01d..648fddbf37a 100644 --- a/sonar-duplications/src/main/java/org/sonar/duplications/internal/pmd/TokensLine.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/cpd/internal/TokensLine.java @@ -17,14 +17,12 @@ * 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.duplications.internal.pmd; - -import org.sonar.duplications.CodeFragment; +package org.sonar.api.batch.sensor.cpd.internal; /** * Immutable code fragment, which formed from tokens of one line. */ -public class TokensLine implements CodeFragment { +public class TokensLine { private final String value; @@ -51,7 +49,6 @@ public class TokensLine implements CodeFragment { return value; } - @Override public int getStartLine() { return startLine; } @@ -59,7 +56,6 @@ public class TokensLine implements CodeFragment { /** * Same as {@link #getStartLine()} */ - @Override public int getEndLine() { return startLine; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java index 76977f55bd7..3559ebdb258 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/batch/sensor/internal/SensorContextTester.java @@ -53,6 +53,7 @@ import org.sonar.api.batch.sensor.coverage.NewCoverage; import org.sonar.api.batch.sensor.coverage.internal.DefaultCoverage; import org.sonar.api.batch.sensor.cpd.NewCpdTokens; import org.sonar.api.batch.sensor.cpd.internal.DefaultCpdTokens; +import org.sonar.api.batch.sensor.cpd.internal.TokensLine; import org.sonar.api.batch.sensor.error.AnalysisError; import org.sonar.api.batch.sensor.error.NewAnalysisError; import org.sonar.api.batch.sensor.error.internal.DefaultAnalysisError; @@ -80,7 +81,6 @@ import org.sonar.api.internal.SonarRuntimeImpl; import org.sonar.api.measures.Metric; import org.sonar.api.utils.System2; import org.sonar.api.utils.Version; -import org.sonar.duplications.internal.pmd.TokensLine; import static java.util.Collections.unmodifiableMap; diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/server/authentication/IdentityProvider.java b/sonar-plugin-api/src/main/java/org/sonar/api/server/authentication/IdentityProvider.java index 3b0e01073e9..fff63e272fd 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/server/authentication/IdentityProvider.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/server/authentication/IdentityProvider.java @@ -19,6 +19,7 @@ */ package org.sonar.api.server.authentication; +import org.sonar.api.ExtensionPoint; import org.sonar.api.server.ServerSide; /** @@ -32,6 +33,7 @@ import org.sonar.api.server.ServerSide; * @since 5.4 */ @ServerSide +@ExtensionPoint public interface IdentityProvider { /** diff --git a/sonar-scanner-engine/build.gradle b/sonar-scanner-engine/build.gradle index 2442d85d34d..9ad0ce807ba 100644 --- a/sonar-scanner-engine/build.gradle +++ b/sonar-scanner-engine/build.gradle @@ -30,6 +30,7 @@ dependencies { compile project(':sonar-core') compile project(':sonar-scanner-protocol') compile project(':sonar-ws') + compile project(':sonar-duplications') runtime project(path: ':sonar-plugin-api', configuration: 'shadow') compileOnly project(path: ':sonar-plugin-api') -- 2.39.5