]> source.dussan.org Git - sonarqube.git/commitdiff
SONAR-10591 drop module sonar-home
authorSimon Brandhof <simon.brandhof@sonarsource.com>
Thu, 10 May 2018 19:54:03 +0000 (21:54 +0200)
committerSonarTech <sonartech@sonarsource.com>
Fri, 11 May 2018 18:20:47 +0000 (20:20 +0200)
16 files changed:
settings.gradle
sonar-home/src/main/java/org/sonar/home/cache/DirectoryLock.java [deleted file]
sonar-home/src/main/java/org/sonar/home/cache/FileCache.java [deleted file]
sonar-home/src/main/java/org/sonar/home/cache/FileCacheBuilder.java [deleted file]
sonar-home/src/main/java/org/sonar/home/cache/FileHashes.java [deleted file]
sonar-home/src/test/java/org/sonar/home/cache/DirectoryLockTest.java [deleted file]
sonar-home/src/test/java/org/sonar/home/cache/FileCacheBuilderTest.java [deleted file]
sonar-home/src/test/java/org/sonar/home/cache/FileCacheTest.java [deleted file]
sonar-home/src/test/java/org/sonar/home/cache/FileHashesTest.java [deleted file]
sonar-scanner-engine/build.gradle
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DirectoryLock.java [new file with mode: 0644]
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/ProjectLock.java
sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/WorkDirectoriesInitializer.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DirectoryLockTest.java [new file with mode: 0644]
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/ProjectLockTest.java
sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/WorkDirectoriesInitializerTest.java

index bc05b4e8080173cd51ea0fc33c9333ce67f5ed57..98b327c91112a6f799298ed2161910acc4f856be 100644 (file)
@@ -19,7 +19,6 @@ include 'sonar-application'
 include 'sonar-check-api'
 include 'sonar-core'
 include 'sonar-duplications'
-include 'sonar-home'
 include 'sonar-markdown'
 include 'sonar-plugin-api'
 include 'sonar-plugin-api-deps'
diff --git a/sonar-home/src/main/java/org/sonar/home/cache/DirectoryLock.java b/sonar-home/src/main/java/org/sonar/home/cache/DirectoryLock.java
deleted file mode 100644 (file)
index db61bac..0000000
+++ /dev/null
@@ -1,80 +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.home.cache;
-
-import java.io.IOException;
-import java.io.RandomAccessFile;
-import java.nio.channels.FileChannel;
-import java.nio.channels.FileLock;
-import java.nio.file.Path;
-
-public class DirectoryLock {
-  public static final String LOCK_FILE_NAME = ".sonar_lock";
-  private final Path lockFilePath;
-  private final Logger logger;
-
-  private RandomAccessFile lockRandomAccessFile;
-  private FileChannel lockChannel;
-  private FileLock lockFile;
-
-  public DirectoryLock(Path directory, Logger logger) {
-    this.logger = logger;
-    this.lockFilePath = directory.resolve(LOCK_FILE_NAME).toAbsolutePath();
-  }
-
-  public boolean tryLock() {
-    try {
-      lockRandomAccessFile = new RandomAccessFile(lockFilePath.toFile(), "rw");
-      lockChannel = lockRandomAccessFile.getChannel();
-      lockFile = lockChannel.tryLock(0, 1024, false);
-
-      return lockFile != null;
-    } catch (IOException e) {
-      throw new IllegalStateException("Failed to create lock in " + lockFilePath.toString(), e);
-    }
-  }
-
-  public void unlock() {
-    if (lockFile != null) {
-      try {
-        lockFile.release();
-        lockFile = null;
-      } catch (IOException e) {
-        logger.error("Error releasing lock", e);
-      }
-    }
-    if (lockChannel != null) {
-      try {
-        lockChannel.close();
-        lockChannel = null;
-      } catch (IOException e) {
-        logger.error("Error closing file channel", e);
-      }
-    }
-    if (lockRandomAccessFile != null) {
-      try {
-        lockRandomAccessFile.close();
-        lockRandomAccessFile = null;
-      } catch (IOException e) {
-        logger.error("Error closing file", e);
-      }
-    }
-  }
-}
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
deleted file mode 100644 (file)
index bc42ed0..0000000
+++ /dev/null
@@ -1,193 +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.home.cache;
-
-import java.io.BufferedInputStream;
-import java.io.BufferedOutputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.nio.file.Files;
-import java.nio.file.Path;
-import java.util.jar.JarOutputStream;
-import java.util.jar.Pack200;
-import java.util.zip.GZIPInputStream;
-
-/**
- * This class is responsible for managing Sonar batch file cache. You can put file into cache and
- * later try to retrieve them. MD5 is used to differentiate files (name is not secure as files may come
- * from different Sonar servers and have same name but be actually different, and same for SNAPSHOTs).
- */
-public class FileCache {
-
-  /** Maximum loop count when creating temp directories. */
-  private static final int TEMP_DIR_ATTEMPTS = 10_000;
-
-  private final File cacheDir;
-  private final File tmpDir;
-  private final FileHashes hashes;
-  private final Logger logger;
-
-  FileCache(File dir, FileHashes fileHashes, Logger logger) {
-    this.hashes = fileHashes;
-    this.logger = logger;
-    this.cacheDir = createDir(dir, "user cache: ");
-    logger.info(String.format("User cache: %s", dir.getAbsolutePath()));
-    this.tmpDir = createDir(new File(dir, "_tmp"), "temp dir");
-  }
-
-  public static FileCache create(File dir, Logger logger) {
-    return new FileCache(dir, new FileHashes(), logger);
-  }
-
-  public File getDir() {
-    return cacheDir;
-  }
-
-  public interface Downloader {
-    void download(String filename, File toFile) throws IOException;
-  }
-
-  /**
-   * Look for a file in the cache by its filename and md5 checksum. If the file is not
-   * present then try to download it. In case of error or if the file is not found
-   * an exception is thrown. {@code null} is never returned.
-   */
-  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, filename);
-    if (!targetFile.exists()) {
-      cacheMiss(targetFile, hash, downloader);
-    }
-    return targetFile;
-  }
-
-  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 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(jarFile)));
-        InputStream in = new GZIPInputStream(new BufferedInputStream(Files.newInputStream(compressedFile)))) {
-        unpacker.unpack(in, jarStream);
-      }
-    } catch (IOException e) {
-      throw new IllegalStateException(e);
-    }
-  }
-
-  private static void download(Downloader downloader, String filename, File tempFile) {
-    try {
-      downloader.download(filename, tempFile);
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to download " + filename + " to " + tempFile, e);
-    }
-  }
-
-  private void renameQuietly(File sourceFile, File targetFile) {
-    boolean rename = sourceFile.renameTo(targetFile);
-    // Check if the file was cached by another process during download
-    if (!rename && !targetFile.exists()) {
-      logger.warn(String.format("Unable to rename %s to %s", sourceFile.getAbsolutePath(), targetFile.getAbsolutePath()));
-      logger.warn("A copy/delete will be tempted but with no guarantee of atomicity");
-      try {
-        Files.move(sourceFile.toPath(), targetFile.toPath());
-      } catch (IOException e) {
-        throw new IllegalStateException("Fail to move " + sourceFile.getAbsolutePath() + " to " + targetFile, e);
-      }
-    }
-  }
-
-  private File hashDir(String hash) {
-    return new File(cacheDir, hash);
-  }
-
-  private static void mkdirQuietly(File hashDir) {
-    try {
-      Files.createDirectories(hashDir.toPath());
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to create cache directory: " + hashDir, e);
-    }
-  }
-
-  private File newTempFile() {
-    try {
-      return File.createTempFile("fileCache", null, tmpDir);
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to create temp file in " + tmpDir, e);
-    }
-  }
-
-  public File createTempDir() {
-    String baseName = System.currentTimeMillis() + "-";
-
-    for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) {
-      File tempDir = new File(tmpDir, baseName + counter);
-      if (tempDir.mkdir()) {
-        return tempDir;
-      }
-    }
-    throw new IllegalStateException("Failed to create directory in " + tmpDir);
-  }
-
-  private File createDir(File dir, String debugTitle) {
-    if (!dir.isDirectory() || !dir.exists()) {
-      logger.debug("Create : " + dir.getAbsolutePath());
-      try {
-        Files.createDirectories(dir.toPath());
-      } catch (IOException e) {
-        throw new IllegalStateException("Unable to create " + debugTitle + dir.getAbsolutePath(), e);
-      }
-    }
-    return dir;
-  }
-}
diff --git a/sonar-home/src/main/java/org/sonar/home/cache/FileCacheBuilder.java b/sonar-home/src/main/java/org/sonar/home/cache/FileCacheBuilder.java
deleted file mode 100644 (file)
index 0bb78aa..0000000
+++ /dev/null
@@ -1,55 +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.home.cache;
-
-import java.io.File;
-
-import javax.annotation.Nullable;
-
-public class FileCacheBuilder {
-  private final Logger logger;
-  private File userHome;
-
-  public FileCacheBuilder(Logger logger) {
-    this.logger = logger;
-  }
-
-  public FileCacheBuilder setUserHome(@Nullable File dir) {
-    this.userHome = dir;
-    return this;
-  }
-
-  public FileCache build() {
-    if (userHome == null) {
-      userHome = findHome();
-    }
-    File cacheDir = new File(userHome, "cache");
-    return FileCache.create(cacheDir, logger);
-  }
-  
-  private static File findHome() {
-    String path = System.getenv("SONAR_USER_HOME");
-    if (path == null) {
-      // Default
-      path = System.getProperty("user.home") + File.separator + ".sonar";
-    }
-    return new File(path);
-  }
-}
diff --git a/sonar-home/src/main/java/org/sonar/home/cache/FileHashes.java b/sonar-home/src/main/java/org/sonar/home/cache/FileHashes.java
deleted file mode 100644 (file)
index a76f17c..0000000
+++ /dev/null
@@ -1,73 +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.home.cache;
-
-import java.io.File;
-import java.io.FileInputStream;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.security.MessageDigest;
-
-/**
- * Hashes used to store files in the cache directory.
- *
- * @since 3.5
- */
-public class FileHashes {
-
-  private static final int STREAM_BUFFER_LENGTH = 1024;
-
-  public String of(File file) {
-    try {
-      return of(new FileInputStream(file));
-    } catch (IOException e) {
-      throw new IllegalStateException("Fail to compute hash of: " + file.getAbsolutePath(), e);
-    }
-  }
-
-  /**
-   * Computes the hash of given stream. The stream is closed by this method.
-   */
-  public String of(InputStream input) {
-    try(InputStream is = input) {
-      MessageDigest digest = MessageDigest.getInstance("MD5");
-      byte[] hash = digest(is, digest);
-      return toHex(hash);
-    } catch (Exception e) {
-      throw new IllegalStateException("Fail to compute hash", e);
-    }
-  }
-
-  private static byte[] digest(InputStream input, MessageDigest digest) throws IOException {
-    final byte[] buffer = new byte[STREAM_BUFFER_LENGTH];
-    int read = input.read(buffer, 0, STREAM_BUFFER_LENGTH);
-    while (read > -1) {
-      digest.update(buffer, 0, read);
-      read = input.read(buffer, 0, STREAM_BUFFER_LENGTH);
-    }
-    return digest.digest();
-  }
-
-  static String toHex(byte[] bytes) {
-    BigInteger bi = new BigInteger(1, bytes);
-    return String.format("%0" + (bytes.length << 1) + "x", bi);
-  }
-}
diff --git a/sonar-home/src/test/java/org/sonar/home/cache/DirectoryLockTest.java b/sonar-home/src/test/java/org/sonar/home/cache/DirectoryLockTest.java
deleted file mode 100644 (file)
index 36815b3..0000000
+++ /dev/null
@@ -1,66 +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.home.cache;
-
-import java.nio.file.Paths;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class DirectoryLockTest {
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-  private DirectoryLock lock;
-
-  @Before
-  public void setUp() {
-    lock = new DirectoryLock(temp.getRoot().toPath(), mock(Logger.class));
-  }
-
-  @Test
-  public void tryLock() {
-    assertThat(temp.getRoot().list()).isEmpty();
-    lock.tryLock();
-    assertThat(temp.getRoot().toPath().resolve(".sonar_lock")).exists();
-    lock.unlock();
-  }
-
-  @Test
-  public void unlockWithoutLock() {
-    lock.unlock();
-  }
-
-  @Test
-  public void errorTryLock() {
-    lock = new DirectoryLock(Paths.get("non", "existing", "path"), mock(Logger.class));
-
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Failed to create lock");
-
-    lock.tryLock();
-  }
-}
diff --git a/sonar-home/src/test/java/org/sonar/home/cache/FileCacheBuilderTest.java b/sonar-home/src/test/java/org/sonar/home/cache/FileCacheBuilderTest.java
deleted file mode 100644 (file)
index 8e144c9..0000000
+++ /dev/null
@@ -1,60 +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.home.cache;
-
-import java.io.File;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.TemporaryFolder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.Mockito.mock;
-
-public class FileCacheBuilderTest {
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Test
-  public void setUserHome() throws Exception {
-    File userHome = temp.newFolder();
-    FileCache cache = new FileCacheBuilder(mock(Logger.class)).setUserHome(userHome).build();
-
-    assertThat(cache.getDir()).isDirectory().exists();
-    assertThat(cache.getDir().getName()).isEqualTo("cache");
-    assertThat(cache.getDir().getParentFile()).isEqualTo(userHome);
-  }
-
-  @Test
-  public void user_home_property_can_be_null() {
-    FileCache cache = new FileCacheBuilder(mock(Logger.class)).setUserHome(null).build();
-
-    // does not fail. It uses default path or env variable
-    assertThat(cache.getDir()).isDirectory().exists();
-    assertThat(cache.getDir().getName()).isEqualTo("cache");
-  }
-
-  @Test
-  public void use_default_path_or_env_variable() {
-    FileCache cache = new FileCacheBuilder(mock(Logger.class)).build();
-
-    assertThat(cache.getDir()).isDirectory().exists();
-    assertThat(cache.getDir().getName()).isEqualTo("cache");
-  }
-}
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
deleted file mode 100644 (file)
index 63d4d85..0000000
+++ /dev/null
@@ -1,179 +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.home.cache;
-
-import java.io.File;
-import java.io.IOException;
-import org.apache.commons.io.FileUtils;
-import org.junit.Before;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.verifyZeroInteractions;
-import static org.mockito.Mockito.when;
-
-public class FileCacheTest {
-
-  @Rule
-  public TemporaryFolder tempFolder = new TemporaryFolder();
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  private FileHashes fileHashes = mock(FileHashes.class);
-  private FileCache cache;
-
-  @Before
-  public void setUp() {
-    cache = new FileCache(tempFolder.getRoot(), fileHashes, mock(Logger.class));
-  }
-
-  @Test
-  public void fail_to_download() {
-    when(fileHashes.of(any(File.class))).thenReturn("ABCDE");
-
-    FileCache.Downloader downloader = (filename, toFile) -> {
-      throw new IOException("fail");
-    };
-    expectedException.expect(IllegalStateException.class);
-    expectedException.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();
-    expectedException.expect(IllegalStateException.class);
-    expectedException.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();
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Fail to create cache directory");
-    cache.get("sonar-foo-plugin-1.5.jar", "ABCDE", mock(FileCache.Downloader.class));
-  }
-
-  @Test
-  public void download_and_add_to_cache() throws IOException {
-    when(fileHashes.of(any(File.class))).thenReturn("ABCDE");
-
-    FileCache.Downloader downloader = (filename, toFile) -> FileUtils.write(toFile, "body");
-    File cachedFile = cache.get("sonar-foo-plugin-1.5.jar", "ABCDE", downloader);
-    assertThat(cachedFile).isNotNull().exists().isFile();
-    assertThat(cachedFile.getName()).isEqualTo("sonar-foo-plugin-1.5.jar");
-    assertThat(cachedFile.getParentFile().getParentFile()).isEqualTo(cache.getDir());
-    assertThat(FileUtils.readFileToString(cachedFile)).isEqualTo("body");
-  }
-
-  @Test
-  public void download_and_add_to_cache_compressed_file() {
-    when(fileHashes.of(any(File.class))).thenReturn("ABCDE");
-
-    FileCache.Downloader downloader = (filename, toFile) -> 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() {
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("INVALID HASH");
-
-    when(fileHashes.of(any(File.class))).thenReturn("VWXYZ");
-
-    FileCache.Downloader downloader = (filename, toFile) -> FileUtils.write(toFile, "corrupted body");
-    cache.get("sonar-foo-plugin-1.5.jar", "ABCDE", downloader);
-  }
-
-  @Test
-  public void concurrent_download() throws IOException {
-    when(fileHashes.of(any(File.class))).thenReturn("ABCDE");
-
-    FileCache.Downloader downloader = (filename, toFile) -> {
-      // Emulate a concurrent download that adds file to cache before
-      File cachedFile = new File(new File(cache.getDir(), "ABCDE"), "sonar-foo-plugin-1.5.jar");
-      FileUtils.write(cachedFile, "downloaded by other");
-
-      FileUtils.write(toFile, "downloaded by me");
-    };
-
-    // do not fail
-    File cachedFile = cache.get("sonar-foo-plugin-1.5.jar", "ABCDE", downloader);
-    assertThat(cachedFile).isNotNull().exists().isFile();
-    assertThat(cachedFile.getName()).isEqualTo("sonar-foo-plugin-1.5.jar");
-    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/java/org/sonar/home/cache/FileHashesTest.java b/sonar-home/src/test/java/org/sonar/home/cache/FileHashesTest.java
deleted file mode 100644 (file)
index 35bb977..0000000
+++ /dev/null
@@ -1,127 +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.home.cache;
-
-import org.apache.commons.codec.binary.Hex;
-import org.apache.commons.codec.digest.DigestUtils;
-import org.apache.commons.io.FileUtils;
-import org.apache.commons.io.IOUtils;
-import org.junit.Rule;
-import org.junit.Test;
-import org.junit.rules.ExpectedException;
-import org.junit.rules.TemporaryFolder;
-
-import java.io.ByteArrayInputStream;
-import java.io.File;
-import java.io.IOException;
-import java.io.InputStream;
-import java.math.BigInteger;
-import java.nio.charset.StandardCharsets;
-import java.nio.file.Files;
-import java.security.SecureRandom;
-
-import static org.assertj.core.api.Assertions.assertThat;
-import static org.mockito.ArgumentMatchers.any;
-import static org.mockito.ArgumentMatchers.anyInt;
-import static org.mockito.Mockito.mock;
-import static org.mockito.Mockito.when;
-
-public class FileHashesTest {
-
-  private SecureRandom secureRandom = new SecureRandom();
-
-  @Rule
-  public ExpectedException expectedException = ExpectedException.none();
-
-  @Rule
-  public TemporaryFolder temp = new TemporaryFolder();
-
-  @Test
-  public void test_md5_hash() {
-    assertThat(hash("sonar")).isEqualTo("d85e336d61f5344395c42126fac239bc");
-
-    // compare results with commons-codec
-    for (int index = 0; index < 100; index++) {
-      String random = randomString();
-      assertThat(hash(random)).as(random).isEqualTo(
-        DigestUtils.md5Hex(random).toLowerCase()
-        );
-    }
-  }
-
-  @Test
-  public void test_hash_file() throws IOException {
-    File f = temp.newFile();
-    Files.write(f.toPath(), "sonar".getBytes(StandardCharsets.UTF_8));
-    assertThat(hashFile(f)).isEqualTo("d85e336d61f5344395c42126fac239bc");
-  }
-
-  @Test
-  public void test_toHex() {
-    // lower-case
-    assertThat(FileHashes.toHex("aloa_bi_bop_a_loula".getBytes())).isEqualTo("616c6f615f62695f626f705f615f6c6f756c61");
-
-    // compare results with commons-codec
-    for (int index = 0; index < 100; index++) {
-      String random = randomString();
-      assertThat(FileHashes.toHex(random.getBytes())).as(random).isEqualTo(
-        Hex.encodeHexString(random.getBytes()).toLowerCase()
-        );
-    }
-  }
-
-  @Test
-  public void fail_if_file_does_not_exist() throws IOException {
-    File file = temp.newFile("does_not_exist");
-    FileUtils.forceDelete(file);
-
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Fail to compute hash of: " + file.getAbsolutePath());
-
-    new FileHashes().of(file);
-  }
-
-  @Test
-  public void fail_if_stream_is_closed() throws Exception {
-    expectedException.expect(IllegalStateException.class);
-    expectedException.expectMessage("Fail to compute hash");
-
-    InputStream input = mock(InputStream.class);
-    when(input.read(any(byte[].class), anyInt(), anyInt())).thenThrow(new IllegalThreadStateException());
-    new FileHashes().of(input);
-  }
-
-  private String randomString() {
-    return new BigInteger(130, secureRandom).toString(32);
-  }
-
-  private String hash(String s) {
-    InputStream in = new ByteArrayInputStream(s.getBytes());
-    try {
-      return new FileHashes().of(in);
-    } finally {
-      IOUtils.closeQuietly(in);
-    }
-  }
-
-  private String hashFile(File f) {
-    return new FileHashes().of(f);
-  }
-}
index b58fbf87ce634d9770fda7b0f304f12b751422b8..6186e58573c4060acea725756e3dd14d06f6e900 100644 (file)
@@ -28,7 +28,6 @@ dependencies {
   compile 'org.slf4j:slf4j-api'
   compile 'org.sonarsource:sonar-persistit'
   compile project(':sonar-core')
-  compile project(':sonar-home')
   compile project(':sonar-scanner-protocol')
   compile project(':sonar-ws')
   runtime project(path: ':sonar-plugin-api', configuration: 'shadow')
diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DirectoryLock.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/scan/DirectoryLock.java
new file mode 100644 (file)
index 0000000..187793f
--- /dev/null
@@ -0,0 +1,82 @@
+/*
+ * 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.scanner.scan;
+
+import java.io.IOException;
+import java.io.RandomAccessFile;
+import java.nio.channels.FileChannel;
+import java.nio.channels.FileLock;
+import java.nio.file.Path;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+
+public class DirectoryLock {
+  private static final Logger LOGGER = LoggerFactory.getLogger(DirectoryLock.class);
+  public static final String LOCK_FILE_NAME = ".sonar_lock";
+
+  private final Path lockFilePath;
+
+  private RandomAccessFile lockRandomAccessFile;
+  private FileChannel lockChannel;
+  private FileLock lockFile;
+
+  public DirectoryLock(Path directory) {
+    this.lockFilePath = directory.resolve(LOCK_FILE_NAME).toAbsolutePath();
+  }
+
+  public boolean tryLock() {
+    try {
+      lockRandomAccessFile = new RandomAccessFile(lockFilePath.toFile(), "rw");
+      lockChannel = lockRandomAccessFile.getChannel();
+      lockFile = lockChannel.tryLock(0, 1024, false);
+
+      return lockFile != null;
+    } catch (IOException e) {
+      throw new IllegalStateException("Failed to create lock in " + lockFilePath.toString(), e);
+    }
+  }
+
+  public void unlock() {
+    if (lockFile != null) {
+      try {
+        lockFile.release();
+        lockFile = null;
+      } catch (IOException e) {
+        LOGGER.error("Error releasing lock", e);
+      }
+    }
+    if (lockChannel != null) {
+      try {
+        lockChannel.close();
+        lockChannel = null;
+      } catch (IOException e) {
+        LOGGER.error("Error closing file channel", e);
+      }
+    }
+    if (lockRandomAccessFile != null) {
+      try {
+        lockRandomAccessFile.close();
+        lockRandomAccessFile = null;
+      } catch (IOException e) {
+        LOGGER.error("Error closing file", e);
+      }
+    }
+  }
+}
index 6221ad42c8b474aa25ac1c9b61b84cefbd19fd93..ec0efe6b06352708c48bc887b92bcae0867fd006 100644 (file)
@@ -25,8 +25,6 @@ import java.nio.file.Files;
 import java.nio.file.Path;
 import org.picocontainer.Startable;
 import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
-import org.sonar.home.cache.DirectoryLock;
-import org.sonar.scanner.bootstrap.Slf4jLogger;
 
 public class ProjectLock implements Startable {
   private final DirectoryLock lock;
@@ -40,7 +38,7 @@ public class ProjectLock implements Startable {
     } catch (IOException e) {
       throw new IllegalStateException("Failed to create work directory", e);
     }
-    this.lock = new DirectoryLock(directory.toAbsolutePath(), new Slf4jLogger());
+    this.lock = new DirectoryLock(directory.toAbsolutePath());
   }
 
   public void tryLock() {
index 27fad933fe794cdf7c3fb6bf1fcb6acdffb1679d..aa1fa5d813a99a8166eefcf6544c3e3fb146db4b 100644 (file)
@@ -27,7 +27,6 @@ import java.util.Iterator;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
 import org.sonar.core.util.FileUtils;
-import org.sonar.home.cache.DirectoryLock;
 
 /**
  * Clean and create working directories of each module.
diff --git a/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DirectoryLockTest.java b/sonar-scanner-engine/src/test/java/org/sonar/scanner/scan/DirectoryLockTest.java
new file mode 100644 (file)
index 0000000..dc3c7eb
--- /dev/null
@@ -0,0 +1,65 @@
+/*
+ * 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.scanner.scan;
+
+import java.nio.file.Paths;
+import org.junit.Before;
+import org.junit.Rule;
+import org.junit.Test;
+import org.junit.rules.ExpectedException;
+import org.junit.rules.TemporaryFolder;
+
+import static org.assertj.core.api.Assertions.assertThat;
+
+public class DirectoryLockTest {
+  @Rule
+  public TemporaryFolder temp = new TemporaryFolder();
+  @Rule
+  public ExpectedException expectedException = ExpectedException.none();
+  private DirectoryLock lock;
+
+  @Before
+  public void setUp() {
+    lock = new DirectoryLock(temp.getRoot().toPath());
+  }
+
+  @Test
+  public void tryLock() {
+    assertThat(temp.getRoot().list()).isEmpty();
+    lock.tryLock();
+    assertThat(temp.getRoot().toPath().resolve(".sonar_lock")).exists();
+    lock.unlock();
+  }
+
+  @Test
+  public void unlockWithoutLock() {
+    lock.unlock();
+  }
+
+  @Test
+  public void errorTryLock() {
+    lock = new DirectoryLock(Paths.get("non", "existing", "path"));
+
+    expectedException.expect(IllegalStateException.class);
+    expectedException.expectMessage("Failed to create lock");
+
+    lock.tryLock();
+  }
+}
index e6f3794ed0cff68170063ad6ef9b1f0c86cefb19..6905dece613248ab2b4b8d61cb63a1d290d18413 100644 (file)
@@ -29,7 +29,6 @@ import org.junit.rules.ExpectedException;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
-import org.sonar.home.cache.DirectoryLock;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;
index 25350fed2699402e5814fae792263f957b470931..8a86ddfb5117ab116382eb52b2c4ddc66c920a9c 100644 (file)
@@ -28,7 +28,6 @@ import org.junit.Test;
 import org.junit.rules.TemporaryFolder;
 import org.sonar.api.batch.fs.internal.DefaultInputModule;
 import org.sonar.api.batch.fs.internal.InputModuleHierarchy;
-import org.sonar.home.cache.DirectoryLock;
 
 import static org.assertj.core.api.Assertions.assertThat;
 import static org.mockito.Mockito.mock;