From 5fa26cf357a2b4f078ce27cfec89f4018a9bb0c7 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/pom.xml | 2 +- .../org/eclipse/m2e/core/embedder/IMaven.java | 11 +++ .../m2e/core/internal/embedder/MavenImpl.java | 56 ++++++++++++--- org.eclipse.m2e.jdt/META-INF/MANIFEST.MF | 2 +- .../AbstractJavaProjectConfigurator.java | 68 ++++++++++++------- 6 files changed, 101 insertions(+), 40 deletions(-) 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..7fbe0dd256 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,14 @@ 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)); + .error(NLS.bind(Messages.MavenImpl_error_param_for_execution, parameterLabel, mojoExecution.getExecutionId()), + e)); } } @@ -740,7 +750,31 @@ 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/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..1e1918873d 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,34 +846,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 = ((MavenImpl) maven).getMojoParameterValue(mavenProject, mojoExecution, + List.of("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 +896,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 and minor version here, micro and qualifier not relevant inside IDE (probably) + ArtifactVersion normalizedRecommendedVersion = new DefaultArtifactVersion( + recommendedVersion.getMajorVersion() + "." + recommendedVersion.getMinorVersion()); + int compareTo = normalizedRecommendedVersion.compareTo(environmentVersion); foundMatchingVersion = compareTo <= 0; } if(foundMatchingVersion) {