BUG-114: added artifact version check in yang-maven-plugin. 24/6724/2
authorMartin Vitez <mvitez@cisco.com>
Wed, 30 Apr 2014 09:35:14 +0000 (11:35 +0200)
committerMartin Vitez <mvitez@cisco.com>
Mon, 5 May 2014 15:38:50 +0000 (17:38 +0200)
This patch bypasses use of maven aether due to version incompatibility between maven 3.0.x and 3.1.x.

Signed-off-by: Martin Vitez <mvitez@cisco.com>
Change-Id: If1c09a59353ef32a320131f7cbdbe92aa66acae2

yang/yang-maven-plugin-it/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/it/YangToSourcesPluginTestIT.java
yang/yang-maven-plugin-it/src/test/resources/InvalidVersion/pom.xml [new file with mode: 0644]
yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/Util.java
yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesMojo.java
yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/GenerateSourcesTest.java

index 72796c6752da78649ebf795e001187f2b1dc52e7..daf737089d1bff86c2297fd263255d31cf716d58 100644 (file)
@@ -109,6 +109,13 @@ public class YangToSourcesPluginTestIT {
         v.verifyTextInLog("[WARNING] yang-to-sources: No code generators provided");
     }
 
+    @Test
+    public void testInvalidVersion() throws Exception {
+        Verifier v = setUp("InvalidVersion/", false);
+        v.verifyErrorFreeLog();
+        v.verifyTextInLog("[WARNING] yang-to-sources: Dependency resolution conflict:");
+    }
+
     @Test
     public void testUnknownGenerator() throws Exception {
         Verifier v = setUp("UnknownGenerator/", true);
diff --git a/yang/yang-maven-plugin-it/src/test/resources/InvalidVersion/pom.xml b/yang/yang-maven-plugin-it/src/test/resources/InvalidVersion/pom.xml
new file mode 100644 (file)
index 0000000..d33ca7d
--- /dev/null
@@ -0,0 +1,82 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!-- vi: set et smarttab sw=4 tabstop=4: -->
+<!-- Copyright (c) 2013 Cisco Systems, Inc. and others. All rights reserved. This
+    program and the accompanying materials are made available under the terms of the
+    Eclipse Public License v1.0 which accompanies this distribution, and is available
+    at http://www.eclipse.org/legal/epl-v10.html -->
+<project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
+    xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd">
+    <modelVersion>4.0.0</modelVersion>
+
+    <groupId>org.opendaylight.yangtools</groupId>
+    <version>0.5-SNAPSHOT</version>
+    <artifactId>test</artifactId>
+
+    <!-- Testing dependency -->
+    <!-- yang-common dependency added here only for purpose of 'artifact version
+        check' test: version of yang-common artifact has to be different than one defined
+        in yang-maven-plugin to make test pass -->
+    <repositories>
+        <repository>
+            <id>opendaylight-mirror</id>
+            <name>opendaylight-mirror</name>
+            <url>http://nexus.opendaylight.org/content/groups/public/</url>
+            <snapshots>
+                <enabled>false</enabled>
+            </snapshots>
+            <releases>
+                <enabled>true</enabled>
+                <updatePolicy>never</updatePolicy>
+            </releases>
+        </repository>
+    </repositories>
+    <dependencies>
+        <dependency>
+            <groupId>org.opendaylight.yangtools</groupId>
+            <artifactId>yang-common</artifactId>
+            <version>0.6.1</version>
+        </dependency>
+    </dependencies>
+    <!-- End of Testing dependency -->
+
+    <build>
+        <plugins>
+            <plugin>
+                <groupId>org.opendaylight.yangtools</groupId>
+                <artifactId>yang-maven-plugin</artifactId>
+                <version>${it-project.version}</version>
+                <executions>
+                    <execution>
+                        <goals>
+                            <goal>generate-sources</goal>
+                        </goals>
+                        <configuration>
+                            <yangFilesRootDir>../files</yangFilesRootDir>
+                            <inspectDependencies>false</inspectDependencies>
+                            <codeGenerators>
+                            </codeGenerators>
+                            <resourceProviders>
+                                <provider>
+                                    <resourceProviderClass>
+                                        org.opendaylight.yangtools.yang2sources.spi.ResourceProviderTestImpl
+                                    </resourceProviderClass>
+                                    <outputBaseDir>
+                                        outDir/
+                                    </outputBaseDir>
+                                </provider>
+                            </resourceProviders>
+                        </configuration>
+                    </execution>
+                </executions>
+                <dependencies>
+                    <dependency>
+                        <groupId>org.opendaylight.yangtools</groupId>
+                        <artifactId>yang-maven-plugin-spi</artifactId>
+                        <version>${it-project.version}</version>
+                        <type>test-jar</type>
+                    </dependency>
+                </dependencies>
+            </plugin>
+        </plugins>
+    </build>
+</project>
index b1dee91efec763483ea461f7fdd0f23cea2a631d..a3c2110b8c578c18208ce2bf67d9fc06ce86bfbc 100644 (file)
@@ -17,6 +17,7 @@ import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.Collection;
 import java.util.Enumeration;
+import java.util.HashMap;
 import java.util.List;
 import java.util.Map;
 import java.util.Set;
@@ -25,12 +26,18 @@ import java.util.zip.ZipFile;
 
 import org.apache.commons.io.FileUtils;
 import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.resolver.ArtifactResolutionRequest;
+import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
+import org.apache.maven.model.Dependency;
+import org.apache.maven.model.Plugin;
 import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
 import org.opendaylight.yangtools.yang.model.api.Module;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.util.NamedFileInputStream;
+import org.apache.maven.repository.RepositorySystem;
 
 import com.google.common.base.Preconditions;
 import com.google.common.collect.Lists;
@@ -146,6 +153,103 @@ final class Util {
         return dependencies;
     }
 
+    /**
+     * Read current project dependencies and check if it don't grab incorrect
+     * artifacts versions which could be in conflict with plugin dependencies.
+     *
+     * @param project
+     *            current project
+     * @param repoSystem
+     *            repository system
+     * @param localRepo
+     *            local repository
+     * @param remoteRepos
+     *            remote repositories
+     * @param log
+     *            logger
+     */
+    static void checkClasspath(MavenProject project, RepositorySystem repoSystem, ArtifactRepository localRepo,
+            List<ArtifactRepository> remoteRepos, Log log) {
+        Plugin plugin = project.getPlugin(YangToSourcesMojo.PLUGIN_NAME);
+        if (plugin == null) {
+            log.warn(message("%s not found, dependencies version check skipped", YangToSourcesProcessor.LOG_PREFIX,
+                    YangToSourcesMojo.PLUGIN_NAME));
+        } else {
+            Map<Artifact, Collection<Artifact>> pluginDependencies = new HashMap<>();
+            getPluginTransitiveDependencies(plugin, pluginDependencies, repoSystem, localRepo, remoteRepos, log);
+
+            Set<Artifact> projectDependencies = project.getDependencyArtifacts();
+            for (Map.Entry<Artifact, Collection<Artifact>> entry : pluginDependencies.entrySet()) {
+                checkArtifact(entry.getKey(), projectDependencies, log);
+                for (Artifact dependency : entry.getValue()) {
+                    checkArtifact(dependency, projectDependencies, log);
+                }
+            }
+        }
+    }
+
+    /**
+     * Read transitive dependencies of given plugin and store them in map.
+     *
+     * @param plugin
+     *            plugin to read
+     * @param map
+     *            map, where founded transitive dependencies will be stored
+     * @param repoSystem
+     *            repository system
+     * @param localRepository
+     *            local repository
+     * @param remoteRepos
+     *            list of remote repositories
+     * @param log
+     *            logger
+     */
+    private static void getPluginTransitiveDependencies(Plugin plugin, Map<Artifact, Collection<Artifact>> map,
+            RepositorySystem repoSystem, ArtifactRepository localRepository, List<ArtifactRepository> remoteRepos,
+            Log log) {
+
+        List<Dependency> pluginDependencies = plugin.getDependencies();
+        for (Dependency dep : pluginDependencies) {
+            Artifact artifact = repoSystem.createDependencyArtifact(dep);
+
+            ArtifactResolutionRequest request = new ArtifactResolutionRequest();
+            request.setArtifact(artifact);
+            request.setResolveTransitively(true);
+            request.setLocalRepository(localRepository);
+            request.setRemoteRepositories(remoteRepos);
+
+            ArtifactResolutionResult result = repoSystem.resolve(request);
+            Set<Artifact> pluginDependencyDependencies = result.getArtifacts();
+            map.put(artifact, pluginDependencyDependencies);
+        }
+    }
+
+    /**
+     * Check artifact against collection of dependencies. If collection contains
+     * artifact with same groupId and artifactId, but different version, logs a
+     * warning.
+     *
+     * @param artifact
+     *            artifact to check
+     * @param dependencies
+     *            collection of dependencies
+     * @param log
+     *            logger
+     */
+    private static void checkArtifact(Artifact artifact, Collection<Artifact> dependencies, Log log) {
+        for (org.apache.maven.artifact.Artifact d : dependencies) {
+            if (artifact.getGroupId().equals(d.getGroupId()) && artifact.getArtifactId().equals(d.getArtifactId())) {
+                if (!(artifact.getVersion().equals(d.getVersion()))) {
+                    log.warn(message("Dependency resolution conflict:", YangToSourcesProcessor.LOG_PREFIX));
+                    log.warn(message("'%s' dependency [%s] has different version than one "
+                            + "declared in current project [%s]. It is recommended to fix this problem "
+                            + "because it may cause compilation errors.", YangToSourcesProcessor.LOG_PREFIX,
+                            YangToSourcesMojo.PLUGIN_NAME, artifact, d));
+                }
+            }
+        }
+    }
+
     private static final String JAR_SUFFIX = ".jar";
 
     private static boolean isJar(File element) {
index 174e2acf5f571902a7dad7f873079a689b22449f..1f678a02230634155eca3f4e26795fe92e74ff27 100644 (file)
@@ -13,6 +13,7 @@ import java.util.Collections;
 import java.util.List;
 import java.util.Set;
 
+import org.apache.maven.artifact.repository.ArtifactRepository;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
@@ -22,6 +23,7 @@ import org.apache.maven.plugins.annotations.Mojo;
 import org.apache.maven.plugins.annotations.Parameter;
 import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
+import org.apache.maven.repository.RepositorySystem;
 import org.opendaylight.yangtools.yang.model.api.SchemaContext;
 import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl;
 import org.opendaylight.yangtools.yang2sources.plugin.ConfigArg.CodeGeneratorArg;
@@ -46,6 +48,7 @@ import com.google.common.annotations.VisibleForTesting;
  */
 @Mojo(name = "generate-sources", defaultPhase = LifecyclePhase.GENERATE_SOURCES, requiresDependencyResolution = ResolutionScope.COMPILE, requiresProject = true)
 public final class YangToSourcesMojo extends AbstractMojo {
+    public static final String PLUGIN_NAME = "org.opendaylight.yangtools:yang-maven-plugin";
 
     /**
      * Classes implementing {@link CodeGenerator} interface. An instance will be
@@ -78,8 +81,17 @@ public final class YangToSourcesMojo extends AbstractMojo {
 
     private YangToSourcesProcessor yangToSourcesProcessor;
 
-    public YangToSourcesMojo() {
+    @Component
+    private RepositorySystem repoSystem;
+
+    @Parameter( readonly = true, defaultValue = "${localRepository}" )
+    private ArtifactRepository localRepository;
+
+    @Parameter( readonly = true, defaultValue = "${project.remoteArtifactRepositories}" )
+    private List<ArtifactRepository> remoteRepos;
 
+
+    public YangToSourcesMojo() {
     }
 
     public void setProject(MavenProject project) {
@@ -94,6 +106,9 @@ public final class YangToSourcesMojo extends AbstractMojo {
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
         StaticLoggerBinder.getSingleton().setMavenLog(this.getLog());
+
+        Util.checkClasspath(project, repoSystem, localRepository, remoteRepos, getLog());
+
         if (yangToSourcesProcessor == null) {
             List<CodeGeneratorArg> codeGeneratorArgs = processCodeGenerators(codeGenerators);
 
@@ -101,8 +116,8 @@ public final class YangToSourcesMojo extends AbstractMojo {
             File yangFilesRootFile = processYangFilesRootDir(yangFilesRootDir, project.getBasedir());
             File[] excludedFiles = processExcludeFiles(excludeFiles, yangFilesRootFile);
 
-            yangToSourcesProcessor = new YangToSourcesProcessor(buildContext, getLog(), yangFilesRootFile, excludedFiles,
-                    codeGeneratorArgs, project, inspectDependencies);
+            yangToSourcesProcessor = new YangToSourcesProcessor(buildContext, getLog(), yangFilesRootFile,
+                    excludedFiles, codeGeneratorArgs, project, inspectDependencies);
         }
         yangToSourcesProcessor.execute();
     }
index 3ab8a8c228734b633f9f80a5d3a82abceca320e4..3389839e325f0fda116cf5701ac3da603949bd6e 100644 (file)
@@ -16,9 +16,12 @@ import static org.mockito.Mockito.*;
 import java.io.File;
 import java.io.IOException;
 import java.util.Collection;
+import java.util.Collections;
 import java.util.Map;
 import java.util.Set;
 
+import org.apache.maven.model.Plugin;
+import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugin.logging.Log;
 import org.apache.maven.project.MavenProject;
 import org.junit.Before;
@@ -40,6 +43,8 @@ public class GenerateSourcesTest {
     private File outDir;
     @Mock
     private MavenProject project;
+    @Mock
+    private Plugin plugin;
 
     @Before
     public void setUp() throws Exception {
@@ -56,6 +61,8 @@ public class GenerateSourcesTest {
                 mock);
         mojo = new YangToSourcesMojo(processor);
         doReturn(new File("")).when(project).getBasedir();
+        doReturn(Collections.emptyList()).when(plugin).getDependencies();
+        doReturn(plugin).when(project).getPlugin(YangToSourcesMojo.PLUGIN_NAME);
         mojo.setProject(project);
     }