Skip to content

Commit f5e8019

Browse files
committed
SCANJLIB-221 Fallback to local JRE if no result from server
1 parent b9b0d0e commit f5e8019

11 files changed

Lines changed: 43 additions & 45 deletions

File tree

lib/src/main/java/org/sonarsource/scanner/lib/InProcessScannerEngineFacade.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import javax.annotation.Nullable;
2424
import org.sonarsource.scanner.lib.internal.IsolatedLauncherFactory;
2525

26-
public class InProcessScannerEngineFacade extends ScannerEngineFacade {
26+
class InProcessScannerEngineFacade extends ScannerEngineFacade {
2727
private final IsolatedLauncherFactory.IsolatedLauncherAndClassloader launcherAndCl;
2828

2929
InProcessScannerEngineFacade(Map<String, String> bootstrapProperties, IsolatedLauncherFactory.IsolatedLauncherAndClassloader launcherAndCl,

lib/src/main/java/org/sonarsource/scanner/lib/NewScannerEngineFacade.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,7 @@
2323
import javax.annotation.Nullable;
2424
import org.sonarsource.scanner.lib.internal.ScannerEngineLauncher;
2525

26-
public class NewScannerEngineFacade extends ScannerEngineFacade {
26+
class NewScannerEngineFacade extends ScannerEngineFacade {
2727
private final ScannerEngineLauncher launcher;
2828

2929
NewScannerEngineFacade(Map<String, String> bootstrapProperties, ScannerEngineLauncher launcher, LogOutput logOutput,

lib/src/main/java/org/sonarsource/scanner/lib/ScannerEngineBootstrapper.java

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -33,6 +33,7 @@
3333
import org.sonarsource.scanner.lib.internal.InternalProperties;
3434
import org.sonarsource.scanner.lib.internal.IsolatedLauncherFactory;
3535
import org.sonarsource.scanner.lib.internal.OsResolver;
36+
import org.sonarsource.scanner.lib.internal.Paths2;
3637
import org.sonarsource.scanner.lib.internal.ScannerEngineLauncherFactory;
3738
import org.sonarsource.scanner.lib.internal.cache.FileCache;
3839
import org.sonarsource.scanner.lib.internal.cache.Logger;

lib/src/main/java/org/sonarsource/scanner/lib/SimulationScannerEngineFacade.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
import javax.annotation.Nullable;
3232
import org.sonarsource.scanner.lib.internal.InternalProperties;
3333

34-
public class SimulationScannerEngineFacade extends ScannerEngineFacade {
34+
class SimulationScannerEngineFacade extends ScannerEngineFacade {
3535

3636
SimulationScannerEngineFacade(Map<String, String> bootstrapProperties, LogOutput logOutput, boolean isSonarCloud,
3737
@Nullable String serverVersion) {

lib/src/main/java/org/sonarsource/scanner/lib/internal/JavaRunner.java

Lines changed: 4 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -42,7 +42,7 @@ public class JavaRunner {
4242
private final Logger logger;
4343
private final JreCacheHit jreCacheHit;
4444

45-
public JavaRunner(@Nullable Path javaExecutable, Logger logger, JreCacheHit jreCacheHit) {
45+
public JavaRunner(Path javaExecutable, Logger logger, JreCacheHit jreCacheHit) {
4646
this.javaExecutable = javaExecutable;
4747
this.logger = logger;
4848
this.jreCacheHit = jreCacheHit;
@@ -55,7 +55,7 @@ public JreCacheHit getJreCacheHit() {
5555
public void execute(List<String> args, @Nullable String input) {
5656
try {
5757
List<String> command = new ArrayList<>(args);
58-
command.add(0, getJavaExecutable());
58+
command.add(0, javaExecutable.toString());
5959
Process process = new ProcessBuilder(command).start();
6060
if (input != null) {
6161
try (OutputStream stdin = process.getOutputStream();
@@ -74,12 +74,8 @@ public void execute(List<String> args, @Nullable String input) {
7474
}
7575
}
7676

77-
String getJavaExecutable() {
78-
if (javaExecutable != null) {
79-
return javaExecutable.toAbsolutePath().toString();
80-
}
81-
// Will try to use the java executable in the PATH
82-
return "java";
77+
public Path getJavaExecutable() {
78+
return javaExecutable;
8379
}
8480

8581
void tryParse(String stdout) {

lib/src/main/java/org/sonarsource/scanner/lib/internal/JavaRunnerFactory.java

Lines changed: 17 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -34,6 +34,7 @@
3434
import java.util.ArrayList;
3535
import java.util.List;
3636
import java.util.Map;
37+
import java.util.Optional;
3738
import javax.annotation.Nullable;
3839
import org.apache.commons.lang3.StringUtils;
3940
import org.apache.commons.lang3.SystemUtils;
@@ -77,32 +78,38 @@ public JavaRunner createRunner(ServerConnection serverConnection, FileCache file
7778
logger.info("JRE provisioning is disabled");
7879
} else {
7980
var cachedFile = getJreFromServer(serverConnection, fileCache, properties, true);
80-
// TODO catch exception and fallback to system java
81-
return new JavaRunner(cachedFile.getPathInCache(), logger, cachedFile.isCacheHit() ? JreCacheHit.HIT : JreCacheHit.MISS);
81+
if (cachedFile.isPresent()) {
82+
return new JavaRunner(cachedFile.get().getPathInCache(), logger, cachedFile.get().isCacheHit() ? JreCacheHit.HIT : JreCacheHit.MISS);
83+
}
8284
}
8385
String javaHome = system.getEnvironmentVariable("JAVA_HOME");
86+
var javaExe = "java" + (SystemUtils.IS_OS_WINDOWS ? ".exe" : "");
8487
if (javaHome != null) {
85-
var javaExecutable = Paths.get(javaHome, "bin", "java" + (SystemUtils.IS_OS_WINDOWS ? ".exe" : ""));
88+
var javaExecutable = Paths.get(javaHome, "bin", javaExe);
8689
if (Files.exists(javaExecutable)) {
8790
logger.info(format("Using the java executable '%s' from JAVA_HOME", javaExecutable));
8891
return new JavaRunner(javaExecutable, logger, JreCacheHit.DISABLED);
8992
}
9093
}
9194
logger.info("The java executable in the PATH will be used");
92-
return new JavaRunner(null, logger, JreCacheHit.DISABLED);
95+
return new JavaRunner(Paths.get(javaExe), logger, JreCacheHit.DISABLED);
9396
}
9497

95-
private CachedFile getJreFromServer(ServerConnection serverConnection, FileCache fileCache, Map<String, String> properties, boolean retry) {
98+
private Optional<CachedFile> getJreFromServer(ServerConnection serverConnection, FileCache fileCache, Map<String, String> properties, boolean retry) {
9699
String os = properties.get(SCANNER_OS);
97100
String arch = properties.get(SCANNER_ARCH);
98101
logger.info(format("JRE provisioning: os[%s], arch[%s]", os, arch));
99102

100103
try {
101104
var jreMetadata = getJreMetadata(serverConnection, os, arch);
102-
var cachedFile = fileCache.getOrDownload(jreMetadata.getFilename(), jreMetadata.getSha256(), "SHA-256",
103-
new JreDownloader(serverConnection, jreMetadata));
105+
if (jreMetadata.isEmpty()) {
106+
logger.info("No JRE found for this OS/architecture");
107+
return Optional.empty();
108+
}
109+
var cachedFile = fileCache.getOrDownload(jreMetadata.get().getFilename(), jreMetadata.get().getSha256(), "SHA-256",
110+
new JreDownloader(serverConnection, jreMetadata.get()));
104111
var extractedDirectory = extractArchive(cachedFile.getPathInCache());
105-
return new CachedFile(extractedDirectory.resolve(jreMetadata.javaPath), cachedFile.isCacheHit());
112+
return Optional.of(new CachedFile(extractedDirectory.resolve(jreMetadata.get().javaPath), cachedFile.isCacheHit()));
106113
} catch (HashMismatchException e) {
107114
if (retry) {
108115
// A new JRE might have been published between the metadata fetch and the download
@@ -113,16 +120,13 @@ private CachedFile getJreFromServer(ServerConnection serverConnection, FileCache
113120
}
114121
}
115122

116-
private static JreMetadata getJreMetadata(ServerConnection serverConnection, String os, String arch) {
123+
private static Optional<JreMetadata> getJreMetadata(ServerConnection serverConnection, String os, String arch) {
117124
try {
118125
String response = serverConnection.callRestApi(format(API_PATH_JRE + "?os=%s&arch=%s", os, arch));
119126
Type listType = new TypeToken<ArrayList<JreMetadata>>() {
120127
}.getType();
121128
List<JreMetadata> jres = new Gson().fromJson(response, listType);
122-
if (jres.isEmpty()) {
123-
throw new IllegalStateException("No JRE metadata found for os[" + os + "] and arch[" + arch + "]");
124-
}
125-
return jres.get(0);
129+
return jres.stream().findFirst();
126130
} catch (IOException e) {
127131
throw new IllegalStateException("Failed to get JRE metadata", e);
128132
}

lib/src/main/java/org/sonarsource/scanner/lib/internal/OsResolver.java

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -23,7 +23,6 @@
2323
import java.nio.file.Files;
2424
import java.util.List;
2525
import java.util.Locale;
26-
import org.sonarsource.scanner.lib.Paths2;
2726
import org.sonarsource.scanner.lib.System2;
2827
import org.sonarsource.scanner.lib.internal.cache.Logger;
2928

lib/src/main/java/org/sonarsource/scanner/lib/Paths2.java renamed to lib/src/main/java/org/sonarsource/scanner/lib/internal/Paths2.java

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -17,7 +17,7 @@
1717
* along with this program; if not, write to the Free Software Foundation,
1818
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
1919
*/
20-
package org.sonarsource.scanner.lib;
20+
package org.sonarsource.scanner.lib.internal;
2121

2222
import java.nio.file.Path;
2323
import java.nio.file.Paths;

lib/src/test/java/org/sonarsource/scanner/lib/internal/JavaRunnerFactoryTest.java

Lines changed: 11 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -24,6 +24,7 @@
2424
import java.nio.charset.StandardCharsets;
2525
import java.nio.file.Files;
2626
import java.nio.file.Path;
27+
import java.nio.file.Paths;
2728
import java.util.HashMap;
2829
import java.util.Map;
2930
import org.apache.commons.io.FileUtils;
@@ -39,7 +40,6 @@
3940

4041
import static java.util.Objects.requireNonNull;
4142
import static org.assertj.core.api.Assertions.assertThat;
42-
import static org.assertj.core.api.Assertions.assertThatThrownBy;
4343
import static org.mockito.ArgumentMatchers.any;
4444
import static org.mockito.ArgumentMatchers.eq;
4545
import static org.mockito.ArgumentMatchers.matches;
@@ -76,17 +76,18 @@ void createRunner_jreProvisioning() throws IOException {
7676
JavaRunner runner = underTest.createRunner(serverConnection, fileCache, new HashMap<>());
7777

7878
assertThat(runner.getJavaExecutable()).isNotNull();
79-
assertThat(new File(runner.getJavaExecutable())).exists();
79+
assertThat(runner.getJavaExecutable()).exists();
8080
}
8181

8282
@Test
83-
void createRunner_jreProvisioning_noMatch() throws IOException {
83+
void createRunner_jreProvisioning_noMatch_fallback_to_local() throws IOException {
8484
when(serverConnection.callRestApi(matches(API_PATH_JRE + ".*"))).thenReturn("[]");
85-
8685
Map<String, String> props = Map.of(SCANNER_OS, "linux", SCANNER_ARCH, "x64");
87-
assertThatThrownBy(() -> underTest.createRunner(serverConnection, fileCache, props))
88-
.isInstanceOf(IllegalStateException.class)
89-
.hasMessage("No JRE metadata found for os[linux] and arch[x64]");
86+
87+
JavaRunner runner = underTest.createRunner(serverConnection, fileCache, props);
88+
89+
assertThat(runner.getJavaExecutable()).isEqualTo(Paths.get("java"+ (SystemUtils.IS_OS_WINDOWS ? ".exe" : "")));
90+
assertThat(runner.getJreCacheHit()).isEqualTo(JreCacheHit.DISABLED);
9091
}
9192

9293
@Test
@@ -96,7 +97,7 @@ void createRunner_jreExeProperty() {
9697

9798
JavaRunner runner = underTest.createRunner(serverConnection, fileCache, properties);
9899

99-
assertThat(runner.getJavaExecutable()).isEqualTo(javaExe.toAbsolutePath().toString());
100+
assertThat(runner.getJavaExecutable()).isEqualTo(javaExe);
100101
assertThat(runner.getJreCacheHit()).isEqualTo(JreCacheHit.DISABLED);
101102
}
102103

@@ -112,7 +113,7 @@ void createRunner_jreProvisioningSkipAndJavaHome() throws IOException {
112113
JavaRunner runner = underTest.createRunner(serverConnection, fileCache, properties);
113114

114115
assertThat(runner.getJavaExecutable()).isEqualTo(
115-
temp.resolve("bin/java" + (SystemUtils.IS_OS_WINDOWS ? ".exe" : "")).toAbsolutePath().toString());
116+
temp.resolve("bin/java" + (SystemUtils.IS_OS_WINDOWS ? ".exe" : "")));
116117
assertThat(runner.getJreCacheHit()).isEqualTo(JreCacheHit.DISABLED);
117118
}
118119

@@ -122,7 +123,7 @@ void createRunner_jreProvisioningSkipAndNoJavaHome() {
122123

123124
JavaRunner runner = underTest.createRunner(serverConnection, fileCache, properties);
124125

125-
assertThat(runner.getJavaExecutable()).isEqualTo("java");
126+
assertThat(runner.getJavaExecutable()).isEqualTo(Paths.get("java" + (SystemUtils.IS_OS_WINDOWS ? ".exe" : "")));
126127
assertThat(runner.getJreCacheHit()).isEqualTo(JreCacheHit.DISABLED);
127128
}
128129

lib/src/test/java/org/sonarsource/scanner/lib/internal/JavaRunnerTest.java

Lines changed: 6 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -22,26 +22,24 @@
2222
import java.nio.file.Paths;
2323
import java.util.List;
2424
import org.junit.jupiter.api.Test;
25-
import org.junit.jupiter.api.extension.ExtendWith;
2625
import org.mockito.Mock;
27-
import org.mockito.junit.jupiter.MockitoExtension;
2826
import org.sonarsource.scanner.lib.internal.cache.Logger;
2927

3028
import static org.assertj.core.api.Assertions.assertThatThrownBy;
3129
import static org.mockito.ArgumentMatchers.anyString;
3230
import static org.mockito.ArgumentMatchers.matches;
3331
import static org.mockito.Mockito.after;
32+
import static org.mockito.Mockito.mock;
3433
import static org.mockito.Mockito.verify;
3534

36-
@ExtendWith(MockitoExtension.class)
3735
class JavaRunnerTest {
3836

3937
@Mock
40-
private Logger logger;
38+
private Logger logger = mock(Logger.class);
4139

4240
@Test
4341
void execute_shouldLogProcessOutput() {
44-
JavaRunner runner = new JavaRunner(null, logger, JreCacheHit.DISABLED);
42+
JavaRunner runner = new JavaRunner(Paths.get("java"), logger, JreCacheHit.DISABLED);
4543

4644
runner.execute(List.of("--version"), "test");
4745
verify(logger, after(1000).atLeastOnce()).info(anyString());
@@ -61,7 +59,7 @@ void execute_whenInvalidRunner_shouldFail() {
6159

6260
@Test
6361
void execute_shouldFailWhenBadRunner() {
64-
JavaRunner runner = new JavaRunner(null, logger, JreCacheHit.DISABLED);
62+
JavaRunner runner = new JavaRunner(Paths.get("java"), logger, JreCacheHit.DISABLED);
6563
List<String> command = List.of("unknown-command");
6664
assertThatThrownBy(() -> runner.execute(command, "test"))
6765
.isInstanceOf(IllegalStateException.class)
@@ -70,7 +68,7 @@ void execute_shouldFailWhenBadRunner() {
7068

7169
@Test
7270
void tryParse_shouldParseLogMessages() {
73-
JavaRunner runner = new JavaRunner(null, logger, JreCacheHit.DISABLED);
71+
JavaRunner runner = new JavaRunner(Paths.get("java"), logger, JreCacheHit.DISABLED);
7472

7573
runner.tryParse("{\n" +
7674
" \"level\": \"ERROR\",\n" +
@@ -92,7 +90,7 @@ void tryParse_shouldParseLogMessages() {
9290

9391
@Test
9492
void tryParse_whenCannotParse_shouldLogInfo() {
95-
JavaRunner runner = new JavaRunner(null, logger, JreCacheHit.DISABLED);
93+
JavaRunner runner = new JavaRunner(Paths.get("java"), logger, JreCacheHit.DISABLED);
9694
runner.tryParse("INFO: test");
9795
verify(logger).info("[stdout] INFO: test");
9896
}

0 commit comments

Comments
 (0)