You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by hb...@apache.org on 2019/12/06 13:38:09 UTC

[maven-studies] branch maven-buildinfo-plugin updated: added a note about Maven minumum version algorithm

This is an automated email from the ASF dual-hosted git repository.

hboutemy pushed a commit to branch maven-buildinfo-plugin
in repository https://gitbox.apache.org/repos/asf/maven-studies.git


The following commit(s) were added to refs/heads/maven-buildinfo-plugin by this push:
     new 6d455ed  added a note about Maven minumum version algorithm
6d455ed is described below

commit 6d455ed079af4e37e533eb83aad3b50d86431110
Author: Hervé Boutemy <hb...@apache.org>
AuthorDate: Fri Dec 6 14:38:00 2019 +0100

    added a note about Maven minumum version algorithm
---
 .../buildinfo/RequiredMavenVersionFinder.java      | 290 +++++++++++++++++++++
 .../apache/maven/plugins/buildinfo/SaveMojo.java   |   1 +
 2 files changed, 291 insertions(+)

diff --git a/src/main/java/org/apache/maven/plugins/buildinfo/RequiredMavenVersionFinder.java b/src/main/java/org/apache/maven/plugins/buildinfo/RequiredMavenVersionFinder.java
new file mode 100644
index 0000000..4e7f017
--- /dev/null
+++ b/src/main/java/org/apache/maven/plugins/buildinfo/RequiredMavenVersionFinder.java
@@ -0,0 +1,290 @@
+package org.apache.maven.plugins.buildinfo;
+
+import org.apache.maven.artifact.versioning.ArtifactVersion;
+import org.apache.maven.artifact.versioning.DefaultArtifactVersion;
+import org.apache.maven.model.Plugin;
+import org.apache.maven.model.PluginExecution;
+import org.apache.maven.model.Prerequisites;
+import org.apache.maven.project.MavenProject;
+import org.codehaus.plexus.util.xml.Xpp3Dom;
+
+import java.util.ArrayList;
+import java.util.List;
+
+/**
+ * Finds the minimum Maven version required by a Maven project. Checks for the existence of both the prerequisites.maven
+ * property and for maven-enforcer-plugin:enforce goal. Returns null if no minimum version is found. Checks project and
+ * it's parents recursively.
+ * <p>
+ * Pros: works with Maven 3.5.0 which throws a warning if prerequisites.maven is set for a non Maven-Plugin project.
+ * Cons: tightly coupled with the maven-enforcer-plugin and the Xpp3Dom configuration tag.
+ */
+public class RequiredMavenVersionFinder
+{
+
+    private final MavenProject mavenProject;
+
+    RequiredMavenVersionFinder( MavenProject mavenProject )
+    {
+        this.mavenProject = mavenProject;
+    }
+
+    ArtifactVersion find()
+    {
+        ArtifactVersion childMavenVersion = getHighestArtifactVersion( getPrerequisitesMavenVersion(),
+                getEnforcerMavenVersion() );
+
+        if ( !mavenProject.hasParent() )
+        {
+            return childMavenVersion;
+        }
+
+        ArtifactVersion parentMavenVersion = new RequiredMavenVersionFinder( mavenProject.getParent() ).find();
+
+        return getHighestArtifactVersion( childMavenVersion, parentMavenVersion );
+    }
+
+    private ArtifactVersion getPrerequisitesMavenVersion()
+    {
+        Prerequisites prerequisites = mavenProject.getPrerequisites();
+        if ( null == prerequisites )
+        {
+            return null;
+        }
+
+        String prerequisitesMavenValue = prerequisites.getMaven();
+        if ( null == prerequisitesMavenValue )
+        {
+            return null;
+        }
+
+        return new DefaultArtifactVersion( prerequisitesMavenValue );
+    }
+
+    private ArtifactVersion getEnforcerMavenVersion()
+    {
+        List<Plugin> buildPlugins = mavenProject.getBuildPlugins();
+        if ( null == buildPlugins )
+        {
+            return null;
+        }
+
+        Plugin mavenEnforcerPlugin = getMavenEnforcerPlugin( buildPlugins );
+        if ( null == mavenEnforcerPlugin )
+        {
+            return null;
+        }
+
+        List<PluginExecution> pluginExecutions = mavenEnforcerPlugin.getExecutions();
+        if ( null == pluginExecutions )
+        {
+            return null;
+        }
+
+        List<PluginExecution> pluginExecutionsWithEnforceGoal = getPluginExecutionsWithEnforceGoal( pluginExecutions );
+        if ( pluginExecutionsWithEnforceGoal.isEmpty() )
+        {
+            return null;
+        }
+
+        Xpp3Dom requireMavenVersionTag = getRequireMavenVersionTag( pluginExecutionsWithEnforceGoal );
+        if ( null == requireMavenVersionTag )
+        {
+            return null;
+        }
+
+        Xpp3Dom versionTag = requireMavenVersionTag.getChild( "version" );
+        if ( null == versionTag )
+        {
+            return null;
+        }
+
+        String versionTagValue = versionTag.getValue();
+        if ( null == versionTagValue || "".equals( versionTagValue ) )
+        {
+            return null;
+        }
+
+        return processMavenVersionRange( versionTagValue );
+    }
+
+    private Plugin getMavenEnforcerPlugin( List<Plugin> buildPlugins )
+    {
+        for ( Plugin plugin : buildPlugins )
+        {
+            if ( "maven-enforcer-plugin".equals( plugin.getArtifactId() ) )
+            {
+                return plugin;
+            }
+        }
+        return null;
+    }
+
+    private List<PluginExecution> getPluginExecutionsWithEnforceGoal( List<PluginExecution> executions )
+    {
+        List<PluginExecution> pluginExecutions = new ArrayList<>();
+        for ( PluginExecution pluginExecution : executions )
+        {
+            List<String> goals = pluginExecution.getGoals();
+            if ( goals != null && goals.contains( "enforce" ) )
+            {
+                pluginExecutions.add( pluginExecution );
+            }
+        }
+        return pluginExecutions;
+    }
+
+    private Xpp3Dom getRequireMavenVersionTag( List<PluginExecution> executions )
+    {
+        for ( PluginExecution pluginExecution : executions )
+        {
+            Xpp3Dom configurationTag = (Xpp3Dom) pluginExecution.getConfiguration();
+            if ( null == configurationTag )
+            {
+                continue;
+            }
+
+            Xpp3Dom rulesTag = configurationTag.getChild( "rules" );
+            if ( null == rulesTag )
+            {
+                continue;
+            }
+
+            Xpp3Dom requireMavenVersionTag = rulesTag.getChild( "requireMavenVersion" );
+            if ( null == requireMavenVersionTag )
+            {
+                continue;
+            }
+
+            return requireMavenVersionTag;
+        }
+        return null;
+    }
+
+    private ArtifactVersion getHighestArtifactVersion( ArtifactVersion firstMavenVersion, ArtifactVersion secondMavenVersion )
+    {
+        if ( null == firstMavenVersion && null == secondMavenVersion )
+        {
+            return null;
+        }
+
+        if ( null == firstMavenVersion )
+        {
+            return secondMavenVersion;
+        }
+
+        if ( null == secondMavenVersion )
+        {
+            return firstMavenVersion;
+        }
+
+        if ( firstMavenVersion.compareTo( secondMavenVersion ) < 0 )
+        {
+            return secondMavenVersion;
+        }
+
+        return firstMavenVersion;
+    }
+
+    /**
+     * The below method implements the specification found at
+     * https://maven.apache.org/enforcer/enforcer-rules/versionRanges.html
+     */
+    private ArtifactVersion processMavenVersionRange( String versionRange )
+    {
+
+        int openIndicesCount = 0;
+        int closeIndicesCount = 0;
+
+        for ( int i = 0; i < versionRange.length(); i++ )
+        {
+            char character = versionRange.charAt( i );
+
+            if ( '(' == character || '[' == character )
+            {
+                openIndicesCount++;
+            }
+            else if ( ')' == character || ']' == character )
+            {
+                closeIndicesCount++;
+            }
+        }
+
+        if ( openIndicesCount != closeIndicesCount )
+        {
+            return null;
+        }
+
+        if ( openIndicesCount == 0 )
+        {
+            return new DefaultArtifactVersion( versionRange );
+        }
+
+        if ( !( ( versionRange.charAt( 0 ) == '[' || versionRange.charAt( 0 ) == '(' ) && ( versionRange.charAt(
+                versionRange.length() - 1 ) == ']' || versionRange.charAt( versionRange.length() - 1 ) == ')' ) ) )
+        {
+            return null;
+        }
+
+        if ( openIndicesCount != 1 )
+        {
+            return null;
+        }
+
+        String innerString = versionRange.substring( 1, versionRange.length() - 1 );
+
+        int commaIndex = innerString.indexOf( ',' );
+
+        if ( commaIndex == -1 )
+        {
+            if ( versionRange.charAt( 0 ) == '[' && versionRange.charAt( versionRange.length() - 1 ) == ']' )
+            {
+                return new DefaultArtifactVersion( innerString );
+            }
+            else
+            {
+                return null;
+            }
+        }
+
+        if ( commaIndex == 0 )
+        {
+            return null;
+        }
+
+        if ( commaIndex == innerString.length() - 1 )
+        {
+            String minimumVersion = innerString.substring( 0, innerString.length() - 1 );
+
+            if ( versionRange.charAt( 0 ) == '[' && versionRange.charAt( versionRange.length() - 1 ) == ')' )
+            {
+                return new DefaultArtifactVersion( minimumVersion );
+            }
+
+            if ( versionRange.charAt( 0 ) == '(' && versionRange.charAt( versionRange.length() - 1 ) == ')' )
+            {
+                // this is actually wrong - the Maven version should be higher than this,
+                // the Maven version cannot be equal to this, but the Maven Enforcer plugin should capture this
+                return new DefaultArtifactVersion( minimumVersion );
+            }
+
+            return null;
+        }
+
+        String minimumVersion = innerString.substring( 0, commaIndex );
+
+        if ( versionRange.charAt( 0 ) == '[' )
+        {
+            return new DefaultArtifactVersion( minimumVersion );
+        }
+
+        if ( versionRange.charAt( 0 ) == '(' )
+        {
+            // this is actually wrong - the Maven version should be higher than this,
+            // the Maven version cannot be equal to this, but the Maven Enforcer plugin should capture this
+            return new DefaultArtifactVersion( minimumVersion );
+        }
+
+        return null;
+    }
+}
diff --git a/src/main/java/org/apache/maven/plugins/buildinfo/SaveMojo.java b/src/main/java/org/apache/maven/plugins/buildinfo/SaveMojo.java
index d4baf45..37d105f 100644
--- a/src/main/java/org/apache/maven/plugins/buildinfo/SaveMojo.java
+++ b/src/main/java/org/apache/maven/plugins/buildinfo/SaveMojo.java
@@ -120,6 +120,7 @@ public class SaveMojo
             p.println( "mvn.version=" + MavenVersion.createMavenVersionString() );
             if ( ( project.getPrerequisites() != null ) && ( project.getPrerequisites().getMaven() != null ) )
             {
+                // TODO wrong algorithm, should reuse algorithm written in versions-maven-plugin
                 p.println( "mvn.minimum.version=" + project.getPrerequisites().getMaven() );
             }
             p.println();