From d4659909aab7c9d7b80c54527b934039a3863e08 Mon Sep 17 00:00:00 2001 From: =?utf8?q?S=C3=A9bastien=20Lesaint?= Date: Fri, 17 Apr 2015 22:04:30 +0200 Subject: [PATCH] SONAR-6383 add method to list downloaded plugins as PluginMetadata --- .../server/plugins/PluginDownloader.java | 62 +++++++++----- .../plugins/ws/PendingPluginsWsAction.java | 2 +- .../java/org/sonar/server/ui/JRubyFacade.java | 2 +- .../server/plugins/PluginDownloaderTest.java | 79 ++++++++++++------ .../ws/PendingPluginsWsActionTest.java | 4 +- .../PluginDownloaderTest/foo-plugin-1.0.jar | Bin 0 -> 955 bytes 6 files changed, 101 insertions(+), 48 deletions(-) create mode 100644 server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginDownloaderTest/foo-plugin-1.0.jar diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java index 295a58a916a..860ad0f53af 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java +++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/PluginDownloader.java @@ -20,12 +20,12 @@ package org.sonar.server.plugins; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; import org.picocontainer.Startable; +import org.sonar.api.utils.HttpDownloader; import org.sonar.api.utils.SonarException; import org.sonar.api.utils.log.Logger; import org.sonar.api.utils.log.Loggers; -import org.sonar.api.utils.HttpDownloader; +import org.sonar.core.plugins.DefaultPluginMetadata; import org.sonar.server.platform.DefaultServerFileSystem; import org.sonar.updatecenter.common.Release; import org.sonar.updatecenter.common.Version; @@ -38,6 +38,16 @@ import java.util.ArrayList; import java.util.Collection; import java.util.List; +import static com.google.common.collect.Iterables.transform; +import static com.google.common.collect.Lists.newArrayList; +import static org.apache.commons.io.FileUtils.cleanDirectory; +import static org.apache.commons.io.FileUtils.copyFile; +import static org.apache.commons.io.FileUtils.copyFileToDirectory; +import static org.apache.commons.io.FileUtils.deleteQuietly; +import static org.apache.commons.io.FileUtils.forceMkdir; +import static org.apache.commons.io.FileUtils.toFile; +import static org.apache.commons.lang.StringUtils.substringAfterLast; + public class PluginDownloader implements Startable { private static final Logger LOG = Loggers.get(PluginDownloader.class); @@ -46,12 +56,14 @@ public class PluginDownloader implements Startable { private final UpdateCenterMatrixFactory updateCenterMatrixFactory; private final HttpDownloader downloader; + private final ServerPluginJarInstaller installer; private final File downloadDir; public PluginDownloader(UpdateCenterMatrixFactory updateCenterMatrixFactory, HttpDownloader downloader, - DefaultServerFileSystem fileSystem) { + DefaultServerFileSystem fileSystem, ServerPluginJarInstaller installer) { this.updateCenterMatrixFactory = updateCenterMatrixFactory; this.downloader = downloader; + this.installer = installer; this.downloadDir = fileSystem.getDownloadedPluginsDir(); } @@ -63,12 +75,10 @@ public class PluginDownloader implements Startable { @Override public void start() { try { - FileUtils.forceMkdir(downloadDir); - Collection tempFiles = FileUtils.listFiles(downloadDir, new String[] {TMP_SUFFIX}, false); - for (File tempFile : tempFiles) { - FileUtils.deleteQuietly(tempFile); + forceMkdir(downloadDir); + for (File tempFile : listTempFile(this.downloadDir)) { + deleteQuietly(tempFile); } - } catch (IOException e) { throw new IllegalStateException("Fail to create the directory: " + downloadDir, e); } @@ -82,7 +92,7 @@ public class PluginDownloader implements Startable { public void cancelDownloads() { try { if (downloadDir.exists()) { - FileUtils.cleanDirectory(downloadDir); + cleanDirectory(downloadDir); } } catch (IOException e) { throw new IllegalStateException("Fail to clean the plugin downloads directory: " + downloadDir, e); @@ -90,18 +100,24 @@ public class PluginDownloader implements Startable { } public boolean hasDownloads() { - return !getDownloads().isEmpty(); + return !getDownloadedPluginFilenames().isEmpty(); } - public List getDownloads() { - List names = new ArrayList(); - List files = (List) FileUtils.listFiles(downloadDir, new String[] {PLUGIN_EXTENSION}, false); - for (File file : files) { + public List getDownloadedPluginFilenames() { + List names = new ArrayList<>(); + for (File file : listPlugins(this.downloadDir)) { names.add(file.getName()); } return names; } + /** + * @return the list of download plugins as {@link DefaultPluginMetadata} instances + */ + public Collection getDownloadedPlugins() { + return newArrayList(transform(listPlugins(this.downloadDir), installer.fileToPlugin(false))); + } + public void download(String pluginKey, Version version) { for (Release release : updateCenterMatrixFactory.getUpdateCenter(true).findInstallablePlugins(pluginKey, version)) { try { @@ -122,18 +138,26 @@ public class PluginDownloader implements Startable { URI uri = new URI(url); if (url.startsWith("file:")) { // used for tests - File file = FileUtils.toFile(uri.toURL()); - FileUtils.copyFileToDirectory(file, downloadDir); + File file = toFile(uri.toURL()); + copyFileToDirectory(file, downloadDir); } else { - String filename = StringUtils.substringAfterLast(uri.getPath(), "/"); + String filename = substringAfterLast(uri.getPath(), "/"); if (!filename.endsWith("." + PLUGIN_EXTENSION)) { filename = release.getKey() + "-" + release.getVersion() + "." + PLUGIN_EXTENSION; } File targetFile = new File(downloadDir, filename); File tempFile = new File(downloadDir, filename + "." + TMP_SUFFIX); downloader.download(uri, tempFile); - FileUtils.copyFile(tempFile, targetFile); - FileUtils.deleteQuietly(tempFile); + copyFile(tempFile, targetFile); + deleteQuietly(tempFile); } } + + private static Collection listTempFile(File dir) { + return FileUtils.listFiles(dir, new String[]{TMP_SUFFIX}, false); + } + + private static Collection listPlugins(File dir) { + return FileUtils.listFiles(dir, new String[]{PLUGIN_EXTENSION}, false); + } } diff --git a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java index eaf8d6eb2d4..9c9d6be3f4a 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java +++ b/server/sonar-server/src/main/java/org/sonar/server/plugins/ws/PendingPluginsWsAction.java @@ -74,7 +74,7 @@ public class PendingPluginsWsAction implements PluginsWsAction { private void writeInstalling(JsonWriter jsonWriter) { jsonWriter.name(ARRAY_INSTALLING); jsonWriter.beginArray(); - for (String fileName : copyOf(CASE_INSENSITIVE_ORDER, pluginDownloader.getDownloads())) { + for (String fileName : copyOf(CASE_INSENSITIVE_ORDER, pluginDownloader.getDownloadedPluginFilenames())) { writeArchive(jsonWriter, fileName); } jsonWriter.endArray(); diff --git a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java index f8ea22a46c7..eceb52ec6d3 100644 --- a/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java +++ b/server/sonar-server/src/main/java/org/sonar/server/ui/JRubyFacade.java @@ -141,7 +141,7 @@ public final class JRubyFacade { } public List getPluginDownloads() { - return get(PluginDownloader.class).getDownloads(); + return get(PluginDownloader.class).getDownloadedPluginFilenames(); } public void uninstallPlugin(String pluginKey) { diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java index f98c49dd844..b5e92448752 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/PluginDownloaderTest.java @@ -19,8 +19,6 @@ */ package org.sonar.server.plugins; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; import org.junit.After; import org.junit.Before; import org.junit.Rule; @@ -31,16 +29,21 @@ import org.mockito.invocation.InvocationOnMock; import org.mockito.stubbing.Answer; import org.sonar.api.utils.HttpDownloader; import org.sonar.api.utils.SonarException; +import org.sonar.core.plugins.DefaultPluginMetadata; import org.sonar.server.platform.DefaultServerFileSystem; import org.sonar.updatecenter.common.Plugin; import org.sonar.updatecenter.common.Release; import org.sonar.updatecenter.common.UpdateCenter; -import org.sonar.updatecenter.common.Version; import java.io.File; import java.net.URI; +import java.net.URISyntaxException; +import java.net.URL; import static com.google.common.collect.Lists.newArrayList; +import static org.apache.commons.io.FileUtils.copyFileToDirectory; +import static org.apache.commons.io.FileUtils.touch; +import static org.apache.commons.io.FilenameUtils.separatorsToUnix; import static org.assertj.core.api.Assertions.assertThat; import static org.junit.Assert.fail; import static org.mockito.Matchers.any; @@ -52,6 +55,7 @@ import static org.mockito.Mockito.mock; import static org.mockito.Mockito.never; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; +import static org.sonar.updatecenter.common.Version.create; public class PluginDownloaderTest { @@ -62,6 +66,7 @@ public class PluginDownloaderTest { UpdateCenter updateCenter; HttpDownloader httpDownloader; PluginDownloader pluginDownloader; + ServerPluginJarInstaller installer; @Before public void before() throws Exception { @@ -74,7 +79,7 @@ public class PluginDownloaderTest { @Override public Object answer(InvocationOnMock inv) throws Throwable { File toFile = (File) inv.getArguments()[1]; - FileUtils.touch(toFile); + touch(toFile); return null; } }).when(httpDownloader).download(any(URI.class), any(File.class)); @@ -83,7 +88,8 @@ public class PluginDownloaderTest { downloadDir = testFolder.newFolder("downloads"); when(defaultServerFileSystem.getDownloadedPluginsDir()).thenReturn(downloadDir); - pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, defaultServerFileSystem); + installer = new ServerPluginJarInstaller(); + pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, defaultServerFileSystem, installer); } @After @@ -93,8 +99,8 @@ public class PluginDownloaderTest { @Test public void clean_temporary_files_at_startup() throws Exception { - FileUtils.touch(new File(downloadDir, "sonar-php.jar")); - FileUtils.touch(new File(downloadDir, "sonar-js.jar.tmp")); + touch(new File(downloadDir, "sonar-php.jar")); + touch(new File(downloadDir, "sonar-js.jar.tmp")); assertThat(downloadDir.listFiles()).hasSize(2); pluginDownloader.start(); @@ -109,10 +115,10 @@ public class PluginDownloaderTest { Release test10 = new Release(test, "1.0").setDownloadUrl("http://server/test-1.0.jar"); test.addRelease(test10); - when(updateCenter.findInstallablePlugins("foo", Version.create("1.0"))).thenReturn(newArrayList(test10)); + when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); pluginDownloader.start(); - pluginDownloader.download("foo", Version.create("1.0")); + pluginDownloader.download("foo", create("1.0")); // SONAR-4523: do not corrupt JAR files when restarting the server while a plugin is being downloaded. // The JAR file is downloaded in a temp file @@ -130,10 +136,10 @@ public class PluginDownloaderTest { Release test10 = new Release(test, "1.0").setDownloadUrl("http://server/redirect?r=release&g=test&a=test&v=1.0&e=jar"); test.addRelease(test10); - when(updateCenter.findInstallablePlugins("foo", Version.create("1.0"))).thenReturn(newArrayList(test10)); + when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); pluginDownloader.start(); - pluginDownloader.download("foo", Version.create("1.0")); + pluginDownloader.download("foo", create("1.0")); // SONAR-4523: do not corrupt JAR files when restarting the server while a plugin is being downloaded. // The JAR file is downloaded in a temp file @@ -149,7 +155,7 @@ public class PluginDownloaderTest { File downloadDir = testFolder.newFile(); when(defaultServerFileSystem.getDownloadedPluginsDir()).thenReturn(downloadDir); - pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, defaultServerFileSystem); + pluginDownloader = new PluginDownloader(updateCenterMatrixFactory, httpDownloader, defaultServerFileSystem, installer); try { pluginDownloader.start(); fail(); @@ -163,13 +169,13 @@ public class PluginDownloaderTest { Plugin test = new Plugin("test"); File file = testFolder.newFile("test-1.0.jar"); file.createNewFile(); - Release test10 = new Release(test, "1.0").setDownloadUrl("file://" + FilenameUtils.separatorsToUnix(file.getCanonicalPath())); + Release test10 = new Release(test, "1.0").setDownloadUrl("file://" + separatorsToUnix(file.getCanonicalPath())); test.addRelease(test10); - when(updateCenter.findInstallablePlugins("foo", Version.create("1.0"))).thenReturn(newArrayList(test10)); + when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); pluginDownloader.start(); - pluginDownloader.download("foo", Version.create("1.0")); + pluginDownloader.download("foo", create("1.0")); verify(httpDownloader, never()).download(any(URI.class), any(File.class)); assertThat(pluginDownloader.hasDownloads()).isTrue(); } @@ -180,11 +186,11 @@ public class PluginDownloaderTest { Release test10 = new Release(test, "1.0").setDownloadUrl("file://not_found"); test.addRelease(test10); - when(updateCenter.findInstallablePlugins("foo", Version.create("1.0"))).thenReturn(newArrayList(test10)); + when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); pluginDownloader.start(); try { - pluginDownloader.download("foo", Version.create("1.0")); + pluginDownloader.download("foo", create("1.0")); fail(); } catch (SonarException e) { // ok @@ -196,13 +202,13 @@ public class PluginDownloaderTest { Plugin test = new Plugin("test"); Release test10 = new Release(test, "1.0").setDownloadUrl("http://server/test-1.0.jar"); test.addRelease(test10); - when(updateCenter.findInstallablePlugins("foo", Version.create("1.0"))).thenReturn(newArrayList(test10)); + when(updateCenter.findInstallablePlugins("foo", create("1.0"))).thenReturn(newArrayList(test10)); doThrow(new RuntimeException()).when(httpDownloader).download(any(URI.class), any(File.class)); pluginDownloader.start(); try { - pluginDownloader.download("foo", Version.create("1.0")); + pluginDownloader.download("foo", create("1.0")); fail(); } catch (SonarException e) { // ok @@ -212,14 +218,37 @@ public class PluginDownloaderTest { @Test public void read_download_folder() throws Exception { pluginDownloader.start(); - assertThat(pluginDownloader.getDownloads()).hasSize(0); + assertThat(pluginDownloader.getDownloadedPluginFilenames()).hasSize(0); + + copyFileToDirectory(new File(resource("foo-plugin-1.0.jar")), downloadDir); + + assertThat(pluginDownloader.getDownloadedPlugins()).hasSize(1); + DefaultPluginMetadata metadata = pluginDownloader.getDownloadedPlugins().iterator().next(); + assertThat(metadata.getKey()).isEqualTo("foo"); + assertThat(metadata.getName()).isEqualTo("Foo"); + assertThat(metadata.getVersion()).isEqualTo("1.0"); + assertThat(metadata.getOrganization()).isEqualTo("SonarSource"); + assertThat(metadata.getOrganizationUrl()).isEqualTo("http://www.sonarsource.org"); + assertThat(metadata.getLicense()).isEqualTo("LGPL 3"); + assertThat(metadata.getMainClass()).isEqualTo("foo.Main"); + } + + private URI resource(String fileName) throws URISyntaxException { + URL resource = getClass().getResource(getClass().getSimpleName() + "/" + fileName); + return resource.toURI(); + } + + @Test + public void getDownloadedPluginFilenames_reads_plugin_metadata_of_files_in_download_folder() throws Exception { + pluginDownloader.start(); + assertThat(pluginDownloader.getDownloadedPlugins()).hasSize(0); File file1 = new File(downloadDir, "file1.jar"); file1.createNewFile(); File file2 = new File(downloadDir, "file2.jar"); file2.createNewFile(); - assertThat(pluginDownloader.getDownloads()).hasSize(2); + assertThat(pluginDownloader.getDownloadedPluginFilenames()).hasSize(2); } @Test @@ -250,12 +279,12 @@ public class PluginDownloaderTest { Release testDepR = new Release(testDep, "1.0").setDownloadUrl("http://server/testdep-1.0.jar"); testDep.addRelease(testDepR); - when(updateCenter.findInstallablePlugins("test1", Version.create("1.0"))).thenReturn(newArrayList(test1R, testDepR)); - when(updateCenter.findInstallablePlugins("test2", Version.create("1.0"))).thenReturn(newArrayList(test2R, testDepR)); + when(updateCenter.findInstallablePlugins("test1", create("1.0"))).thenReturn(newArrayList(test1R, testDepR)); + when(updateCenter.findInstallablePlugins("test2", create("1.0"))).thenReturn(newArrayList(test2R, testDepR)); pluginDownloader.start(); - pluginDownloader.download("test1", Version.create("1.0")); - pluginDownloader.download("test2", Version.create("1.0")); + pluginDownloader.download("test1", create("1.0")); + pluginDownloader.download("test2", create("1.0")); assertThat(new File(downloadDir, "test1-1.0.jar")).exists(); assertThat(new File(downloadDir, "test2-1.0.jar")).exists(); diff --git a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java index 5a9fb7c4b31..240c6a56621 100644 --- a/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java +++ b/server/sonar-server/src/test/java/org/sonar/server/plugins/ws/PendingPluginsWsActionTest.java @@ -74,7 +74,7 @@ public class PendingPluginsWsActionTest { @Test public void verify_properties_displayed_in_json_per_installing_plugin() throws Exception { - when(pluginDownloader.getDownloads()).thenReturn(of("installed_file.jar")); + when(pluginDownloader.getDownloadedPluginFilenames()).thenReturn(of("installed_file.jar")); underTest.handle(request, response); @@ -116,7 +116,7 @@ public class PendingPluginsWsActionTest { @Test public void installing_plugin_are_sorted_and_unique() throws Exception { - when(pluginDownloader.getDownloads()).thenReturn(of("file2.jar", "file0.jar", "file0.jar", "file1.jar")); + when(pluginDownloader.getDownloadedPluginFilenames()).thenReturn(of("file2.jar", "file0.jar", "file0.jar", "file1.jar")); underTest.handle(request, response); diff --git a/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginDownloaderTest/foo-plugin-1.0.jar b/server/sonar-server/src/test/resources/org/sonar/server/plugins/PluginDownloaderTest/foo-plugin-1.0.jar new file mode 100644 index 0000000000000000000000000000000000000000..3b3ed4b1b7824ac20bda0943f058516093348456 GIT binary patch literal 955 zcmWIWW@Zs#;Nak3h+?jEVL$?$3@i-3t|5-Po_=on|4uP5Ff#;rvvYt{FhP|C;M6Pv zQ~}rQ>*(j{<{BKL=j)a`;iA_O0|D3j%s<=zIBed{#Z`HGokqs$){9HR{R7xqezJiA>C}(h zHIIQokjuyb3^Z5>hhT&-1B0GRaC~q{eo^Y%85^?>8;H2RFSeCnT6?VTS7XbTcm*e; zlz047mTY11xpQ>)_PVm{udz+d!Wqk^e3ScV(fmcFa^e@B17dGaGYc?;6g*~DUn!x? zb<5_L<-NegN2SYd%%7L-a>Y?OFSL`#&wOIKuO}^lpxM>E?%O?~7{cJ|7ls5pd!# zJQ8#D$*$W1PJf&}{SN1Aj)S|^#ksdF)-CYfwTM|3BrX?q?9t&Jn>IRa z1j@yJIqCFAIxj}?{(tQ`YyY|%#@MuQX2J$ene?T5afJUHKpxzJgW(D~f=p`10mq2