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 Oct 11, 2022
1 parent 0223a44 commit de53541
Show file tree
Hide file tree
Showing 4 changed files with 104 additions and 37 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.1.0.qualifier
Bundle-Activator: org.eclipse.m2e.core.internal.MavenPluginActivator
Bundle-Vendor: %Bundle-Vendor
Bundle-Localization: plugin
Expand Down
34 changes: 34 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 @@ -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;

Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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 <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
* @see IMaven#getMojoParameterValue(MavenProject, MojoExecution, List, Class, IProgressMonitor)
*/
<T> T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, String parameter,
Class<T> 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 <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
* @since 2.1.0
* @see IMaven#getMojoParameterValue(MavenProject, MojoExecution, String, Class, IProgressMonitor)
*/
<T> T getMojoParameterValue(MavenProject project, MojoExecution mojoExecution, List<String> parameterPath,
Class<T> asType, IProgressMonitor monitor) throws CoreException;

/**
* @since 1.4
*/
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -730,8 +730,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 @@ -740,14 +756,7 @@ 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);
Expand All @@ -761,9 +770,18 @@ private <T> T getMojoParameterValue(MavenSession session, MojoExecution mojoExec
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,
Collections.singletonList(parameter), asType),
monitor);
}

@Override
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,
ConfigurationContainer configuration, String goal) throws CoreException {
Xpp3Dom config = (Xpp3Dom) configuration.getConfiguration();
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down Expand Up @@ -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;
}

Expand Down Expand Up @@ -845,34 +845,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 = 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 {
Expand All @@ -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) {
Expand Down

0 comments on commit de53541

Please sign in to comment.