diff options
author | Julien HENRY <julien.henry@sonarsource.com> | 2013-10-15 17:14:44 +0200 |
---|---|---|
committer | Julien HENRY <julien.henry@sonarsource.com> | 2013-10-16 15:25:41 +0200 |
commit | 18a4c15b060d1b56f08826bf6006d08eaf2625ec (patch) | |
tree | 03cc1afb062054a3d3d74849bf18e7a6485ab05c | |
parent | 3f946fc11c49585f8cdf003c54f19c322a4aab29 (diff) | |
download | sonarqube-18a4c15b060d1b56f08826bf6006d08eaf2625ec.tar.gz sonarqube-18a4c15b060d1b56f08826bf6006d08eaf2625ec.zip |
SONAR-4748 Introduce a new extension for managing temp files/folders.
29 files changed, 611 insertions, 260 deletions
diff --git a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesStackTest.java b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesStackTest.java index 51c8597b778..6a6d8c140a8 100644 --- a/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesStackTest.java +++ b/plugins/sonar-core-plugin/src/test/java/org/sonar/plugins/core/issue/InitialOpenIssuesStackTest.java @@ -20,24 +20,45 @@ package org.sonar.plugins.core.issue; +import edu.emory.mathcs.backport.java.util.Collections; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.CoreProperties; +import org.sonar.batch.bootstrap.BatchTempUtils; +import org.sonar.batch.bootstrap.BootstrapProperties; +import org.sonar.batch.bootstrap.BootstrapSettings; import org.sonar.batch.index.Caches; import org.sonar.core.issue.db.IssueDto; +import java.io.IOException; import java.util.List; -import static com.google.common.collect.Lists.newArrayList; import static org.fest.assertions.Assertions.assertThat; public class InitialOpenIssuesStackTest { + @ClassRule + public static TemporaryFolder temp = new TemporaryFolder(); + + public static Caches createCacheOnTemp(TemporaryFolder temp) { + BootstrapSettings bootstrapSettings = new BootstrapSettings(new BootstrapProperties(Collections.emptyMap())); + try { + bootstrapSettings.properties().put(CoreProperties.WORKING_DIRECTORY, temp.newFolder().getAbsolutePath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + return new Caches(new BatchTempUtils(bootstrapSettings)); + } + InitialOpenIssuesStack stack; - Caches caches = new Caches(); + Caches caches; @Before - public void setUp() { + public void setUp() throws Exception { + caches = createCacheOnTemp(temp); caches.start(); stack = new InitialOpenIssuesStack(caches); } diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java index d54cc63c806..762525fd992 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchPluginRepository.java @@ -30,6 +30,7 @@ import org.sonar.api.Plugin; import org.sonar.api.config.Settings; import org.sonar.api.platform.PluginMetadata; import org.sonar.api.platform.PluginRepository; +import org.sonar.api.utils.TempUtils; import org.sonar.core.plugins.PluginClassloaders; import org.sonar.core.plugins.PluginInstaller; import org.sonar.core.plugins.RemotePlugin; @@ -53,12 +54,12 @@ public class BatchPluginRepository implements PluginRepository { private Map<String, PluginMetadata> metadataByKey; private Settings settings; private PluginClassloaders classLoaders; - private TempDirectories workingDirectories; + private TempUtils tempDirectories; private final AnalysisMode analysisMode; - public BatchPluginRepository(PluginDownloader pluginDownloader, TempDirectories workingDirectories, Settings settings, AnalysisMode analysisMode) { + public BatchPluginRepository(PluginDownloader pluginDownloader, TempUtils tempDirectories, Settings settings, AnalysisMode analysisMode) { this.pluginDownloader = pluginDownloader; - this.workingDirectories = workingDirectories; + this.tempDirectories = tempDirectories; this.settings = settings; this.analysisMode = analysisMode; } @@ -76,7 +77,7 @@ public class BatchPluginRepository implements PluginRepository { if (filter.accepts(remote.getKey())) { List<File> pluginFiles = pluginDownloader.downloadPlugin(remote); List<File> extensionFiles = pluginFiles.subList(1, pluginFiles.size()); - File targetDir = workingDirectories.getDir("plugins/" + remote.getKey()); + File targetDir = tempDirectories.createDirectory("plugins/" + remote.getKey()); LOG.debug("Installing plugin {} into {}", remote.getKey(), targetDir.getAbsolutePath()); PluginMetadata metadata = extractor.install(pluginFiles.get(0), remote.isCore(), extensionFiles, targetDir); if (StringUtils.isBlank(metadata.getBasePlugin()) || filter.accepts(metadata.getBasePlugin())) { diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchTempUtils.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchTempUtils.java new file mode 100644 index 00000000000..d31e9691f8e --- /dev/null +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BatchTempUtils.java @@ -0,0 +1,43 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.batch.bootstrap; + +import org.apache.commons.io.FileUtils; +import org.sonar.api.CoreProperties; +import org.sonar.core.utils.AbstractTempUtils; + +import java.io.File; +import java.io.IOException; + +public class BatchTempUtils extends AbstractTempUtils { + + public BatchTempUtils(BootstrapSettings bootstrapSettings) { + String workingDirPath = bootstrapSettings.property(CoreProperties.WORKING_DIRECTORY, CoreProperties.WORKING_DIRECTORY_DEFAULT_VALUE); + File workingDir = new File(workingDirPath); + File tempDir = new File(workingDir, "tmp"); + try { + FileUtils.forceMkdir(tempDir); + } catch (IOException e) { + throw new IllegalStateException("Unable to create root temp directory " + tempDir, e); + } + setTempDir(tempDir); + } + +} diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java index 6aa2b6b31b5..163d9a86ec3 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/BootstrapContainer.java @@ -87,7 +87,7 @@ public class BootstrapContainer extends ComponentContainer { Logback.class, ServerMetadata.class, org.sonar.batch.ServerMetadata.class, - TempDirectories.class, + BatchTempUtils.class, HttpDownloader.class, UriReader.class, new FileCacheProvider()); diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PreviewDatabase.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PreviewDatabase.java index 222a40fad01..3ba51cd2f1a 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PreviewDatabase.java +++ b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/PreviewDatabase.java @@ -30,6 +30,7 @@ import org.sonar.api.config.Settings; import org.sonar.api.database.DatabaseProperties; import org.sonar.api.utils.HttpDownloader.HttpException; import org.sonar.api.utils.SonarException; +import org.sonar.api.utils.TempUtils; import java.io.File; import java.net.SocketTimeoutException; @@ -50,19 +51,19 @@ public class PreviewDatabase implements BatchComponent { private final Settings settings; private final ServerClient server; - private final TempDirectories tempDirectories; + private final TempUtils tempUtils; private final AnalysisMode mode; - public PreviewDatabase(Settings settings, ServerClient server, TempDirectories tempDirectories, AnalysisMode mode) { + public PreviewDatabase(Settings settings, ServerClient server, TempUtils tempUtils, AnalysisMode mode) { this.settings = settings; this.server = server; - this.tempDirectories = tempDirectories; + this.tempUtils = tempUtils; this.mode = mode; } public void start() { if (mode.isPreview()) { - File databaseFile = tempDirectories.getFile("", "preview.h2.db"); + File databaseFile = tempUtils.createTempFile("preview", ".h2.db"); int readTimeoutSec = getReadTimeout(); downloadDatabase(databaseFile, readTimeoutSec * 1000); diff --git a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TempDirectories.java b/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TempDirectories.java deleted file mode 100644 index bbe53331079..00000000000 --- a/sonar-batch/src/main/java/org/sonar/batch/bootstrap/TempDirectories.java +++ /dev/null @@ -1,104 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.batch.bootstrap; - -import com.google.common.collect.Maps; -import org.apache.commons.io.FileUtils; -import org.apache.commons.io.filefilter.AgeFileFilter; -import org.apache.commons.io.filefilter.AndFileFilter; -import org.apache.commons.io.filefilter.DirectoryFileFilter; -import org.apache.commons.io.filefilter.PrefixFileFilter; -import org.apache.commons.lang.StringUtils; -import org.slf4j.LoggerFactory; -import org.sonar.api.utils.SonarException; -import org.sonar.api.utils.TempFileUtils; - -import java.io.File; -import java.io.FileFilter; -import java.io.IOException; -import java.util.Arrays; -import java.util.Map; - -public class TempDirectories { - - public static final String DIR_PREFIX = "sonar-batch"; - - // this timeout must be greater than the longest analysis - public static final int AGE_BEFORE_DELETION = 24 * 60 * 60 * 1000; - - private File rootDir; - private Map<String, File> directoriesByKey = Maps.newHashMap(); - - public TempDirectories() throws IOException { - this.rootDir = TempFileUtils.createTempDirectory(DIR_PREFIX); - LoggerFactory.getLogger(getClass()).debug("Temporary directory: " + rootDir.getAbsolutePath()); - } - - public File getRoot() { - return rootDir; - } - - /** - * Get or create a working directory - */ - public File getDir(String key) { - if (StringUtils.isBlank(key)) { - return rootDir; - } - - File dir = directoriesByKey.get(key); - if (dir == null) { - dir = new File(rootDir, key); - try { - FileUtils.forceMkdir(dir); - directoriesByKey.put(key, dir); - - } catch (IOException e) { - throw new SonarException("Can not create the temp directory: " + dir, e); - } - } - return dir; - } - - public File getFile(String directoryKey, String filename) { - File dir = getDir(directoryKey); - return new File(dir, filename); - } - - /** - * This method is executed by picocontainer during shutdown. - */ - public void stop() { - directoriesByKey.clear(); - - // Deleting temp directory does not work on MS Windows and Sun JVM because URLClassLoader locks JARs and resources. - // The workaround is that sonar deletes orphans itself. - - // older than AGE_BEFORE_DELETION to be sure that the current dir is deleted on mac and linux. - rootDir.setLastModified(System.currentTimeMillis() - AGE_BEFORE_DELETION - 60 * 60 * 1000); - - File[] directoriesToDelete = rootDir.getParentFile().listFiles((FileFilter) new AndFileFilter(Arrays.asList( - DirectoryFileFilter.DIRECTORY, new PrefixFileFilter(DIR_PREFIX), new AgeFileFilter(System.currentTimeMillis() - AGE_BEFORE_DELETION)))); - for (File dir : directoriesToDelete) { - LoggerFactory.getLogger(getClass()).debug("Delete temporary directory: " + dir); - FileUtils.deleteQuietly(dir); - } - } -} diff --git a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java index f67a7468055..7783e62380c 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java +++ b/sonar-batch/src/main/java/org/sonar/batch/index/Caches.java @@ -21,7 +21,6 @@ package org.sonar.batch.index; import com.google.common.base.Preconditions; import com.google.common.collect.Sets; -import com.google.common.io.Files; import com.persistit.Exchange; import com.persistit.Persistit; import com.persistit.Volume; @@ -31,6 +30,7 @@ import org.apache.commons.io.FileUtils; import org.picocontainer.Startable; import org.slf4j.LoggerFactory; import org.sonar.api.BatchComponent; +import org.sonar.api.utils.TempUtils; import java.io.File; import java.io.Serializable; @@ -48,14 +48,16 @@ public class Caches implements BatchComponent, Startable { private File tempDir; private Persistit persistit; private Volume volume; + private final TempUtils tempUtils; - public Caches() { + public Caches(TempUtils tempUtils) { + this.tempUtils = tempUtils; initPersistit(); } private void initPersistit() { try { - tempDir = Files.createTempDir(); + tempDir = tempUtils.createTempDirectory("caches"); persistit = new Persistit(); persistit.setPersistitLogger(new Slf4jAdapter(LoggerFactory.getLogger("PERSISTIT"))); Properties props = new Properties(); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/DefaultProjectBootstrapper.java b/sonar-batch/src/main/java/org/sonar/batch/scan/DefaultProjectBootstrapper.java index 910c5696cb8..5ca8e682c65 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/DefaultProjectBootstrapper.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/DefaultProjectBootstrapper.java @@ -82,12 +82,6 @@ class DefaultProjectBootstrapper implements ProjectBootstrapper { ); /** - * @since 1.4 - */ - private static final String PROPERTY_WORK_DIRECTORY = "sonar.working.directory"; - private static final String DEF_VALUE_WORK_DIRECTORY = ".sonar"; - - /** * Array of all mandatory properties required for a project without child. */ private static final String[] MANDATORY_PROPERTIES_FOR_SIMPLE_PROJECT = { @@ -151,9 +145,9 @@ class DefaultProjectBootstrapper implements ProjectBootstrapper { @VisibleForTesting protected File initRootProjectWorkDir(File baseDir) { - String workDir = settings.property(PROPERTY_WORK_DIRECTORY); + String workDir = settings.property(CoreProperties.WORKING_DIRECTORY); if (StringUtils.isBlank(workDir)) { - return new File(baseDir, DEF_VALUE_WORK_DIRECTORY); + return new File(baseDir, CoreProperties.WORKING_DIRECTORY_DEFAULT_VALUE); } File customWorkDir = new File(workDir); diff --git a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleFileSystemInitializer.java b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleFileSystemInitializer.java index 583340fe11c..8b3d726c6d4 100644 --- a/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleFileSystemInitializer.java +++ b/sonar-batch/src/main/java/org/sonar/batch/scan/filesystem/ModuleFileSystemInitializer.java @@ -24,7 +24,7 @@ import org.apache.commons.io.FileUtils; import org.sonar.api.BatchComponent; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.scan.filesystem.PathResolver; -import org.sonar.batch.bootstrap.TempDirectories; +import org.sonar.api.utils.TempUtils; import java.io.File; import java.util.List; @@ -41,19 +41,19 @@ public class ModuleFileSystemInitializer implements BatchComponent { private List<File> additionalSourceFiles; private List<File> additionalTestFiles; - public ModuleFileSystemInitializer(ProjectDefinition module, TempDirectories tempDirectories, PathResolver pathResolver) { + public ModuleFileSystemInitializer(ProjectDefinition module, TempUtils tempUtils, PathResolver pathResolver) { baseDir = module.getBaseDir(); buildDir = module.getBuildDir(); - initWorkingDir(module, tempDirectories); + initWorkingDir(module, tempUtils); initBinaryDirs(module, pathResolver); initSources(module, pathResolver); initTests(module, pathResolver); } - private void initWorkingDir(ProjectDefinition module, TempDirectories tempDirectories) { + private void initWorkingDir(ProjectDefinition module, TempUtils tempUtils) { workingDir = module.getWorkDir(); if (workingDir == null) { - workingDir = tempDirectories.getDir("work"); + workingDir = tempUtils.createTempDirectory("work"); } else { try { FileUtils.forceMkdir(workingDir); diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java index 56cdc053f3c..1b13dbbf591 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchPluginRepositoryTest.java @@ -28,6 +28,7 @@ import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.CoreProperties; import org.sonar.api.config.Settings; +import org.sonar.api.utils.TempUtils; import org.sonar.core.plugins.RemotePlugin; import org.sonar.core.plugins.RemotePluginFile; import org.sonar.test.TestUtils; @@ -63,9 +64,9 @@ public class BatchPluginRepositoryTest { @Test public void shouldLoadPlugin() throws IOException { - TempDirectories tempDirs = mock(TempDirectories.class); + TempUtils tempDirs = mock(TempUtils.class); File toDir = temp.newFolder(); - when(tempDirs.getDir("plugins/checkstyle")).thenReturn(toDir); + when(tempDirs.createDirectory("plugins/checkstyle")).thenReturn(toDir); RemotePlugin checkstyle = new RemotePlugin("checkstyle", true); PluginDownloader downloader = mock(PluginDownloader.class); @@ -83,11 +84,11 @@ public class BatchPluginRepositoryTest { @Test public void shouldLoadPluginExtension() throws IOException { - TempDirectories tempDirs = mock(TempDirectories.class); + TempUtils tempDirs = mock(TempUtils.class); File toDir1 = temp.newFolder(); File toDir2 = temp.newFolder(); - when(tempDirs.getDir("plugins/checkstyle")).thenReturn(toDir1); - when(tempDirs.getDir("plugins/checkstyleextensions")).thenReturn(toDir2); + when(tempDirs.createDirectory("plugins/checkstyle")).thenReturn(toDir1); + when(tempDirs.createDirectory("plugins/checkstyleextensions")).thenReturn(toDir2); RemotePlugin checkstyle = new RemotePlugin("checkstyle", true); RemotePlugin checkstyleExt = new RemotePlugin("checkstyleextensions", false); @@ -108,9 +109,9 @@ public class BatchPluginRepositoryTest { @Test public void shouldLoadPluginDeprecatedExtensions() throws IOException { - TempDirectories tempDirs = mock(TempDirectories.class); + TempUtils tempDirs = mock(TempUtils.class); File toDir = temp.newFolder(); - when(tempDirs.getDir("plugins/checkstyle")).thenReturn(toDir); + when(tempDirs.createDirectory("plugins/checkstyle")).thenReturn(toDir); RemotePlugin checkstyle = new RemotePlugin("checkstyle", true); checkstyle.getFiles().add(new RemotePluginFile("checkstyle-ext.xml", "fakemd5")); @@ -130,11 +131,11 @@ public class BatchPluginRepositoryTest { @Test public void shouldExcludePluginAndItsExtensions() throws IOException { - TempDirectories tempDirs = mock(TempDirectories.class); + BatchTempUtils tempDirs = mock(BatchTempUtils.class); File toDir1 = temp.newFolder(); File toDir2 = temp.newFolder(); - when(tempDirs.getDir("plugins/checkstyle")).thenReturn(toDir1); - when(tempDirs.getDir("plugins/checkstyleextensions")).thenReturn(toDir2); + when(tempDirs.createDirectory("plugins/checkstyle")).thenReturn(toDir1); + when(tempDirs.createDirectory("plugins/checkstyleextensions")).thenReturn(toDir2); RemotePlugin checkstyle = new RemotePlugin("checkstyle", true); RemotePlugin checkstyleExt = new RemotePlugin("checkstyleextensions", false); diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchTempUtilsTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchTempUtilsTest.java new file mode 100644 index 00000000000..04005adea68 --- /dev/null +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BatchTempUtilsTest.java @@ -0,0 +1,54 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.batch.bootstrap; + +import com.google.common.collect.ImmutableMap; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.CoreProperties; + +import java.io.File; + +import static org.fest.assertions.Assertions.assertThat; + +public class BatchTempUtilsTest { + + @Rule + public ExpectedException throwable = ExpectedException.none(); + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Test + public void createTempFolder() throws Exception { + File workingDir = temp.newFolder(); + BatchTempUtils tempUtils = new BatchTempUtils(new BootstrapSettings( + new BootstrapProperties(ImmutableMap.of(CoreProperties.WORKING_DIRECTORY, workingDir.getAbsolutePath())))); + tempUtils.createTempDirectory(); + tempUtils.createTempFile(); + assertThat(new File(workingDir, "tmp")).exists(); + assertThat(new File(workingDir, "tmp").list()).hasSize(2); + + tempUtils.stop(); + assertThat(new File(workingDir, "tmp")).doesNotExist(); + } +} diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapContainerTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapContainerTest.java index 1196f51be1a..3e62bf619cd 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapContainerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/BootstrapContainerTest.java @@ -42,10 +42,11 @@ public class BootstrapContainerTest { @Test public void should_add_components() { BootstrapContainer container = BootstrapContainer.create(Collections.emptyList()); + container.add(new BootstrapProperties(Collections.<String, String>emptyMap())); container.doBeforeStart(); assertThat(container.getComponentByType(Logback.class)).isNotNull(); - assertThat(container.getComponentByType(TempDirectories.class)).isNotNull(); + assertThat(container.getComponentByType(BatchTempUtils.class)).isNotNull(); } @Test @@ -62,11 +63,11 @@ public class BootstrapContainerTest { PluginMetadata metadata = mock(PluginMetadata.class); FakePlugin plugin = new FakePlugin(); BatchPluginRepository pluginRepository = mock(BatchPluginRepository.class); - when(pluginRepository.getPluginsByMetadata()).thenReturn(ImmutableMap.<PluginMetadata, Plugin> of( - metadata, plugin - )); + when(pluginRepository.getPluginsByMetadata()).thenReturn(ImmutableMap.<PluginMetadata, Plugin>of( + metadata, plugin + )); - BootstrapContainer container = spy(BootstrapContainer.create(Lists.<Object> newArrayList(pluginRepository))); + BootstrapContainer container = spy(BootstrapContainer.create(Lists.<Object>newArrayList(pluginRepository))); doNothing().when(container).executeTask(); container.doAfterStart(); diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/PreviewDatabaseTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/PreviewDatabaseTest.java index cd41618236d..d0a0ff569f9 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/PreviewDatabaseTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/PreviewDatabaseTest.java @@ -30,6 +30,7 @@ import org.sonar.api.config.Settings; import org.sonar.api.database.DatabaseProperties; import org.sonar.api.utils.HttpDownloader; import org.sonar.api.utils.SonarException; +import org.sonar.api.utils.TempUtils; import java.io.File; import java.net.SocketTimeoutException; @@ -44,7 +45,7 @@ import static org.mockito.Mockito.when; public class PreviewDatabaseTest { Settings settings; ServerClient server = mock(ServerClient.class); - TempDirectories tempDirectories = mock(TempDirectories.class); + TempUtils tempUtils = mock(TempUtils.class); File databaseFile; private AnalysisMode mode; @@ -57,7 +58,7 @@ public class PreviewDatabaseTest { @Before public void setUp() throws Exception { databaseFile = temp.newFile("preview.h2.db"); - when(tempDirectories.getFile("", "preview.h2.db")).thenReturn(databaseFile); + when(tempUtils.createTempFile("preview", ".h2.db")).thenReturn(databaseFile); settings = new Settings(); settings.setProperty(CoreProperties.PROJECT_KEY_PROPERTY, "group:project"); @@ -68,14 +69,14 @@ public class PreviewDatabaseTest { @Test public void should_be_disabled_if_not_preview() { when(mode.isPreview()).thenReturn(false); - new PreviewDatabase(settings, server, tempDirectories, mode).start(); + new PreviewDatabase(settings, server, tempUtils, mode).start(); - verifyZeroInteractions(tempDirectories, server); + verifyZeroInteractions(tempUtils, server); } @Test public void should_download_database() { - new PreviewDatabase(settings, server, tempDirectories, mode).start(); + new PreviewDatabase(settings, server, tempUtils, mode).start(); verify(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 60000); } @@ -83,7 +84,7 @@ public class PreviewDatabaseTest { @Test public void should_download_database_with_deprecated_overriden_timeout() { settings.setProperty(CoreProperties.DRY_RUN_READ_TIMEOUT_SEC, 80); - new PreviewDatabase(settings, server, tempDirectories, mode).start(); + new PreviewDatabase(settings, server, tempUtils, mode).start(); verify(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 80000); } @@ -91,7 +92,7 @@ public class PreviewDatabaseTest { @Test public void should_download_database_with_overriden_timeout() { settings.setProperty(CoreProperties.PREVIEW_READ_TIMEOUT_SEC, 80); - new PreviewDatabase(settings, server, tempDirectories, mode).start(); + new PreviewDatabase(settings, server, tempUtils, mode).start(); verify(server).download("/batch_bootstrap/db?project=group:project", databaseFile, 80000); } @@ -99,14 +100,14 @@ public class PreviewDatabaseTest { @Test public void should_download_database_on_branch() { settings.setProperty(CoreProperties.PROJECT_BRANCH_PROPERTY, "mybranch"); - new PreviewDatabase(settings, server, tempDirectories, mode).start(); + new PreviewDatabase(settings, server, tempUtils, mode).start(); verify(server).download("/batch_bootstrap/db?project=group:project:mybranch", databaseFile, 60000); } @Test public void should_replace_database_settings() { - new PreviewDatabase(settings, server, tempDirectories, mode).start(); + new PreviewDatabase(settings, server, tempUtils, mode).start(); assertThat(settings.getString(DatabaseProperties.PROP_DIALECT)).isEqualTo("h2"); assertThat(settings.getString(DatabaseProperties.PROP_DRIVER)).isEqualTo("org.h2.Driver"); @@ -122,7 +123,7 @@ public class PreviewDatabaseTest { thrown.expect(SonarException.class); thrown.expectMessage("You don't have access rights to project [group:project]"); - new PreviewDatabase(settings, server, tempDirectories, mode).start(); + new PreviewDatabase(settings, server, tempUtils, mode).start(); } @Test @@ -132,7 +133,7 @@ public class PreviewDatabaseTest { thrown.expect(SonarException.class); thrown.expectMessage("Preview database read timed out after 60000 ms. You can try to increase read timeout with property -Dsonar.preview.readTimeout (in seconds)"); - new PreviewDatabase(settings, server, tempDirectories, mode).start(); + new PreviewDatabase(settings, server, tempUtils, mode).start(); } @Test @@ -142,14 +143,14 @@ public class PreviewDatabaseTest { thrown.expect(SonarException.class); thrown.expectMessage("BUG"); - new PreviewDatabase(settings, server, tempDirectories, mode).start(); + new PreviewDatabase(settings, server, tempUtils, mode).start(); } @Test public void project_should_be_optional() { // on non-scan tasks settings.removeProperty(CoreProperties.PROJECT_KEY_PROPERTY); - new PreviewDatabase(settings, server, tempDirectories, mode).start(); + new PreviewDatabase(settings, server, tempUtils, mode).start(); verify(server).download("/batch_bootstrap/db", databaseFile, 60000); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/TempDirectoriesTest.java b/sonar-batch/src/test/java/org/sonar/batch/bootstrap/TempDirectoriesTest.java deleted file mode 100644 index d32157de8fa..00000000000 --- a/sonar-batch/src/test/java/org/sonar/batch/bootstrap/TempDirectoriesTest.java +++ /dev/null @@ -1,82 +0,0 @@ -/* - * SonarQube, open source software quality management tool. - * Copyright (C) 2008-2013 SonarSource - * mailto:contact AT sonarsource DOT com - * - * SonarQube 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. - * - * SonarQube 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.batch.bootstrap; - -import org.junit.After; -import org.junit.Before; -import org.junit.Test; - -import java.io.File; -import java.io.IOException; - -import static org.fest.assertions.Assertions.assertThat; - -public class TempDirectoriesTest { - - private TempDirectories tempDirectories; - - @Before - public void before() throws IOException { - tempDirectories = new TempDirectories(); - } - - @After - public void after() { - if (tempDirectories != null) { - tempDirectories.stop(); - } - } - - @Test - public void shouldCreateRoot() { - assertThat(tempDirectories.getRoot()).isNotNull(); - assertThat(tempDirectories.getRoot()).exists(); - assertThat(tempDirectories.getRoot()).isDirectory(); - assertThat(tempDirectories.getDir("")).isEqualTo(tempDirectories.getRoot()); - } - - @Test - public void shouldCreateDirectory() { - File findbugsDir = tempDirectories.getDir("findbugs"); - assertThat(findbugsDir).isNotNull(); - assertThat(findbugsDir).exists(); - assertThat(findbugsDir.getParentFile()).isEqualTo(tempDirectories.getRoot()); - assertThat(findbugsDir.getName()).isEqualTo("findbugs"); - } - - @Test - public void shouldStopAndDeleteDirectory() { - File root = tempDirectories.getRoot(); - File findbugsDir = tempDirectories.getDir("findbugs"); - assertThat(findbugsDir).exists(); - - tempDirectories.stop(); - - assertThat(root).doesNotExist(); - assertThat(findbugsDir).doesNotExist(); - } - - @Test - public void shouldCreateDirectoryWhenGettingFile() { - File file = tempDirectories.getFile("findbugs", "bcel.jar"); - assertThat(file).isNotNull(); - assertThat(file.getParentFile().getName()).isEqualTo("findbugs"); - } -} diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java index 48bfe91417f..a888e5eb6bb 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/CacheTest.java @@ -23,15 +23,22 @@ import com.google.common.collect.Iterables; import com.persistit.exception.PersistitException; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import static org.fest.assertions.Assertions.assertThat; public class CacheTest { - Caches caches = new Caches(); + + @ClassRule + public static TemporaryFolder temp = new TemporaryFolder(); + + Caches caches; @Before - public void start() { + public void start() throws Exception { + caches = CachesTest.createCacheOnTemp(temp); caches.start(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java index 200a4295afd..eafec808dc8 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/CachesTest.java @@ -19,17 +19,45 @@ */ package org.sonar.batch.index; +import edu.emory.mathcs.backport.java.util.Collections; import org.junit.After; +import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.CoreProperties; +import org.sonar.batch.bootstrap.BatchTempUtils; +import org.sonar.batch.bootstrap.BootstrapProperties; +import org.sonar.batch.bootstrap.BootstrapSettings; import java.io.File; +import java.io.IOException; import java.io.Serializable; import static org.fest.assertions.Assertions.assertThat; import static org.fest.assertions.Fail.fail; public class CachesTest { - Caches caches = new Caches(); + + @ClassRule + public static TemporaryFolder temp = new TemporaryFolder(); + + public static Caches createCacheOnTemp(TemporaryFolder temp) { + BootstrapSettings bootstrapSettings = new BootstrapSettings(new BootstrapProperties(Collections.emptyMap())); + try { + bootstrapSettings.properties().put(CoreProperties.WORKING_DIRECTORY, temp.newFolder().getAbsolutePath()); + } catch (IOException e) { + throw new RuntimeException(e); + } + return new Caches(new BatchTempUtils(bootstrapSettings)); + } + + Caches caches; + + @Before + public void prepare() throws Exception { + caches = createCacheOnTemp(temp); + } @After public void stop() { diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataCacheTest.java index 5b6e67b2149..26d4b8cbbe2 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataCacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataCacheTest.java @@ -21,16 +21,22 @@ package org.sonar.batch.index; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import static org.fest.assertions.Assertions.assertThat; public class ComponentDataCacheTest { - Caches caches = new Caches(); + @ClassRule + public static TemporaryFolder temp = new TemporaryFolder(); + + Caches caches; @Before - public void start() { + public void start() throws Exception { + caches = CachesTest.createCacheOnTemp(temp); caches.start(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataPersisterTest.java b/sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataPersisterTest.java index 3910b0ca85b..286c75447b2 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataPersisterTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/index/ComponentDataPersisterTest.java @@ -21,19 +21,25 @@ package org.sonar.batch.index; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.sonar.api.database.model.Snapshot; import org.sonar.core.persistence.AbstractDaoTestCase; import org.sonar.core.source.jdbc.SnapshotDataDao; public class ComponentDataPersisterTest extends AbstractDaoTestCase { + @ClassRule + public static TemporaryFolder temp = new TemporaryFolder(); + SnapshotCache snapshots = new SnapshotCache(); ComponentDataCache data; - Caches caches = new Caches(); + Caches caches; @Before - public void start() { + public void start() throws Exception { + caches = CachesTest.createCacheOnTemp(temp); caches.start(); } @@ -59,6 +65,6 @@ public class ComponentDataPersisterTest extends AbstractDaoTestCase { ComponentDataPersister persister = new ComponentDataPersister(data, snapshots, dataDao, getMyBatis()); persister.persist(); - checkTables("should_persist_component_data", new String[]{"id", "created_at", "updated_at"}, "snapshot_data"); + checkTables("should_persist_component_data", new String[] {"id", "created_at", "updated_at"}, "snapshot_data"); } } diff --git a/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java index efff3e6a4d9..ed56e22d176 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/issue/IssueCacheTest.java @@ -24,11 +24,14 @@ import com.google.common.collect.Collections2; import com.google.common.collect.ImmutableList; import org.junit.After; import org.junit.Before; +import org.junit.ClassRule; import org.junit.Test; +import org.junit.rules.TemporaryFolder; import org.sonar.api.issue.Issue; import org.sonar.api.issue.internal.DefaultIssue; import org.sonar.api.rule.Severity; import org.sonar.batch.index.Caches; +import org.sonar.batch.index.CachesTest; import javax.annotation.Nullable; @@ -39,10 +42,14 @@ import static org.fest.assertions.Assertions.assertThat; public class IssueCacheTest { - Caches caches = new Caches(); + @ClassRule + public static TemporaryFolder temp = new TemporaryFolder(); + + Caches caches; @Before - public void start() { + public void start() throws Exception { + caches = CachesTest.createCacheOnTemp(temp); caches.start(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java index a2474ac5ce8..d7dd87ebbbf 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/InputFileCacheTest.java @@ -28,6 +28,7 @@ import org.junit.rules.TemporaryFolder; import org.sonar.api.scan.filesystem.InputFile; import org.sonar.api.scan.filesystem.internal.DefaultInputFile; import org.sonar.batch.index.Caches; +import org.sonar.batch.index.CachesTest; import static org.fest.assertions.Assertions.assertThat; @@ -36,10 +37,11 @@ public class InputFileCacheTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); - Caches caches = new Caches(); + Caches caches; @Before - public void start() { + public void start() throws Exception { + caches = CachesTest.createCacheOnTemp(temp); caches.start(); } diff --git a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ModuleFileSystemInitializerTest.java b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ModuleFileSystemInitializerTest.java index 77205514a7d..3662390946a 100644 --- a/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ModuleFileSystemInitializerTest.java +++ b/sonar-batch/src/test/java/org/sonar/batch/scan/filesystem/ModuleFileSystemInitializerTest.java @@ -21,22 +21,23 @@ package org.sonar.batch.scan.filesystem; import org.apache.commons.io.FileUtils; import org.apache.commons.io.FilenameUtils; -import org.junit.Rule; +import org.junit.ClassRule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import org.sonar.api.batch.bootstrap.ProjectDefinition; import org.sonar.api.scan.filesystem.PathResolver; -import org.sonar.batch.bootstrap.TempDirectories; +import org.sonar.api.utils.TempUtils; import java.io.File; import java.io.IOException; import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; public class ModuleFileSystemInitializerTest { - @Rule - public TemporaryFolder temp = new TemporaryFolder(); + @ClassRule + public static TemporaryFolder temp = new TemporaryFolder(); PathResolver pathResolver = new PathResolver(); @@ -46,7 +47,7 @@ public class ModuleFileSystemInitializerTest { File workDir = temp.newFolder("work"); ProjectDefinition module = ProjectDefinition.create().setBaseDir(baseDir).setWorkDir(workDir); - ModuleFileSystemInitializer initializer = new ModuleFileSystemInitializer(module, new TempDirectories(), pathResolver); + ModuleFileSystemInitializer initializer = new ModuleFileSystemInitializer(module, mock(TempUtils.class), pathResolver); assertThat(initializer.baseDir().getCanonicalPath()).isEqualTo(baseDir.getCanonicalPath()); assertThat(initializer.workingDir().getCanonicalPath()).isEqualTo(workDir.getCanonicalPath()); @@ -72,7 +73,7 @@ public class ModuleFileSystemInitializerTest { .addTestDirs("src/test/java", "src/test/unknown") .addBinaryDir("target/classes"); - ModuleFileSystemInitializer initializer = new ModuleFileSystemInitializer(project, new TempDirectories(), pathResolver); + ModuleFileSystemInitializer initializer = new ModuleFileSystemInitializer(project, mock(TempUtils.class), pathResolver); assertThat(initializer.baseDir().getCanonicalPath()).isEqualTo(baseDir.getCanonicalPath()); assertThat(initializer.buildDir().getCanonicalPath()).isEqualTo(buildDir.getCanonicalPath()); diff --git a/sonar-core/src/main/java/org/sonar/core/utils/AbstractTempUtils.java b/sonar-core/src/main/java/org/sonar/core/utils/AbstractTempUtils.java new file mode 100644 index 00000000000..20155a31d95 --- /dev/null +++ b/sonar-core/src/main/java/org/sonar/core/utils/AbstractTempUtils.java @@ -0,0 +1,121 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.utils; + +import org.apache.commons.io.FileUtils; +import org.picocontainer.Startable; +import org.sonar.api.utils.TempUtils; + +import javax.annotation.Nullable; + +import java.io.File; +import java.io.IOException; + +public abstract class AbstractTempUtils implements TempUtils, Startable { + + /** Maximum loop count when creating temp directories. */ + private static final int TEMP_DIR_ATTEMPTS = 10000; + + private File tempDir; + + protected void setTempDir(File tempDir) { + this.tempDir = tempDir; + } + + @Override + public File createTempDirectory() { + return createTempDirectory(null); + } + + @Override + public File createTempDirectory(@Nullable String prefix) { + return createTempDir(tempDir, prefix); + } + + /** + * Copied from guava waiting for JDK 7 Files#createTempDirectory + */ + private static File createTempDir(File baseDir, String prefix) { + String baseName = prefix + System.currentTimeMillis() + "-"; + + for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) { + File tempDir = new File(baseDir, baseName + counter); + if (tempDir.mkdir()) { + return tempDir; + } + } + throw new IllegalStateException("Failed to create directory within " + + TEMP_DIR_ATTEMPTS + " attempts (tried " + + baseName + "0 to " + baseName + (TEMP_DIR_ATTEMPTS - 1) + ')'); + } + + @Override + public File createDirectory(String name) { + File dir = new File(tempDir, name); + try { + FileUtils.forceMkdir(dir); + } catch (IOException e) { + throw new IllegalStateException("Unable to create temp directory in " + dir, e); + } + return dir; + } + + @Override + public File createTempFile() { + return createTempFile(null, null); + } + + @Override + public File createTempFile(@Nullable String prefix, @Nullable String suffix) { + return createTempFile(tempDir, prefix, suffix); + } + + /** + * Inspired by guava waiting for JDK 7 Files#createTempFile + */ + private static File createTempFile(File baseDir, String prefix, String suffix) { + String baseName = prefix + System.currentTimeMillis() + "-"; + + try { + for (int counter = 0; counter < TEMP_DIR_ATTEMPTS; counter++) { + File tempFile = new File(baseDir, baseName + counter + suffix); + if (tempFile.createNewFile()) { + return tempFile; + } + } + } catch (IOException e) { + throw new IllegalStateException("Failed to create temp file", e); + } + throw new IllegalStateException("Failed to create temp file within " + + TEMP_DIR_ATTEMPTS + " attempts (tried " + + baseName + "0" + suffix + " to " + baseName + (TEMP_DIR_ATTEMPTS - 1) + suffix + ")"); + } + + @Override + public void start() { + // Nothing to do + } + + @Override + public void stop() { + FileUtils.deleteQuietly(tempDir); + } + +} diff --git a/sonar-core/src/test/java/org/sonar/core/utils/AbstractTempUtilsTest.java b/sonar-core/src/test/java/org/sonar/core/utils/AbstractTempUtilsTest.java new file mode 100644 index 00000000000..a5d030fda2a --- /dev/null +++ b/sonar-core/src/test/java/org/sonar/core/utils/AbstractTempUtilsTest.java @@ -0,0 +1,71 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.core.utils; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; + +import java.io.File; + +import static org.fest.assertions.Assertions.assertThat; + +public class AbstractTempUtilsTest { + + @Rule + public ExpectedException throwable = ExpectedException.none(); + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Test + public void createTempFolderAndFile() throws Exception { + File tempFolder = temp.newFolder(); + AbstractTempUtils tempUtils = new CustomTempUtils(tempFolder); + File dir = tempUtils.createTempDirectory(); + assertThat(dir).exists().isDirectory(); + File file = tempUtils.createTempFile(); + assertThat(file).exists().isFile(); + + tempUtils.stop(); + assertThat(tempFolder).doesNotExist(); + } + + @Test + public void createTempFolderWithName() throws Exception { + File tempFolder = temp.newFolder(); + AbstractTempUtils tempUtils = new CustomTempUtils(tempFolder); + File dir = tempUtils.createDirectory("sample"); + assertThat(dir).exists().isDirectory(); + assertThat(new File(tempFolder, "sample")).isEqualTo(dir); + + tempUtils.stop(); + assertThat(tempFolder).doesNotExist(); + } + + private static class CustomTempUtils extends AbstractTempUtils { + + public CustomTempUtils(File tempDir) { + setTempDir(tempDir); + } + + } +} diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java index c256ed45d9b..a9e07108eeb 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/CoreProperties.java @@ -522,4 +522,10 @@ public interface CoreProperties { */ String PREVIEW_EXCLUDE_PLUGINS = "sonar.preview.excludePlugins"; String PREVIEW_EXCLUDE_PLUGINS_DEFAULT_VALUE = "devcockpit,pdfreport,report,scmactivity,views,jira"; + + /** + * @since 4.0 + */ + String WORKING_DIRECTORY = "sonar.working.directory"; + String WORKING_DIRECTORY_DEFAULT_VALUE = ".sonar"; } diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/TempFileUtils.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/TempFileUtils.java index f82ff852991..fb940b5af04 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/TempFileUtils.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/TempFileUtils.java @@ -22,6 +22,10 @@ package org.sonar.api.utils; import java.io.File; import java.io.IOException; +/** + * @deprecated since 4.0 use {@link TempUtils} + */ +@Deprecated public final class TempFileUtils { private TempFileUtils() { diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/TempUtils.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/TempUtils.java new file mode 100644 index 00000000000..7557d502676 --- /dev/null +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/TempUtils.java @@ -0,0 +1,60 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.api.utils; + +import org.sonar.api.ServerComponent; +import org.sonar.api.task.TaskComponent; + +import javax.annotation.Nullable; + +import java.io.File; + +/** + * Use this component to deal with temp files/folders. Root location of temp files/folders + * depends on situation: + * <ul> + * <li>${SONAR_HOME}/temp on server side</li> + * <li>Working directory on batch side (see sonar.working.directory)</li> + * </ul> + * @since 4.0 + * + */ +public interface TempUtils extends TaskComponent, ServerComponent { + + /** + * Create a directory in temp folder with a random unique name. + */ + File createTempDirectory(); + + /** + * Create a directory in temp folder with a random unique name and using the provided prefix when possible. + */ + File createTempDirectory(@Nullable String prefix); + + /** + * Create a directory in temp folder using provided name. + */ + File createDirectory(String name); + + File createTempFile(); + + File createTempFile(@Nullable String prefix, @Nullable String suffix); + +} diff --git a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java index 6c5f06364c7..b30b64b45bc 100644 --- a/sonar-server/src/main/java/org/sonar/server/platform/Platform.java +++ b/sonar-server/src/main/java/org/sonar/server/platform/Platform.java @@ -148,6 +148,7 @@ import org.sonar.server.ui.SecurityRealmFactory; import org.sonar.server.ui.Views; import org.sonar.server.user.DefaultUserService; import org.sonar.server.user.NewUserNotifier; +import org.sonar.server.util.ServerTempUtils; import javax.servlet.ServletContext; @@ -239,6 +240,7 @@ public final class Platform { rootContainer.addSingleton(PreviewDatabaseFactory.class); rootContainer.addSingleton(SemaphoreUpdater.class); rootContainer.addSingleton(SemaphoresImpl.class); + rootContainer.addSingleton(ServerTempUtils.class); rootContainer.startComponents(); } diff --git a/sonar-server/src/main/java/org/sonar/server/util/ServerTempUtils.java b/sonar-server/src/main/java/org/sonar/server/util/ServerTempUtils.java new file mode 100644 index 00000000000..bc43ca71481 --- /dev/null +++ b/sonar-server/src/main/java/org/sonar/server/util/ServerTempUtils.java @@ -0,0 +1,41 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.util; + +import org.apache.commons.io.FileUtils; +import org.sonar.api.platform.ServerFileSystem; +import org.sonar.core.utils.AbstractTempUtils; + +import java.io.File; +import java.io.IOException; + +public class ServerTempUtils extends AbstractTempUtils { + + public ServerTempUtils(ServerFileSystem fs) { + File tempDir = new File(fs.getTempDir(), "tmp"); + try { + FileUtils.forceMkdir(tempDir); + } catch (IOException e) { + throw new IllegalStateException("Unable to create root temp directory " + tempDir, e); + } + setTempDir(tempDir); + } + +} diff --git a/sonar-server/src/test/java/org/sonar/server/util/ServerTempUtilsTest.java b/sonar-server/src/test/java/org/sonar/server/util/ServerTempUtilsTest.java new file mode 100644 index 00000000000..7d057de0f7d --- /dev/null +++ b/sonar-server/src/test/java/org/sonar/server/util/ServerTempUtilsTest.java @@ -0,0 +1,56 @@ +/* + * SonarQube, open source software quality management tool. + * Copyright (C) 2008-2013 SonarSource + * mailto:contact AT sonarsource DOT com + * + * SonarQube 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. + * + * SonarQube 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.util; + +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; +import org.junit.rules.TemporaryFolder; +import org.sonar.api.platform.ServerFileSystem; + +import java.io.File; + +import static org.fest.assertions.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; + +public class ServerTempUtilsTest { + + @Rule + public ExpectedException throwable = ExpectedException.none(); + + @Rule + public TemporaryFolder temp = new TemporaryFolder(); + + @Test + public void createTempFolder() throws Exception { + ServerFileSystem fs = mock(ServerFileSystem.class); + File serverTempFolder = temp.newFolder(); + when(fs.getTempDir()).thenReturn(serverTempFolder); + ServerTempUtils tempUtils = new ServerTempUtils(fs); + tempUtils.createTempDirectory(); + tempUtils.createTempFile(); + assertThat(new File(serverTempFolder, "tmp")).exists(); + assertThat(new File(serverTempFolder, "tmp").list()).hasSize(2); + + tempUtils.stop(); + assertThat(new File(serverTempFolder, "tmp")).doesNotExist(); + } +} |