diff --git a/pom.xml b/pom.xml index 78ccec51..4e11119b 100644 --- a/pom.xml +++ b/pom.xml @@ -22,6 +22,7 @@ echo sonar-orchestrator + sonar-orchestrator-config sonar-orchestrator-junit4 sonar-orchestrator-junit5 @@ -41,8 +42,6 @@ GNU LGPL v3 3.5.2 - 2.7 - 2.6 1.3 18.0 4.13.2 @@ -54,9 +53,7 @@ orchestrator - 11 - 8 - 8 + 11 @@ -66,16 +63,43 @@ jsr305 3.0.1 + + commons-io + commons-io + 2.19.0 + + + org.apache.commons + commons-lang3 + 3.18.0 + + + org.apache.commons + commons-text + 1.14.0 + + + org.junit + junit-bom + 5.13.4 + pom + import + org.assertj assertj-core - 3.9.1 + 3.27.3 org.mockito mockito-core 5.16.0 + + org.wiremock + wiremock-standalone + 3.13.1 + diff --git a/sonar-orchestrator-config/pom.xml b/sonar-orchestrator-config/pom.xml new file mode 100644 index 00000000..6e569120 --- /dev/null +++ b/sonar-orchestrator-config/pom.xml @@ -0,0 +1,47 @@ + + + 4.0.0 + + org.sonarsource.orchestrator + orchestrator-parent + 5.6.2-SNAPSHOT + + sonar-orchestrator-config + Orchestrator Configuration + + + + com.google.code.findbugs + jsr305 + provided + + + commons-io + commons-io + + + org.apache.commons + commons-lang3 + + + org.apache.commons + commons-text + + + org.junit.jupiter + junit-jupiter + test + + + org.assertj + assertj-core + test + + + org.wiremock + wiremock-standalone + test + + + + diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/Configuration.java b/sonar-orchestrator-config/src/main/java/com/sonar/orchestrator/config/Configuration.java similarity index 68% rename from sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/Configuration.java rename to sonar-orchestrator-config/src/main/java/com/sonar/orchestrator/config/Configuration.java index 8ebb6ea8..4ba3cce9 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/Configuration.java +++ b/sonar-orchestrator-config/src/main/java/com/sonar/orchestrator/config/Configuration.java @@ -1,5 +1,5 @@ /* - * Orchestrator + * Orchestrator Configuration * Copyright (C) 2011-2025 SonarSource SA * mailto:info AT sonarsource DOT com * @@ -19,12 +19,11 @@ */ package com.sonar.orchestrator.config; -import com.sonar.orchestrator.locator.ArtifactoryFactory; -import com.sonar.orchestrator.locator.FileLocation; -import com.sonar.orchestrator.locator.Locators; import java.io.File; import java.net.MalformedURLException; import java.net.URI; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collections; import java.util.HashMap; import java.util.Map; @@ -35,62 +34,45 @@ import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.text.StrSubstitutor; +import org.apache.commons.text.StringSubstitutor; -import static com.sonar.orchestrator.util.OrchestratorUtils.checkState; -import static com.sonar.orchestrator.util.OrchestratorUtils.defaultIfNull; -import static com.sonar.orchestrator.util.OrchestratorUtils.isEmpty; -import static java.lang.String.format; import static java.nio.charset.StandardCharsets.UTF_8; -import static java.util.Objects.requireNonNull; import static org.apache.commons.io.FileUtils.getUserDirectory; +import static org.apache.commons.lang3.ObjectUtils.getIfNull; +import static org.apache.commons.lang3.StringUtils.isEmpty; public class Configuration { - private static final String ENV_SHARED_DIR = "SONAR_IT_SOURCES"; - private static final String PROP_SHARED_DIR = "orchestrator.it_sources"; private final Map props; private final FileSystem fileSystem; - private final Locators locators; - private Configuration(File homeDir, Map props) { + private Configuration(Path homeDir, Map props) { this.props = Collections.unmodifiableMap(new HashMap<>(props)); this.fileSystem = new FileSystem(homeDir, this); - this.locators = new Locators(this.fileSystem, ArtifactoryFactory.createArtifactory(this)); } - public FileSystem fileSystem() { - return fileSystem; + public static Configuration createEnv() { + return builder().addEnvVariables().addSystemProperties().build(); } - public Locators locators() { - return locators; + public static Configuration create(Properties properties) { + return builder().addProperties(properties).build(); } - /** - * File located in the shared directory defined by the system property orchestrator.it_sources or environment variable SONAR_IT_SOURCES. - * Example : getFileLocationOfShared("javascript/performancing/pom.xml") - */ - public FileLocation getFileLocationOfShared(String relativePath) { - // try to read it_sources - // in the System.getProperties - // in the prop file (from orchestrator.properties file) - // in the environment variable - String rootPath; - rootPath = System.getProperty(PROP_SHARED_DIR); - if (rootPath == null) { - rootPath = props.get(PROP_SHARED_DIR); - } - if (rootPath == null) { - rootPath = System.getenv(ENV_SHARED_DIR); - } - requireNonNull(rootPath, format("Property '%s' or environment variable '%s' is missing", PROP_SHARED_DIR, ENV_SHARED_DIR)); + public static Configuration create(Map properties) { + return builder().addProperties(properties).build(); + } + + public static Configuration create() { + return builder().build(); + } - File rootDir = new File(rootPath); - checkState(rootDir.isDirectory() && rootDir.exists(), - "Please check the definition of it_sources (%s or %s) because the directory does not exist: %s", PROP_SHARED_DIR, ENV_SHARED_DIR, rootDir); + public static Builder builder() { + return new Builder(); + } - return FileLocation.of(new File(rootDir, relativePath)); + public FileSystem fileSystem() { + return fileSystem; } public String getString(String key) { @@ -102,7 +84,7 @@ public String getString(String key) { } public String getString(String key, @Nullable String defaultValue) { - return defaultIfNull(props.get(key), defaultValue); + return getIfNull(props.get(key), defaultValue); } @CheckForNull @@ -133,32 +115,24 @@ public Map asMap() { return props; } - public static Configuration createEnv() { - return builder().addEnvVariables().addSystemProperties().build(); - } - - public static Configuration create(Properties properties) { - return builder().addProperties(properties).build(); - } - - public static Configuration create(Map properties) { - return builder().addProperties(properties).build(); - } - - public static Configuration create() { - return builder().build(); - } - - public static Builder builder() { - return new Builder(); - } - public static final class Builder { - private Map props = new HashMap<>(); + private final Map props = new HashMap<>(); private Builder() { } + private static Map interpolateProperties(Map map) { + Map copy = new HashMap<>(); + for (Map.Entry entry : map.entrySet()) { + copy.put(entry.getKey(), interpolate(entry.getValue(), map)); + } + return copy; + } + + private static String interpolate(String prop, Map with) { + return StringSubstitutor.replace(prop, with, "${", "}"); + } + public Builder addConfiguration(Configuration c) { return addMap(c.asMap()); } @@ -180,9 +154,7 @@ public Builder addProperties(Properties p) { } public Builder addProperties(Map p) { - for (Map.Entry entry : p.entrySet()) { - props.put(entry.getKey(), entry.getValue()); - } + props.putAll(p); return this; } @@ -198,20 +170,20 @@ public Builder setProperty(String key, @Nullable String value) { return this; } - public Builder setProperty(String key, File file) { - props.put(key, file.getAbsolutePath()); + public Builder setProperty(String key, Path file) { + props.put(key, file.toAbsolutePath().toString()); return this; } - private File loadProperties() { - File homeDir = Stream.of( + private Path loadProperties() { + Path homeDir = Stream.of( props.get("orchestrator.home"), props.get("ORCHESTRATOR_HOME"), props.get("SONAR_USER_HOME")) .filter(s -> !isEmpty(s)) .findFirst() - .map(File::new) - .orElse(new File(getUserDirectory(), ".sonar/orchestrator")); + .map(Path::of) + .orElse(getUserDirectory().toPath().resolve(".sonar/orchestrator")); String configUrl = Stream.of( props.get("orchestrator.configUrl"), @@ -219,9 +191,9 @@ private File loadProperties() { .filter(s -> !isEmpty(s)) .findFirst() .orElseGet(() -> { - File file = new File(homeDir, "orchestrator.properties"); + Path file = homeDir.resolve("orchestrator.properties"); try { - return file.exists() ? file.getAbsoluteFile().toURI().toURL().toString() : null; + return Files.exists(file) ? file.toAbsolutePath().toUri().toURL().toString() : null; } catch (MalformedURLException e) { throw new IllegalStateException("Unable to read configuration file", e); } @@ -245,20 +217,8 @@ private File loadProperties() { return homeDir; } - private static Map interpolateProperties(Map map) { - Map copy = new HashMap<>(); - for (Map.Entry entry : map.entrySet()) { - copy.put(entry.getKey(), interpolate(entry.getValue(), map)); - } - return copy; - } - - private static String interpolate(String prop, Map with) { - return StrSubstitutor.replace(prop, with, "${", "}"); - } - public Configuration build() { - File homeDir = loadProperties(); + Path homeDir = loadProperties(); Map interpolatedProperties = interpolateProperties(props); return new Configuration(homeDir, interpolatedProperties); } diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/FileSystem.java b/sonar-orchestrator-config/src/main/java/com/sonar/orchestrator/config/FileSystem.java similarity index 67% rename from sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/FileSystem.java rename to sonar-orchestrator-config/src/main/java/com/sonar/orchestrator/config/FileSystem.java index 668f2baa..26d3be76 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/FileSystem.java +++ b/sonar-orchestrator-config/src/main/java/com/sonar/orchestrator/config/FileSystem.java @@ -1,5 +1,5 @@ /* - * Orchestrator + * Orchestrator Configuration * Copyright (C) 2011-2025 SonarSource SA * mailto:info AT sonarsource DOT com * @@ -19,7 +19,7 @@ */ package com.sonar.orchestrator.config; -import java.io.File; +import java.nio.file.Path; import java.util.List; import java.util.Objects; import javax.annotation.CheckForNull; @@ -30,69 +30,69 @@ import static org.apache.commons.io.FileUtils.getUserDirectory; public class FileSystem { - private File orchestratorHome; + private final Path orchestratorHome; @Nullable - private File mavenHome; - private File mavenLocalRepository; - private File sonarQubeZipsDir; - private File workspace; + private final Path mavenHome; + private final Path mavenLocalRepository; + private final Path sonarQubeZipsDir; + private final Path workspace; @Nullable - private File javaHome; + private final Path javaHome; @Nullable - private File antHome; + private final Path antHome; - public FileSystem(File homeDir, Configuration config) { + public FileSystem(Path homeDir, Configuration config) { this.orchestratorHome = homeDir; this.mavenHome = initDir(config, asList("maven.home", "MAVEN_HOME"), null); - this.mavenLocalRepository = initDir(config, asList("maven.localRepository", "MAVEN_LOCAL_REPOSITORY"), new File(getUserDirectory(), ".m2/repository")); - this.sonarQubeZipsDir = initDir(config, singletonList("orchestrator.sonarInstallsDir"), new File(orchestratorHome, "zips")); - this.workspace = initDir(config, singletonList("orchestrator.workspaceDir"), new File("target")); + this.mavenLocalRepository = initDir(config, asList("maven.localRepository", "MAVEN_LOCAL_REPOSITORY"), getUserDirectory().toPath().resolve(".m2/repository")); + this.sonarQubeZipsDir = initDir(config, singletonList("orchestrator.sonarInstallsDir"), orchestratorHome.resolve("zips")); + this.workspace = initDir(config, singletonList("orchestrator.workspaceDir"), Path.of("target")); this.javaHome = initDir(config, asList("java.home", "JAVA_HOME"), null); this.antHome = initDir(config, asList("ant.home", "ANT_HOME"), null); } - public File mavenLocalRepository() { + @CheckForNull + private static Path initDir(Configuration config, List propertyKeys, @Nullable Path defaultPath) { + return propertyKeys.stream() + .map(config::getString) + .filter(Objects::nonNull) + .findFirst() + .map(Path::of) + .orElse(defaultPath); + } + + public Path mavenLocalRepository() { return mavenLocalRepository; } @CheckForNull - public File mavenHome() { + public Path mavenHome() { return mavenHome; } @CheckForNull - public File antHome() { + public Path antHome() { return antHome; } @CheckForNull - public File javaHome() { + public Path javaHome() { return javaHome; } - public File getOrchestratorHome() { + public Path getOrchestratorHome() { return orchestratorHome; } - public File getCacheDir() { - return new File(orchestratorHome, "cache"); + public Path getCacheDir() { + return orchestratorHome.resolve("cache"); } - public File getSonarQubeZipsDir() { + public Path getSonarQubeZipsDir() { return sonarQubeZipsDir; } - public File workspace() { + public Path workspace() { return workspace; } - - @CheckForNull - private static File initDir(Configuration config, List propertyKeys, @Nullable File defaultFile) { - return propertyKeys.stream() - .map(config::getString) - .filter(Objects::nonNull) - .findFirst() - .map(File::new) - .orElse(defaultFile); - } } diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/package-info.java b/sonar-orchestrator-config/src/main/java/com/sonar/orchestrator/config/package-info.java similarity index 96% rename from sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/package-info.java rename to sonar-orchestrator-config/src/main/java/com/sonar/orchestrator/config/package-info.java index 631a0749..dc1dd2dd 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/package-info.java +++ b/sonar-orchestrator-config/src/main/java/com/sonar/orchestrator/config/package-info.java @@ -1,5 +1,5 @@ /* - * Orchestrator + * Orchestrator Configuration * Copyright (C) 2011-2025 SonarSource SA * mailto:info AT sonarsource DOT com * diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/config/ConfigurationTest.java b/sonar-orchestrator-config/src/test/java/com/sonar/orchestrator/config/ConfigurationTest.java similarity index 50% rename from sonar-orchestrator/src/test/java/com/sonar/orchestrator/config/ConfigurationTest.java rename to sonar-orchestrator-config/src/test/java/com/sonar/orchestrator/config/ConfigurationTest.java index 284d327a..3e64ff06 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/config/ConfigurationTest.java +++ b/sonar-orchestrator-config/src/test/java/com/sonar/orchestrator/config/ConfigurationTest.java @@ -1,5 +1,5 @@ /* - * Orchestrator + * Orchestrator Configuration * Copyright (C) 2011-2025 SonarSource SA * mailto:info AT sonarsource DOT com * @@ -19,38 +19,33 @@ */ package com.sonar.orchestrator.config; -import com.google.common.collect.ImmutableMap; -import com.sonar.orchestrator.PropertyAndEnvTest; -import com.sonar.orchestrator.locator.FileLocation; -import com.sonar.orchestrator.test.MockHttpServer; +import com.github.tomakehurst.wiremock.WireMockServer; import java.io.File; import java.io.IOException; -import java.net.URISyntaxException; import java.net.URL; -import java.util.HashMap; +import java.nio.file.Path; import java.util.Map; import java.util.Properties; import org.apache.commons.io.FileUtils; -import org.apache.commons.io.FilenameUtils; -import org.apache.commons.lang.StringUtils; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.ExpectedException; -import org.junit.rules.TemporaryFolder; - -import static com.sonar.orchestrator.TestModules.setEnv; +import org.apache.commons.lang3.Strings; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; +import org.junit.jupiter.params.ParameterizedTest; +import org.junit.jupiter.params.provider.ValueSource; + +import static com.github.tomakehurst.wiremock.client.WireMock.aResponse; +import static com.github.tomakehurst.wiremock.client.WireMock.get; +import static com.github.tomakehurst.wiremock.client.WireMock.notFound; +import static com.github.tomakehurst.wiremock.client.WireMock.urlMatching; +import static com.github.tomakehurst.wiremock.core.WireMockConfiguration.options; import static org.assertj.core.api.Assertions.assertThat; +import static org.assertj.core.api.Assertions.assertThatThrownBy; import static org.assertj.core.data.MapEntry.entry; -public class ConfigurationTest extends PropertyAndEnvTest { - - @Rule - public ExpectedException thrown = ExpectedException.none(); - @Rule - public TemporaryFolder temp = new TemporaryFolder(); +class ConfigurationTest { @Test - public void getString() { + void getString() { Properties props = new Properties(); props.setProperty("foo", "bar"); Configuration config = Configuration.create(props); @@ -61,7 +56,7 @@ public void getString() { } @Test - public void getInt() { + void getInt() { Properties props = new Properties(); props.setProperty("one", "1"); Configuration config = Configuration.create(props); @@ -71,7 +66,7 @@ public void getInt() { } @Test - public void asMap() { + void asMap() { Properties props = new Properties(); props.setProperty("foo", "1"); props.setProperty("bar", "2"); @@ -82,24 +77,23 @@ public void asMap() { } @Test - public void asMap_immutable() { - thrown.expect(UnsupportedOperationException.class); - + void asMap_immutable() { Properties props = new Properties(); props.setProperty("foo", "bar"); Configuration config = Configuration.create(props); - config.asMap().put("new", "property"); + Map map = config.asMap(); + assertThatThrownBy(() -> map.put("new", "property")).isInstanceOf(UnsupportedOperationException.class); } @Test - public void createEnv() { + void createEnv() { Configuration config = Configuration.createEnv(); assertThat(config.getString("java.io.tmpdir")).isNotNull(); } @Test - public void interpolateProperties() { + void interpolateProperties() { Properties props = new Properties(); props.setProperty("where", "FR"); props.setProperty("codeStory", "devoxx${where}"); @@ -109,7 +103,7 @@ public void interpolateProperties() { } @Test - public void loadPropertiesFile() { + void loadPropertiesFile() { URL url = getClass().getResource("/com/sonar/orchestrator/config/ConfigurationTest/sample.properties"); Properties props = new Properties(); props.setProperty("foo", "bar"); @@ -122,10 +116,9 @@ public void loadPropertiesFile() { } @Test - public void loadPropertiesFileFromHomeByDefault() throws IOException { + void loadPropertiesFileFromHomeByDefault(@TempDir Path homeDir) throws IOException { URL url = getClass().getResource("/com/sonar/orchestrator/config/ConfigurationTest/sample.properties"); - File homeDir = temp.newFolder(); - FileUtils.copyURLToFile(url, new File(homeDir, "orchestrator.properties")); + FileUtils.copyURLToFile(url, new File(homeDir.toFile(), "orchestrator.properties")); Properties props = new Properties(); props.setProperty("foo", "bar"); props.setProperty("orchestrator.home", homeDir.toString()); @@ -149,89 +142,34 @@ public void shouldOverridePropertiesFile() { assertThat(config.getString("loadedFromFile")).isEqualTo("vrai"); } - @Test - public void getFileLocationOfShared() throws URISyntaxException { - URL url = getClass().getResource("/com/sonar/orchestrator/config/ConfigurationTest/sample.properties"); - Properties props = new Properties(); - props.setProperty("orchestrator.configUrl", url.toString()); - props.setProperty("orchestrator.it_sources", FilenameUtils.getFullPath(url.toURI().getPath())); - Configuration config = Configuration.create(props); - - FileLocation location = config.getFileLocationOfShared("sample.properties"); - assertThat(location.getFile()).isFile(); - assertThat(location.getFile()).exists(); - assertThat(location.getFile().getName()).isEqualTo("sample.properties"); - } - - @Test - public void getFileLocationOfSharedApplyPriority() throws URISyntaxException { - URL url = getClass().getResource("/com/sonar/orchestrator/config/ConfigurationTest/sample.properties"); - Properties props = new Properties(); - props.setProperty("orchestrator.configUrl", url.toString()); - Map envVariables = new HashMap<>(System.getenv()); - envVariables.put("SONAR_IT_SOURCES", FilenameUtils.getFullPath(url.toURI().getPath())); - setEnv(ImmutableMap.copyOf(envVariables)); - props.setProperty("orchestrator.it_sources", FilenameUtils.getFullPath(url.toURI().getPath())); - Configuration config = Configuration.create(props); - - FileLocation location = config.getFileLocationOfShared("sample.properties"); - assertThat(location.getFile().exists()).isTrue(); - } - - @Test - public void getFileLocationOfShared_bad_place() { - thrown.expect(IllegalStateException.class); - - URL url = getClass().getResource("/com/sonar/orchestrator/config/ConfigurationTest/sample.properties"); - Properties props = new Properties(); - props.setProperty("orchestrator.configUrl", url.toString()); - props.setProperty("orchestrator.it_sources", "/com/sonar/orchestrator/config/ConfigurationTest"); - Configuration config = Configuration.create(props); - - config.getFileLocationOfShared("/bad/path"); - } - - @Test - public void getFileLocationOfShared_not_a_directory() { - thrown.expect(IllegalStateException.class); - - URL url = getClass().getResource("/com/sonar/orchestrator/config/ConfigurationTest/sample.properties"); - Properties props = new Properties(); - props.setProperty("orchestrator.configUrl", url.toString()); - props.setProperty("orchestrator.it_sources", "/com/sonar/orchestrator/config/ConfigurationTest/sample.properties"); - Configuration config = Configuration.create(props); - - config.getFileLocationOfShared("."); - } - @Test public void loadRemotePropertiesFile() throws Exception { - MockHttpServer server = new MockHttpServer(); - server.start(); - server.setMockResponseData("foo=bar"); + WireMockServer wireMockServer = new WireMockServer(options().dynamicPort()); try { + wireMockServer.start(); + wireMockServer.stubFor(get(urlMatching(".*")).willReturn(aResponse().withBody("foo=bar"))); Properties props = new Properties(); - props.setProperty("orchestrator.configUrl", "http://localhost:" + server.getPort() + "/jenkins/orchestrator.properties"); + props.setProperty("orchestrator.configUrl", wireMockServer.baseUrl() + "/jenkins/orchestrator.properties"); Configuration config = Configuration.create(props); assertThat(config.getString("foo")).isEqualTo("bar"); } finally { - server.stop(); + wireMockServer.stop(); } } - @Test(expected = IllegalStateException.class) + @Test public void loadRemotePropertiesFile_fail_if_not_found() throws Exception { - MockHttpServer server = new MockHttpServer(); - server.start(); - server.setMockResponseStatus(404); + WireMockServer wireMockServer = new WireMockServer(options().dynamicPort()); try { + wireMockServer.start(); + wireMockServer.stubFor(get(urlMatching(".*")).willReturn(notFound())); Properties props = new Properties(); - props.setProperty("orchestrator.configUrl", "http://localhost:" + server.getPort()); + props.setProperty("orchestrator.configUrl", wireMockServer.baseUrl()); - Configuration.create(props); + assertThatThrownBy(() -> Configuration.create(props)).isInstanceOf(IllegalStateException.class); } finally { - server.stop(); + wireMockServer.stop(); } } @@ -239,10 +177,10 @@ public void loadRemotePropertiesFile_fail_if_not_found() throws Exception { * ORCH-88 */ @Test - public void interpolate_config_url() { + void interpolate_config_url() { URL url = getClass().getResource("/com/sonar/orchestrator/config/ConfigurationTest/sample.properties"); Properties props = new Properties(); - String value = StringUtils.replace(url.toString(), "sample.properties", "${filename}"); + String value = Strings.CS.replace(url.toString(), "sample.properties", "${filename}"); props.setProperty("orchestrator.configUrl", value); props.setProperty("filename", "sample.properties"); @@ -252,7 +190,7 @@ public void interpolate_config_url() { } @Test - public void should_support_h2_as_embedded_database() { + void should_support_h2_as_embedded_database() { Properties props = new Properties(); props.setProperty("sonar.jdbc.dialect", "embedded"); @@ -260,28 +198,12 @@ public void should_support_h2_as_embedded_database() { assertThat(config.getString("sonar.jdbc.dialect")).isEqualTo("h2"); } - @Test - public void configure_orchestrator_home_with_deprecated_property() throws Exception { - String property = "SONAR_USER_HOME"; - testOrchestratorHome(property); - } - - @Test - public void configure_orchestrator_home() throws Exception { - testOrchestratorHome("orchestrator.home"); - } - - @Test - public void configure_orchestrator_home_with_env_variable() throws Exception { - testOrchestratorHome("ORCHESTRATOR_HOME"); - } - - private void testOrchestratorHome(String property) throws IOException { - File dir = temp.newFolder(); - - Configuration underTest = Configuration.builder().setProperty(property, dir.getCanonicalPath()).build(); + @ParameterizedTest + @ValueSource(strings = {"SONAR_USER_HOME", "ORCHESTRATOR_HOME", "orchestrator.home"}) + void configure_orchestrator_home_with_deprecated_property(String property, @TempDir Path dir) { + Configuration underTest = Configuration.builder().setProperty(property, dir).build(); - assertThat(underTest.fileSystem().getOrchestratorHome().getCanonicalPath()).isEqualTo(dir.getCanonicalPath()); + assertThat(underTest.fileSystem().getOrchestratorHome()).isEqualTo(dir); } } diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/config/FileSystemTest.java b/sonar-orchestrator-config/src/test/java/com/sonar/orchestrator/config/FileSystemTest.java similarity index 54% rename from sonar-orchestrator/src/test/java/com/sonar/orchestrator/config/FileSystemTest.java rename to sonar-orchestrator-config/src/test/java/com/sonar/orchestrator/config/FileSystemTest.java index 8e2fa4eb..e568fd7d 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/config/FileSystemTest.java +++ b/sonar-orchestrator-config/src/test/java/com/sonar/orchestrator/config/FileSystemTest.java @@ -1,5 +1,5 @@ /* - * Orchestrator + * Orchestrator Configuration * Copyright (C) 2011-2025 SonarSource SA * mailto:info AT sonarsource DOT com * @@ -19,69 +19,58 @@ */ package com.sonar.orchestrator.config; -import java.io.File; import java.io.IOException; +import java.nio.file.Path; import org.apache.commons.io.FileUtils; -import org.junit.Before; -import org.junit.Rule; -import org.junit.Test; -import org.junit.rules.TemporaryFolder; +import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.io.TempDir; import static org.assertj.core.api.Assertions.assertThat; -public class FileSystemTest { +class FileSystemTest { - @Rule - public TemporaryFolder temp = new TemporaryFolder(); - private File homeDir; - - @Before - public void setUp() throws Exception { - homeDir = temp.newFolder(); - } + @TempDir + private Path homeDir; @Test - public void test_defaults() throws Exception { + void test_defaults() throws Exception { FileSystem underTest = new FileSystem(homeDir, Configuration.create()); - File userHome = FileUtils.getUserDirectory(); + Path userHome = FileUtils.getUserDirectory().toPath(); // optional directories assertThat(underTest.javaHome()).isNull(); assertThat(underTest.antHome()).isNull(); assertThat(underTest.mavenHome()).isNull(); - verifySameDirs(underTest.mavenLocalRepository(), new File(userHome, ".m2/repository")); - verifySameDirs(underTest.workspace(), new File("target")); + verifySameDirs(underTest.mavenLocalRepository(), userHome.resolve(".m2/repository")); + verifySameDirs(underTest.workspace(), Path.of("target")); verifySameDirs(underTest.getOrchestratorHome(), homeDir); - verifySameDirs(underTest.getCacheDir(), new File(homeDir, "cache")); - verifySameDirs(underTest.getSonarQubeZipsDir(), new File(homeDir, "zips")); + verifySameDirs(underTest.getCacheDir(), homeDir.resolve("cache")); + verifySameDirs(underTest.getSonarQubeZipsDir(), homeDir.resolve("zips")); } @Test - public void configure_java_home() throws Exception { - File dir = temp.newFolder(); - FileSystem underTest = new FileSystem(homeDir, Configuration.builder().setProperty("java.home", dir.getCanonicalPath()).build()); + void configure_java_home(@TempDir Path dir) throws Exception { + FileSystem underTest = new FileSystem(homeDir, Configuration.builder().setProperty("java.home", dir).build()); verifySameDirs(underTest.javaHome(), dir); } @Test - public void configure_maven_home() throws Exception { - File dir = temp.newFolder(); - FileSystem underTest = new FileSystem(homeDir, Configuration.builder().setProperty("maven.home", dir.getCanonicalPath()).build()); + void configure_maven_home(@TempDir Path dir) throws Exception { + FileSystem underTest = new FileSystem(homeDir, Configuration.builder().setProperty("maven.home", dir).build()); verifySameDirs(underTest.mavenHome(), dir); } @Test - public void configure_maven_local_repository() throws Exception { - File dir = temp.newFolder(); - FileSystem underTest = new FileSystem(homeDir, Configuration.builder().setProperty("maven.localRepository", dir.getCanonicalPath()).build()); + void configure_maven_local_repository(@TempDir Path dir) throws Exception { + FileSystem underTest = new FileSystem(homeDir, Configuration.builder().setProperty("maven.localRepository", dir).build()); verifySameDirs(underTest.mavenLocalRepository(), dir); } - private static void verifySameDirs(File dir1, File dir2) throws IOException { - assertThat(dir1.getCanonicalPath()).isEqualTo(dir2.getCanonicalPath()); + private static void verifySameDirs(Path dir1, Path dir2) { + assertThat(dir1.toAbsolutePath()).isEqualTo(dir2.toAbsolutePath()); } } diff --git a/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/ConfigurationTest/sample.properties b/sonar-orchestrator-config/src/test/resources/com/sonar/orchestrator/config/ConfigurationTest/sample.properties similarity index 100% rename from sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/ConfigurationTest/sample.properties rename to sonar-orchestrator-config/src/test/resources/com/sonar/orchestrator/config/ConfigurationTest/sample.properties diff --git a/sonar-orchestrator-junit5/pom.xml b/sonar-orchestrator-junit5/pom.xml index ab3528e7..78548da2 100644 --- a/sonar-orchestrator-junit5/pom.xml +++ b/sonar-orchestrator-junit5/pom.xml @@ -19,7 +19,6 @@ org.junit.jupiter junit-jupiter-api - 5.9.2 org.sonarsource.orchestrator @@ -31,7 +30,6 @@ org.junit.jupiter junit-jupiter-engine - 5.9.2 test diff --git a/sonar-orchestrator/pom.xml b/sonar-orchestrator/pom.xml index f6c70716..25b620d3 100644 --- a/sonar-orchestrator/pom.xml +++ b/sonar-orchestrator/pom.xml @@ -23,6 +23,11 @@ jsr305 provided + + ${project.groupId} + sonar-orchestrator-config + ${project.version} + com.squareup.okhttp3 okhttp @@ -36,12 +41,10 @@ commons-io commons-io - ${commonsIO.version} - commons-lang - commons-lang - ${commonsLang.version} + org.apache.commons + commons-lang3 org.apache.commons diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/Orchestrator.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/Orchestrator.java index cfb5406e..5072930d 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/Orchestrator.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/Orchestrator.java @@ -27,7 +27,6 @@ import com.sonar.orchestrator.build.SynchronousAnalyzer; import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.config.FileSystem; -import com.sonar.orchestrator.config.Licenses; import com.sonar.orchestrator.container.Server; import com.sonar.orchestrator.container.SonarDistribution; import com.sonar.orchestrator.db.Database; @@ -35,8 +34,10 @@ import com.sonar.orchestrator.http.HttpCall; import com.sonar.orchestrator.http.HttpMethod; import com.sonar.orchestrator.http.HttpResponse; +import com.sonar.orchestrator.licenses.Licenses; import com.sonar.orchestrator.locator.FileLocation; import com.sonar.orchestrator.locator.Location; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.server.Packaging; import com.sonar.orchestrator.server.PackagingResolver; import com.sonar.orchestrator.server.ServerCommandLineFactory; @@ -44,6 +45,7 @@ import com.sonar.orchestrator.server.ServerProcess; import com.sonar.orchestrator.server.ServerProcessImpl; import com.sonar.orchestrator.server.StartupLogWatcher; +import com.sonar.orchestrator.util.SharedDir; import java.util.Arrays; import java.util.UUID; import java.util.concurrent.atomic.AtomicBoolean; @@ -59,6 +61,8 @@ public class Orchestrator { private static final String SONAR_TOKEN_PROPERTY_NAME = "sonar.token"; private final Configuration config; + private final Locators locators; + private final SharedDir shareDir; private final SonarDistribution distribution; private final Licenses licenses; private final AtomicBoolean started = new AtomicBoolean(false); @@ -76,6 +80,8 @@ public class Orchestrator { */ public Orchestrator(Configuration config, SonarDistribution distribution, @Nullable StartupLogWatcher startupLogWatcher) { this.config = requireNonNull(config); + this.locators = new Locators(config); + this.shareDir = new SharedDir(config); this.distribution = requireNonNull(distribution); this.licenses = new Licenses(config); this.startupLogWatcher = startupLogWatcher; @@ -89,12 +95,12 @@ public Orchestrator(Configuration config, SonarDistribution distribution, @Nulla */ public Server install() { if (server == null) { - database = new DefaultDatabase(config); + database = new DefaultDatabase(config, locators); database.start(); - PackagingResolver packagingResolver = new PackagingResolver(config.locators()); + PackagingResolver packagingResolver = new PackagingResolver(locators); packaging = packagingResolver.resolve(distribution); - ServerInstaller serverInstaller = new ServerInstaller(packagingResolver, config, config.locators(), database.getClient()); + ServerInstaller serverInstaller = new ServerInstaller(packagingResolver, config, locators, database.getClient()); server = serverInstaller.install(distribution); } return server; @@ -129,7 +135,7 @@ public void start() { activateLicense(); } - buildRunner = new BuildRunner(config); + buildRunner = new BuildRunner(config, locators); } /** @@ -199,6 +205,10 @@ public Configuration getConfiguration() { return config; } + public Locators getLocators() { + return locators; + } + public Server getServer() { return server; } @@ -208,7 +218,7 @@ public Server getServer() { * Example : getFileLocationOfShared("javascript/performancing/pom.xml") */ public FileLocation getFileLocationOfShared(String relativePath) { - return config.getFileLocationOfShared(relativePath); + return shareDir.getFileLocationOfShared(relativePath); } public SonarDistribution getDistribution() { @@ -248,6 +258,13 @@ private BuildResult executeBuildInternal(Build build, boolean quietly, boolea return buildResult; } + public String getDefaultAdminToken() { + if (this.adminToken != null) { + return this.adminToken; + } + return generateDefaultAdminToken(); + } + private void setDefaultAdminToken(Build build) { if (build.getProperties().containsKey(SONAR_LOGIN_PROPERTY_NAME) || build.getProperties().containsKey(SONAR_TOKEN_PROPERTY_NAME)) { return; @@ -267,13 +284,6 @@ private void setDefaultAdminToken(Build build) { } } - public String getDefaultAdminToken() { - if (this.adminToken != null) { - return this.adminToken; - } - return generateDefaultAdminToken(); - } - private String generateDefaultAdminToken() { HttpCall httpCall = server.newHttpCall("api/user_tokens/generate") .setParam("name", UUID.randomUUID().toString()) diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AbstractBuildExecutor.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AbstractBuildExecutor.java index 4eaf1656..0a937a5e 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AbstractBuildExecutor.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AbstractBuildExecutor.java @@ -21,6 +21,7 @@ import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.coverage.JaCoCoArgumentsBuilder; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.util.CommandExecutor; import java.util.Map; import org.slf4j.Logger; @@ -30,18 +31,18 @@ abstract class AbstractBuildExecutor> { private static final Logger LOG = LoggerFactory.getLogger(AbstractBuildExecutor.class); - final BuildResult execute(T build, Configuration config, Map adjustedProperties) { - return execute(build, config, adjustedProperties, CommandExecutor.create()); + final BuildResult execute(T build, Configuration config, Locators locators, Map adjustedProperties) { + return execute(build, config, locators, adjustedProperties, CommandExecutor.create()); } - abstract BuildResult execute(T build, Configuration config, Map adjustedProperties, CommandExecutor create); + abstract BuildResult execute(T build, Configuration config, Locators locators, Map adjustedProperties, CommandExecutor create); /** * Append JaCoCo agent JVM arguments to a given environment variable (SONAR_RUNNER_OPTS, MAVEN_OPTS, ...) * @param optsVariableName The name of the environment variable to append to */ - static void appendCoverageArgumentToOpts(Map environmentVariables, Configuration config, String optsVariableName) { - String jaCoCoArgument = JaCoCoArgumentsBuilder.getJaCoCoArgument(config); + static void appendCoverageArgumentToOpts(Map environmentVariables, Configuration config, Locators locators, String optsVariableName) { + String jaCoCoArgument = JaCoCoArgumentsBuilder.getJaCoCoArgument(config, locators); if (jaCoCoArgument != null) { if (environmentVariables.containsKey(optsVariableName)) { String opts = environmentVariables.get(optsVariableName) + " " + jaCoCoArgument; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AntBuild.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AntBuild.java index 14a350c8..d857219a 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AntBuild.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AntBuild.java @@ -21,6 +21,7 @@ import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.locator.Location; +import com.sonar.orchestrator.locator.Locators; import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -33,16 +34,16 @@ public final class AntBuild extends Build { private Location buildLocation; private List targets; - public File getAntHome() { - return antHome; + public static AntBuild create() { + return new AntBuild(); } - public Location getBuildLocation() { - return buildLocation; + public static AntBuild create(Location buildFile, String[] targets, String... keyValueProperties) { + return new AntBuild().setBuildLocation(buildFile).setTargets(targets).setProperties(keyValueProperties); } - public List getTargets() { - return targets; + public File getAntHome() { + return antHome; } public AntBuild setAntHome(File antHome) { @@ -50,16 +51,29 @@ public AntBuild setAntHome(File antHome) { return this; } + public Location getBuildLocation() { + return buildLocation; + } + public AntBuild setBuildLocation(Location buildLocation) { this.buildLocation = buildLocation; return this; } + public List getTargets() { + return targets; + } + public AntBuild setTargets(List targets) { this.targets = targets; return this; } + public AntBuild setTargets(String... targets) { + this.targets = Arrays.asList(targets); + return this; + } + public AntBuild addTarget(String s) { if (this.targets == null) { this.targets = new ArrayList<>(); @@ -68,11 +82,6 @@ public AntBuild addTarget(String s) { return this; } - public AntBuild setTargets(String... targets) { - this.targets = Arrays.asList(targets); - return this; - } - @Override public String toString() { StringBuilder sb = new StringBuilder("AntBuild{"); @@ -84,15 +93,7 @@ public String toString() { } @Override - BuildResult execute(Configuration config, Map adjustedProperties) { - return new AntBuildExecutor().execute(this, config, adjustedProperties); - } - - public static AntBuild create() { - return new AntBuild(); - } - - public static AntBuild create(Location buildFile, String[] targets, String... keyValueProperties) { - return new AntBuild().setBuildLocation(buildFile).setTargets(targets).setProperties(keyValueProperties); + BuildResult execute(Configuration config, Locators locators, Map adjustedProperties) { + return new AntBuildExecutor().execute(this, config, locators, adjustedProperties); } } diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AntBuildExecutor.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AntBuildExecutor.java index 9b25ae82..83802999 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AntBuildExecutor.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/AntBuildExecutor.java @@ -20,40 +20,52 @@ package com.sonar.orchestrator.build; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.util.Command; import com.sonar.orchestrator.util.CommandExecutor; import com.sonar.orchestrator.util.StreamConsumer; import java.io.File; -import java.io.IOException; +import java.nio.file.Path; import java.util.Map; import javax.annotation.Nullable; -import org.apache.commons.lang.SystemUtils; +import org.apache.commons.lang3.SystemUtils; import org.slf4j.LoggerFactory; import static com.sonar.orchestrator.util.OrchestratorUtils.checkState; class AntBuildExecutor extends AbstractBuildExecutor { + private static String getAntPath(@Nullable Path antHome) { + String program = "ant"; + if (SystemUtils.IS_OS_WINDOWS) { + program += ".bat"; + } + if (antHome != null) { + program = antHome.resolve("bin/" + program).toAbsolutePath().toString(); + } + return program; + } + @Override - BuildResult execute(AntBuild build, Configuration config, Map adjustedProperties, CommandExecutor commandExecutor) { + BuildResult execute(AntBuild build, Configuration config, Locators locators, Map adjustedProperties, CommandExecutor commandExecutor) { BuildResult result = new BuildResult(); for (String target : build.getTargets()) { - executeTarget(build, config, adjustedProperties, target, result, commandExecutor); + executeTarget(build, config, locators, adjustedProperties, target, result, commandExecutor); } return result; } - private void executeTarget(AntBuild build, Configuration config, Map adjustedProperties, String target, + private void executeTarget(AntBuild build, Configuration config, Locators locators, Map adjustedProperties, String target, BuildResult result, CommandExecutor commandExecutor) { try { - File home = build.getAntHome() != null ? build.getAntHome() : config.fileSystem().antHome(); + Path home = build.getAntHome() != null ? build.getAntHome().toPath() : config.fileSystem().antHome(); Command command = Command.create(getAntPath(home)); for (Map.Entry env : build.getEnvironmentVariables().entrySet()) { command.setEnvironmentVariable(env.getKey(), env.getValue()); } command.addArguments(target.split(" ")); - File antFile = config.locators().locate(build.getBuildLocation()); + File antFile = locators.locate(build.getBuildLocation()); checkState(antFile.exists(), "Ant build file does not exist: %s", build.getBuildLocation()); command.addArgument("-f").addArgument(antFile.getCanonicalPath()); @@ -71,15 +83,4 @@ private void executeTarget(AntBuild build, Configuration config, Map adjustedProperties); + abstract BuildResult execute(Configuration config, Locators locators, Map adjustedProperties); } diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/BuildRunner.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/BuildRunner.java index 06be33ff..e3d60d94 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/BuildRunner.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/BuildRunner.java @@ -21,6 +21,7 @@ import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.container.Server; +import com.sonar.orchestrator.locator.Locators; import java.util.HashMap; import java.util.Map; import javax.annotation.Nullable; @@ -29,13 +30,15 @@ public class BuildRunner { public static final String SONAR_HOST_URL = "sonar.host.url"; private final Configuration config; + private final Locators locators; - public BuildRunner(Configuration config) { + public BuildRunner(Configuration config, Locators locators) { this.config = config; + this.locators = locators; } public BuildResult runQuietly(@Nullable Server server, Build build) { - return build.execute(config, adjustProperties(server, build)); + return build.execute(config, locators, adjustProperties(server, build)); } public BuildResult run(@Nullable Server server, Build build) { diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/GradleBuild.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/GradleBuild.java index ecbffedf..3be4d0d4 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/GradleBuild.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/GradleBuild.java @@ -22,6 +22,7 @@ import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.locator.FileLocation; import com.sonar.orchestrator.locator.Location; +import com.sonar.orchestrator.locator.Locators; import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -37,8 +38,8 @@ public final class GradleBuild extends Build { private List tasks = new ArrayList<>(); @Override - BuildResult execute(Configuration config, Map adjustedProperties) { - return new GradleBuildExecutor().execute(this, config, adjustedProperties); + BuildResult execute(Configuration config, Locators locators, Map adjustedProperties) { + return new GradleBuildExecutor().execute(this, config, locators, adjustedProperties); } public GradleBuild setProjectDirectory(Location projectDirectory) { diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/GradleBuildExecutor.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/GradleBuildExecutor.java index de81acff..586adf79 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/GradleBuildExecutor.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/GradleBuildExecutor.java @@ -20,12 +20,13 @@ package com.sonar.orchestrator.build; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.util.Command; import com.sonar.orchestrator.util.CommandExecutor; import com.sonar.orchestrator.util.StreamConsumer; import java.io.File; import java.util.Map; -import org.apache.commons.lang.SystemUtils; +import org.apache.commons.lang3.SystemUtils; import org.slf4j.LoggerFactory; import static com.sonar.orchestrator.util.OrchestratorUtils.checkState; @@ -44,19 +45,19 @@ public class GradleBuildExecutor extends AbstractBuildExecutor { } @Override - BuildResult execute(GradleBuild build, Configuration config, Map adjustedProperties, CommandExecutor commandExecutor) { + BuildResult execute(GradleBuild build, Configuration config, Locators locators, Map adjustedProperties, CommandExecutor commandExecutor) { BuildResult result = new BuildResult(); for (String task : build.getTasks()) { - executeTask(build, config, adjustedProperties, task, result, commandExecutor); + executeTask(build, config, locators, adjustedProperties, task, result, commandExecutor); } return result; } - private void executeTask(GradleBuild build, Configuration config, Map adjustedProperties, String task, + private void executeTask(GradleBuild build, Configuration config, Locators locators, Map adjustedProperties, String task, final BuildResult result, CommandExecutor commandExecutor) { try { - File projectDir = config.locators().locate(build.getProjectDirectory()); + File projectDir = locators.locate(build.getProjectDirectory()); File gradlew = getGradleWrapper(projectDir); checkState(gradlew.exists(), "Gradle wrapper does not exist: '%s'", gradlew.toString()); diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/MavenBuild.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/MavenBuild.java index 37cc5550..62c9fa2b 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/MavenBuild.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/MavenBuild.java @@ -22,6 +22,7 @@ import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.locator.FileLocation; import com.sonar.orchestrator.locator.Location; +import com.sonar.orchestrator.locator.Locators; import java.io.File; import java.util.ArrayList; import java.util.Arrays; @@ -142,7 +143,7 @@ public static MavenBuild create(File pom) { } @Override - BuildResult execute(Configuration config, Map adjustedProperties) { - return new MavenBuildExecutor().execute(this, config, adjustedProperties); + BuildResult execute(Configuration config, Locators locators, Map adjustedProperties) { + return new MavenBuildExecutor().execute(this, config, locators, adjustedProperties); } } diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/MavenBuildExecutor.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/MavenBuildExecutor.java index 58babb12..5315e711 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/MavenBuildExecutor.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/MavenBuildExecutor.java @@ -20,23 +20,25 @@ package com.sonar.orchestrator.build; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.util.Command; import com.sonar.orchestrator.util.CommandExecutor; import com.sonar.orchestrator.util.StreamConsumer; import java.io.File; import java.io.IOException; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Map; import java.util.Optional; -import org.apache.commons.lang.SystemUtils; +import org.apache.commons.lang3.SystemUtils; import org.slf4j.LoggerFactory; import static com.sonar.orchestrator.util.OrchestratorUtils.checkState; class MavenBuildExecutor extends AbstractBuildExecutor { - private final Os os; - private static final String MAVEN_OPTS = "MAVEN_OPTS"; + private final Os os; // visible for tests MavenBuildExecutor(Os os) { @@ -48,19 +50,19 @@ public MavenBuildExecutor() { } @Override - BuildResult execute(MavenBuild build, Configuration config, Map adjustedProperties, CommandExecutor commandExecutor) { + BuildResult execute(MavenBuild build, Configuration config, Locators locators, Map adjustedProperties, CommandExecutor commandExecutor) { BuildResult result = new BuildResult(); for (String goal : build.getGoals()) { - appendCoverageArgumentToOpts(build.getEnvironmentVariables(), config, MAVEN_OPTS); - executeGoal(build, config, adjustedProperties, goal, result, commandExecutor); + appendCoverageArgumentToOpts(build.getEnvironmentVariables(), config, locators, MAVEN_OPTS); + executeGoal(build, config, locators, adjustedProperties, goal, result, commandExecutor); } return result; } - private void executeGoal(MavenBuild build, Configuration config, Map adjustedProperties, String goal, + private void executeGoal(MavenBuild build, Configuration config, Locators locators, Map adjustedProperties, String goal, final BuildResult result, CommandExecutor commandExecutor) { try { - File mavenHome = config.fileSystem().mavenHome(); + Path mavenHome = config.fileSystem().mavenHome(); Command command = Command.create(buildMvnPath(config)); if (build.getExecutionDir() != null) { command.setDirectory(build.getExecutionDir()); @@ -70,7 +72,7 @@ private void executeGoal(MavenBuild build, Configuration config, Map binary = Optional.ofNullable(config.getStringByKeys("maven.binary", "MAVEN_BINARY")); - File home = config.fileSystem().mavenHome(); + Path home = config.fileSystem().mavenHome(); if (home == null) { return binary.orElse(os.isWindows() ? "mvn.cmd" : "mvn"); } if (binary.isPresent()) { - return new File(home, "bin/" + binary.get()).getCanonicalPath(); + return home.resolve("bin/" + binary.get()).toAbsolutePath().toString(); } if (os.isWindows()) { // .bat is required for maven versions <= 3.2 - File bin = new File(home, "bin/mvn.bat"); - if (bin.exists()) { - return bin.getCanonicalPath(); + Path bin = home.resolve("bin/mvn.bat"); + if (Files.exists(bin)) { + return bin.toAbsolutePath().toString(); } - return new File(home, "bin/mvn.cmd").getCanonicalPath(); + return home.resolve("bin/mvn.cmd").toAbsolutePath().toString(); } - return new File(home, "bin/mvn").getCanonicalPath(); + return home.resolve("bin/mvn").toAbsolutePath().toString(); } static class Os { diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/ScannerForMSBuild.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/ScannerForMSBuild.java index 35557780..45e33359 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/ScannerForMSBuild.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/ScannerForMSBuild.java @@ -20,20 +20,20 @@ package com.sonar.orchestrator.build; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.ArtifactoryFactory; import com.sonar.orchestrator.locator.GitHub; import com.sonar.orchestrator.locator.GitHubImpl; import com.sonar.orchestrator.locator.Location; import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.locator.MavenLocation; import com.sonar.orchestrator.version.Version; -import java.util.Optional; -import org.slf4j.Logger; -import org.slf4j.LoggerFactory; - import java.io.File; import java.util.Map; +import java.util.Optional; import javax.annotation.CheckForNull; import javax.annotation.Nullable; +import org.slf4j.Logger; +import org.slf4j.LoggerFactory; import static com.sonar.orchestrator.util.OrchestratorUtils.checkArgument; import static com.sonar.orchestrator.util.OrchestratorUtils.checkState; @@ -46,11 +46,11 @@ * @since 3.13 */ public class ScannerForMSBuild extends Build { + public static final String LATEST_RELEASE = "LATEST_RELEASE"; // 4.1.0.1148 static final int DOT_NET_CORE_INTRODUCTION_MAJOR_VERSION = 4; static final int DOT_NET_CORE_INTRODUCTION_MINOR_VERSION = 1; public static final String DOT_NET_CORE_INTRODUCTION_VERSION = DOT_NET_CORE_INTRODUCTION_MAJOR_VERSION + "." + DOT_NET_CORE_INTRODUCTION_MINOR_VERSION; - public static final String LATEST_RELEASE = "LATEST_RELEASE"; private static final Logger LOG = LoggerFactory.getLogger(ScannerForMSBuild.class); private final GitHub gitHub; @@ -72,6 +72,46 @@ public class ScannerForMSBuild extends Build { this.gitHub = gitHub; } + private static Optional getLatestScannerVersionFromArtifactory() { + Configuration config = Configuration.createEnv(); + Locators locators = new Locators(config); + MavenLocation build = MavenLocation.builder() + .setGroupId("org.sonarsource.scanner.msbuild") + .setArtifactId("sonar-scanner") + .setVersion(LATEST_RELEASE) + .build(); + return locators.maven().resolveVersion(build); + } + + public static ScannerForMSBuild create() { + return new ScannerForMSBuild(); + } + + public static ScannerForMSBuild create(File projectDir, String... keyValueProperties) { + return + // default value + create() + // incoming values + .setProjectDir(projectDir) + .setProperties(keyValueProperties); + } + + private static void checkDotNetCoreCompatibility(Version scannerVersion, boolean useDotNetCore) { + if (useDotNetCore) { + checkArgument(scannerVersion != null, "Default version of SonarScanner for MSBuild embedded by Orchestrator does not support .NET Core. " + + "Please provide a scanner version >= %s.", DOT_NET_CORE_INTRODUCTION_VERSION); + checkState(scannerVersion.isGreaterThanOrEquals(DOT_NET_CORE_INTRODUCTION_MAJOR_VERSION, DOT_NET_CORE_INTRODUCTION_MINOR_VERSION), + "Version of ScannerForMSBuild should be greater than or equals to %s to be able to use .Net Core.", + DOT_NET_CORE_INTRODUCTION_VERSION); + } + } + + private static void checkProjectDir(File dir) { + requireNonNull(dir, "Project directory must be set"); + checkArgument(dir.exists(), "Project directory must exist"); + checkArgument(dir.isDirectory(), "Project directory must be... a directory"); + } + @CheckForNull public Version scannerVersion() { return scannerVersion; @@ -90,21 +130,7 @@ public ScannerForMSBuild setUseDotNetCore(boolean useDotnetCore) { } /** - * Providing a .NET Core executable to be used during analysis, force usage of .NET Core version of the scanner. If - * not provided and usage of .NET Core is enabled, orchestrator will assume that the dotnet executable is available in PATH. - * - * Note that there is no need to call {@link #setUseDotNetCore(boolean)} if manually setting the dotnet executable. - * - * @param dotNetCoreExecutable the path to the .NET Core executable - * @return The scanner being built - */ - public ScannerForMSBuild setDotNetCoreExecutable(File dotNetCoreExecutable) { - this.dotNetCoreExecutable = dotNetCoreExecutable; - return setUseDotNetCore(true); - } - - /** - * In order to use .NET Core, the provided version of SonarScanner for MSBuild should be higher or + * In order to use .NET Core, the provided version of SonarScanner for MSBuild should be higher or * equal to {@link ScannerForMSBuild#DOT_NET_CORE_INTRODUCTION_VERSION}. * * @return true if using .NET Core and provided version of SonarScanner for MSBuild is compatible. @@ -122,10 +148,30 @@ public File getDotNetCoreExecutable() { return dotNetCoreExecutable; } + /** + * Providing a .NET Core executable to be used during analysis, force usage of .NET Core version of the scanner. If + * not provided and usage of .NET Core is enabled, orchestrator will assume that the dotnet executable is available in PATH. + * + * Note that there is no need to call {@link #setUseDotNetCore(boolean)} if manually setting the dotnet executable. + * + * @param dotNetCoreExecutable the path to the .NET Core executable + * @return The scanner being built + */ + public ScannerForMSBuild setDotNetCoreExecutable(File dotNetCoreExecutable) { + this.dotNetCoreExecutable = dotNetCoreExecutable; + return setUseDotNetCore(true); + } + public File getProjectDir() { return projectDir; } + public ScannerForMSBuild setProjectDir(File dir) { + checkProjectDir(dir); + this.projectDir = dir; + return this; + } + @CheckForNull public Location getLocation() { return location; @@ -135,6 +181,11 @@ public boolean isDebugLogs() { return debugLogs; } + public ScannerForMSBuild setDebugLogs(boolean b) { + this.debugLogs = b; + return this; + } + public ScannerForMSBuild setScannerVersion(String s) { checkArgument(!isEmpty(s), "version must be set"); if (s.equals(LATEST_RELEASE)) { @@ -151,39 +202,18 @@ public ScannerForMSBuild setScannerVersion(String s) { return this; } - private static Optional getLatestScannerVersionFromArtifactory() { - Locators locators = Configuration.createEnv().locators(); - MavenLocation build = MavenLocation.builder() - .setGroupId("org.sonarsource.scanner.msbuild") - .setArtifactId("sonar-scanner") - .setVersion(LATEST_RELEASE) - .build(); - return locators.maven().resolveVersion(build); - } - public ScannerForMSBuild setScannerLocation(Location location) { requireNonNull(location); this.location = location; return this; } - public ScannerForMSBuild setProjectDir(File dir) { - checkProjectDir(dir); - this.projectDir = dir; - return this; - } - - public ScannerForMSBuild setProjectKey(@Nullable String s) { - this.projectKey = s; - return this; - } - public String getProjectKey() { return projectKey; } - public ScannerForMSBuild setProjectVersion(@Nullable String s) { - this.projectVersion = s; + public ScannerForMSBuild setProjectKey(@Nullable String s) { + this.projectKey = s; return this; } @@ -191,8 +221,8 @@ public String getProjectVersion() { return projectVersion; } - public ScannerForMSBuild setProjectName(@Nullable String s) { - this.projectName = s; + public ScannerForMSBuild setProjectVersion(@Nullable String s) { + this.projectVersion = s; return this; } @@ -200,28 +230,15 @@ public String getProjectName() { return projectName; } - public ScannerForMSBuild setDebugLogs(boolean b) { - this.debugLogs = b; + public ScannerForMSBuild setProjectName(@Nullable String s) { + this.projectName = s; return this; } - public static ScannerForMSBuild create() { - return new ScannerForMSBuild(); - } - - public static ScannerForMSBuild create(File projectDir, String... keyValueProperties) { - return - // default value - create() - // incoming values - .setProjectDir(projectDir) - .setProperties(keyValueProperties); - } - @Override - BuildResult execute(Configuration config, Map adjustedProperties) { + BuildResult execute(Configuration config, Locators locators, Map adjustedProperties) { check(); - return new ScannerForMSBuildExecutor().execute(this, config, adjustedProperties); + return new ScannerForMSBuildExecutor().execute(this, config, locators, adjustedProperties); } void check() { @@ -229,20 +246,4 @@ void check() { checkDotNetCoreCompatibility(scannerVersion, useDotnetCore); } - private static void checkDotNetCoreCompatibility(Version scannerVersion, boolean useDotNetCore) { - if (useDotNetCore) { - checkArgument(scannerVersion != null, "Default version of SonarScanner for MSBuild embedded by Orchestrator does not support .NET Core. " - + "Please provide a scanner version >= %s.", DOT_NET_CORE_INTRODUCTION_VERSION); - checkState(scannerVersion.isGreaterThanOrEquals(DOT_NET_CORE_INTRODUCTION_MAJOR_VERSION, DOT_NET_CORE_INTRODUCTION_MINOR_VERSION), - "Version of ScannerForMSBuild should be greater than or equals to %s to be able to use .Net Core.", - DOT_NET_CORE_INTRODUCTION_VERSION); - } - } - - private static void checkProjectDir(File dir) { - requireNonNull(dir, "Project directory must be set"); - checkArgument(dir.exists(), "Project directory must exist"); - checkArgument(dir.isDirectory(), "Project directory must be... a directory"); - } - } diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/ScannerForMSBuildExecutor.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/ScannerForMSBuildExecutor.java index a5833303..092e56cb 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/ScannerForMSBuildExecutor.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/ScannerForMSBuildExecutor.java @@ -20,6 +20,7 @@ package com.sonar.orchestrator.build; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.util.Command; import com.sonar.orchestrator.util.CommandExecutor; import com.sonar.orchestrator.util.StreamConsumer; @@ -32,8 +33,8 @@ class ScannerForMSBuildExecutor extends AbstractBuildExecutor { @Override - BuildResult execute(ScannerForMSBuild build, Configuration config, Map adjustedProperties, CommandExecutor create) { - return execute(build, config, adjustedProperties, new ScannerForMSBuildInstaller(config.locators()), create); + BuildResult execute(ScannerForMSBuild build, Configuration config, Locators locators, Map adjustedProperties, CommandExecutor create) { + return execute(build, config, adjustedProperties, new ScannerForMSBuildInstaller(locators), create); } BuildResult execute(ScannerForMSBuild build, Configuration config, Map adjustedProperties, ScannerForMSBuildInstaller installer, @@ -42,7 +43,7 @@ BuildResult execute(ScannerForMSBuild build, Configuration config, Map adjustedProperties) { + BuildResult execute(Configuration config, Locators locators, Map adjustedProperties) { check(); - return new SonarScannerExecutor().execute(this, config, adjustedProperties); + return new SonarScannerExecutor().execute(this, config, locators, adjustedProperties); } void check() { diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/SonarScannerExecutor.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/SonarScannerExecutor.java index 8160a6c2..e66110a9 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/SonarScannerExecutor.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/SonarScannerExecutor.java @@ -20,6 +20,7 @@ package com.sonar.orchestrator.build; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.util.Command; import com.sonar.orchestrator.util.CommandExecutor; import com.sonar.orchestrator.util.StreamConsumer; @@ -31,29 +32,6 @@ class SonarScannerExecutor extends AbstractBuildExecutor { private static final String SONAR_SCANNER_OPTS = "SONAR_SCANNER_OPTS"; - @Override - BuildResult execute(SonarScanner build, Configuration config, Map adjustedProperties, CommandExecutor create) { - return execute(build, config, adjustedProperties, new SonarScannerInstaller(config.locators()), create); - } - - BuildResult execute(SonarScanner build, Configuration config, Map adjustedProperties, SonarScannerInstaller installer, - CommandExecutor commandExecutor) { - BuildResult result = new BuildResult(); - File scannerScript = installer.install(build.scannerVersion(), build.classifier(), config.fileSystem().workspace()); - try { - appendCoverageArgumentToOpts(build.getEnvironmentVariables(), config, SONAR_SCANNER_OPTS); - Command command = createCommand(build, adjustedProperties, scannerScript); - LoggerFactory.getLogger(SonarScanner.class).info("Execute: {}", command); - StreamConsumer.Pipe writer = new StreamConsumer.Pipe(result.getLogsWriter()); - int status = commandExecutor.execute(command, writer, build.getTimeoutSeconds() * 1000); - result.addStatus(status); - return result; - - } catch (Exception e) { - throw new IllegalStateException("Fail to execute SonarQube Scanner", e); - } - } - private static Command createCommand(SonarScanner build, Map adjustedProperties, File runnerScript) { Command command = Command.create(runnerScript.getAbsolutePath()); command.setDirectory(build.getProjectDir()); @@ -75,4 +53,27 @@ private static Command createCommand(SonarScanner build, Map adj return command; } + @Override + BuildResult execute(SonarScanner build, Configuration config, Locators locators, Map adjustedProperties, CommandExecutor create) { + return execute(build, config, locators, adjustedProperties, new SonarScannerInstaller(locators), create); + } + + BuildResult execute(SonarScanner build, Configuration config, Locators locators, Map adjustedProperties, SonarScannerInstaller installer, + CommandExecutor commandExecutor) { + BuildResult result = new BuildResult(); + File scannerScript = installer.install(build.scannerVersion(), build.classifier(), config.fileSystem().workspace().toFile()); + try { + appendCoverageArgumentToOpts(build.getEnvironmentVariables(), config, locators, SONAR_SCANNER_OPTS); + Command command = createCommand(build, adjustedProperties, scannerScript); + LoggerFactory.getLogger(SonarScanner.class).info("Execute: {}", command); + StreamConsumer.Pipe writer = new StreamConsumer.Pipe(result.getLogsWriter()); + int status = commandExecutor.execute(command, writer, build.getTimeoutSeconds() * 1000); + result.addStatus(status); + return result; + + } catch (Exception e) { + throw new IllegalStateException("Fail to execute SonarQube Scanner", e); + } + } + } diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/SonarScannerInstaller.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/SonarScannerInstaller.java index 7fdccfe7..d3b7a997 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/SonarScannerInstaller.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/build/SonarScannerInstaller.java @@ -27,7 +27,7 @@ import java.net.URL; import javax.annotation.Nullable; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.SystemUtils; +import org.apache.commons.lang3.SystemUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/container/Server.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/container/Server.java index fa33dd0b..659ab5e7 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/container/Server.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/container/Server.java @@ -35,7 +35,7 @@ import okhttp3.HttpUrl; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import static java.nio.charset.StandardCharsets.UTF_8; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/coverage/JaCoCoArgumentsBuilder.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/coverage/JaCoCoArgumentsBuilder.java index d1808fe6..76adbc74 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/coverage/JaCoCoArgumentsBuilder.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/coverage/JaCoCoArgumentsBuilder.java @@ -20,6 +20,7 @@ package com.sonar.orchestrator.coverage; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.locator.MavenLocation; import java.io.File; import java.util.Properties; @@ -36,10 +37,6 @@ public class JaCoCoArgumentsBuilder { static String jaCoCoVersion; static MavenLocation agentLocation; - private JaCoCoArgumentsBuilder() { - // prevents instantiation - } - static { Properties props = readProperties("jacoco.properties"); jaCoCoVersion = props.getProperty("jacoco.version"); @@ -51,6 +48,10 @@ private JaCoCoArgumentsBuilder() { .build(); } + private JaCoCoArgumentsBuilder() { + // prevents instantiation + } + static Properties readProperties(String propertyFileName) { Properties props = new Properties(); try { @@ -66,7 +67,7 @@ static Properties readProperties(String propertyFileName) { * @param config * @return null if code coverage is not enabled */ - public static String getJaCoCoArgument(Configuration config) { + public static String getJaCoCoArgument(Configuration config, Locators locators) { String computeCoverage = config.getString("orchestrator.computeCoverage", "false"); if (!"true".equals(computeCoverage)) { return null; @@ -75,7 +76,7 @@ public static String getJaCoCoArgument(Configuration config) { String destFile = config.getString("orchestrator.coverageReportPath", "target/jacoco.exec"); destFile = FilenameUtils.separatorsToUnix(destFile); - File jacocoLocation = config.locators().locate(agentLocation); + File jacocoLocation = locators.locate(agentLocation); if (jacocoLocation == null) { throw new IllegalStateException("Unable to locate jacoco: " + agentLocation + " in " + config.fileSystem().mavenLocalRepository()); } diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/db/DefaultDatabase.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/db/DefaultDatabase.java index 8978b914..629bfdfe 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/db/DefaultDatabase.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/db/DefaultDatabase.java @@ -20,6 +20,7 @@ package com.sonar.orchestrator.db; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.Locators; import java.sql.Connection; import java.sql.Driver; import java.sql.DriverManager; @@ -47,8 +48,8 @@ public final class DefaultDatabase implements Database { private DatabaseClient databaseClient; private boolean started = false; - public DefaultDatabase(Configuration config) { - this.databaseClient = DatabaseFactory.create(config, config.locators()); + public DefaultDatabase(Configuration config, Locators locators) { + this.databaseClient = DatabaseFactory.create(config, locators); } public DefaultDatabase(DatabaseClient client) { @@ -316,7 +317,7 @@ private List selectOtherConnections(Connection connection) throws SQLExc } List spids = new ArrayList<>(); try (Statement stmt = connection.createStatement(); - ResultSet rs = stmt.executeQuery(sql)) { + ResultSet rs = stmt.executeQuery(sql)) { while (rs.next()) { String spid = rs.getString(1); if (!isEmpty(spid)) { diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/db/H2.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/db/H2.java index fd0136e3..af48f2f0 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/db/H2.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/db/H2.java @@ -21,7 +21,7 @@ import java.io.File; import java.net.InetAddress; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/http/HttpCall.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/http/HttpCall.java index 3f6241a4..704a7a19 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/http/HttpCall.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/http/HttpCall.java @@ -37,7 +37,7 @@ import okhttp3.Request; import okhttp3.Response; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import static com.sonar.orchestrator.container.Server.ADMIN_LOGIN; import static com.sonar.orchestrator.container.Server.ADMIN_PASSWORD; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/Licenses.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/licenses/Licenses.java similarity index 96% rename from sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/Licenses.java rename to sonar-orchestrator/src/main/java/com/sonar/orchestrator/licenses/Licenses.java index 6da67c26..61576128 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/config/Licenses.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/licenses/Licenses.java @@ -17,8 +17,9 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package com.sonar.orchestrator.config; +package com.sonar.orchestrator.licenses; +import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.container.Edition; import com.sonar.orchestrator.http.HttpClientFactory; import com.sonar.orchestrator.http.HttpResponse; @@ -26,7 +27,7 @@ import java.util.EnumMap; import java.util.Map; import okhttp3.HttpUrl; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import static com.sonar.orchestrator.util.OrchestratorUtils.defaultIfNull; import static java.lang.String.format; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/licenses/package-info.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/licenses/package-info.java new file mode 100644 index 00000000..4d093e69 --- /dev/null +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/licenses/package-info.java @@ -0,0 +1,24 @@ +/* + * Orchestrator + * Copyright (C) 2011-2025 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. + */ +@ParametersAreNonnullByDefault +package com.sonar.orchestrator.licenses; + +import javax.annotation.ParametersAreNonnullByDefault; + diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/Artifactory.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/Artifactory.java index abb6dd80..f9a8e7c3 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/Artifactory.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/Artifactory.java @@ -32,7 +32,7 @@ import javax.annotation.Nullable; import okhttp3.HttpUrl; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/ArtifactoryFactory.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/ArtifactoryFactory.java index 4a7eba24..69d83bec 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/ArtifactoryFactory.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/ArtifactoryFactory.java @@ -38,7 +38,7 @@ public class ArtifactoryFactory { *

*/ public static Artifactory createArtifactory(Configuration configuration) { - File downloadTempDir = new File(configuration.fileSystem().workspace(), "temp-downloads"); + File downloadTempDir = new File(configuration.fileSystem().workspace().toFile(), "temp-downloads"); String baseUrl = defaultIfEmpty(configuration.getStringByKeys("orchestrator.artifactory.url", "ARTIFACTORY_URL"), DEFAULT_ARTIFACTORY_URL); if (baseUrl.startsWith(DEFAULT_ARTIFACTORY_PREFIX)) { diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/DefaultArtifactory.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/DefaultArtifactory.java index f9b0bdd5..3c249a7d 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/DefaultArtifactory.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/DefaultArtifactory.java @@ -42,7 +42,7 @@ protected DefaultArtifactory(File tempDir, String baseUrl, @Nullable String acce } protected static DefaultArtifactory create(Configuration configuration) { - File downloadTempDir = new File(configuration.fileSystem().workspace(), "temp-downloads"); + File downloadTempDir = new File(configuration.fileSystem().workspace().toFile(), "temp-downloads"); String baseUrl = defaultIfEmpty(configuration.getStringByKeys("orchestrator.artifactory.url", "ARTIFACTORY_URL"), "https://repox.jfrog.io/repox"); String apiKey = configuration.getStringByKeys("orchestrator.artifactory.apiKey", "ARTIFACTORY_API_KEY"); String accessToken = configuration.getStringByKeys("orchestrator.artifactory.accessToken", "ARTIFACTORY_ACCESS_TOKEN"); diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/Locators.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/Locators.java index 94a6c2ed..236ae4e7 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/Locators.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/Locators.java @@ -19,6 +19,7 @@ */ package com.sonar.orchestrator.locator; +import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.config.FileSystem; import java.io.File; import java.io.InputStream; @@ -30,7 +31,11 @@ public class Locators { private final ResourceLocator resourceLocator; private final URLLocator urlLocator; - public Locators(FileSystem fileSystem, Artifactory artifactory) { + public Locators(Configuration configuration) { + this(configuration.fileSystem(), ArtifactoryFactory.createArtifactory(configuration)); + } + + Locators(FileSystem fileSystem, Artifactory artifactory) { fileLocator = new FileLocator(); mavenLocator = new MavenLocator(fileSystem, artifactory); resourceLocator = new ResourceLocator(); diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/MavenLocation.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/MavenLocation.java index ef93bebe..544f1204 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/MavenLocation.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/MavenLocation.java @@ -19,8 +19,8 @@ */ package com.sonar.orchestrator.locator; -import org.apache.commons.lang.ObjectUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.ObjectUtils; +import org.apache.commons.lang3.StringUtils; import static com.sonar.orchestrator.util.OrchestratorUtils.checkArgument; import static com.sonar.orchestrator.util.OrchestratorUtils.isEmpty; @@ -50,6 +50,25 @@ public MavenLocation(Builder builder) { } } + public static MavenLocation create(String groupId, String artifactId, String version) { + return builder().setGroupId(groupId).setArtifactId(artifactId).setVersion(version).build(); + } + + public static MavenLocation create(String groupId, String artifactId, String version, String classifier) { + return builder().setGroupId(groupId).setArtifactId(artifactId).setVersion(version).setClassifier(classifier).build(); + } + + /** + * @since 2.10.1. Shortcut for {@link #create(String, String, String)} + */ + public static MavenLocation of(String groupId, String artifactId, String version) { + return create(groupId, artifactId, version); + } + + public static Builder builder() { + return new Builder(); + } + public String getGroupId() { return groupId; } @@ -104,26 +123,6 @@ public String toString() { } } - public static MavenLocation create(String groupId, String artifactId, String version) { - return builder().setGroupId(groupId).setArtifactId(artifactId).setVersion(version).build(); - } - - public static MavenLocation create(String groupId, String artifactId, String version, String classifier) { - return builder().setGroupId(groupId).setArtifactId(artifactId).setVersion(version).setClassifier(classifier).build(); - } - - - /** - * @since 2.10.1. Shortcut for {@link #create(String, String, String)} - */ - public static MavenLocation of(String groupId, String artifactId, String version) { - return create(groupId, artifactId, version); - } - - public static Builder builder() { - return new Builder(); - } - public static class Builder> { private String groupId; private String artifactId; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/MavenLocator.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/MavenLocator.java index 39482c82..724afa50 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/MavenLocator.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/MavenLocator.java @@ -23,13 +23,15 @@ 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.Collection; import java.util.Optional; import javax.annotation.CheckForNull; import javax.annotation.Nullable; import org.apache.commons.codec.digest.DigestUtils; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.Strings; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -44,6 +46,14 @@ public MavenLocator(FileSystem fileSystem, Artifactory artifactory) { this.artifactory = artifactory; } + private static String pathInMavenLocalRepository(MavenLocation location) { + return Strings.CS.replace(location.getGroupId(), ".", "/") + "/" + location.getArtifactId() + "/" + location.getVersion() + "/" + location.getFilename(); + } + + static String cacheKeyOf(MavenLocation location) { + return DigestUtils.md5Hex(location.toString()); + } + @Override public File locate(MavenLocation location) { // resolve the version alias if needed (requires to be online) @@ -55,9 +65,9 @@ public File locate(MavenLocation location) { File locateResolvedVersion(MavenLocation resolvedLocation) { // check local cache String cacheKey = cacheKeyOf(resolvedLocation); - File cachedDir = new File(fileSystem.getCacheDir(), cacheKey); - if (cachedDir.exists()) { - Collection files = FileUtils.listFiles(cachedDir, null, false); + Path cachedDir = fileSystem.getCacheDir().resolve(cacheKey); + if (Files.exists(cachedDir)) { + Collection files = FileUtils.listFiles(cachedDir.toFile(), null, false); if (files.size() == 1) { File file = files.iterator().next(); LOG.info("Found {} at {}", resolvedLocation, file); @@ -77,9 +87,9 @@ File locateResolvedVersion(MavenLocation resolvedLocation) { if (resolvedLocation.getVersion().endsWith("-SNAPSHOT")) { return null; } - File cachedFile = new File(cachedDir, resolvedLocation.getFilename()); - boolean found = artifactory.downloadToFile(resolvedLocation, cachedFile); - return found ? cachedFile : null; + Path cachedFile = cachedDir.resolve(resolvedLocation.getFilename()); + boolean found = artifactory.downloadToFile(resolvedLocation, cachedFile.toFile()); + return found ? cachedFile.toFile() : null; } private MavenLocation resolveLocation(MavenLocation location) { @@ -105,10 +115,10 @@ public Optional resolveVersion(MavenLocation location) { @CheckForNull private File locateInLocalRepository(MavenLocation location) { - if (fileSystem.mavenLocalRepository() != null && fileSystem.mavenLocalRepository().exists()) { - File file = new File(fileSystem.mavenLocalRepository(), pathInMavenLocalRepository(location)); - if (file.exists()) { - return file; + if (fileSystem.mavenLocalRepository() != null && Files.exists(fileSystem.mavenLocalRepository())) { + Path file = fileSystem.mavenLocalRepository().resolve(pathInMavenLocalRepository(location)); + if (Files.exists(file)) { + return file.toFile(); } } return null; @@ -158,12 +168,4 @@ public InputStream openInputStream(MavenLocation location) { throw new IllegalStateException("Fail to open " + target, e); } } - - private static String pathInMavenLocalRepository(MavenLocation location) { - return StringUtils.replace(location.getGroupId(), ".", "/") + "/" + location.getArtifactId() + "/" + location.getVersion() + "/" + location.getFilename(); - } - - static String cacheKeyOf(MavenLocation location) { - return DigestUtils.md5Hex(location.toString()); - } } diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/ResourceLocation.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/ResourceLocation.java index 44c1cfcb..feeea8e1 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/ResourceLocation.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/ResourceLocation.java @@ -20,7 +20,7 @@ package com.sonar.orchestrator.locator; import java.net.URL; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import static com.sonar.orchestrator.util.OrchestratorUtils.checkArgument; import static java.util.Objects.requireNonNull; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/URLLocation.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/URLLocation.java index 48ce83af..16d51949 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/URLLocation.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/URLLocation.java @@ -22,7 +22,7 @@ import java.net.URISyntaxException; import java.net.URL; import javax.annotation.Nullable; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import static java.util.Objects.requireNonNull; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/URLLocator.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/URLLocator.java index 1eae5490..51fe9f6d 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/URLLocator.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/locator/URLLocator.java @@ -29,7 +29,7 @@ import javax.annotation.Nullable; import okhttp3.HttpUrl; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/server/ServerCommandLineFactory.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/server/ServerCommandLineFactory.java index 1e81ca55..c082d979 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/server/ServerCommandLineFactory.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/server/ServerCommandLineFactory.java @@ -22,6 +22,8 @@ import com.sonar.orchestrator.config.FileSystem; import com.sonar.orchestrator.container.Server; import java.io.File; +import java.nio.file.Files; +import java.nio.file.Path; import java.util.Collection; import org.apache.commons.exec.CommandLine; import org.apache.commons.io.FileUtils; @@ -56,11 +58,11 @@ public CommandLine create(Server server) { private CommandLine createJavaCommandLine() { CommandLine command; - File javaHome = fs.javaHome(); - if (javaHome == null || !javaHome.exists()) { + Path javaHome = fs.javaHome(); + if (javaHome == null || !Files.exists(javaHome)) { command = new CommandLine("java"); } else { - command = new CommandLine(FileUtils.getFile(javaHome, "bin", "java")); + command = new CommandLine(javaHome.resolve("bin/java").toFile()); } return command; } diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/server/ServerInstaller.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/server/ServerInstaller.java index 0d5ac9f5..042bb3f0 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/server/ServerInstaller.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/server/ServerInstaller.java @@ -44,7 +44,7 @@ import okhttp3.HttpUrl; import org.apache.commons.io.FileUtils; import org.apache.commons.io.filefilter.FileFilterUtils; -import org.apache.commons.lang.SystemUtils; +import org.apache.commons.lang3.SystemUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; @@ -115,7 +115,7 @@ private void preparePlugins(SonarDistribution distrib, File homeDir) { } private File unzip(Packaging packaging) { - File toDir = new File(configuration.fileSystem().workspace(), valueOf(sharedDirId.addAndGet(1))); + File toDir = new File(configuration.fileSystem().workspace().toFile(), valueOf(sharedDirId.addAndGet(1))); try { FileUtils.deleteDirectory(toDir); } catch (IOException e) { diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/Command.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/Command.java index 565aeb58..53157520 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/Command.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/Command.java @@ -27,7 +27,7 @@ import java.util.List; import java.util.Map; import java.util.stream.Collectors; -import org.apache.commons.lang.SystemUtils; +import org.apache.commons.lang3.SystemUtils; import static com.sonar.orchestrator.util.OrchestratorUtils.checkArgument; import static com.sonar.orchestrator.util.OrchestratorUtils.isEmpty; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/MavenVersionResolver.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/MavenVersionResolver.java index bb346234..2e58c935 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/MavenVersionResolver.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/MavenVersionResolver.java @@ -30,7 +30,7 @@ import java.util.stream.Collectors; import javax.annotation.Nullable; import okhttp3.HttpUrl; -import org.apache.commons.lang.StringUtils; +import org.apache.commons.lang3.StringUtils; import org.jetbrains.annotations.NotNull; import static com.sonar.orchestrator.util.OrchestratorUtils.isEmpty; diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/SharedDir.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/SharedDir.java new file mode 100644 index 00000000..d78dea6e --- /dev/null +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/SharedDir.java @@ -0,0 +1,66 @@ +/* + * Orchestrator + * Copyright (C) 2011-2025 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 com.sonar.orchestrator.util; + +import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.FileLocation; +import java.io.File; + +import static com.sonar.orchestrator.util.OrchestratorUtils.checkState; +import static java.lang.String.format; +import static java.util.Objects.requireNonNull; + +public class SharedDir { + private static final String ENV_SHARED_DIR = "SONAR_IT_SOURCES"; + private static final String PROP_SHARED_DIR = "orchestrator.it_sources"; + + private final Configuration configuration; + + public SharedDir(Configuration configuration) { + this.configuration = configuration; + } + + /** + * File located in the shared directory defined by the system property orchestrator.it_sources or environment variable SONAR_IT_SOURCES. + * Example : getFileLocationOfShared("javascript/performancing/pom.xml") + */ + public FileLocation getFileLocationOfShared(String relativePath) { + // try to read it_sources + // in the System.getProperties + // in the prop file (from orchestrator.properties file) + // in the environment variable + String rootPath; + rootPath = System.getProperty(PROP_SHARED_DIR); + if (rootPath == null) { + rootPath = configuration.getString(PROP_SHARED_DIR); + } + if (rootPath == null) { + rootPath = System.getenv(ENV_SHARED_DIR); + } + requireNonNull(rootPath, format("Property '%s' or environment variable '%s' is missing", PROP_SHARED_DIR, ENV_SHARED_DIR)); + + File rootDir = new File(rootPath); + checkState(rootDir.isDirectory() && rootDir.exists(), + "Please check the definition of it_sources (%s or %s) because the directory does not exist: %s", PROP_SHARED_DIR, ENV_SHARED_DIR, rootDir); + + return FileLocation.of(new File(rootDir, relativePath)); + } + +} diff --git a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/ZipUtils.java b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/ZipUtils.java index 33323bbc..17df3cbf 100644 --- a/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/ZipUtils.java +++ b/sonar-orchestrator/src/main/java/com/sonar/orchestrator/util/ZipUtils.java @@ -29,7 +29,7 @@ import java.util.zip.ZipFile; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; -import org.apache.commons.lang.SystemUtils; +import org.apache.commons.lang3.SystemUtils; public final class ZipUtils { private ZipUtils() { diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/AbstractBuildExecutorTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/AbstractBuildExecutorTest.java index 1d2f16e4..145ea14b 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/AbstractBuildExecutorTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/AbstractBuildExecutorTest.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMap; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.test.MockHttpServerInterceptor; import java.util.HashMap; import java.util.Map; @@ -41,7 +42,9 @@ public void shouldNotAppendCoverageArgumentToOptsByDefault() { Configuration config = Configuration.create(new HashMap()); - AbstractBuildExecutor.appendCoverageArgumentToOpts(env, config, "SONAR_OPTS"); + AbstractBuildExecutor.appendCoverageArgumentToOpts(env, config, null, "SONAR_OPTS"); + + assertThat(env).isEmpty(); } @Test @@ -53,8 +56,9 @@ public void shouldAppendCoverageArgumentToOpts() { .addProperties(singletonMap("orchestrator.computeCoverage", "true")) .addEnvVariables() .build(); + Locators locators = new Locators(config); - AbstractBuildExecutor.appendCoverageArgumentToOpts(env, config, "SONAR_OPTS"); + AbstractBuildExecutor.appendCoverageArgumentToOpts(env, config, locators, "SONAR_OPTS"); assertThat(env.get("SONAR_OPTS")).startsWith("foo -javaagent:"); } @@ -67,8 +71,9 @@ public void shouldCreateEnvironmentVariableIfNeeded() { .addProperties(singletonMap("orchestrator.computeCoverage", "true")) .addEnvVariables() .build(); + Locators locators = new Locators(config); - AbstractBuildExecutor.appendCoverageArgumentToOpts(env, config, "SONAR_OPTS"); + AbstractBuildExecutor.appendCoverageArgumentToOpts(env, config, locators, "SONAR_OPTS"); assertThat(env.get("SONAR_OPTS")).startsWith("-javaagent:"); } diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/AntBuildExecutorTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/AntBuildExecutorTest.java index 1c59be37..9c794666 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/AntBuildExecutorTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/AntBuildExecutorTest.java @@ -21,6 +21,7 @@ import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.locator.FileLocation; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.util.Command; import com.sonar.orchestrator.util.CommandExecutor; import com.sonar.orchestrator.util.StreamConsumer; @@ -51,7 +52,8 @@ public void execute_command() { CommandExecutor executor = mock(CommandExecutor.class); when(executor.execute(any(Command.class), any(StreamConsumer.class), anyLong())).thenReturn(2); - new AntBuildExecutor().execute(build, Configuration.create(), props, executor); + Configuration config = Configuration.create(); + new AntBuildExecutor().execute(build, config, new Locators(config), props, executor); verify(executor).execute(argThat(c -> c.toCommandLine().contains("ant") && c.toCommandLine().contains("-f") && diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/BuildRunnerTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/BuildRunnerTest.java index 435176a9..56f68634 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/BuildRunnerTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/BuildRunnerTest.java @@ -35,6 +35,7 @@ import static org.mockito.ArgumentMatchers.any; import static org.mockito.ArgumentMatchers.anyMap; import static org.mockito.ArgumentMatchers.eq; +import static org.mockito.ArgumentMatchers.isNull; import static org.mockito.Mockito.mock; import static org.mockito.Mockito.verify; import static org.mockito.Mockito.when; @@ -53,12 +54,12 @@ public void inject_server_properties() { Build build = mock(Build.class); when(build.getProperties()).thenReturn(ImmutableMap.of("sonar.projectKey", "SAMPLE", "language", "java")); - BuildRunner runner = new BuildRunner(config); + BuildRunner runner = new BuildRunner(config, null); runner.runQuietly(server, build); ArgumentCaptor captor = ArgumentCaptor.forClass(Map.class); - verify(build).execute(eq(config), captor.capture()); + verify(build).execute(eq(config), isNull(), captor.capture()); assertThat(captor.getValue()).containsOnly( entry("sonar.projectKey", "SAMPLE"), @@ -77,12 +78,12 @@ public void inject_properties_for_msbuild_start() { Build build = mock(ScannerForMSBuild.class); when(build.getProperties()).thenReturn(ImmutableMap.of("sonar.projectKey", "SAMPLE", "language", "java")); - BuildRunner runner = new BuildRunner(config); + BuildRunner runner = new BuildRunner(config, null); runner.runQuietly(server, build); ArgumentCaptor captor = ArgumentCaptor.forClass(Map.class); - verify(build).execute(eq(config), captor.capture()); + verify(build).execute(eq(config), isNull(), captor.capture()); assertThat(captor.getValue()).containsOnly( entry("sonar.projectKey", "SAMPLE"), @@ -101,12 +102,12 @@ public void dont_inject_properties_for_msbuild_end() { Build build = mock(ScannerForMSBuild.class); when(build.arguments()).thenReturn(Arrays.asList("end")); - BuildRunner runner = new BuildRunner(config); + BuildRunner runner = new BuildRunner(config, null); runner.runQuietly(server, build); ArgumentCaptor captor = ArgumentCaptor.forClass(Map.class); - verify(build).execute(eq(config), captor.capture()); + verify(build).execute(eq(config), isNull(), captor.capture()); assertThat(captor.getValue()).isEmpty(); @@ -118,9 +119,9 @@ public void runQuietly() { Server server = mock(Server.class); when(server.version()).thenReturn(Version.create("5.6")); Build build = mock(Build.class); - when(build.execute(any(Configuration.class), anyMap())).thenReturn(new BuildResult().addStatus(2)); + when(build.execute(any(Configuration.class), any(), anyMap())).thenReturn(new BuildResult().addStatus(2)); - BuildRunner runner = new BuildRunner(config); + BuildRunner runner = new BuildRunner(config, null); BuildResult result = runner.runQuietly(server, build); assertThat(result.getLastStatus()).isEqualTo(2); @@ -137,9 +138,9 @@ public void throw_exception_if_run_fails() { Configuration config = Configuration.create(); Server server = mock(Server.class); when(server.version()).thenReturn(Version.create("5.6")); - when(build.execute(any(Configuration.class), anyMap())).thenReturn(new BuildResult().addStatus(2)); + when(build.execute(any(Configuration.class), any(), anyMap())).thenReturn(new BuildResult().addStatus(2)); - BuildRunner runner = new BuildRunner(config); + BuildRunner runner = new BuildRunner(config, null); runner.run(server, build); } catch (BuildFailureException e) { @@ -162,9 +163,9 @@ public void throw_exception_if_any_run_fails() { Configuration config = Configuration.create(); Server server = mock(Server.class); when(server.version()).thenReturn(Version.create("5.6")); - when(build.execute(any(Configuration.class), anyMap())).thenReturn(new BuildResult().addStatus(2).addStatus(0)); + when(build.execute(any(Configuration.class), any(), anyMap())).thenReturn(new BuildResult().addStatus(2).addStatus(0)); - BuildRunner runner = new BuildRunner(config); + BuildRunner runner = new BuildRunner(config, null); runner.run(server, build); } catch (BuildFailureException e) { @@ -183,9 +184,9 @@ public void return_status_zero_if_run_passes() { Server server = mock(Server.class); when(server.version()).thenReturn(Version.create("5.6")); Build build = mock(Build.class); - when(build.execute(any(Configuration.class), anyMap())).thenReturn(new BuildResult().addStatus(0)); + when(build.execute(any(Configuration.class), any(), anyMap())).thenReturn(new BuildResult().addStatus(0)); - BuildRunner runner = new BuildRunner(config); + BuildRunner runner = new BuildRunner(config, null); BuildResult result = runner.run(server, build); assertThat(result.isSuccess()).isTrue(); diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/BuildTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/BuildTest.java index bebe802f..b9366538 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/BuildTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/BuildTest.java @@ -21,6 +21,7 @@ import com.google.common.collect.ImmutableMap; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.Locators; import java.util.Arrays; import java.util.Map; import org.assertj.core.data.MapEntry; @@ -141,7 +142,7 @@ protected Map doGetEnvironmentVariablePrefixes() { static class FakeBuild extends Build { @Override - BuildResult execute(Configuration config, Map adjustedProperties) { + BuildResult execute(Configuration config, Locators locators, Map adjustedProperties) { return null; } } diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/FakeBuild.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/FakeBuild.java index 2608aa92..2c7cb32a 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/FakeBuild.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/FakeBuild.java @@ -20,6 +20,7 @@ package com.sonar.orchestrator.build; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.Locators; import java.util.Map; public class FakeBuild extends Build { @@ -35,7 +36,7 @@ public static FakeBuild create(BuildResult result) { } @Override - BuildResult execute(Configuration config, Map adjustedProperties) { + BuildResult execute(Configuration config, Locators locators, Map adjustedProperties) { return result; } } diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/GradleBuildExecutorTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/GradleBuildExecutorTest.java index b94006f9..d2ff8e30 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/GradleBuildExecutorTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/GradleBuildExecutorTest.java @@ -22,6 +22,7 @@ import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.locator.FileLocation; import com.sonar.orchestrator.locator.Location; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.util.Command; import com.sonar.orchestrator.util.CommandExecutor; import com.sonar.orchestrator.util.StreamConsumer; @@ -59,7 +60,8 @@ public void execute_unix() { GradleBuildExecutor.Os os = mock(GradleBuildExecutor.Os.class); when(os.isWindows()).thenReturn(false); - new GradleBuildExecutor(os).execute(build, Configuration.create(), props, executor); + Configuration config = Configuration.create(); + new GradleBuildExecutor(os).execute(build, config, new Locators(config), props, executor); verify(executor).execute(argThat(gradlewMatcher(projectDir.getFile(), "gradlew", "clean")), any(), eq(30000L)); verify(executor).execute(argThat(gradlewMatcher(projectDir.getFile(), "gradlew", "sonarqube")), any(), eq(30000L)); @@ -82,7 +84,8 @@ public void execute_windows() { GradleBuildExecutor.Os os = mock(GradleBuildExecutor.Os.class); when(os.isWindows()).thenReturn(true); - new GradleBuildExecutor(os).execute(build, Configuration.create(), props, executor); + Configuration config = Configuration.create(); + new GradleBuildExecutor(os).execute(build, config, new Locators(config), props, executor); verify(executor).execute(argThat(gradlewMatcher(projectDir.getFile(), "gradlew.bat", "clean")), any(), eq(30000L)); verify(executor).execute(argThat(gradlewMatcher(projectDir.getFile(), "gradlew.bat", "sonarqube")), any(), eq(30000L)); @@ -107,6 +110,7 @@ public void execute_invalid_path() { .setTasks("clean", "sonarqube"); CommandExecutor executor = mock(CommandExecutor.class); - new GradleBuildExecutor().execute(build, Configuration.create(), new HashMap<>(), executor); + Configuration config = Configuration.create(); + new GradleBuildExecutor().execute(build, config, new Locators(config), new HashMap<>(), executor); } } diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/MavenBuildExecutorTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/MavenBuildExecutorTest.java index 5314ff8c..8d5caac5 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/MavenBuildExecutorTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/MavenBuildExecutorTest.java @@ -22,6 +22,7 @@ import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.locator.FileLocation; import com.sonar.orchestrator.locator.Location; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.util.Command; import com.sonar.orchestrator.util.CommandExecutor; import java.io.File; @@ -45,10 +46,10 @@ public class MavenBuildExecutorTest { - @Rule - public TemporaryFolder temp = new TemporaryFolder(); private final MavenBuildExecutor.Os os = mock(MavenBuildExecutor.Os.class); private final MavenBuildExecutor underTest = new MavenBuildExecutor(os); + @Rule + public TemporaryFolder temp = new TemporaryFolder(); @Test public void configure_command_in_PATH_on_linux() throws Exception { @@ -180,7 +181,8 @@ public void shouldStoreLogs() { Location pom = FileLocation.of(getClass().getResource("/com/sonar/orchestrator/build/MavenBuildTest/pom.xml")); MavenBuild build = MavenBuild.create(pom).addGoal("clean"); - BuildResult result = new MavenBuildExecutor().execute(build, Configuration.createEnv(), new HashMap<>()); + Configuration config = Configuration.createEnv(); + BuildResult result = new MavenBuildExecutor().execute(build, config, new Locators(config), new HashMap<>()); assertThat(result.getLogs().length()).isGreaterThan(0); assertThat(result.getLogs()).containsSubsequence("[INFO] Scanning for projects...", "[INFO] Total time"); @@ -193,7 +195,8 @@ public void shouldPassAdditionalArguments() { Location pom = FileLocation.of(getClass().getResource("/com/sonar/orchestrator/build/MavenBuildTest/pom.xml")); MavenBuild build = MavenBuild.create(pom).addGoal("clean").addArguments("-PnotExists"); - BuildResult result = new MavenBuildExecutor().execute(build, Configuration.createEnv(), new HashMap<>()); + Configuration config = Configuration.createEnv(); + BuildResult result = new MavenBuildExecutor().execute(build, config, new Locators(config), new HashMap<>()); assertThat(result.getLogs().length()).isGreaterThan(0); assertThat(result.getLogs()).contains("[WARNING] The requested profile \"notExists\" could not be activated because it does not exist."); @@ -213,7 +216,8 @@ public void execute_command() throws Exception { CommandExecutor executor = mock(CommandExecutor.class); when(executor.execute(any(), any(), anyLong())).thenReturn(2); - new MavenBuildExecutor().execute(build, Configuration.create(), props, executor); + Configuration config = Configuration.create(); + new MavenBuildExecutor().execute(build, config, new Locators(config), props, executor); verify(executor).execute(argThat(mvnMatcher(pom, "clean")), any(), eq(30000L)); verify(executor).execute(argThat(mvnMatcher(pom, "sonar:sonar")), any(), eq(30000L)); diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/SonarScannerExecutorTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/SonarScannerExecutorTest.java index bab27292..63355a15 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/SonarScannerExecutorTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/build/SonarScannerExecutorTest.java @@ -56,7 +56,7 @@ public void execute_command() { CommandExecutor executor = mock(CommandExecutor.class); when(executor.execute(any(Command.class), any(StreamConsumer.class), anyLong())).thenReturn(2); - new SonarScannerExecutor().execute(build, Configuration.create(), props, installer, executor); + new SonarScannerExecutor().execute(build, Configuration.create(), null, props, installer, executor); verify(executor).execute(argThat(c -> c.getDirectory().equals(new File(".")) && c.toCommandLine().contains("sonar-runner") @@ -79,7 +79,7 @@ public void execute_command_with_additional_args() { CommandExecutor executor = mock(CommandExecutor.class); when(executor.execute(any(Command.class), any(StreamConsumer.class), anyLong())).thenReturn(2); - new SonarScannerExecutor().execute(build, Configuration.create(), props, installer, executor); + new SonarScannerExecutor().execute(build, Configuration.create(), null, props, installer, executor); verify(executor).execute(argThat(c -> c.getDirectory().equals(new File(".")) && c.toCommandLine().contains("sonar-scanner.sh") @@ -100,7 +100,7 @@ public void execute_native() { CommandExecutor executor = mock(CommandExecutor.class); - new SonarScannerExecutor().execute(build, Configuration.create(), props, installer, executor); + new SonarScannerExecutor().execute(build, Configuration.create(), null, props, installer, executor); verify(installer).install(eq(build.scannerVersion()), eq(classifier), any()); } } diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/coverage/JaCoCoArgumentsBuilderTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/coverage/JaCoCoArgumentsBuilderTest.java index b84bc103..12cc40da 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/coverage/JaCoCoArgumentsBuilderTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/coverage/JaCoCoArgumentsBuilderTest.java @@ -20,6 +20,7 @@ package com.sonar.orchestrator.coverage; import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.Locators; import com.sonar.orchestrator.test.MockHttpServerInterceptor; import java.io.File; import java.io.IOException; @@ -42,11 +43,6 @@ public class JaCoCoArgumentsBuilderTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); - @Test - public void all_constructors_are_private() { - assertThat(hasOnlyPrivateConstructors(JaCoCoArgumentsBuilder.class)).isTrue(); - } - /** * Asserts that all constructors are private, usually for helper classes with * only static methods. If a constructor does not have any parameters, then @@ -68,6 +64,11 @@ private static boolean hasOnlyPrivateConstructors(Class clazz) { return ok; } + @Test + public void all_constructors_are_private() { + assertThat(hasOnlyPrivateConstructors(JaCoCoArgumentsBuilder.class)).isTrue(); + } + @Test public void shouldGetJaCoCoVersionFromPom() { assertThat(JaCoCoArgumentsBuilder.jaCoCoVersion).isNotEmpty(); @@ -77,7 +78,7 @@ public void shouldGetJaCoCoVersionFromPom() { public void shouldReturnNullByDefault() { Configuration config = Configuration.create(new HashMap<>()); - assertThat(JaCoCoArgumentsBuilder.getJaCoCoArgument(config)).isNull(); + assertThat(JaCoCoArgumentsBuilder.getJaCoCoArgument(config, new Locators(config))).isNull(); } @Test(expected = IllegalStateException.class) @@ -96,7 +97,7 @@ public void shouldReturnJaCoCoArgument() throws IOException { .addEnvVariables() .build(); - String argument = JaCoCoArgumentsBuilder.getJaCoCoArgument(config); + String argument = JaCoCoArgumentsBuilder.getJaCoCoArgument(config, new Locators(config)); assertThat(argument).matches("-javaagent:.*=destfile=" + Matcher.quoteReplacement(FilenameUtils.separatorsToUnix(output.getAbsolutePath())) + diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/db/DatabaseFactoryTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/db/DatabaseFactoryTest.java index 7d189d90..f7ed62e9 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/db/DatabaseFactoryTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/db/DatabaseFactoryTest.java @@ -46,7 +46,7 @@ public void shouldUseDatabaseProperties() { .setProperty("sonar.jdbc.password", "password") .setProperty("sonar.jdbc.rootUsername", "new_root") .setProperty("sonar.jdbc.rootPassword", "new_pass") - .setProperty("sonar.jdbc.driverFile", driverFile) + .setProperty("sonar.jdbc.driverFile", driverFile.toPath()) .setProperty("orchestrator.keepDatabase", "yes") .build(); diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/config/LicensesTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/licenses/LicensesTest.java similarity index 97% rename from sonar-orchestrator/src/test/java/com/sonar/orchestrator/config/LicensesTest.java rename to sonar-orchestrator/src/test/java/com/sonar/orchestrator/licenses/LicensesTest.java index 2b70860e..f462fc78 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/config/LicensesTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/licenses/LicensesTest.java @@ -17,8 +17,9 @@ * along with this program; if not, write to the Free Software Foundation, * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. */ -package com.sonar.orchestrator.config; +package com.sonar.orchestrator.licenses; +import com.sonar.orchestrator.config.Configuration; import com.sonar.orchestrator.container.Edition; import com.sonar.orchestrator.version.Version; import okhttp3.mockwebserver.MockResponse; @@ -29,7 +30,6 @@ import org.junit.rules.ExpectedException; import static org.assertj.core.api.Assertions.assertThat; -import static org.assertj.core.api.Assertions.catchThrowable; public class LicensesTest { diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/locator/MavenLocatorTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/locator/MavenLocatorTest.java index 0e507c48..d1d83245 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/locator/MavenLocatorTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/locator/MavenLocatorTest.java @@ -23,6 +23,7 @@ import java.io.File; import java.io.IOException; import java.io.InputStream; +import java.nio.charset.StandardCharsets; import java.util.Optional; import org.apache.commons.io.FileUtils; import org.apache.commons.io.IOUtils; @@ -41,23 +42,22 @@ public class MavenLocatorTest { + private final FileSystem fileSystem = mock(FileSystem.class, Mockito.RETURNS_DEEP_STUBS); + private final Artifactory artifactory = mock(Artifactory.class, Mockito.RETURNS_DEEP_STUBS); + private final MavenLocator underTest = new MavenLocator(fileSystem, artifactory); @Rule public TemporaryFolder temp = new TemporaryFolder(); - private FileSystem fileSystem = mock(FileSystem.class, Mockito.RETURNS_DEEP_STUBS); - private Artifactory artifactory = mock(Artifactory.class, Mockito.RETURNS_DEEP_STUBS); - private MavenLocator underTest = new MavenLocator(fileSystem, artifactory); - @Before public void setUp() throws Exception { File cacheDir = temp.newFolder(); - when(fileSystem.getCacheDir()).thenReturn(cacheDir); + when(fileSystem.getCacheDir()).thenReturn(cacheDir.toPath()); } @Test public void find_in_cache() throws Exception { MavenLocation location = MavenLocation.of("foo", "bar", "1.0"); - File cachedFile = new File(fileSystem.getCacheDir() + File.separator + MavenLocator.cacheKeyOf(location), "the_file.jar"); + File cachedFile = fileSystem.getCacheDir().resolve(MavenLocator.cacheKeyOf(location)).resolve("the_file.jar").toFile(); FileUtils.touch(cachedFile); File file = underTest.locateResolvedVersion(location); @@ -70,7 +70,7 @@ public void find_in_cache() throws Exception { public void find_in_maven_local_repository_if_defined() throws IOException { File localRepository = temp.newFolder(); FileUtils.touch(new File(localRepository, "foo/bar/1.0/bar-1.0.jar")); - when(fileSystem.mavenLocalRepository()).thenReturn(localRepository); + when(fileSystem.mavenLocalRepository()).thenReturn(localRepository.toPath()); markAsAbsentFromArtifactory(); File file = underTest.locateResolvedVersion(MavenLocation.of("foo", "bar", "1.0")); @@ -85,7 +85,7 @@ public void find_in_maven_local_repository_if_defined() throws IOException { public void search_but_not_find_in_maven_local_repository_if_defined() throws IOException { File localRepository = temp.newFolder(); FileUtils.touch(new File(localRepository, "foo/bar/1.0/bar-1.0.jar")); - when(fileSystem.mavenLocalRepository()).thenReturn(localRepository); + when(fileSystem.mavenLocalRepository()).thenReturn(localRepository.toPath()); markAsAbsentFromArtifactory(); File file = underTest.locateResolvedVersion(MavenLocation.of("foo", "bar", "1.1")); @@ -97,7 +97,7 @@ public void search_but_not_find_in_maven_local_repository_if_defined() throws IO public void download_from_artifactory_and_add_to_cache() throws Exception { when(artifactory.downloadToFile(any(), any())).thenAnswer((Answer) invocationOnMock -> { File file = (File) invocationOnMock.getArguments()[1]; - FileUtils.write(file, "content of file"); + FileUtils.write(file, "content of file", StandardCharsets.UTF_8); return true; }); @@ -105,12 +105,13 @@ public void download_from_artifactory_and_add_to_cache() throws Exception { assertThat(file) .exists() .isFile() + .usingCharset(StandardCharsets.UTF_8) .hasContent("content of file"); - assertThat(file.getCanonicalPath()).startsWith(fileSystem.getCacheDir().getCanonicalPath()); + assertThat(file.getAbsolutePath()).startsWith(fileSystem.getCacheDir().toFile().getCanonicalPath()); } private void verifyEmptyCache() { - assertThat(FileUtils.listFiles(fileSystem.getCacheDir(), null, true)).hasSize(0); + assertThat(fileSystem.getCacheDir()).isEmptyDirectory(); } private void markAsAbsentFromArtifactory() { @@ -149,7 +150,7 @@ public void copyToDirectory_returns_null_if_artifact_not_found() throws IOExcept File result = underTest.copyToDirectory(location, toDir); assertThat(result).isNull(); - assertThat(toDir.listFiles()).isEmpty(); + assertThat(toDir).isEmptyDirectory(); } @Test @@ -182,12 +183,12 @@ public void copyToFile_returns_null_if_artifact_not_found() throws IOException { public void openInputStream_existing_artifact() throws IOException { MavenLocation location = MavenLocation.of("foo", "bar", "1.0"); File cachedFile = new File(fileSystem.getCacheDir() + File.separator + MavenLocator.cacheKeyOf(location), "the_file.jar"); - FileUtils.write(cachedFile, "content"); + FileUtils.write(cachedFile, "content", StandardCharsets.UTF_8); markVersionsAsResolved(); try (InputStream result = underTest.openInputStream(location)) { assertThat(result).isNotNull(); - assertThat(IOUtils.toString(result)).isEqualTo("content"); + assertThat(IOUtils.toString(result, StandardCharsets.UTF_8)).isEqualTo("content"); } } @@ -198,9 +199,4 @@ public void openInputStream_returns_null_if_artifact_not_found() { assertThat(underTest.openInputStream(location)).isNull(); } - - @Test - public void resolveVersion() { - - } } diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/server/ServerCommandLineFactoryTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/server/ServerCommandLineFactoryTest.java index 0c6f22b7..b5702251 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/server/ServerCommandLineFactoryTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/server/ServerCommandLineFactoryTest.java @@ -62,7 +62,7 @@ public void create_command_line() throws Exception { public void override_java_home() throws Exception { generateValidFileSystem(); File javaHome = temp.newFolder(); - when(fs.javaHome()).thenReturn(javaHome); + when(fs.javaHome()).thenReturn(javaHome.toPath()); ServerCommandLineFactory underTest = new ServerCommandLineFactory(fs); diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/util/CommandExecutorTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/util/CommandExecutorTest.java index b3331c01..833656ae 100644 --- a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/util/CommandExecutorTest.java +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/util/CommandExecutorTest.java @@ -30,7 +30,7 @@ import java.util.Properties; import java.util.Set; import org.apache.commons.io.FileUtils; -import org.apache.commons.lang.SystemUtils; +import org.apache.commons.lang3.SystemUtils; import org.junit.Before; import org.junit.Rule; import org.junit.Test; diff --git a/sonar-orchestrator/src/test/java/com/sonar/orchestrator/util/SharedDirTest.java b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/util/SharedDirTest.java new file mode 100644 index 00000000..97360fcd --- /dev/null +++ b/sonar-orchestrator/src/test/java/com/sonar/orchestrator/util/SharedDirTest.java @@ -0,0 +1,103 @@ +/* + * Orchestrator + * Copyright (C) 2011-2025 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 com.sonar.orchestrator.util; + +import com.google.common.collect.ImmutableMap; +import com.sonar.orchestrator.PropertyAndEnvTest; +import com.sonar.orchestrator.config.Configuration; +import com.sonar.orchestrator.locator.FileLocation; +import java.net.URISyntaxException; +import java.net.URL; +import java.util.HashMap; +import java.util.Map; +import java.util.Properties; +import org.apache.commons.io.FilenameUtils; +import org.junit.Rule; +import org.junit.Test; +import org.junit.rules.ExpectedException; + +import static com.sonar.orchestrator.TestModules.setEnv; +import static org.assertj.core.api.Assertions.assertThat; + +public class SharedDirTest extends PropertyAndEnvTest { + + @Rule + public ExpectedException thrown = ExpectedException.none(); + + @Test + public void getFileLocationOfShared() throws URISyntaxException { + URL url = getClass().getResource("/com/sonar/orchestrator/util/SharedDirTest/sample.properties"); + Properties props = new Properties(); + props.setProperty("orchestrator.configUrl", url.toString()); + props.setProperty("orchestrator.it_sources", FilenameUtils.getFullPath(url.toURI().getPath())); + Configuration config = Configuration.create(props); + SharedDir underTest = new SharedDir(config); + + FileLocation location = underTest.getFileLocationOfShared("sample.properties"); + assertThat(location.getFile()).isFile(); + assertThat(location.getFile()).exists(); + assertThat(location.getFile().getName()).isEqualTo("sample.properties"); + } + + @Test + public void getFileLocationOfSharedApplyPriority() throws URISyntaxException { + URL url = getClass().getResource("/com/sonar/orchestrator/util/SharedDirTest/sample.properties"); + Properties props = new Properties(); + props.setProperty("orchestrator.configUrl", url.toString()); + Map envVariables = new HashMap<>(System.getenv()); + envVariables.put("SONAR_IT_SOURCES", FilenameUtils.getFullPath(url.toURI().getPath())); + setEnv(ImmutableMap.copyOf(envVariables)); + props.setProperty("orchestrator.it_sources", FilenameUtils.getFullPath(url.toURI().getPath())); + Configuration config = Configuration.create(props); + SharedDir underTest = new SharedDir(config); + + FileLocation location = underTest.getFileLocationOfShared("sample.properties"); + assertThat(location.getFile().exists()).isTrue(); + } + + @Test + public void getFileLocationOfShared_bad_place() { + thrown.expect(IllegalStateException.class); + + URL url = getClass().getResource("/com/sonar/orchestrator/util/SharedDirTest/sample.properties"); + Properties props = new Properties(); + props.setProperty("orchestrator.configUrl", url.toString()); + props.setProperty("orchestrator.it_sources", "/com/sonar/orchestrator/util/SharedDirTest"); + Configuration config = Configuration.create(props); + SharedDir underTest = new SharedDir(config); + + underTest.getFileLocationOfShared("/bad/path"); + } + + @Test + public void getFileLocationOfShared_not_a_directory() { + thrown.expect(IllegalStateException.class); + + URL url = getClass().getResource("/com/sonar/orchestrator/util/SharedDirTest/sample.properties"); + Properties props = new Properties(); + props.setProperty("orchestrator.configUrl", url.toString()); + props.setProperty("orchestrator.it_sources", "/com/sonar/orchestrator/util/SharedDirTest/sample.properties"); + Configuration config = Configuration.create(props); + SharedDir underTest = new SharedDir(config); + + underTest.getFileLocationOfShared("."); + } + +} diff --git a/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/java/fake.txt b/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/java/fake.txt deleted file mode 100644 index f0f877ce..00000000 --- a/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/java/fake.txt +++ /dev/null @@ -1 +0,0 @@ -fake \ No newline at end of file diff --git a/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/maven/bin/fake.cmd b/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/maven/bin/fake.cmd deleted file mode 100644 index db723e46..00000000 --- a/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/maven/bin/fake.cmd +++ /dev/null @@ -1 +0,0 @@ -echo Fake script for Maven binary detection \ No newline at end of file diff --git a/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/maven/fake.txt b/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/maven/fake.txt deleted file mode 100644 index f0f877ce..00000000 --- a/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/maven/fake.txt +++ /dev/null @@ -1 +0,0 @@ -fake \ No newline at end of file diff --git a/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/maven/repository/repository.xml b/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/maven/repository/repository.xml deleted file mode 100644 index 75a263db..00000000 --- a/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/config/FileSystemTest/maven/repository/repository.xml +++ /dev/null @@ -1 +0,0 @@ - \ No newline at end of file diff --git a/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/util/SharedDirTest/sample.properties b/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/util/SharedDirTest/sample.properties new file mode 100644 index 00000000..267aa822 --- /dev/null +++ b/sonar-orchestrator/src/test/resources/com/sonar/orchestrator/util/SharedDirTest/sample.properties @@ -0,0 +1,2 @@ +yes=true +loadedFromFile=${yes} \ No newline at end of file