Skip to content

Commit

Permalink
Only evaluate major and minor version of enforcer java rule
Browse files Browse the repository at this point in the history
Fix evaluation of expressions in m-enforcer-p parameter
Only select ExecutionEnvironments with at least one compatible VM
installed.
This closes #842
  • Loading branch information
kwin committed Nov 27, 2022
1 parent d07bc99 commit 5fa26cf
Show file tree
Hide file tree
Showing 6 changed files with 101 additions and 40 deletions.
2 changes: 1 addition & 1 deletion org.eclipse.m2e.core/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down
2 changes: 1 addition & 1 deletion org.eclipse.m2e.core/pom.xml
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@
</parent>

<artifactId>org.eclipse.m2e.core</artifactId>
<version>2.0.4-SNAPSHOT</version>
<version>2.0.5-SNAPSHOT</version>
<packaging>eclipse-plugin</packaging>

<name>Maven Integration for Eclipse Core Plug-in</name>
Expand Down
11 changes: 11 additions & 0 deletions org.eclipse.m2e.core/src/org/eclipse/m2e/core/embedder/IMaven.java
Original file line number Diff line number Diff line change
Expand Up @@ -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 <T>
* @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> T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, String parameter,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -709,8 +709,24 @@ private String formatAsDirectory(String directory) {
return directory.replace(GROUP_SEPARATOR, PATH_SEPARATOR);
}

private <T> T getMojoParameterValue(MavenSession session, MojoExecution mojoExecution, String parameter,
private <T> T getMojoParameterValue(MavenSession session, MojoExecution mojoExecution, List<String> parameterPath,
Class<T> 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> T getMojoParameterValue(MavenSession session, MojoExecution mojoExecution,
PlexusConfiguration configuration, Class<T> asType, String parameterLabel) throws CoreException {
try {
MojoDescriptor mojoDescriptor = mojoExecution.getMojoDescriptor();

Expand All @@ -719,28 +735,46 @@ private <T> 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));
}
}

@Override
public <T> T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, String parameter,
Class<T> 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 <T>
* @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 <configuration>} 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> T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, List<String> parameterPath,
Class<T> asType, IProgressMonitor monitor) throws CoreException {
return getExecutionContext().execute(project,
(context, pm) -> getMojoParameterValue(context.getSession(), mojoExecution, parameterPath, asType), monitor);
}

private <T> T getMojoParameterValue(String parameter, Class<T> type, MavenSession session, Plugin plugin,
Expand Down
2 changes: 1 addition & 1 deletion org.eclipse.m2e.jdt/META-INF/MANIFEST.MF
Original file line number Diff line number Diff line change
Expand Up @@ -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",
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -44,18 +44,18 @@
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;
import org.apache.maven.project.MavenProject;

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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -845,34 +846,46 @@ private String getMinimumJavaBuildEnvironmentId(ProjectConfigurationRequest requ
try {
List<MojoExecution> 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 {
Expand All @@ -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) {
Expand Down

0 comments on commit 5fa26cf

Please sign in to comment.