diff options
author | Duarte Meneses <duarte.meneses@sonarsource.com> | 2019-05-14 16:02:43 -0500 |
---|---|---|
committer | SonarTech <sonartech@sonarsource.com> | 2019-05-16 20:21:08 +0200 |
commit | 74cbdd7c043e8e9ee51d7c18aeef86db386df136 (patch) | |
tree | 480cb1cca1765b6a0d985cb754de31d325604a4e | |
parent | 9240dd9a15b317d94c1db5c94281398a16b2b36a (diff) | |
download | sonarqube-74cbdd7c043e8e9ee51d7c18aeef86db386df136.tar.gz sonarqube-74cbdd7c043e8e9ee51d7c18aeef86db386df136.zip |
SONAR-12108 Support Java 11 RTE
11 files changed, 209 insertions, 52 deletions
diff --git a/server/sonar-main/src/main/java/org/sonar/application/command/CeJvmOptions.java b/server/sonar-main/src/main/java/org/sonar/application/command/CeJvmOptions.java index 6b4502813f4..44a58d1d52d 100644 --- a/server/sonar-main/src/main/java/org/sonar/application/command/CeJvmOptions.java +++ b/server/sonar-main/src/main/java/org/sonar/application/command/CeJvmOptions.java @@ -24,15 +24,21 @@ import java.util.LinkedHashMap; import java.util.Map; public class CeJvmOptions extends JvmOptions<CeJvmOptions> { - public CeJvmOptions(File tmpDir) { - super(mandatoryOptions(tmpDir)); + + public CeJvmOptions(File tmpDir, JavaVersion javaVersion) { + super(mandatoryOptions(tmpDir, javaVersion)); } - private static Map<String, String> mandatoryOptions(File tmpDir) { + private static Map<String, String> mandatoryOptions(File tmpDir, JavaVersion javaVersion) { Map<String, String> res = new LinkedHashMap<>(3); res.put("-Djava.awt.headless=", "true"); res.put("-Dfile.encoding=", "UTF-8"); res.put("-Djava.io.tmpdir=", tmpDir.getAbsolutePath()); + + if (javaVersion.isAtLeastJava11()) { + // avoid illegal reflective access operations done by MyBatis + res.put("--add-opens=java.base/java.util=ALL-UNNAMED", ""); + } return res; } } diff --git a/server/sonar-main/src/main/java/org/sonar/application/command/CommandFactoryImpl.java b/server/sonar-main/src/main/java/org/sonar/application/command/CommandFactoryImpl.java index 2afbc0310c9..738cabf841d 100644 --- a/server/sonar-main/src/main/java/org/sonar/application/command/CommandFactoryImpl.java +++ b/server/sonar-main/src/main/java/org/sonar/application/command/CommandFactoryImpl.java @@ -68,11 +68,13 @@ public class CommandFactoryImpl implements CommandFactory { private final Props props; private final File tempDir; private final System2 system2; + private final JavaVersion javaVersion; - public CommandFactoryImpl(Props props, File tempDir, System2 system2) { + public CommandFactoryImpl(Props props, File tempDir, System2 system2, JavaVersion javaVersion) { this.props = props; this.tempDir = tempDir; this.system2 = system2; + this.javaVersion = javaVersion; String javaToolOptions = system2.getenv(ENV_VAR_JAVA_TOOL_OPTIONS); if (javaToolOptions != null && !javaToolOptions.trim().isEmpty()) { LoggerFactory.getLogger(CommandFactoryImpl.class) @@ -149,7 +151,7 @@ public class CommandFactoryImpl implements CommandFactory { public JavaCommand createWebCommand(boolean leader) { File homeDir = props.nonNullValueAsFile(PATH_HOME.getKey()); - WebJvmOptions jvmOptions = new WebJvmOptions(tempDir) + WebJvmOptions jvmOptions = new WebJvmOptions(tempDir, javaVersion) .addFromMandatoryProperty(props, WEB_JAVA_OPTS.getKey()) .addFromMandatoryProperty(props, WEB_JAVA_ADDITIONAL_OPTS.getKey()); addProxyJvmOptions(jvmOptions); @@ -175,7 +177,7 @@ public class CommandFactoryImpl implements CommandFactory { public JavaCommand createCeCommand() { File homeDir = props.nonNullValueAsFile(PATH_HOME.getKey()); - CeJvmOptions jvmOptions = new CeJvmOptions(tempDir) + CeJvmOptions jvmOptions = new CeJvmOptions(tempDir, javaVersion) .addFromMandatoryProperty(props, CE_JAVA_OPTS.getKey()) .addFromMandatoryProperty(props, CE_JAVA_ADDITIONAL_OPTS.getKey()); addProxyJvmOptions(jvmOptions); diff --git a/server/sonar-main/src/main/java/org/sonar/application/command/JavaVersion.java b/server/sonar-main/src/main/java/org/sonar/application/command/JavaVersion.java new file mode 100644 index 00000000000..448f8d508f4 --- /dev/null +++ b/server/sonar-main/src/main/java/org/sonar/application/command/JavaVersion.java @@ -0,0 +1,33 @@ +/* + * SonarQube + * Copyright (C) 2009-2019 SonarSource SA + * mailto:info AT sonarsource DOT com + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 3 of the License, or (at your option) any later version. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public License + * along with this program; if not, write to the Free Software Foundation, + * Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + */ +package org.sonar.application.command; + +public class JavaVersion { + public static final JavaVersion INSTANCE = new JavaVersion(); + + public boolean isAtLeastJava11() { + try { + String.class.getMethod("isBlank"); + return true; + } catch (NoSuchMethodException e) { + return false; + } + } +} diff --git a/server/sonar-main/src/main/java/org/sonar/application/command/WebJvmOptions.java b/server/sonar-main/src/main/java/org/sonar/application/command/WebJvmOptions.java index 998f2e25974..8e55debe854 100644 --- a/server/sonar-main/src/main/java/org/sonar/application/command/WebJvmOptions.java +++ b/server/sonar-main/src/main/java/org/sonar/application/command/WebJvmOptions.java @@ -24,15 +24,25 @@ import java.util.LinkedHashMap; import java.util.Map; public class WebJvmOptions extends JvmOptions<WebJvmOptions> { - public WebJvmOptions(File tmpDir) { - super(mandatoryOptions(tmpDir)); + public WebJvmOptions(File tmpDir, JavaVersion javaVersion) { + super(mandatoryOptions(tmpDir, javaVersion)); } - private static Map<String, String> mandatoryOptions(File tmpDir) { + private static Map<String, String> mandatoryOptions(File tmpDir, JavaVersion javaVersion) { Map<String, String> res = new LinkedHashMap<>(3); res.put("-Djava.awt.headless=", "true"); res.put("-Dfile.encoding=", "UTF-8"); res.put("-Djava.io.tmpdir=", tmpDir.getAbsolutePath()); + + if (javaVersion.isAtLeastJava11()) { + // avoid illegal reflective access operations done by MyBatis + res.put("--add-opens=java.base/java.util=ALL-UNNAMED", ""); + + // avoid illegal reflective access operations done by Tomcat + res.put("--add-opens=java.base/java.lang=ALL-UNNAMED", ""); + res.put("--add-opens=java.base/java.io=ALL-UNNAMED", ""); + res.put("--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED", ""); + } return res; } } diff --git a/server/sonar-main/src/test/java/org/sonar/application/command/CeJvmOptionsTest.java b/server/sonar-main/src/test/java/org/sonar/application/command/CeJvmOptionsTest.java index 98dcb5c9eff..863ee763340 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/command/CeJvmOptionsTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/command/CeJvmOptionsTest.java @@ -21,22 +21,42 @@ package org.sonar.application.command; import java.io.File; import java.io.IOException; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class CeJvmOptionsTest { @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); - @Test - public void constructor_sets_mandatory_JVM_options() throws IOException { - File tmpDir = temporaryFolder.newFolder(); - CeJvmOptions underTest = new CeJvmOptions(tmpDir); + private File tmpDir; + private JavaVersion javaVersion = mock(JavaVersion.class); + private CeJvmOptions underTest; + + @Before + public void setUp() throws IOException { + tmpDir = temporaryFolder.newFolder(); + } + @Test + public void constructor_sets_mandatory_JVM_options_before_java11() { + when(javaVersion.isAtLeastJava11()).thenReturn(false); + underTest = new CeJvmOptions(tmpDir, javaVersion); assertThat(underTest.getAll()).containsExactly( "-Djava.awt.headless=true", "-Dfile.encoding=UTF-8", "-Djava.io.tmpdir=" + tmpDir.getAbsolutePath()); } + + @Test + public void constructor_sets_mandatory_JVM_options_for_java11() { + when(javaVersion.isAtLeastJava11()).thenReturn(true); + underTest = new CeJvmOptions(tmpDir, javaVersion); + assertThat(underTest.getAll()).containsExactly( + "-Djava.awt.headless=true", "-Dfile.encoding=UTF-8", "-Djava.io.tmpdir=" + tmpDir.getAbsolutePath(), + "--add-opens=java.base/java.util=ALL-UNNAMED"); + } } diff --git a/server/sonar-main/src/test/java/org/sonar/application/command/CommandFactoryImplTest.java b/server/sonar-main/src/test/java/org/sonar/application/command/CommandFactoryImplTest.java index 0868f4150a8..1f3a059a34c 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/command/CommandFactoryImplTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/command/CommandFactoryImplTest.java @@ -32,15 +32,14 @@ import org.junit.rules.ExpectedException; import org.junit.rules.TemporaryFolder; import org.mockito.Mockito; import org.sonar.application.es.EsInstallation; +import org.sonar.application.logging.ListAppender; import org.sonar.process.ProcessId; import org.sonar.process.ProcessProperties; import org.sonar.process.Props; import org.sonar.process.System2; -import org.sonar.application.logging.ListAppender; import static org.assertj.core.api.Assertions.assertThat; import static org.assertj.core.api.Assertions.entry; -import static org.mockito.ArgumentMatchers.anyString; import static org.mockito.Mockito.when; public class CommandFactoryImplTest { @@ -50,6 +49,8 @@ public class CommandFactoryImplTest { @Rule public TemporaryFolder temp = new TemporaryFolder(); + private System2 system2 = Mockito.mock(System2.class); + private JavaVersion javaVersion = Mockito.mock(JavaVersion.class); private File homeDir; private File tempDir; private File logsDir; @@ -71,22 +72,19 @@ public class CommandFactoryImplTest { @Test public void constructor_logs_no_warning_if_env_variable_JAVA_TOOL_OPTIONS_is_not_set() { - System2 system2 = Mockito.mock(System2.class); - when(system2.getenv(anyString())).thenReturn(null); attachMemoryAppenderToLoggerOf(CommandFactoryImpl.class); - new CommandFactoryImpl(new Props(new Properties()), tempDir, system2); + new CommandFactoryImpl(new Props(new Properties()), tempDir, system2, javaVersion); assertThat(listAppender.getLogs()).isEmpty(); } @Test public void constructor_logs_warning_if_env_variable_JAVA_TOOL_OPTIONS_is_set() { - System2 system2 = Mockito.mock(System2.class); when(system2.getenv("JAVA_TOOL_OPTIONS")).thenReturn("sds"); attachMemoryAppenderToLoggerOf(CommandFactoryImpl.class); - new CommandFactoryImpl(new Props(new Properties()), tempDir, system2); + new CommandFactoryImpl(new Props(new Properties()), tempDir, system2, javaVersion); assertThat(listAppender.getLogs()) .extracting(ILoggingEvent::getMessage) @@ -97,11 +95,10 @@ public class CommandFactoryImplTest { @Test public void constructor_logs_warning_if_env_variable_ES_JAVA_OPTS_is_set() { - System2 system2 = Mockito.mock(System2.class); when(system2.getenv("ES_JAVA_OPTS")).thenReturn("xyz"); attachMemoryAppenderToLoggerOf(CommandFactoryImpl.class); - new CommandFactoryImpl(new Props(new Properties()), tempDir, system2); + new CommandFactoryImpl(new Props(new Properties()), tempDir, system2, javaVersion); assertThat(listAppender.getLogs()) .extracting(ILoggingEvent::getMessage) @@ -120,7 +117,6 @@ public class CommandFactoryImplTest { @Test public void createEsCommand_for_unix_returns_command_for_default_settings() throws Exception { - System2 system2 = Mockito.mock(System2.class); when(system2.isOsWindows()).thenReturn(false); prepareEsFileSystem(); @@ -157,7 +153,6 @@ public class CommandFactoryImplTest { @Test public void createEsCommand_for_windows_returns_command_for_default_settings() throws Exception { - System2 system2 = Mockito.mock(System2.class); when(system2.isOsWindows()).thenReturn(true); prepareEsFileSystem(); @@ -326,7 +321,7 @@ public class CommandFactoryImplTest { Props props = new Props(p); ProcessProperties.completeDefaults(props); - return new CommandFactoryImpl(props, tempDir, system2); + return new CommandFactoryImpl(props, tempDir, system2, javaVersion); } private <T> void attachMemoryAppenderToLoggerOf(Class<T> loggerClass) { diff --git a/server/sonar-main/src/test/java/org/sonar/application/command/WebJvmOptionsTest.java b/server/sonar-main/src/test/java/org/sonar/application/command/WebJvmOptionsTest.java index 0f0b42e72f3..8cc87861f5f 100644 --- a/server/sonar-main/src/test/java/org/sonar/application/command/WebJvmOptionsTest.java +++ b/server/sonar-main/src/test/java/org/sonar/application/command/WebJvmOptionsTest.java @@ -21,23 +21,46 @@ package org.sonar.application.command; import java.io.File; import java.io.IOException; +import org.junit.Before; import org.junit.Rule; import org.junit.Test; import org.junit.rules.TemporaryFolder; import static org.assertj.core.api.Assertions.assertThat; +import static org.mockito.Mockito.mock; +import static org.mockito.Mockito.when; public class WebJvmOptionsTest { @Rule public TemporaryFolder temporaryFolder = new TemporaryFolder(); - @Test - public void constructor_sets_mandatory_JVM_options() throws IOException { - File tmpDir = temporaryFolder.newFolder(); - WebJvmOptions underTest = new WebJvmOptions(tmpDir); + private File tmpDir; + private JavaVersion javaVersion = mock(JavaVersion.class); + private WebJvmOptions underTest; + + @Before + public void setUp() throws IOException { + tmpDir = temporaryFolder.newFolder(); + } + @Test + public void constructor_sets_mandatory_JVM_options_before_java11() { + when(javaVersion.isAtLeastJava11()).thenReturn(false); + underTest = new WebJvmOptions(tmpDir, javaVersion); assertThat(underTest.getAll()).containsExactly( "-Djava.awt.headless=true", "-Dfile.encoding=UTF-8", "-Djava.io.tmpdir=" + tmpDir.getAbsolutePath()); } + @Test + public void constructor_sets_mandatory_JVM_options_for_java11() { + when(javaVersion.isAtLeastJava11()).thenReturn(true); + underTest = new WebJvmOptions(tmpDir, javaVersion); + assertThat(underTest.getAll()).containsExactly( + "-Djava.awt.headless=true", "-Dfile.encoding=UTF-8", "-Djava.io.tmpdir=" + tmpDir.getAbsolutePath(), + "--add-opens=java.base/java.util=ALL-UNNAMED", + "--add-opens=java.base/java.lang=ALL-UNNAMED", + "--add-opens=java.base/java.io=ALL-UNNAMED", + "--add-opens=java.rmi/sun.rmi.transport=ALL-UNNAMED"); + } + } diff --git a/sonar-application/src/main/java/org/sonar/application/App.java b/sonar-application/src/main/java/org/sonar/application/App.java index 268d4c997e8..d262fe5df9c 100644 --- a/sonar-application/src/main/java/org/sonar/application/App.java +++ b/sonar-application/src/main/java/org/sonar/application/App.java @@ -20,8 +20,12 @@ package org.sonar.application; import java.io.IOException; +import org.slf4j.LoggerFactory; +import org.sonar.api.SonarEdition; +import org.sonar.api.internal.MetadataLoader; import org.sonar.application.command.CommandFactory; import org.sonar.application.command.CommandFactoryImpl; +import org.sonar.application.command.JavaVersion; import org.sonar.application.config.AppSettings; import org.sonar.application.config.AppSettingsLoader; import org.sonar.application.config.AppSettingsLoaderImpl; @@ -38,8 +42,13 @@ import static org.sonar.process.ProcessProperties.Property.CLUSTER_NAME; public class App { private final SystemExit systemExit = new SystemExit(); + private final JavaVersion javaVersion; private StopRequestWatcher stopRequestWatcher; + public App(JavaVersion javaVersion) { + this.javaVersion = javaVersion; + } + public void start(String[] cliArguments) throws IOException { AppSettingsLoader settingsLoader = new AppSettingsLoaderImpl(cliArguments); AppSettings settings = settingsLoader.load(); @@ -47,13 +56,14 @@ public class App { AppLogging logging = new AppLogging(settings); logging.configure(); AppFileSystem fileSystem = new AppFileSystem(settings); + checkJavaVersion(); try (AppState appState = new AppStateFactory(settings).create()) { appState.registerSonarQubeVersion(getSonarqubeVersion()); appState.registerClusterName(settings.getProps().nonNullValue(CLUSTER_NAME.getKey())); AppReloader appReloader = new AppReloaderImpl(settingsLoader, fileSystem, appState, logging); fileSystem.reset(); - CommandFactory commandFactory = new CommandFactoryImpl(settings.getProps(), fileSystem.getTempDir(), System2.INSTANCE); + CommandFactory commandFactory = new CommandFactoryImpl(settings.getProps(), fileSystem.getTempDir(), System2.INSTANCE, JavaVersion.INSTANCE); try (ProcessLauncher processLauncher = new ProcessLauncherImpl(fileSystem.getTempDir())) { Scheduler scheduler = new SchedulerImpl(settings, appReloader, commandFactory, processLauncher, appState); @@ -74,8 +84,18 @@ public class App { systemExit.exit(0); } + private void checkJavaVersion() { + if (MetadataLoader.loadEdition(org.sonar.api.utils.System2.INSTANCE) == SonarEdition.SONARCLOUD) { + return; + } + + if (!javaVersion.isAtLeastJava11()) { + LoggerFactory.getLogger(this.getClass()).warn("SonarQube will require Java 11+ starting on next version"); + } + } + public static void main(String... args) throws IOException { - new App().start(args); + new App(JavaVersion.INSTANCE).start(args); } private class ShutdownHook extends Thread { diff --git a/sonar-duplications/src/test/java/org/sonar/duplications/java/JavaStatementBuilderTest.java b/sonar-duplications/src/test/java/org/sonar/duplications/java/JavaStatementBuilderTest.java index c739fa666ab..92b2085ef3d 100644 --- a/sonar-duplications/src/test/java/org/sonar/duplications/java/JavaStatementBuilderTest.java +++ b/sonar-duplications/src/test/java/org/sonar/duplications/java/JavaStatementBuilderTest.java @@ -19,13 +19,6 @@ */ package org.sonar.duplications.java; -import org.apache.commons.io.IOUtils; -import org.junit.Test; -import org.sonar.duplications.DuplicationsTestUtil; -import org.sonar.duplications.statement.Statement; -import org.sonar.duplications.statement.StatementChunker; -import org.sonar.duplications.token.TokenChunker; - import java.io.File; import java.io.FileInputStream; import java.io.FileNotFoundException; @@ -33,6 +26,12 @@ import java.io.InputStreamReader; import java.io.Reader; import java.nio.charset.StandardCharsets; import java.util.List; +import org.apache.commons.io.IOUtils; +import org.junit.Test; +import org.sonar.duplications.DuplicationsTestUtil; +import org.sonar.duplications.statement.Statement; +import org.sonar.duplications.statement.StatementChunker; +import org.sonar.duplications.token.TokenChunker; import static org.assertj.core.api.Assertions.assertThat; @@ -318,6 +317,51 @@ public class JavaStatementBuilderTest { assertThat(statements.get(1).getValue()).isEqualTo("something()"); } + /** + * Java 8. + */ + @Test + public void shouldHandleLambda() { + List<Statement> statements; + statements = chunk("List<String> result = lines.stream().filter(line -> !\"mkyong\".equals(line)).collect(Collectors.toList());"); + assertThat(statements.size()).isEqualTo(1); + assertThat(statements).extracting(Statement::getValue).containsExactly("List<String>result=lines.stream().filter(line->!$CHARS.equals(line)).collect(Collectors.toList())"); + + statements = chunk("items.forEach((k,v)->{System.out.println(\"Item : \" + k + \" Count : \" + v); if(\"E\".equals(k)) { System.out.println(\"Hello E\");}});"); + assertThat(statements.size()).isEqualTo(5); + assertThat(statements).extracting(Statement::getValue) + .containsExactly("items.forEach((k,v)->", + "System.out.println($CHARS+k+$CHARS+v)", + "if($CHARS.equals(k))", + "System.out.println($CHARS)", + ")"); + } + + /** + * Java 9. + */ + @Test + public void shouldHandleModuleInfo() { + List<Statement> statements; + statements = chunk("module com.application.infra { requires com.application.domain; exports com.application.infra.api; }"); + assertThat(statements.size()).isEqualTo(3); + assertThat(statements).extracting(Statement::getValue) + .containsExactly("modulecom.application.infra", + "requirescom.application.domain", + "exportscom.application.infra.api"); + } + + /** + * Java 11. + */ + @Test + public void shouldHandleVar() { + List<Statement> statements; + statements = chunk("IFunc f = (@NonNull var x, final var y) -> Foo.foo(x, y);"); + assertThat(statements.size()).isEqualTo(1); + assertThat(statements).extracting(Statement::getValue).containsExactly("IFuncf=(@NonNullvarx,finalvary)->Foo.foo(x,y)"); + } + @Test public void realExamples() { assertThat(chunk(DuplicationsTestUtil.findFile("/java/MessageResources.java")).size()).isGreaterThan(0); diff --git a/sonar-plugin-api/src/main/java/org/sonar/api/utils/System2.java b/sonar-plugin-api/src/main/java/org/sonar/api/utils/System2.java index 2f2ee31eef1..36dc553a74e 100644 --- a/sonar-plugin-api/src/main/java/org/sonar/api/utils/System2.java +++ b/sonar-plugin-api/src/main/java/org/sonar/api/utils/System2.java @@ -21,14 +21,13 @@ package org.sonar.api.utils; import java.net.URL; import java.time.Clock; -import java.util.Date; import java.util.Map; import java.util.Properties; import java.util.TimeZone; import javax.annotation.CheckForNull; import org.apache.commons.lang.SystemUtils; -import org.sonar.api.scanner.ScannerSide; import org.sonar.api.ce.ComputeEngineSide; +import org.sonar.api.scanner.ScannerSide; import org.sonar.api.server.ServerSide; /** @@ -61,7 +60,6 @@ import org.sonar.api.server.ServerSide; * Note that the name System2 was chosen to not conflict with {@link java.lang.System}. * <br> * An instance is available in IoC container since 4.3. - * * Since 6.4 you can also inject {@link Clock} instead of {@link System2} if you are only interested by date/time operations * * @since 4.2 @@ -98,6 +96,7 @@ public class System2 { /** * Shortcut for {@code System{@link #setProperty(String, String)}} + * * @since 6.4 */ public System2 setProperty(String key, String value) { @@ -129,6 +128,7 @@ public class System2 { /** * True if Java 7 or Java 8 runtime environment + * * @since 4.3 * @deprecated in 6.4. Java 8+ is required, so this method always returns {@code true}. */ @@ -142,24 +142,16 @@ public class System2 { } /** - * @deprecated in 5.2. Please use {@link #now()} - */ - @Deprecated - public Date newDate() { - return new Date(); - } - - /** - * @since 5.1 * @return the JVM's default time zone + * @since 5.1 */ public TimeZone getDefaultTimeZone() { return TimeZone.getDefault(); } /** - * @since 5.5 * @see Class#getResource(String) + * @since 5.5 */ public URL getResource(String name) { return getClass().getResource(name); @@ -167,6 +159,7 @@ public class System2 { /** * Closes the object and throws an {@link java.lang.IllegalStateException} on error. + * * @since 5.1 */ public void close(AutoCloseable closeable) { diff --git a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java index 690509a8daa..9b407ba2a3d 100644 --- a/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java +++ b/sonar-scanner-engine/src/main/java/org/sonar/scanner/bootstrap/GlobalContainer.java @@ -22,10 +22,10 @@ package org.sonar.scanner.bootstrap; import java.time.Clock; import java.util.List; import java.util.Map; -import org.sonar.api.SonarEdition; import org.apache.commons.lang.StringUtils; import org.sonar.api.CoreProperties; import org.sonar.api.Plugin; +import org.sonar.api.SonarEdition; import org.sonar.api.SonarQubeSide; import org.sonar.api.SonarQubeVersion; import org.sonar.api.internal.MetadataLoader; @@ -78,9 +78,20 @@ public class GlobalContainer extends ComponentContainer { addBootstrapComponents(); } + private static void checkJavaVersion() { + try { + String.class.getMethod("isBlank"); + } catch (NoSuchMethodException e) { + LOG.warn("SonarQube scanners will require Java 11+ starting on next version"); + } + } + private void addBootstrapComponents() { Version apiVersion = MetadataLoader.loadVersion(System2.INSTANCE); SonarEdition edition = MetadataLoader.loadEdition(System2.INSTANCE); + if (edition != SonarEdition.SONARCLOUD) { + checkJavaVersion(); + } LOG.debug("{} {}", edition.getLabel(), apiVersion); add( // plugins |