diff options
author | Simon Brandhof <simon.brandhof@gmail.com> | 2013-02-05 12:43:45 +0100 |
---|---|---|
committer | Simon Brandhof <simon.brandhof@gmail.com> | 2013-02-05 12:43:45 +0100 |
commit | 7bf52372a4f63be30ae6513bae70d2f8b775e29b (patch) | |
tree | 459e8af8de426d1b4c320270b367962176390fc4 /sonar-home/src/main | |
parent | 5c6c22c2820f420428cb308a22c1a5262d0295e9 (diff) | |
download | sonarqube-7bf52372a4f63be30ae6513bae70d2f8b775e29b.tar.gz sonarqube-7bf52372a4f63be30ae6513bae70d2f8b775e29b.zip |
SONAR-2291 move management of file cache to the new module sonar-home
Diffstat (limited to 'sonar-home/src/main')
8 files changed, 450 insertions, 0 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 new file mode 100644 index 00000000000..5e57d82a4a0 --- /dev/null +++ b/sonar-home/src/main/java/org/sonar/home/cache/FileCache.java @@ -0,0 +1,143 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.home.cache; + +import org.apache.commons.io.FileUtils; +import org.sonar.home.log.Log; + +import javax.annotation.CheckForNull; + +import java.io.File; +import java.io.IOException; + +/** + * 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 { + + private final File dir; + private final FileHashes hashes; + private final Log log; + + FileCache(File dir, Log log, FileHashes fileHashes) { + this.dir = dir; + this.hashes = fileHashes; + this.log = log; + if (!dir.exists()) { + log.debug(String.format("Create cache directory: %s", dir.getAbsolutePath())); + try { + FileUtils.forceMkdir(dir); + } catch (IOException e) { + throw new IllegalStateException("Unable to create cache directory " + dir.getAbsolutePath(), e); + } + } + log.info(String.format("User cache: %s", dir.getAbsolutePath())); + } + + public static FileCache create(File dir, Log log) { + return new FileCache(dir, log, new FileHashes()); + } + + public File getDir() { + return dir; + } + + /** + * Look for a file in the cache by its filename and md5 checksum. If the file is not + * present then return null. + */ + @CheckForNull + public File get(String filename, String hash) { + File cachedFile = new File(new File(dir, hash), filename); + if (cachedFile.exists()) { + return cachedFile; + } + log.debug(String.format("No file found in the cache with name %s and hash %s", filename, hash)); + return null; + } + + public static interface Downloader { + void download(String filename, File toFile) throws IOException; + } + + 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()) { + File tempFile = newTempFile(filename); + download(downloader, filename, tempFile); + String downloadedHash = hashes.of(tempFile); + if (!hash.equals(downloadedHash)) { + throw new IllegalStateException("INVALID HASH: File " + tempFile.getAbsolutePath() + " was expected to have hash " + hash + + " but was downloaded with hash " + downloadedHash); + } + mkdirQuietly(hashDir); + renameQuietly(tempFile, targetFile); + } + return targetFile; + } + + private 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 File newTempFile(String filename) { + try { + return File.createTempFile(filename, ".tmp"); + } catch (IOException e) { + throw new IllegalStateException("Fail to create temp file", e); + } + } + + private void renameQuietly(File sourceFile, File targetFile) { + boolean rename = sourceFile.renameTo(targetFile); + if (!rename) { + // Check if the file was cached by another process during download + if (!targetFile.exists()) { + log.warn(String.format("Unable to rename %s to %s", sourceFile.getAbsolutePath(), targetFile.getAbsolutePath())); + log.warn(String.format("A copy/delete will be tempted but with no garantee of atomicity")); + try { + FileUtils.moveFile(sourceFile, targetFile); + } catch (IOException e) { + throw new IllegalStateException("Fail to move " + sourceFile.getAbsolutePath() + " to " + targetFile, e); + } + } + } + } + + private File hashDir(String hash) { + return new File(dir, hash); + } + + private void mkdirQuietly(File hashDir) { + try { + FileUtils.forceMkdir(hashDir); + } catch (IOException e) { + throw new IllegalStateException("Fail to create cache directory: " + hashDir, e); + } + } +} 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 new file mode 100644 index 00000000000..79c88b4ce68 --- /dev/null +++ b/sonar-home/src/main/java/org/sonar/home/cache/FileCacheBuilder.java @@ -0,0 +1,61 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.home.cache; + +import org.sonar.home.log.Log; +import org.sonar.home.log.StandardLog; + +import javax.annotation.Nullable; + +import java.io.File; + +public class FileCacheBuilder { + + private File userHome; + private Log log = new StandardLog(); + + public FileCacheBuilder setUserHome(File d) { + this.userHome = d; + return this; + } + + public FileCacheBuilder setLog(Log log) { + this.log = log; + return this; + } + + public FileCacheBuilder setUserHome(@Nullable String path) { + this.userHome = (path == null ? null : new File(path)); + return this; + } + + public FileCache build() { + if (userHome == null) { + String path = System.getenv("SONAR_USER_HOME"); + if (path == null) { + // Default + path = System.getProperty("user.home") + File.separator + ".sonar"; + } + userHome = new File(path); + } + File cacheDir = new File(userHome, "cache"); + return FileCache.create(cacheDir, log); + } +} 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 new file mode 100644 index 00000000000..89a973fd2f4 --- /dev/null +++ b/sonar-home/src/main/java/org/sonar/home/cache/FileHashes.java @@ -0,0 +1,73 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.home.cache; + +import org.apache.commons.io.IOUtils; + +import java.io.File; +import java.io.FileInputStream; +import java.io.IOException; +import java.io.InputStream; +import java.math.BigInteger; +import java.security.DigestInputStream; +import java.security.MessageDigest; + +/** + * Hashes used to store files in the cache directory. + * + * @since 3.5 + */ +public class FileHashes { + + 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) { + DigestInputStream digestInputStream = null; + try { + MessageDigest digest = MessageDigest.getInstance("MD5"); + digestInputStream = new DigestInputStream(input, digest); + while (digestInputStream.read() != -1) { + } + byte[] hash = digest.digest(); + return toHex(hash); + + } catch (Exception e) { + throw new IllegalStateException("Fail to compute hash", e); + + } finally { + IOUtils.closeQuietly(digestInputStream); + IOUtils.closeQuietly(input); + } + } + + static String toHex(byte[] bytes) { + BigInteger bi = new BigInteger(1, bytes); + return String.format("%0" + (bytes.length << 1) + "X", bi); + } +}
\ No newline at end of file diff --git a/sonar-home/src/main/java/org/sonar/home/cache/package-info.java b/sonar-home/src/main/java/org/sonar/home/cache/package-info.java new file mode 100644 index 00000000000..ca0cf6417d7 --- /dev/null +++ b/sonar-home/src/main/java/org/sonar/home/cache/package-info.java @@ -0,0 +1,25 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ + +@ParametersAreNonnullByDefault +package org.sonar.home.cache; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-home/src/main/java/org/sonar/home/log/Log.java b/sonar-home/src/main/java/org/sonar/home/log/Log.java new file mode 100644 index 00000000000..21c6a0eb459 --- /dev/null +++ b/sonar-home/src/main/java/org/sonar/home/log/Log.java @@ -0,0 +1,31 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.home.log; + +public interface Log { + void debug(String s); + + void info(String s); + + void warn(String s); + + void error(String s, Throwable throwable); + +} diff --git a/sonar-home/src/main/java/org/sonar/home/log/Slf4jLog.java b/sonar-home/src/main/java/org/sonar/home/log/Slf4jLog.java new file mode 100644 index 00000000000..736e624dac2 --- /dev/null +++ b/sonar-home/src/main/java/org/sonar/home/log/Slf4jLog.java @@ -0,0 +1,58 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.home.log; + +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; + +public class Slf4jLog implements Log { + + private final Logger logger; + + public Slf4jLog(Logger logger) { + this.logger = logger; + } + + public Slf4jLog(Class loggerClass) { + this.logger = LoggerFactory.getLogger(loggerClass); + } + + public boolean isDebugEnabled() { + return logger.isDebugEnabled(); + } + + public void debug(String s) { + logger.debug(s); + } + + public void info(String s) { + logger.info(s); + } + + public void warn(String s) { + logger.warn(s); + } + + public void error(String s, Throwable throwable) { + logger.error(s, throwable); + } + + +} diff --git a/sonar-home/src/main/java/org/sonar/home/log/StandardLog.java b/sonar-home/src/main/java/org/sonar/home/log/StandardLog.java new file mode 100644 index 00000000000..264d5dfec60 --- /dev/null +++ b/sonar-home/src/main/java/org/sonar/home/log/StandardLog.java @@ -0,0 +1,34 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ +package org.sonar.home.log; + +public class StandardLog implements Log { + public void debug(String s) { + } + + public void info(String s) { + } + + public void warn(String s) { + } + + public void error(String s, Throwable throwable) { + } +} diff --git a/sonar-home/src/main/java/org/sonar/home/log/package-info.java b/sonar-home/src/main/java/org/sonar/home/log/package-info.java new file mode 100644 index 00000000000..fee20fa530c --- /dev/null +++ b/sonar-home/src/main/java/org/sonar/home/log/package-info.java @@ -0,0 +1,25 @@ +/* + * Sonar, open source software quality management tool. + * Copyright (C) 2008-2012 SonarSource + * mailto:contact AT sonarsource DOT com + * + * Sonar 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. + * + * Sonar 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 Sonar; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02 + */ + +@ParametersAreNonnullByDefault +package org.sonar.home.log; + +import javax.annotation.ParametersAreNonnullByDefault; + |