diff --git a/java-frontend/src/main/java/org/sonar/java/DefaultModuleMetadata.java b/java-frontend/src/main/java/org/sonar/java/DefaultModuleMetadata.java
new file mode 100644
index 00000000000..e9f374f9a09
--- /dev/null
+++ b/java-frontend/src/main/java/org/sonar/java/DefaultModuleMetadata.java
@@ -0,0 +1,44 @@
+/*
+ * SonarQube Java
+ * Copyright (C) 2012-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 Sonar Source-Available License Version 1, as published by SonarSource SA.
+ *
+ * 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 Sonar Source-Available License for more details.
+ *
+ * You should have received a copy of the Sonar Source-Available License
+ * along with this program; if not, see https://sonarsource.com/license/ssal/
+ */
+package org.sonar.java;
+
+import org.sonar.api.config.Configuration;
+import org.sonar.java.model.JavaVersionImpl;
+import org.sonar.plugins.java.api.JavaVersion;
+import org.sonar.plugins.java.api.internal.ModuleMetadata;
+
+public class DefaultModuleMetadata implements ModuleMetadata {
+
+ private final JavaVersion javaVersion;
+ private final String moduleKey;
+
+ public DefaultModuleMetadata(SonarComponents sonarComponents, Configuration configuration) {
+ this.javaVersion = JavaVersionImpl.readFromConfiguration(configuration);
+ this.moduleKey = sonarComponents.getModuleKey();
+ }
+
+ @Override
+ public JavaVersion javaVersion() {
+ return javaVersion;
+ }
+
+ @Override
+ public String moduleKey() {
+ return moduleKey;
+ }
+
+}
diff --git a/java-frontend/src/main/java/org/sonar/java/annotations/Internal.java b/java-frontend/src/main/java/org/sonar/java/annotations/Internal.java
new file mode 100644
index 00000000000..7f2c79a37da
--- /dev/null
+++ b/java-frontend/src/main/java/org/sonar/java/annotations/Internal.java
@@ -0,0 +1,33 @@
+/*
+ * SonarQube Java
+ * Copyright (C) 2012-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 Sonar Source-Available License Version 1, as published by SonarSource SA.
+ *
+ * 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 Sonar Source-Available License for more details.
+ *
+ * You should have received a copy of the Sonar Source-Available License
+ * along with this program; if not, see https://sonarsource.com/license/ssal/
+ */
+package org.sonar.java.annotations;
+
+import java.lang.annotation.Documented;
+import java.lang.annotation.ElementType;
+import java.lang.annotation.Retention;
+import java.lang.annotation.RetentionPolicy;
+import java.lang.annotation.Target;
+
+/**
+ * This annotation should be placed on api elements that are meant to only be consumed by plugins maintained by SonarSource.
+ * Elements with this annotation are not stable and can change at any time.
+ */
+@Retention(RetentionPolicy.CLASS)
+@Target({ElementType.ANNOTATION_TYPE, ElementType.CONSTRUCTOR, ElementType.FIELD, ElementType.METHOD, ElementType.TYPE})
+@Documented
+public @interface Internal {
+}
diff --git a/java-frontend/src/main/java/org/sonar/java/model/JavaVersionImpl.java b/java-frontend/src/main/java/org/sonar/java/model/JavaVersionImpl.java
index 61b4dd478dd..c105d76756e 100644
--- a/java-frontend/src/main/java/org/sonar/java/model/JavaVersionImpl.java
+++ b/java-frontend/src/main/java/org/sonar/java/model/JavaVersionImpl.java
@@ -17,8 +17,10 @@
package org.sonar.java.model;
import java.util.Locale;
+import java.util.Optional;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
+import org.sonar.api.config.Configuration;
import org.sonar.plugins.java.api.JavaVersion;
public class JavaVersionImpl implements JavaVersion {
@@ -230,4 +232,22 @@ private static int convertJavaVersionString(String javaVersion) {
return Integer.parseInt(cleanedVersion);
}
+ public static JavaVersion readFromConfiguration(Configuration config) {
+ Optional javaVersionAsString = config.get(SOURCE_VERSION);
+ if (!javaVersionAsString.isPresent()) {
+ return new JavaVersionImpl();
+ }
+ String enablePreviewAsString = config.get(ENABLE_PREVIEW).orElse("false");
+
+ JavaVersion javaVersion = fromString(javaVersionAsString.get(), enablePreviewAsString);
+ if (javaVersion.arePreviewFeaturesEnabled() && javaVersion.asInt() < MAX_SUPPORTED) {
+ LOG.warn("sonar.java.enablePreview is set but will be discarded as the Java version is less than the max" +
+ " supported version ({} < {})", javaVersion.asInt(), MAX_SUPPORTED);
+ javaVersion = new JavaVersionImpl(javaVersion.asInt(), false);
+ }
+ LOG.info("Configured Java source version ({}): {}, preview features enabled ({}): {}",
+ SOURCE_VERSION, javaVersion.asInt(), ENABLE_PREVIEW, javaVersion.arePreviewFeaturesEnabled());
+ return javaVersion;
+ }
+
}
diff --git a/java-frontend/src/main/java/org/sonar/plugins/java/api/internal/ModuleMetadata.java b/java-frontend/src/main/java/org/sonar/plugins/java/api/internal/ModuleMetadata.java
index de257d5b5d8..0ca2e4e7aab 100644
--- a/java-frontend/src/main/java/org/sonar/plugins/java/api/internal/ModuleMetadata.java
+++ b/java-frontend/src/main/java/org/sonar/plugins/java/api/internal/ModuleMetadata.java
@@ -17,15 +17,14 @@
package org.sonar.plugins.java.api.internal;
import org.sonar.api.scanner.ScannerSide;
-import org.sonar.java.annotations.Beta;
+import org.sonar.java.annotations.Internal;
import org.sonar.plugins.java.api.JavaVersion;
/**
* Interface to access metadata about the module being analyzed by a Sensor.
- * For internal use only, this API will not be supported for custom plugins.
*/
-@Beta
+@Internal
@ScannerSide
public interface ModuleMetadata {
diff --git a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaPlugin.java b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaPlugin.java
index 588f60e88a5..236a7277e1d 100644
--- a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaPlugin.java
+++ b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaPlugin.java
@@ -28,6 +28,7 @@
import org.sonar.api.config.PropertyDefinition;
import org.sonar.java.AnalysisWarningsWrapper;
import org.sonar.java.DefaultJavaResourceLocator;
+import org.sonar.java.DefaultModuleMetadata;
import org.sonar.java.JavaConstants;
import org.sonar.java.SonarComponents;
import org.sonar.java.classpath.ClasspathForMain;
@@ -36,8 +37,8 @@
import org.sonar.java.classpath.ClasspathProperties;
import org.sonar.java.filters.PostAnalysisIssueFilter;
import org.sonar.java.jsp.Jasper;
-import org.sonar.java.telemetry.NoOpTelemetry;
import org.sonar.java.telemetry.DefaultTelemetry;
+import org.sonar.java.telemetry.NoOpTelemetry;
import org.sonar.plugins.java.api.JavaVersion;
import org.sonar.plugins.java.api.caching.SonarLintCache;
import org.sonar.plugins.surefire.SurefireExtensions;
@@ -62,6 +63,7 @@ public void define(Context context) {
list.add(DroppedPropertiesSensor.class);
list.add(JavaSonarWayProfile.class);
list.add(ClasspathForMain.class);
+ list.add(DefaultModuleMetadata.class);
ExternalReportExtensions.define(context);
}
@@ -105,8 +107,7 @@ public void define(Context context) {
" When a package or class is found in both the unnamed module and a named one, modularization is broken." +
" As a result, the parser may be unable to build the project semantic successfully, leading to analysis failure." +
" This parameter allows users to bypass Java platform modularity enforcement to prevent analysis failure." +
- "
"
- )
+ "")
.category(JavaConstants.JAVA_CATEGORY)
.subCategory("Language")
.onConfigScopes(Set.of(PropertyDefinition.ConfigScope.PROJECT))
diff --git a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaSensor.java b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaSensor.java
index b4dc7693661..2219aec774d 100644
--- a/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaSensor.java
+++ b/sonar-java-plugin/src/main/java/org/sonar/plugins/java/JavaSensor.java
@@ -111,7 +111,7 @@ public void execute(SensorContext context) {
Measurer measurer = new Measurer(context, noSonarFilter);
- JavaVersion javaVersion = getJavaVersion();
+ JavaVersion javaVersion = JavaVersionImpl.readFromConfiguration(settings);
telemetry.aggregateAsSortedSet(JAVA_LANGUAGE_VERSION, javaVersion.toString());
telemetry.aggregateAsCounter(JAVA_MODULE_COUNT, 1L);
@@ -181,24 +181,6 @@ private Iterable javaFiles(InputFile.Type type) {
return fs.inputFiles(fs.predicates().and(fs.predicates().hasLanguage(Java.KEY), fs.predicates().hasType(type)));
}
- private JavaVersion getJavaVersion() {
- Optional javaVersionAsString = settings.get(JavaVersion.SOURCE_VERSION);
- if (!javaVersionAsString.isPresent()) {
- return new JavaVersionImpl();
- }
- String enablePreviewAsString = settings.get(JavaVersion.ENABLE_PREVIEW).orElse("false");
-
- JavaVersion javaVersion = JavaVersionImpl.fromString(javaVersionAsString.get(), enablePreviewAsString);
- if (javaVersion.arePreviewFeaturesEnabled() && javaVersion.asInt() < JavaVersionImpl.MAX_SUPPORTED) {
- LOG.warn("sonar.java.enablePreview is set but will be discarded as the Java version is less than the max" +
- " supported version ({} < {})", javaVersion.asInt(), JavaVersionImpl.MAX_SUPPORTED);
- javaVersion = new JavaVersionImpl(javaVersion.asInt(), false);
- }
- LOG.info("Configured Java source version ({}): {}, preview features enabled ({}): {}",
- JavaVersion.SOURCE_VERSION, javaVersion.asInt(), JavaVersion.ENABLE_PREVIEW, javaVersion.arePreviewFeaturesEnabled());
- return javaVersion;
- }
-
@Override
public String toString() {
return getClass().getSimpleName();
diff --git a/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaPluginTest.java b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaPluginTest.java
index dcea09ca414..794c1781f72 100644
--- a/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaPluginTest.java
+++ b/sonar-java-plugin/src/test/java/org/sonar/plugins/java/JavaPluginTest.java
@@ -44,14 +44,13 @@ void sonarLint_9_9_extensions() {
.contains(SonarLintCache.class);
}
-
@Test
void sonarqube_9_9_extensions() {
SonarRuntime sqCommunity = SonarRuntimeImpl.forSonarQube(VERSION_9_9, SonarQubeSide.SCANNER, SonarEdition.COMMUNITY);
Plugin.Context context = new Plugin.Context(sqCommunity);
javaPlugin.define(context);
assertThat(context.getExtensions())
- .hasSize(35)
+ .hasSize(36)
.doesNotContain(Jasper.class);
}
@@ -61,7 +60,7 @@ void sonarqube_9_9_commercial_extensions() {
Plugin.Context context = new Plugin.Context(sqEnterprise);
javaPlugin.define(context);
assertThat(context.getExtensions())
- .hasSize(36)
+ .hasSize(37)
.contains(Jasper.class);
}