diff --git a/org.eclipse.m2e.core/META-INF/MANIFEST.MF b/org.eclipse.m2e.core/META-INF/MANIFEST.MF
index 61cad785ff..187ebf94b8 100644
--- a/org.eclipse.m2e.core/META-INF/MANIFEST.MF
+++ b/org.eclipse.m2e.core/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.eclipse.m2e.core;singleton:=true
-Bundle-Version: 2.0.4.qualifier
+Bundle-Version: 2.0.5.qualifier
Bundle-Activator: org.eclipse.m2e.core.internal.MavenPluginActivator
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: plugin
diff --git a/org.eclipse.m2e.core/pom.xml b/org.eclipse.m2e.core/pom.xml
index 0183680564..559f4b3e2d 100644
--- a/org.eclipse.m2e.core/pom.xml
+++ b/org.eclipse.m2e.core/pom.xml
@@ -19,7 +19,7 @@
org.eclipse.m2e.core
- 2.0.4-SNAPSHOT
+ 2.0.5-SNAPSHOT
eclipse-plugin
Maven Integration for Eclipse Core Plug-in
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/embedder/IMaven.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/embedder/IMaven.java
index fd7c117c79..b632ba2e06 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/embedder/IMaven.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/embedder/IMaven.java
@@ -158,6 +158,17 @@ MojoExecution setupMojoExecution(MavenProject project, MojoExecution execution,
throws CoreException;
/**
+ * Resolves a configuration parameter from the given {@code mojoExecution}. It coerces from String to the given type
+ * and considers expressions and default values.
+ *
+ * @param
+ * @param project the Maven project
+ * @param mojoExecution the mojo execution from which to retrieve the configuration value
+ * @param parameter the name of the parameter (may be nested with separating {@code .})
+ * @param asType the type to coerce to
+ * @param monitor the progress monitor
+ * @return the parameter value or {@code null} if the parameter with the given name was not found
+ * @throws CoreException
* @since 1.4
*/
T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, String parameter,
diff --git a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/MavenImpl.java b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/MavenImpl.java
index a6cc1fc65c..a064c1e866 100644
--- a/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/MavenImpl.java
+++ b/org.eclipse.m2e.core/src/org/eclipse/m2e/core/internal/embedder/MavenImpl.java
@@ -709,8 +709,24 @@ private String formatAsDirectory(String directory) {
return directory.replace(GROUP_SEPARATOR, PATH_SEPARATOR);
}
- private T getMojoParameterValue(MavenSession session, MojoExecution mojoExecution, String parameter,
+ private T getMojoParameterValue(MavenSession session, MojoExecution mojoExecution, List parameterPath,
Class asType) throws CoreException {
+ Xpp3Dom dom = mojoExecution.getConfiguration();
+ if(dom == null) {
+ return null;
+ }
+ PlexusConfiguration configuration = new XmlPlexusConfiguration(dom);
+ for(String parameter : parameterPath) {
+ configuration = configuration.getChild(parameter);
+ if(configuration == null) {
+ return null;
+ }
+ }
+ return getMojoParameterValue(session, mojoExecution, configuration, asType, String.join("/", parameterPath));
+ }
+
+ private T getMojoParameterValue(MavenSession session, MojoExecution mojoExecution,
+ PlexusConfiguration configuration, Class asType, String parameterLabel) throws CoreException {
try {
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();
@@ -719,20 +735,13 @@ private T getMojoParameterValue(MavenSession session, MojoExecution mojoExec
ExpressionEvaluator expressionEvaluator = new PluginParameterExpressionEvaluator(session, mojoExecution);
ConfigurationConverter typeConverter = converterLookup.lookupConverterForType(asType);
- Xpp3Dom dom = mojoExecution.getConfiguration();
- if(dom == null) {
- return null;
- }
- PlexusConfiguration configuration = new XmlPlexusConfiguration(dom).getChild(parameter);
- if(configuration == null) {
- return null;
- }
+
Object value = typeConverter.fromConfiguration(converterLookup, configuration, asType,
mojoDescriptor.getImplementationClass(), pluginRealm, expressionEvaluator, null);
return asType.cast(value);
} catch(Exception e) {
- throw new CoreException(Status
- .error(NLS.bind(Messages.MavenImpl_error_param_for_execution, parameter, mojoExecution.getExecutionId()), e));
+ throw new CoreException(Status.error(
+ NLS.bind(Messages.MavenImpl_error_param_for_execution, parameterLabel, mojoExecution.getExecutionId()), e));
}
}
@@ -740,7 +749,30 @@ private T getMojoParameterValue(MavenSession session, MojoExecution mojoExec
public T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, String parameter,
Class asType, IProgressMonitor monitor) throws CoreException {
return getExecutionContext().execute(project,
- (context, pm) -> getMojoParameterValue(context.getSession(), mojoExecution, parameter, asType), monitor);
+ (context, pm) -> getMojoParameterValue(context.getSession(), mojoExecution, List.of(parameter), asType),
+ monitor);
+ }
+
+ /**
+ * Resolves a nested configuration parameter from the given {@code mojoExecution}. It coerces from String to the given
+ * type and considers expressions and default values. Deliberately no public API yet as probably refactored in the
+ * near future.
+ *
+ * @param
+ * @param project the Maven project
+ * @param mojoExecution the mojo execution from which to retrieve the configuration value
+ * @param parameterPath the path of the parameter to look up, the first item is the name of the element directly below
+ * {@code } and the last one is the element containing the actual value
+ * @param asType the type to coerce to
+ * @param monitor the progress monitor
+ * @return the parameter value or {@code null} if the parameter with the given name was not found
+ * @throws CoreException
+ * @see IMaven#getMojoParameterValue(MavenProject, MojoExecution, String, Class, IProgressMonitor)
+ */
+ public T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, List parameterPath,
+ Class asType, IProgressMonitor monitor) throws CoreException {
+ return getExecutionContext().execute(project,
+ (context, pm) -> getMojoParameterValue(context.getSession(), mojoExecution, parameterPath, asType), monitor);
}
private T getMojoParameterValue(String parameter, Class type, MavenSession session, Plugin plugin,
diff --git a/org.eclipse.m2e.jdt.tests/projects/enforcerSettingsWithVersion/pom.xml b/org.eclipse.m2e.jdt.tests/projects/enforcerSettingsWithVersion/pom.xml
new file mode 100644
index 0000000000..fcf1350b33
--- /dev/null
+++ b/org.eclipse.m2e.jdt.tests/projects/enforcerSettingsWithVersion/pom.xml
@@ -0,0 +1,47 @@
+
+
+ 4.0.0
+ foo.bar
+ demo
+ 0.0.1-SNAPSHOT
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.10.1
+
+
+ 1.8
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ 3.1.0
+
+
+ enforce-java-version
+
+ enforce
+
+ validate
+
+
+
+ 13.0.3
+
+
+
+
+
+
+
+
+
diff --git a/org.eclipse.m2e.jdt.tests/projects/enforcerSettingsWithVersionRange/pom.xml b/org.eclipse.m2e.jdt.tests/projects/enforcerSettingsWithVersionRange/pom.xml
new file mode 100644
index 0000000000..888ab0d305
--- /dev/null
+++ b/org.eclipse.m2e.jdt.tests/projects/enforcerSettingsWithVersionRange/pom.xml
@@ -0,0 +1,47 @@
+
+
+ 4.0.0
+ foo.bar
+ demo
+ 0.0.1-SNAPSHOT
+
+
+
+
+ org.apache.maven.plugins
+ maven-compiler-plugin
+ 3.10.1
+
+
+ 1.8
+
+
+
+
+
+
+ org.apache.maven.plugins
+ maven-enforcer-plugin
+ 3.1.0
+
+
+ enforce-java-version
+
+ enforce
+
+ validate
+
+
+
+ [11.0.10,16)
+
+
+
+
+
+
+
+
+
diff --git a/org.eclipse.m2e.jdt.tests/src/org/eclipse/m2e/jdt/tests/JavaConfigurationFromEnforcer.java b/org.eclipse.m2e.jdt.tests/src/org/eclipse/m2e/jdt/tests/JavaConfigurationFromEnforcer.java
new file mode 100644
index 0000000000..acab42fbf4
--- /dev/null
+++ b/org.eclipse.m2e.jdt.tests/src/org/eclipse/m2e/jdt/tests/JavaConfigurationFromEnforcer.java
@@ -0,0 +1,59 @@
+/*******************************************************************************
+ * Copyright (c) 2022, 2022 Hannes Wellmann and others
+ * All rights reserved. This program and the accompanying materials
+ * are made available under the terms of the Eclipse Public License 2.0
+ * which accompanies this distribution, and is available at
+ * https://www.eclipse.org/legal/epl-2.0/
+ *
+ * SPDX-License-Identifier: EPL-2.0
+ *
+ * Contributors:
+ * Hannes Wellmann - initial API and implementation
+ *******************************************************************************/
+
+package org.eclipse.m2e.jdt.tests;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.Arrays;
+import java.util.List;
+
+import org.eclipse.core.resources.IProject;
+import org.eclipse.core.runtime.IPath;
+import org.eclipse.jdt.core.IClasspathEntry;
+import org.eclipse.jdt.core.IJavaProject;
+import org.eclipse.jdt.core.JavaCore;
+import org.eclipse.jdt.core.JavaModelException;
+import org.eclipse.m2e.tests.common.AbstractMavenProjectTestCase;
+import org.junit.Test;
+
+public class JavaConfigurationFromEnforcer extends AbstractMavenProjectTestCase {
+ private static final String JRE_CONTAINER_PREFIX = "org.eclipse.jdt.launching.JRE_CONTAINER/org.eclipse.jdt.internal.debug.ui.launcher.StandardVMType/";
+
+ @Test
+ public void testEnforcerVersion() throws Exception {
+ IProject project = importProject("projects/enforcerSettingsWithVersion/pom.xml");
+ waitForJobsToComplete();
+ IJavaProject jproject = JavaCore.create(project);
+ assertEquals("1.8", jproject.getOption(JavaCore.COMPILER_SOURCE, false));
+ assertEquals("1.8", jproject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, false));
+ assertEquals(List.of("JavaSE-13"), getJREContainerVMType(jproject));
+ }
+
+ @Test
+ public void testEnforcerVersionRange() throws Exception {
+ IProject project = importProject("projects/enforcerSettingsWithVersionRange/pom.xml");
+ waitForJobsToComplete();
+ IJavaProject jproject = JavaCore.create(project);
+ assertEquals("1.8", jproject.getOption(JavaCore.COMPILER_SOURCE, false));
+ assertEquals("1.8", jproject.getOption(JavaCore.COMPILER_CODEGEN_TARGET_PLATFORM, false));
+ assertEquals(List.of("JavaSE-11"), getJREContainerVMType(jproject));
+ }
+
+ private static List getJREContainerVMType(IJavaProject jproject) throws JavaModelException {
+ return Arrays.stream(jproject.getRawClasspath())
+ .filter(cp -> cp.getEntryKind() == IClasspathEntry.CPE_CONTAINER).map(IClasspathEntry::getPath)
+ .map(IPath::toString).filter(p -> p.startsWith(JRE_CONTAINER_PREFIX))
+ .map(p -> p.substring(JRE_CONTAINER_PREFIX.length())).toList();
+ }
+}
diff --git a/org.eclipse.m2e.jdt/META-INF/MANIFEST.MF b/org.eclipse.m2e.jdt/META-INF/MANIFEST.MF
index a35c32ed4b..b7c512a028 100644
--- a/org.eclipse.m2e.jdt/META-INF/MANIFEST.MF
+++ b/org.eclipse.m2e.jdt/META-INF/MANIFEST.MF
@@ -2,7 +2,7 @@ Manifest-Version: 1.0
Bundle-ManifestVersion: 2
Bundle-Name: %Bundle-Name
Bundle-SymbolicName: org.eclipse.m2e.jdt;singleton:=true
-Bundle-Version: 2.0.2.qualifier
+Bundle-Version: 2.0.3.qualifier
Bundle-Localization: plugin
Export-Package: org.eclipse.m2e.jdt,
org.eclipse.m2e.jdt.internal;x-friends:="org.eclipse.m2e.jdt.ui",
diff --git a/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/AbstractJavaProjectConfigurator.java b/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/AbstractJavaProjectConfigurator.java
index acebe4f8c0..b589e69646 100644
--- a/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/AbstractJavaProjectConfigurator.java
+++ b/org.eclipse.m2e.jdt/src/org/eclipse/m2e/jdt/internal/AbstractJavaProjectConfigurator.java
@@ -44,11 +44,10 @@
import org.eclipse.jdt.launching.environments.IExecutionEnvironment;
import org.eclipse.jdt.launching.environments.IExecutionEnvironmentsManager;
-import org.codehaus.plexus.util.xml.Xpp3Dom;
-
import org.apache.maven.artifact.versioning.ArtifactVersion;
import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
import org.apache.maven.artifact.versioning.InvalidVersionSpecificationException;
+import org.apache.maven.artifact.versioning.Restriction;
import org.apache.maven.artifact.versioning.VersionRange;
import org.apache.maven.model.Resource;
import org.apache.maven.plugin.MojoExecution;
@@ -56,6 +55,7 @@
import org.eclipse.m2e.core.MavenPlugin;
import org.eclipse.m2e.core.internal.M2EUtils;
+import org.eclipse.m2e.core.internal.embedder.MavenImpl;
import org.eclipse.m2e.core.project.IMavenProjectFacade;
import org.eclipse.m2e.core.project.IProjectConfigurationManager;
import org.eclipse.m2e.core.project.configurator.AbstractProjectConfigurator;
@@ -254,11 +254,12 @@ private IExecutionEnvironment getExecutionEnvironment(String environmentId) {
return null;
}
IExecutionEnvironmentsManager manager = JavaRuntime.getExecutionEnvironmentsManager();
- for(IExecutionEnvironment environment : manager.getExecutionEnvironments()) {
- if(environment.getId().equals(environmentId)) {
- return environment;
- }
+ IExecutionEnvironment environment = manager.getEnvironment(environmentId);
+ if(environment != null && environment.getCompatibleVMs().length > 0) {
+ return environment;
}
+ log.error("Failed to find a compatible VM for environment id '{}', falling back to workspace default",
+ environmentId);
return null;
}
@@ -845,45 +846,41 @@ private String getMinimumJavaBuildEnvironmentId(ProjectConfigurationRequest requ
try {
List mojoExecutions = getEnforcerMojoExecutions(request, monitor);
for(MojoExecution mojoExecution : mojoExecutions) {
- String version = getMinimumJavaBuildEnvironmentId(mojoExecution);
+ String version = getMinimumJavaBuildEnvironmentId(request.mavenProject(), mojoExecution, monitor);
if(version != null) {
return version;
}
}
} catch(CoreException | InvalidVersionSpecificationException ex) {
- log.error("Failed to determine minimum build version, assuming default", ex);
+ log.error("Failed to determine minimum build Java version, assuming default", ex);
}
return null;
}
- private String getMinimumJavaBuildEnvironmentId(MojoExecution mojoExecution)
- throws InvalidVersionSpecificationException {
+ private String getMinimumJavaBuildEnvironmentId(MavenProject mavenProject, MojoExecution mojoExecution,
+ IProgressMonitor monitor) throws InvalidVersionSpecificationException, CoreException {
// https://maven.apache.org/enforcer/enforcer-rules/requireJavaVersion.html
- Xpp3Dom dom = mojoExecution.getConfiguration();
- Xpp3Dom rules = dom.getChild("rules");
- if(rules == null) {
- return null;
- }
- Xpp3Dom requireJavaVersion = rules.getChild("requireJavaVersion");
- if(requireJavaVersion == null) {
- return null;
- }
- Xpp3Dom version = requireJavaVersion.getChild("version");
- if(version == null) {
- return null;
- }
- return getMinimumJavaBuildEnvironmentId(version.getValue());
+ String version = ((MavenImpl) maven).getMojoParameterValue(mavenProject, mojoExecution,
+ List.of("rules", "requireJavaVersion", "version"), String.class, monitor);
+ return getMinimumJavaBuildEnvironmentId(version);
}
private String getMinimumJavaBuildEnvironmentId(String versionSpec) throws InvalidVersionSpecificationException {
VersionRange vr = VersionRange.createFromVersionSpec(versionSpec);
ArtifactVersion recommendedVersion = vr.getRecommendedVersion();
+ List versionRestrictions = List.of();
+ if(recommendedVersion == null) {
+ versionRestrictions = getVersionRangeRestrictionsIgnoringMicroAndQualifier(vr);
+ } else {
+ // only consider major and minor version here, micro and qualifier not relevant inside IDE (probably)
+ recommendedVersion = getMajorMinorOnlyVersion(recommendedVersion);
+ }
// find lowest matching environment id
for(Entry entry : ENVIRONMENTS.entrySet()) {
ArtifactVersion environmentVersion = new DefaultArtifactVersion(entry.getKey());
- boolean foundMatchingVersion = false;
+ boolean foundMatchingVersion;
if(recommendedVersion == null) {
- foundMatchingVersion = vr.containsVersion(environmentVersion);
+ foundMatchingVersion = versionRestrictions.stream().anyMatch(r -> r.containsVersion(environmentVersion));
} else {
// only singular versions ever have a recommendedVersion
int compareTo = recommendedVersion.compareTo(environmentVersion);
@@ -896,6 +893,20 @@ private String getMinimumJavaBuildEnvironmentId(String versionSpec) throws Inval
return null;
}
+ private static List getVersionRangeRestrictionsIgnoringMicroAndQualifier(VersionRange versionRange) {
+ return versionRange.getRestrictions().stream().map(restriction -> {
+ ArtifactVersion lowerBound = restriction.getLowerBound();
+ ArtifactVersion upperBound = restriction.getUpperBound();
+ return new Restriction(//
+ lowerBound != null ? getMajorMinorOnlyVersion(lowerBound) : null, restriction.isLowerBoundInclusive(),
+ upperBound != null ? getMajorMinorOnlyVersion(upperBound) : null, restriction.isUpperBoundInclusive());
+ }).toList();
+ }
+
+ private static ArtifactVersion getMajorMinorOnlyVersion(ArtifactVersion lower) {
+ return new DefaultArtifactVersion(lower.getMajorVersion() + "." + lower.getMinorVersion());
+ }
+
private double asDouble(String level) {
if(level == null || level.isEmpty()) {
return -1;