You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@maven.apache.org by rf...@apache.org on 2021/03/21 13:14:48 UTC

[maven] branch MNG-7122 created (now 313f847)

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

rfscholte pushed a change to branch MNG-7122
in repository https://gitbox.apache.org/repos/asf/maven.git.


      at 313f847  [MNG-7122] Require specific Maven compatibility version for plugins

This branch includes the following new commits:

     new 313f847  [MNG-7122] Require specific Maven compatibility version for plugins

The 1 revisions listed above as "new" are entirely new to this
repository and will be described in separate emails.  The revisions
listed as "add" were already present in the repository and have only
been added to this reference.


[maven] 01/01: [MNG-7122] Require specific Maven compatibility version for plugins

Posted by rf...@apache.org.
This is an automated email from the ASF dual-hosted git repository.

rfscholte pushed a commit to branch MNG-7122
in repository https://gitbox.apache.org/repos/asf/maven.git

commit 313f847b9bbed3be3d6178f7893bbf6fb48b7c77
Author: rfscholte <rf...@apache.org>
AuthorDate: Sun Mar 21 14:14:11 2021 +0100

    [MNG-7122] Require specific Maven compatibility version for plugins
---
 .../DefaultPluginDependenciesResolver.java         | 26 ++++++-
 .../internal/IncompatibleDependencyException.java  | 37 ++++++++++
 .../plugin/internal/MavenCompatibilityChecker.java | 80 ++++++++++++++++++++
 .../internal/MavenCompatibilityCheckerTest.java    | 85 ++++++++++++++++++++++
 4 files changed, 227 insertions(+), 1 deletion(-)

diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
index 709bd72..cc90837 100644
--- a/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
+++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/DefaultPluginDependenciesResolver.java
@@ -60,7 +60,11 @@ import org.eclipse.aether.util.filter.AndDependencyFilter;
 import org.eclipse.aether.util.filter.ScopeDependencyFilter;
 import org.eclipse.aether.util.graph.manager.DependencyManagerUtils;
 import org.eclipse.aether.util.graph.selector.AndDependencySelector;
+import org.eclipse.aether.util.graph.transformer.ChainedDependencyGraphTransformer;
 import org.eclipse.aether.util.repository.SimpleArtifactDescriptorPolicy;
+import org.eclipse.aether.util.version.GenericVersionScheme;
+import org.eclipse.aether.version.InvalidVersionSpecificationException;
+import org.eclipse.aether.version.VersionRange;
 
 /**
  * Assists in resolving the dependencies of a plugin. <strong>Warning:</strong> This is an internal utility class that
@@ -75,6 +79,7 @@ import org.eclipse.aether.util.repository.SimpleArtifactDescriptorPolicy;
 public class DefaultPluginDependenciesResolver
     implements PluginDependenciesResolver
 {
+    private static final String MAVENCORE_COMPATIBILITY_VERSIONS = "(,)";
 
     private static final String REPOSITORY_CONTEXT = "plugin";
 
@@ -83,6 +88,23 @@ public class DefaultPluginDependenciesResolver
 
     @Inject
     private RepositorySystem repoSystem;
+    
+    private final VersionRange mavenCompatibilityVersionRange;
+    
+    public DefaultPluginDependenciesResolver() 
+    {
+        try
+        {
+            // o.a.m.plugins:maven-compiler-plugin:jar:3.1 depends on o.a.m:maven-toolchain:jar:1.0
+            // maven-its:mng-4666 depends on o.a.m:maven-model:0.1-stub
+            this.mavenCompatibilityVersionRange =
+                new GenericVersionScheme().parseVersionRange( MAVENCORE_COMPATIBILITY_VERSIONS );
+        }
+        catch ( InvalidVersionSpecificationException e )
+        {
+            throw new RuntimeException( e );
+        }
+    }
 
     private Artifact toArtifact( Plugin plugin, RepositorySystemSession session )
     {
@@ -178,7 +200,9 @@ public class DefaultPluginDependenciesResolver
 
             DefaultRepositorySystemSession pluginSession = new DefaultRepositorySystemSession( session );
             pluginSession.setDependencySelector( selector );
-            pluginSession.setDependencyGraphTransformer( session.getDependencyGraphTransformer() );
+            pluginSession.setDependencyGraphTransformer( ChainedDependencyGraphTransformer.newInstance( 
+                                                session.getDependencyGraphTransformer(),
+                                                new MavenCompatibilityChecker( mavenCompatibilityVersionRange ) ) );
 
             CollectRequest request = new CollectRequest();
             request.setRequestContext( REPOSITORY_CONTEXT );
diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/IncompatibleDependencyException.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/IncompatibleDependencyException.java
new file mode 100644
index 0000000..6a1d074
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/IncompatibleDependencyException.java
@@ -0,0 +1,37 @@
+package org.apache.maven.plugin.internal;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.eclipse.aether.graph.DependencyNode;
+
+class IncompatibleDependencyException extends Exception
+{
+    private final DependencyNode node;
+    
+    IncompatibleDependencyException( DependencyNode node )
+    {
+        this.node = node;
+    }
+    
+    DependencyNode getNode()
+    {
+        return node;
+    }
+}
diff --git a/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenCompatibilityChecker.java b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenCompatibilityChecker.java
new file mode 100644
index 0000000..44b3c5a
--- /dev/null
+++ b/maven-core/src/main/java/org/apache/maven/plugin/internal/MavenCompatibilityChecker.java
@@ -0,0 +1,80 @@
+package org.apache.maven.plugin.internal;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import org.eclipse.aether.RepositoryException;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.collection.DependencyGraphTransformationContext;
+import org.eclipse.aether.collection.DependencyGraphTransformer;
+import org.eclipse.aether.graph.DependencyNode;
+import org.eclipse.aether.version.VersionRange;
+
+/**
+ * Ensure that Maven core dependencies fit within the versionRange
+ * 
+ * @since 4.0.0
+ */
+class MavenCompatibilityChecker implements DependencyGraphTransformer
+{
+    private final VersionRange versionRange;
+    
+    MavenCompatibilityChecker( VersionRange versionRange )
+    {
+        this.versionRange = versionRange;
+    }
+
+    @Override
+    public DependencyNode transformGraph( DependencyNode node, DependencyGraphTransformationContext context )
+        throws RepositoryException
+    {
+        try 
+        {
+            validateNode( node );
+        }
+        catch ( IncompatibleDependencyException e )
+        {
+            throw new RepositoryException( 
+                       String.format( "%s depends on %s, which does not match the required Maven versionrange of %s",
+                                      node.getArtifact(), e.getNode().getArtifact(), versionRange ) );
+        }
+
+        return node;
+    }
+    
+    private void validateNode( DependencyNode node )
+        throws IncompatibleDependencyException
+    {
+        if ( isCoreArtifact( node.getArtifact() ) && !versionRange.containsVersion( node.getVersion() ) ) 
+        {
+            throw new IncompatibleDependencyException( node );
+        }
+        
+        for ( DependencyNode child : node.getChildren() )
+        {
+            validateNode( child );
+        }
+    }
+    
+    private static boolean isCoreArtifact( Artifact artifact )
+    {
+        return artifact.getArtifactId().startsWith( "maven-" )
+            && artifact.getGroupId().equals( "org.apache.maven" );
+    }
+}
diff --git a/maven-core/src/test/java/org/apache/maven/plugin/internal/MavenCompatibilityCheckerTest.java b/maven-core/src/test/java/org/apache/maven/plugin/internal/MavenCompatibilityCheckerTest.java
new file mode 100644
index 0000000..5b4bc29
--- /dev/null
+++ b/maven-core/src/test/java/org/apache/maven/plugin/internal/MavenCompatibilityCheckerTest.java
@@ -0,0 +1,85 @@
+package org.apache.maven.plugin.internal;
+
+/*
+ * Licensed to the Apache Software Foundation (ASF) under one
+ * or more contributor license agreements.  See the NOTICE file
+ * distributed with this work for additional information
+ * regarding copyright ownership.  The ASF licenses this file
+ * to you under the Apache License, Version 2.0 (the
+ * "License"); you may not use this file except in compliance
+ * with the License.  You may obtain a copy of the License at
+ *
+ *   http://www.apache.org/licenses/LICENSE-2.0
+ *
+ * Unless required by applicable law or agreed to in writing,
+ * software distributed under the License is distributed on an
+ * "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY
+ * KIND, either express or implied.  See the License for the
+ * specific language governing permissions and limitations
+ * under the License.
+ */
+
+import static org.hamcrest.MatcherAssert.assertThat;
+import static org.hamcrest.Matchers.is;
+import static org.junit.jupiter.api.Assertions.assertThrows;
+
+import java.util.Collections;
+
+import org.eclipse.aether.RepositoryException;
+import org.eclipse.aether.artifact.Artifact;
+import org.eclipse.aether.artifact.DefaultArtifact;
+import org.eclipse.aether.graph.DefaultDependencyNode;
+import org.eclipse.aether.graph.Dependency;
+import org.eclipse.aether.util.version.GenericVersionScheme;
+import org.eclipse.aether.version.VersionScheme;
+import org.junit.jupiter.api.Test;
+
+class MavenCompatibilityCheckerTest
+{
+    private final VersionScheme versionScheme = new GenericVersionScheme();
+
+    @Test
+    void compatible() throws Exception
+    {
+        MavenCompatibilityChecker checker =
+            new MavenCompatibilityChecker( versionScheme.parseVersionRange( "[3.0,)" ) );
+        
+        Artifact pluginArtifact = new DefaultArtifact( "o.a.m.p:plugin:1.0" );
+        Dependency plugin = new Dependency( pluginArtifact, "compile" );
+        DefaultDependencyNode node = new DefaultDependencyNode( plugin );
+        node.setVersion( versionScheme.parseVersion( "1.0" ) );
+
+        Artifact coreArtifact = new DefaultArtifact( "org.apache.maven:maven-core:3.0" );
+        Dependency core = new Dependency( coreArtifact, "compile" );
+        DefaultDependencyNode coreNode = new DefaultDependencyNode( core );
+        coreNode.setVersion( versionScheme.parseVersion( "3.0" ) );
+        
+        node.setChildren(Collections.singletonList( coreNode ) );
+        
+        assertThat( checker.transformGraph( node, null ), is(node));
+    }
+
+    @Test
+    void incompatible() throws Exception
+    {
+        MavenCompatibilityChecker checker =
+                        new MavenCompatibilityChecker( versionScheme.parseVersionRange( "[3.0,)" ) );
+                    
+        Artifact pluginArtifact = new DefaultArtifact( "o.a.m.p:plugin:1.0" );
+        Dependency plugin = new Dependency( pluginArtifact, "compile" );
+        DefaultDependencyNode node = new DefaultDependencyNode( plugin );
+        node.setVersion( versionScheme.parseVersion( "1.0" ) );
+
+        Artifact coreArtifact = new DefaultArtifact( "org.apache.maven:maven-core:2.0" );
+        Dependency core = new Dependency( coreArtifact, "compile" );
+        DefaultDependencyNode coreNode = new DefaultDependencyNode( core );
+        coreNode.setVersion( versionScheme.parseVersion( "2.0" ) );
+        
+        node.setChildren(Collections.singletonList( coreNode ) );
+        
+        RepositoryException exception = assertThrows( RepositoryException.class, () -> checker.transformGraph( node, null ) );
+        assertThat( exception.getMessage(), is( "o.a.m.p:plugin:jar:1.0 depends on org.apache.maven:maven-core:jar:2.0, "
+            + "which does not match the required Maven versionrange of [3.0,)" ) );
+    }
+
+}