aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--build.gradle2
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/container/CePluginJarExploder.java2
-rw-r--r--server/sonar-ce/src/main/java/org/sonar/ce/container/CePluginRepository.java11
-rw-r--r--server/sonar-ce/src/test/java/org/sonar/ce/container/CePluginJarExploderTest.java7
-rw-r--r--server/sonar-ce/src/test/java/org/sonar/ce/container/CePluginRepositoryTest.java8
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystem.java12
-rw-r--r--server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystemImpl.java7
-rw-r--r--server/sonar-server-common/src/test/java/org/sonar/server/platform/ServerFileSystemImplTest.java108
-rw-r--r--server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java62
-rw-r--r--server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java114
-rw-r--r--sonar-application/build.gradle4
11 files changed, 274 insertions, 63 deletions
diff --git a/build.gradle b/build.gradle
index 4602edeb75b..3e666dfcb1d 100644
--- a/build.gradle
+++ b/build.gradle
@@ -335,7 +335,7 @@ subprojects {
dependency 'org.postgresql:postgresql:42.2.16'
dependency 'org.reflections:reflections:0.9.12'
dependency 'org.simpleframework:simple:4.1.21'
- dependency 'org.sonarsource.orchestrator:sonar-orchestrator:3.27.0.2172'
+ dependency 'org.sonarsource.orchestrator:sonar-orchestrator:3.30.0.2630'
dependency 'org.sonarsource.update-center:sonar-update-center-common:1.23.0.723'
dependency 'org.subethamail:subethasmtp:3.1.7'
dependency 'org.yaml:snakeyaml:1.26'
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/CePluginJarExploder.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/CePluginJarExploder.java
index 1560d042832..18959e76b31 100644
--- a/server/sonar-ce/src/main/java/org/sonar/ce/container/CePluginJarExploder.java
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/CePluginJarExploder.java
@@ -28,7 +28,7 @@ import org.sonar.core.platform.PluginInfo;
import org.sonar.core.platform.PluginJarExploder;
/**
- * Explodes the plugin JARs of extensions/plugins/ into a temporary directory
+ * Explodes the plugin JARs of extensions/plugins or lib/extensions into a temporary directory
* dedicated to compute engine.
*/
public class CePluginJarExploder extends PluginJarExploder {
diff --git a/server/sonar-ce/src/main/java/org/sonar/ce/container/CePluginRepository.java b/server/sonar-ce/src/main/java/org/sonar/ce/container/CePluginRepository.java
index 14b11ada9ca..4c9476647ce 100644
--- a/server/sonar-ce/src/main/java/org/sonar/ce/container/CePluginRepository.java
+++ b/server/sonar-ce/src/main/java/org/sonar/ce/container/CePluginRepository.java
@@ -64,12 +64,17 @@ public class CePluginRepository implements PluginRepository, Startable {
@Override
public void start() {
Loggers.get(getClass()).info("Load plugins");
- for (File file : listJarFiles(fs.getInstalledPluginsDir())) {
+ registerPluginsFromDir(fs.getInstalledBundledPluginsDir());
+ registerPluginsFromDir(fs.getInstalledExternalPluginsDir());
+ pluginInstancesByKeys.putAll(loader.load(pluginInfosByKeys));
+ started.set(true);
+ }
+
+ private void registerPluginsFromDir(File pluginsDir) {
+ for (File file : listJarFiles(pluginsDir)) {
PluginInfo info = PluginInfo.create(file);
pluginInfosByKeys.put(info.getKey(), info);
}
- pluginInstancesByKeys.putAll(loader.load(pluginInfosByKeys));
- started.set(true);
}
@Override
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/CePluginJarExploderTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/CePluginJarExploderTest.java
index 94de2f97a88..e7136f2c67f 100644
--- a/server/sonar-ce/src/test/java/org/sonar/ce/container/CePluginJarExploderTest.java
+++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/CePluginJarExploderTest.java
@@ -125,7 +125,12 @@ public class CePluginJarExploderTest {
}
@Override
- public File getInstalledPluginsDir() {
+ public File getInstalledExternalPluginsDir() {
+ throw new UnsupportedOperationException();
+ }
+
+ @Override
+ public File getInstalledBundledPluginsDir() {
throw new UnsupportedOperationException();
}
diff --git a/server/sonar-ce/src/test/java/org/sonar/ce/container/CePluginRepositoryTest.java b/server/sonar-ce/src/test/java/org/sonar/ce/container/CePluginRepositoryTest.java
index ef691a2150f..047eebf6ead 100644
--- a/server/sonar-ce/src/test/java/org/sonar/ce/container/CePluginRepositoryTest.java
+++ b/server/sonar-ce/src/test/java/org/sonar/ce/container/CePluginRepositoryTest.java
@@ -58,7 +58,7 @@ public class CePluginRepositoryTest {
@Test
public void empty_plugins() throws Exception {
// empty folder
- when(fs.getInstalledPluginsDir()).thenReturn(temp.newFolder());
+ when(fs.getInstalledExternalPluginsDir()).thenReturn(temp.newFolder());
underTest.start();
@@ -69,7 +69,7 @@ public class CePluginRepositoryTest {
@Test
public void load_plugins() {
String pluginKey = "test";
- when(fs.getInstalledPluginsDir()).thenReturn(new File("src/test/plugins/sonar-test-plugin/target"));
+ when(fs.getInstalledExternalPluginsDir()).thenReturn(new File("src/test/plugins/sonar-test-plugin/target"));
underTest.start();
@@ -85,7 +85,7 @@ public class CePluginRepositoryTest {
expectedException.expectMessage("Plugin [foo] does not exist");
// empty folder
- when(fs.getInstalledPluginsDir()).thenReturn(temp.newFolder());
+ when(fs.getInstalledExternalPluginsDir()).thenReturn(temp.newFolder());
underTest.start();
underTest.getPluginInfo("foo");
}
@@ -96,7 +96,7 @@ public class CePluginRepositoryTest {
expectedException.expectMessage("Plugin [foo] does not exist");
// empty folder
- when(fs.getInstalledPluginsDir()).thenReturn(temp.newFolder());
+ when(fs.getInstalledExternalPluginsDir()).thenReturn(temp.newFolder());
underTest.start();
underTest.getPluginInstance("foo");
}
diff --git a/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystem.java b/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystem.java
index 086cf45a9d3..097a2945154 100644
--- a/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystem.java
+++ b/server/sonar-server-common/src/main/java/org/sonar/server/platform/ServerFileSystem.java
@@ -47,16 +47,22 @@ public interface ServerFileSystem {
/**
* Directory of plugins downloaded through update center. Files
- * will be moved to {@link #getInstalledPluginsDir()} on startup.
+ * will be moved to {@link #getInstalledExternalPluginsDir()} on startup.
* @return a directory which may or not exist
*/
File getDownloadedPluginsDir();
/**
- * Directory of currently installed plugins. Used at startup.
+ * Directory of currently installed external plugins. Used at startup.
* @return a directory which may or not exist
*/
- File getInstalledPluginsDir();
+ File getInstalledExternalPluginsDir();
+
+ /**
+ * Directory of currently installed bundled plugins. Used at startup.
+ * @return a directory which may or not exist
+ */
+ File getInstalledBundledPluginsDir();
/**
* The file listing all the installed plugins. Used by scanner only.
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 e8b5f24eefe..d107b99d283 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
@@ -79,11 +79,16 @@ public class ServerFileSystemImpl implements ServerFileSystem, org.sonar.api.pla
}
@Override
- public File getInstalledPluginsDir() {
+ public File getInstalledExternalPluginsDir() {
return new File(getHomeDir(), "extensions/plugins");
}
@Override
+ public File getInstalledBundledPluginsDir() {
+ return new File(getHomeDir(), "lib/extensions");
+ }
+
+ @Override
public File getPluginIndex() {
return new File(deployDir, "plugins/index.txt");
}
diff --git a/server/sonar-server-common/src/test/java/org/sonar/server/platform/ServerFileSystemImplTest.java b/server/sonar-server-common/src/test/java/org/sonar/server/platform/ServerFileSystemImplTest.java
new file mode 100644
index 00000000000..4f9a7650f7b
--- /dev/null
+++ b/server/sonar-server-common/src/test/java/org/sonar/server/platform/ServerFileSystemImplTest.java
@@ -0,0 +1,108 @@
+/*
+ * SonarQube
+ * Copyright (C) 2009-2020 SonarSource SA
+ * mailto:info AT sonarsource DOT com
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU Lesser General Public
+ * License as published by the Free Software Foundation; either
+ * version 3 of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+ * Lesser General Public License for more details.
+ *
+ * You should have received a copy of the GNU Lesser General Public License
+ * along with this program; if not, write to the Free Software Foundation,
+ * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ */
+package org.sonar.server.platform;
+
+import java.io.File;
+import java.io.IOException;
+import java.util.HashMap;
+import java.util.Map;
+import java.util.Optional;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.TemporaryFolder;
+import org.sonar.api.config.Configuration;
+import org.sonar.api.utils.log.LogTester;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class ServerFileSystemImplTest {
+
+ @Rule
+ public TemporaryFolder temporaryFolder = new TemporaryFolder();
+
+ @Rule
+ public LogTester logTester = new LogTester();
+
+ private ServerFileSystemImpl underTest;
+ private File homeDir;
+ private File tempDir;
+ private File dataDir;
+
+ @Before
+ public void before() throws IOException {
+ DumpMapConfiguration configuration = new DumpMapConfiguration();
+ homeDir = temporaryFolder.newFolder();
+ tempDir = temporaryFolder.newFolder();
+ dataDir = temporaryFolder.newFolder();
+ configuration.put("sonar.path.home", homeDir.toPath().toString());
+ configuration.put("sonar.path.temp", tempDir.toPath().toString());
+ configuration.put("sonar.path.data", dataDir.toPath().toString());
+ underTest = new ServerFileSystemImpl(configuration);
+ }
+
+ @Test
+ public void start_should_log() {
+ underTest.start();
+ underTest.stop();
+ assertThat(logTester.logs())
+ .contains("SonarQube home: " + homeDir.toPath().toString());
+ }
+
+ @Test
+ public void verify_values_set() {
+ assertThat(underTest.getHomeDir()).isEqualTo(homeDir);
+ assertThat(underTest.getTempDir()).isEqualTo(tempDir);
+
+ assertThat(underTest.getDeployedPluginsDir()).isEqualTo(new File(dataDir.getAbsolutePath() + "/web/deploy/plugins"));
+ assertThat(underTest.getDownloadedPluginsDir()).isEqualTo(new File(homeDir.getAbsolutePath() + "/extensions/downloads"));
+ assertThat(underTest.getInstalledBundledPluginsDir()).isEqualTo(new File(homeDir.getAbsolutePath() + "/lib/extensions"));
+ assertThat(underTest.getInstalledExternalPluginsDir()).isEqualTo(new File(homeDir.getAbsolutePath() + "/extensions/plugins"));
+
+ assertThat(underTest.getPluginIndex()).isEqualTo(new File(dataDir.getAbsolutePath() + "/web/deploy/plugins/index.txt"));
+
+ assertThat(underTest.getUninstalledPluginsDir()).isEqualTo(new File(tempDir.getAbsolutePath() + "/uninstalled-plugins"));
+ }
+
+ private static class DumpMapConfiguration implements Configuration {
+ private final Map<String, String> keyValues = new HashMap<>();
+
+ public Configuration put(String key, String value) {
+ keyValues.put(key, value.trim());
+ return this;
+ }
+
+ @Override
+ public Optional<String> get(String key) {
+ return Optional.ofNullable(keyValues.get(key));
+ }
+
+ @Override
+ public boolean hasKey(String key) {
+ throw new UnsupportedOperationException("hasKey not implemented");
+ }
+
+ @Override
+ public String[] getStringArray(String key) {
+ throw new UnsupportedOperationException("getStringArray not implemented");
+ }
+ }
+
+}
diff --git a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java
index 13aee7ef774..33b03519040 100644
--- a/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java
+++ b/server/sonar-webserver-api/src/main/java/org/sonar/server/plugins/ServerPluginRepository.java
@@ -127,11 +127,16 @@ public class ServerPluginRepository implements PluginRepository, Startable {
}
/**
- * Load the plugins that are located in extensions/plugins. Blacklisted plugins are
+ * Load the plugins that are located in lib/extensions and extensions/plugins. Blacklisted plugins are
* deleted.
*/
private void loadPreInstalledPlugins() {
- for (File file : listJarFiles(fs.getInstalledPluginsDir())) {
+ registerPluginsFromDir(fs.getInstalledBundledPluginsDir());
+ registerPluginsFromDir(fs.getInstalledExternalPluginsDir());
+ }
+
+ private void registerPluginsFromDir(File pluginsDir) {
+ for (File file : listJarFiles(pluginsDir)) {
PluginInfo info = PluginInfo.create(file);
registerPluginInfo(info);
}
@@ -160,10 +165,18 @@ public class ServerPluginRepository implements PluginRepository, Startable {
}
PluginInfo existing = pluginInfosByKeys.put(pluginKey, info);
if (existing != null) {
- throw MessageException.of(format("Found two versions of the plugin %s [%s] in the directory extensions/plugins. Please remove one of %s or %s.",
- info.getName(), pluginKey, info.getNonNullJarFile().getName(), existing.getNonNullJarFile().getName()));
+ File existingPluginParentDir = existing.getNonNullJarFile().getParentFile();
+ File currentPluginParentDir = info.getNonNullJarFile().getParentFile();
+ if (existingPluginParentDir.equals(currentPluginParentDir)) {
+ String directory = existingPluginParentDir.equals(fs.getInstalledBundledPluginsDir()) ? "lib/extensions" : "extensions/plugins";
+ throw MessageException.of(format("Found two versions of the plugin %s [%s] in the directory %s. Please remove one of %s or %s.",
+ info.getName(), pluginKey, directory, info.getNonNullJarFile().getName(), existing.getNonNullJarFile().getName()));
+ } else {
+ throw MessageException
+ .of(format("Found two versions of the plugin %s [%s] in different directories lib/extensions and extension/plugins. Please remove the one from extension/plugins: %s.",
+ info.getName(), pluginKey, info.getNonNullJarFile().getName()));
+ }
}
-
}
/**
@@ -171,26 +184,31 @@ public class ServerPluginRepository implements PluginRepository, Startable {
* already exists then it's deleted.
*/
private void overrideAndRegisterPlugin(File sourceFile) {
- File destDir = fs.getInstalledPluginsDir();
+ File destDir = fs.getInstalledExternalPluginsDir();
File destFile = new File(destDir, sourceFile.getName());
if (destFile.exists()) {
// plugin with same filename already installed
deleteQuietly(destFile);
}
- try {
- moveFile(sourceFile, destFile);
-
- } catch (IOException e) {
- throw new IllegalStateException(format("Fail to move plugin: %s to %s",
- sourceFile.getAbsolutePath(), destFile.getAbsolutePath()), e);
- }
+ movePlugin(sourceFile, destFile);
PluginInfo info = PluginInfo.create(destFile);
PluginInfo existing = pluginInfosByKeys.put(info.getKey(), info);
+
if (existing != null) {
- if (!existing.getNonNullJarFile().getName().equals(destFile.getName())) {
- deleteQuietly(existing.getNonNullJarFile());
+ File existingJarFile = existing.getNonNullJarFile();
+
+ if (existingJarFile.getParentFile().equals(fs.getInstalledBundledPluginsDir())) {
+ // move downloaded plugin back to origin location
+ movePlugin(destFile, sourceFile);
+ throw MessageException.of(format("Fail to update plugin: %s. Bundled plugin with same key already exists: %s. "
+ + "Move or delete plugin from extensions/downloads directory",
+ sourceFile.getName(), existing.getKey()));
+ }
+
+ if (!existingJarFile.getName().equals(destFile.getName())) {
+ deleteQuietly(existingJarFile);
}
LOG.info("Plugin {} [{}] updated to version {}", info.getName(), info.getKey(), info.getVersion());
} else {
@@ -198,6 +216,16 @@ public class ServerPluginRepository implements PluginRepository, Startable {
}
}
+ private void movePlugin(File sourcePluginFile, File destPluginFile) {
+ try {
+ moveFile(sourcePluginFile, destPluginFile);
+
+ } catch (IOException e) {
+ throw new IllegalStateException(format("Fail to move plugin: %s to %s",
+ sourcePluginFile.getAbsolutePath(), destPluginFile.getAbsolutePath()), e);
+ }
+ }
+
/**
* Removes the plugins that are not compatible with current environment.
*/
@@ -301,7 +329,7 @@ public class ServerPluginRepository implements PluginRepository, Startable {
public void cancelUninstalls(File uninstallDir) {
for (File file : listJarFiles(uninstallDir)) {
try {
- moveFileToDirectory(file, fs.getInstalledPluginsDir(), false);
+ moveFileToDirectory(file, fs.getInstalledExternalPluginsDir(), false);
} catch (IOException e) {
throw new IllegalStateException("Fail to cancel plugin uninstalls", e);
}
@@ -326,7 +354,7 @@ public class ServerPluginRepository implements PluginRepository, Startable {
private File getPluginFile(PluginInfo info) {
// we don't reuse info.getFile() just to be sure that file is located in from extensions/plugins
- return new File(fs.getInstalledPluginsDir(), info.getNonNullJarFile().getName());
+ return new File(fs.getInstalledExternalPluginsDir(), info.getNonNullJarFile().getName());
}
public Map<String, PluginInfo> getPluginInfosByKeys() {
diff --git a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java
index 4424e517ba0..ff8b394c7e9 100644
--- a/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java
+++ b/server/sonar-webserver-api/src/test/java/org/sonar/server/plugins/ServerPluginRepositoryTest.java
@@ -42,6 +42,7 @@ import org.sonar.server.platform.ServerFileSystem;
import org.sonar.updatecenter.common.Version;
import static org.assertj.core.api.Assertions.assertThat;
+import static org.assertj.core.api.Assertions.assertThatThrownBy;
import static org.junit.Assert.fail;
import static org.mockito.Mockito.mock;
import static org.mockito.Mockito.when;
@@ -67,7 +68,8 @@ public class ServerPluginRepositoryTest {
when(fs.getDeployedPluginsDir()).thenReturn(temp.newFolder());
when(fs.getDownloadedPluginsDir()).thenReturn(temp.newFolder());
when(fs.getHomeDir()).thenReturn(temp.newFolder());
- when(fs.getInstalledPluginsDir()).thenReturn(temp.newFolder());
+ when(fs.getInstalledExternalPluginsDir()).thenReturn(temp.newFolder());
+ when(fs.getInstalledBundledPluginsDir()).thenReturn(temp.newFolder());
when(fs.getTempDir()).thenReturn(temp.newFolder());
when(runtime.getApiVersion()).thenReturn(org.sonar.api.utils.Version.parse("5.2"));
}
@@ -78,12 +80,13 @@ public class ServerPluginRepositoryTest {
}
@Test
- public void standard_startup_loads_installed_plugins() throws Exception {
- copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ public void standard_startup_loads_installed_bundled_and_external_plugins() throws Exception {
+ copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
+ copyTestPluginTo("test-extend-plugin", fs.getInstalledBundledPluginsDir());
underTest.start();
- assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase");
+ assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase", "testextend");
}
@Test
@@ -96,9 +99,9 @@ public class ServerPluginRepositoryTest {
}
@Test
- public void fail_if_multiple_jars_for_same_installed_plugin_on_startup() throws Exception {
- copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
- copyTestPluginTo("test-base-plugin-v2", fs.getInstalledPluginsDir());
+ public void fail_if_multiple_jars_for_same_installed_external_plugin_on_startup() throws Exception {
+ copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
+ copyTestPluginTo("test-base-plugin-v2", fs.getInstalledExternalPluginsDir());
try {
underTest.start();
@@ -113,6 +116,39 @@ public class ServerPluginRepositoryTest {
}
@Test
+ public void fail_if_multiple_jars_for_same_installed_bundled_plugin_on_startup() throws Exception {
+ copyTestPluginTo("test-base-plugin", fs.getInstalledBundledPluginsDir());
+ copyTestPluginTo("test-base-plugin-v2", fs.getInstalledBundledPluginsDir());
+
+ try {
+ underTest.start();
+ fail();
+ } catch (MessageException e) {
+ assertThat(e)
+ .hasMessageStartingWith("Found two versions of the plugin Base Plugin [testbase] in the directory lib/extensions. Please remove one of ")
+ // order is not guaranteed, so assertion is split
+ .hasMessageContaining("test-base-plugin-0.1-SNAPSHOT.jar")
+ .hasMessageContaining("test-base-plugin-0.2-SNAPSHOT.jar");
+ }
+ }
+
+ @Test
+ public void fail_if_multiple_jars_for_same_installed_external_bundled_plugin_on_startup() throws Exception {
+ copyTestPluginTo("test-base-plugin", fs.getInstalledBundledPluginsDir());
+ copyTestPluginTo("test-base-plugin-v2", fs.getInstalledExternalPluginsDir());
+
+ try {
+ underTest.start();
+ fail();
+ } catch (MessageException e) {
+ assertThat(e)
+ .hasMessageStartingWith(
+ "Found two versions of the plugin Base Plugin [testbase] in different directories lib/extensions and extension/plugins. Please remove the one from extension/plugins: ")
+ .hasMessageContaining("test-base-plugin-0.2-SNAPSHOT.jar");
+ }
+ }
+
+ @Test
public void install_downloaded_plugins_on_startup() throws Exception {
File downloadedJar = copyTestPluginTo("test-base-plugin", fs.getDownloadedPluginsDir());
@@ -120,13 +156,13 @@ public class ServerPluginRepositoryTest {
// plugin is moved to extensions/plugins then loaded
assertThat(downloadedJar).doesNotExist();
- assertThat(new File(fs.getInstalledPluginsDir(), downloadedJar.getName())).isFile().exists();
+ assertThat(new File(fs.getInstalledExternalPluginsDir(), downloadedJar.getName())).isFile().exists();
assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase");
}
@Test
public void downloaded_file_overrides_existing_installed_file_on_startup() throws Exception {
- File installedV1 = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ File installedV1 = copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
File downloadedV2 = copyTestPluginTo("test-base-plugin-v2", fs.getDownloadedPluginsDir());
underTest.start();
@@ -134,15 +170,33 @@ public class ServerPluginRepositoryTest {
// plugin is moved to extensions/plugins and replaces v1
assertThat(downloadedV2).doesNotExist();
assertThat(installedV1).doesNotExist();
- assertThat(new File(fs.getInstalledPluginsDir(), downloadedV2.getName())).exists();
+ assertThat(new File(fs.getInstalledExternalPluginsDir(), downloadedV2.getName())).exists();
assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase");
assertThat(underTest.getPluginInfo("testbase").getVersion()).isEqualTo(Version.create("0.2-SNAPSHOT"));
}
@Test
+ public void downloaded_file_does_not_override_existing_bundled_file_on_startup() throws Exception {
+ File installedV1 = copyTestPluginTo("test-base-plugin", fs.getInstalledBundledPluginsDir());
+ File downloadedV2 = copyTestPluginTo("test-base-plugin-v2", fs.getDownloadedPluginsDir());
+
+ assertThatThrownBy(() -> underTest.start())
+ .isInstanceOf(MessageException.class)
+ .hasMessage("Fail to update plugin: test-base-plugin-0.2-SNAPSHOT.jar. Bundled plugin with same key already exists: testbase. "
+ + "Move or delete plugin from extensions/downloads directory");
+
+ // downloaded plugin stays in origin location
+ assertThat(downloadedV2).exists();
+ // installed plugin has not been deleted
+ assertThat(installedV1).exists();
+ assertThat(new File(fs.getInstalledExternalPluginsDir(), downloadedV2.getName())).doesNotExist();
+ assertThat(underTest.getPluginInfosByKeys()).containsOnlyKeys("testbase");
+ }
+
+ @Test
public void blacklisted_plugin_is_automatically_uninstalled_on_startup() throws Exception {
underTest.setBlacklistedPluginKeys(ImmutableSet.of("testbase", "issuesreport"));
- File jar = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ File jar = copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
underTest.start();
@@ -153,8 +207,8 @@ public class ServerPluginRepositoryTest {
@Test
public void test_plugin_requirements_at_startup() throws Exception {
- copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
- copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
+ copyTestPluginTo("test-require-plugin", fs.getInstalledExternalPluginsDir());
underTest.start();
@@ -164,7 +218,7 @@ public class ServerPluginRepositoryTest {
@Test
public void plugin_is_ignored_if_required_plugin_is_missing_at_startup() throws Exception {
- copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("test-require-plugin", fs.getInstalledExternalPluginsDir());
underTest.start();
@@ -174,8 +228,8 @@ public class ServerPluginRepositoryTest {
@Test
public void plugin_is_ignored_if_required_plugin_is_too_old_at_startup() throws Exception {
- copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
- copyTestPluginTo("test-requirenew-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
+ copyTestPluginTo("test-requirenew-plugin", fs.getInstalledExternalPluginsDir());
underTest.start();
@@ -187,7 +241,7 @@ public class ServerPluginRepositoryTest {
@Test
public void fail_if_plugin_does_not_support_sq_version() throws Exception {
when(runtime.getApiVersion()).thenReturn(org.sonar.api.utils.Version.parse("1.0"));
- copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
try {
underTest.start();
@@ -199,7 +253,7 @@ public class ServerPluginRepositoryTest {
@Test
public void uninstall() throws Exception {
- File installedJar = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
+ File installedJar = copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
File uninstallDir = temp.newFolder("uninstallDir");
underTest.start();
@@ -214,8 +268,8 @@ public class ServerPluginRepositoryTest {
@Test
public void uninstall_dependents() throws Exception {
- File base = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
- File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir());
+ File base = copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
+ File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledExternalPluginsDir());
File uninstallDir = temp.newFolder("uninstallDir");
underTest.start();
@@ -228,8 +282,8 @@ public class ServerPluginRepositoryTest {
@Test
public void dont_uninstall_non_existing_dependents() throws IOException {
- File base = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
- File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir());
+ File base = copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
+ File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledExternalPluginsDir());
File uninstallDir = temp.newFolder("uninstallDir");
underTest.start();
@@ -245,8 +299,8 @@ public class ServerPluginRepositoryTest {
@Test
public void dont_uninstall_non_existing_files() throws IOException {
- File base = copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
- File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledPluginsDir());
+ File base = copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
+ File extension = copyTestPluginTo("test-require-plugin", fs.getInstalledExternalPluginsDir());
File uninstallDir = temp.newFolder("uninstallDir");
underTest.start();
@@ -262,8 +316,8 @@ public class ServerPluginRepositoryTest {
@Test
public void install_plugin_and_its_extension_plugins_at_startup() throws Exception {
- copyTestPluginTo("test-base-plugin", fs.getInstalledPluginsDir());
- copyTestPluginTo("test-extend-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("test-base-plugin", fs.getInstalledExternalPluginsDir());
+ copyTestPluginTo("test-extend-plugin", fs.getInstalledExternalPluginsDir());
underTest.start();
@@ -273,7 +327,7 @@ public class ServerPluginRepositoryTest {
@Test
public void extension_plugin_is_ignored_if_base_plugin_is_missing_at_startup() throws Exception {
- copyTestPluginTo("test-extend-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("test-extend-plugin", fs.getInstalledExternalPluginsDir());
underTest.start();
@@ -308,7 +362,7 @@ public class ServerPluginRepositoryTest {
@Test
public void fail_when_views_is_installed() throws Exception {
- copyTestPluginTo("fake-views-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("fake-views-plugin", fs.getInstalledExternalPluginsDir());
expectedException.expect(MessageException.class);
expectedException.expectMessage("Plugin 'views' is no longer compatible with this version of SonarQube");
@@ -317,7 +371,7 @@ public class ServerPluginRepositoryTest {
@Test
public void fail_when_sqale_plugin_is_installed() throws Exception {
- copyTestPluginTo("fake-sqale-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("fake-sqale-plugin", fs.getInstalledExternalPluginsDir());
expectedException.expect(MessageException.class);
expectedException.expectMessage("Plugin 'sqale' is no longer compatible with this version of SonarQube");
@@ -326,7 +380,7 @@ public class ServerPluginRepositoryTest {
@Test
public void fail_when_report_is_installed() throws Exception {
- copyTestPluginTo("fake-report-plugin", fs.getInstalledPluginsDir());
+ copyTestPluginTo("fake-report-plugin", fs.getInstalledExternalPluginsDir());
expectedException.expect(MessageException.class);
expectedException.expectMessage("Plugin 'report' is no longer compatible with this version of SonarQube");
diff --git a/sonar-application/build.gradle b/sonar-application/build.gradle
index cc4cb315611..bbb08d36c70 100644
--- a/sonar-application/build.gradle
+++ b/sonar-application/build.gradle
@@ -51,7 +51,7 @@ dependencies {
jdbc_postgresql 'org.postgresql:postgresql'
}
-// declare dependencies in configuration bundledPlugin to be packaged in extensions/plugins
+// declare dependencies in configuration bundledPlugin to be packaged in lib/extensions
apply from: 'bundled_plugins.gradle'
jar {
@@ -130,7 +130,7 @@ task zip(type: Zip, dependsOn: [configurations.compile]) {
into("${archiveDir}/lib/") {
from jar
}
- into("${archiveDir}/extensions/plugins/") {
+ into("${archiveDir}/lib/extensions/") {
from configurations.bundledPlugin
}
into("${archiveDir}/lib/jsw/") {