diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2017-12-07 11:38:28 +0100 |
---|---|---|
committer | Duarte Meneses <duarte.meneses@sonarsource.com> | 2017-12-07 15:40:03 +0100 |
commit | 0001182a007e70261d447023f1fa5ad5e1a0b69f (patch) | |
tree | eaae3a5bb2cf5f54a68ca42ac744494d0ead5908 /sonar-home | |
parent | 204f88df32a21b401b4bff3190ee0e3cfb7628a3 (diff) | |
download | sonarqube-0001182a007e70261d447023f1fa5ad5e1a0b69f.tar.gz sonarqube-0001182a007e70261d447023f1fa5ad5e1a0b69f.zip |
SONAR-10142 Download compressed plugins
Diffstat (limited to 'sonar-home')
-rw-r--r-- | sonar-home/src/main/java/org/sonar/home/cache/FileCache.java | 73 | ||||
-rw-r--r-- | sonar-home/src/test/java/org/sonar/home/cache/FileCacheTest.java | 66 | ||||
-rw-r--r-- | sonar-home/src/test/resources/test.pack.gz | bin | 0 -> 2689 bytes |
3 files changed, 104 insertions, 35 deletions
diff --git a/sonar-home/src/main/java/org/sonar/home/cache/FileCache.java b/sonar-home/src/main/java/org/sonar/home/cache/FileCache.java index 4a03ec24794..e3cbafd22de 100644 --- a/sonar-home/src/main/java/org/sonar/home/cache/FileCache.java +++ b/sonar-home/src/main/java/org/sonar/home/cache/FileCache.java @@ -24,10 +24,8 @@ import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; import java.io.InputStream; -import java.net.URL; import java.nio.file.Files; import java.nio.file.Path; -import java.nio.file.Paths; import java.util.jar.JarOutputStream; import java.util.jar.Pack200; import java.util.zip.GZIPInputStream; @@ -43,7 +41,7 @@ public class FileCache { /** Maximum loop count when creating temp directories. */ private static final int TEMP_DIR_ATTEMPTS = 10_000; - private final File dir; + private final File cacheDir; private final File tmpDir; private final FileHashes hashes; private final Logger logger; @@ -51,7 +49,7 @@ public class FileCache { FileCache(File dir, FileHashes fileHashes, Logger logger) { this.hashes = fileHashes; this.logger = logger; - this.dir = createDir(dir, "user cache: "); + this.cacheDir = createDir(dir, "user cache: "); logger.info(String.format("User cache: %s", dir.getAbsolutePath())); this.tmpDir = createDir(new File(dir, "_tmp"), "temp dir"); } @@ -61,7 +59,7 @@ public class FileCache { } public File getDir() { - return dir; + return cacheDir; } /** @@ -70,7 +68,7 @@ public class FileCache { */ @CheckForNull public File get(String filename, String hash) { - File cachedFile = new File(new File(dir, hash), filename); + File cachedFile = new File(new File(cacheDir, hash), filename); if (cachedFile.exists()) { return cachedFile; } @@ -82,41 +80,54 @@ public class FileCache { void download(String filename, File toFile) throws IOException; } - public File get(String jarFilename, String hash, Downloader downloader) { + public File get(String filename, String hash, Downloader downloader) { // Does not fail if another process tries to create the directory at the same time. File hashDir = hashDir(hash); - File targetFile = new File(hashDir, jarFilename); + File targetFile = new File(hashDir, filename); if (!targetFile.exists()) { - File tempPackedFile = newTempFile(); - File tempJarFile = newTempFile(); - String packedFileName = getPackedFileName(jarFilename); - download(downloader, packedFileName, tempPackedFile); - - logger.debug("Unpacking plugin " + jarFilename); - - unpack200(tempPackedFile.toPath(), tempJarFile.toPath()); - logger.debug("Done"); - String downloadedHash = hashes.of(tempJarFile); - // if (!hash.equals(downloadedHash)) { - // throw new IllegalStateException("INVALID HASH: File " + tempJarFile.getAbsolutePath() + " was expected to have hash " + hash - // + " but was downloaded with hash " + downloadedHash); - // } - mkdirQuietly(hashDir); - renameQuietly(tempJarFile, targetFile); - + cacheMiss(targetFile, hash, downloader); } return targetFile; } - private static String getPackedFileName(String jarName) { - return jarName.substring(0, jarName.length() - 3) + "pack.gz"; + private void cacheMiss(File targetFile, String expectedHash, Downloader downloader) { + File tempFile = newTempFile(); + download(downloader, targetFile.getName(), tempFile); + String downloadedHash = hashes.of(tempFile); + if (!expectedHash.equals(downloadedHash)) { + throw new IllegalStateException("INVALID HASH: File " + tempFile.getAbsolutePath() + " was expected to have hash " + expectedHash + + " but was downloaded with hash " + downloadedHash); + } + mkdirQuietly(targetFile.getParentFile()); + renameQuietly(tempFile, targetFile); + } + + public File getCompressed(String filename, String hash, Downloader downloader) { + File hashDir = hashDir(hash); + File compressedFile = new File(hashDir, filename); + File jarFile = new File(compressedFile.getParentFile(), getUnpackedFileName(compressedFile.getName())); + + if (!jarFile.exists()) { + if (!compressedFile.exists()) { + cacheMiss(compressedFile, hash, downloader); + } + File tempFile = newTempFile(); + unpack200(compressedFile.toPath(), tempFile.toPath()); + renameQuietly(tempFile, jarFile); + } + return jarFile; + } + + private static String getUnpackedFileName(String packedName) { + return packedName.substring(0, packedName.length() - 7) + "jar"; } - private static void unpack200(Path tempFile, Path targetFile) { + private void unpack200(Path compressedFile, Path jarFile) { + logger.debug("Unpacking plugin " + compressedFile); Pack200.Unpacker unpacker = Pack200.newUnpacker(); try { - try (JarOutputStream jarStream = new JarOutputStream(new BufferedOutputStream(Files.newOutputStream(targetFile))); - InputStream in = new GZIPInputStream(new BufferedInputStream(Files.newInputStream(tempFile)))) { + try (JarOutputStream jarStream = new JarOutputStream(new BufferedOutputStream(Files.newOutputStream(jarFile))); + InputStream in = new GZIPInputStream(new BufferedInputStream(Files.newInputStream(compressedFile)))) { unpacker.unpack(in, jarStream); } } catch (IOException e) { @@ -147,7 +158,7 @@ public class FileCache { } private File hashDir(String hash) { - return new File(dir, hash); + return new File(cacheDir, hash); } private static void mkdirQuietly(File hashDir) { diff --git a/sonar-home/src/test/java/org/sonar/home/cache/FileCacheTest.java b/sonar-home/src/test/java/org/sonar/home/cache/FileCacheTest.java index 2a7381c866a..67635b5ab70 100644 --- a/sonar-home/src/test/java/org/sonar/home/cache/FileCacheTest.java +++ b/sonar-home/src/test/java/org/sonar/home/cache/FileCacheTest.java @@ -22,7 +22,6 @@ package org.sonar.home.cache; import java.io.File; import java.io.IOException; import org.apache.commons.io.FileUtils; -import org.assertj.core.util.Files; import org.junit.Before; import org.junit.Rule; import org.junit.Test; @@ -32,6 +31,7 @@ import org.junit.rules.TemporaryFolder; import static org.assertj.core.api.Assertions.assertThat; import static org.mockito.Matchers.any; import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.verifyZeroInteractions; import static org.mockito.Mockito.when; public class FileCacheTest { @@ -77,7 +77,7 @@ public class FileCacheTest { thrown.expectMessage("Fail to download"); cache.get("sonar-foo-plugin-1.5.jar", "ABCDE", downloader); } - + @Test public void fail_create_hash_dir() throws IOException { File file = tempFolder.newFile(); @@ -85,11 +85,11 @@ public class FileCacheTest { thrown.expectMessage("Unable to create user cache"); cache = new FileCache(file, fileHashes, mock(Logger.class)); } - + @Test public void fail_to_create_hash_dir() throws IOException { when(fileHashes.of(any(File.class))).thenReturn("ABCDE"); - + File hashDir = new File(cache.getDir(), "ABCDE"); hashDir.createNewFile(); thrown.expect(IllegalStateException.class); @@ -114,6 +114,60 @@ public class FileCacheTest { } @Test + public void download_and_add_to_cache_compressed_file() throws IOException { + when(fileHashes.of(any(File.class))).thenReturn("ABCDE"); + + FileCache.Downloader downloader = new FileCache.Downloader() { + public void download(String filename, File toFile) throws IOException { + FileUtils.copyFile(compressedFile(), toFile); + } + }; + File cachedFile = cache.getCompressed("sonar-foo-plugin-1.5.pack.gz", "ABCDE", downloader); + assertThat(cachedFile).isNotNull().exists().isFile(); + + assertThat(cachedFile.getName()).isEqualTo("sonar-foo-plugin-1.5.jar"); + assertThat(cachedFile.getParentFile().list()).containsOnly("sonar-foo-plugin-1.5.jar", "sonar-foo-plugin-1.5.pack.gz"); + assertThat(cachedFile.getParentFile().getParentFile()).isEqualTo(cache.getDir()); + } + + @Test + public void dont_download_compressed_file_if_jar_exists() throws IOException { + when(fileHashes.of(any(File.class))).thenReturn("ABCDE"); + FileCache.Downloader downloader = mock(FileCache.Downloader.class); + + File hashDir = new File(cache.getDir(), "ABCDE"); + hashDir.mkdirs(); + File jar = new File(new File(cache.getDir(), "ABCDE"), "sonar-foo-plugin-1.5.jar"); + jar.createNewFile(); + File cachedFile = cache.getCompressed("sonar-foo-plugin-1.5.pack.gz", "ABCDE", downloader); + assertThat(cachedFile).isNotNull().exists().isFile(); + + assertThat(cachedFile.getName()).isEqualTo("sonar-foo-plugin-1.5.jar"); + assertThat(cachedFile.getParentFile().list()).containsOnly("sonar-foo-plugin-1.5.jar"); + assertThat(cachedFile.getParentFile().getParentFile()).isEqualTo(cache.getDir()); + + verifyZeroInteractions(downloader); + } + + @Test + public void dont_download_compressed_file_if_it_exists() throws IOException { + when(fileHashes.of(any(File.class))).thenReturn("ABCDE"); + FileCache.Downloader downloader = mock(FileCache.Downloader.class); + + File hashDir = new File(cache.getDir(), "ABCDE"); + hashDir.mkdirs(); + FileUtils.copyFile(compressedFile(), new File(hashDir, "sonar-foo-plugin-1.5.pack.gz")); + File cachedFile = cache.getCompressed("sonar-foo-plugin-1.5.pack.gz", "ABCDE", downloader); + assertThat(cachedFile).isNotNull().exists().isFile(); + + assertThat(cachedFile.getName()).isEqualTo("sonar-foo-plugin-1.5.jar"); + assertThat(cachedFile.getParentFile().list()).containsOnly("sonar-foo-plugin-1.5.jar", "sonar-foo-plugin-1.5.pack.gz"); + assertThat(cachedFile.getParentFile().getParentFile()).isEqualTo(cache.getDir()); + + verifyZeroInteractions(downloader); + } + + @Test public void download_corrupted_file() throws IOException { thrown.expect(IllegalStateException.class); thrown.expectMessage("INVALID HASH"); @@ -149,4 +203,8 @@ public class FileCacheTest { assertThat(cachedFile.getParentFile().getParentFile()).isEqualTo(cache.getDir()); assertThat(FileUtils.readFileToString(cachedFile)).contains("downloaded by"); } + + private File compressedFile() { + return new File("src/test/resources/test.pack.gz"); + } } diff --git a/sonar-home/src/test/resources/test.pack.gz b/sonar-home/src/test/resources/test.pack.gz Binary files differnew file mode 100644 index 00000000000..8e3a43c8e3d --- /dev/null +++ b/sonar-home/src/test/resources/test.pack.gz |