From de535417ad1b61434bc7f1e0c09bd3c2c1a36f91 Mon Sep 17 00:00:00 2001 From: Konrad Windszus Date: Tue, 11 Oct 2022 14:35:19 +0200 Subject: [PATCH] Only evaluate major and minor version of enforcer java rule Fix evaluation of expressions in m-enforcer-p parameter Only select ExecutionEnvironments with at least one compatible VM installed. This closes #842 --- org.eclipse.m2e.core/META-INF/MANIFEST.MF | 2 +- .../org/eclipse/m2e/core/embedder/IMaven.java | 34 ++++++++++ .../m2e/core/internal/embedder/MavenImpl.java | 38 ++++++++--- .../AbstractJavaProjectConfigurator.java | 67 ++++++++++++------- 4 files changed, 104 insertions(+), 37 deletions(-) diff --git a/org.eclipse.m2e.core/META-INF/MANIFEST.MF b/org.eclipse.m2e.core/META-INF/MANIFEST.MF index 39cb042ba1..ad09f85320 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.1.0.qualifier Bundle-Activator: org.eclipse.m2e.core.internal.MavenPluginActivator Bundle-Vendor: %Bundle-Vendor Bundle-Localization: plugin 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 a61ca63238..3ce66228c2 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 @@ -22,6 +22,8 @@ import java.util.List; import java.util.Map; +import org.osgi.annotation.versioning.ProviderType; + import org.eclipse.core.runtime.CoreException; import org.eclipse.core.runtime.IProgressMonitor; @@ -57,6 +59,7 @@ * @author igor * @noimplement This interface is not intended to be implemented by clients. */ +@ProviderType public interface IMaven extends IComponentLookup { // POM Model read/write operations @@ -149,11 +152,42 @@ 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 + * @see IMaven#getMojoParameterValue(MavenProject, MojoExecution, List, Class, IProgressMonitor) */ T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, String parameter, Class asType, IProgressMonitor monitor) throws CoreException; + /** + * Resolves a nested 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 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 + * @since 2.1.0 + * @see IMaven#getMojoParameterValue(MavenProject, MojoExecution, String, Class, IProgressMonitor) + */ + T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, List parameterPath, + Class asType, IProgressMonitor monitor) throws CoreException; + /** * @since 1.4 */ 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 9fdb0f82a5..df0976e520 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 @@ -730,8 +730,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(); @@ -740,14 +756,7 @@ 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); @@ -761,9 +770,18 @@ 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, + Collections.singletonList(parameter), asType), + monitor); } + @Override + 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, ConfigurationContainer configuration, String goal) throws CoreException { Xpp3Dom config = (Xpp3Dom) configuration.getConfiguration(); 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..42905e7092 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; @@ -254,11 +253,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,34 +845,46 @@ 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 { - // 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; + private String getMinimumJavaBuildEnvironmentId(MavenProject mavenProject, MojoExecution mojoExecution, + IProgressMonitor monitor) throws InvalidVersionSpecificationException, CoreException { + String version = maven.getMojoParameterValue(mavenProject, mojoExecution, + Arrays.asList("rules", "requireJavaVersion", "version"), String.class, monitor); + return getMinimumJavaBuildEnvironmentId(version); + } + + private static boolean containsVersionIgnoringMicroAndQualifier(VersionRange versionRange, ArtifactVersion version) { + for(Restriction restriction : versionRange.getRestrictions()) { + Restriction normalizedRestriction = getRestrictionIgnoringMicroAndQualifier(restriction); + if(normalizedRestriction.containsVersion(version)) { + return true; + } } - return getMinimumJavaBuildEnvironmentId(version.getValue()); + return false; + } + + private static Restriction getRestrictionIgnoringMicroAndQualifier(Restriction restriction) { + return new Restriction( + restriction.getLowerBound() != null + ? new DefaultArtifactVersion( + restriction.getLowerBound().getMajorVersion() + "." + restriction.getLowerBound().getMinorVersion()) + : null, + restriction.isLowerBoundInclusive(), + restriction.getUpperBound() != null + ? new DefaultArtifactVersion( + restriction.getUpperBound().getMajorVersion() + "." + restriction.getUpperBound().getMinorVersion()) + : null, + restriction.isUpperBoundInclusive()); } private String getMinimumJavaBuildEnvironmentId(String versionSpec) throws InvalidVersionSpecificationException { @@ -883,10 +895,13 @@ private String getMinimumJavaBuildEnvironmentId(String versionSpec) throws Inval ArtifactVersion environmentVersion = new DefaultArtifactVersion(entry.getKey()); boolean foundMatchingVersion = false; if(recommendedVersion == null) { - foundMatchingVersion = vr.containsVersion(environmentVersion); + foundMatchingVersion = containsVersionIgnoringMicroAndQualifier(vr, environmentVersion); } else { // only singular versions ever have a recommendedVersion - int compareTo = recommendedVersion.compareTo(environmentVersion); + // only consider major version here, minor version not relevant inside IDE (probably) + ArtifactVersion normalizedRecommendedVersion = new DefaultArtifactVersion( + recommendedVersion.getMajorVersion() + "." + recommendedVersion.getMinorVersion()); + int compareTo = normalizedRecommendedVersion.compareTo(environmentVersion); foundMatchingVersion = compareTo <= 0; } if(foundMatchingVersion) {