From 47538f5568578658ba89f62281a46bab28e81974 Mon Sep 17 00:00:00 2001 From: Martin Vitez Date: Wed, 12 Feb 2014 14:46:16 +0100 Subject: [PATCH] Fix for Bug 114. Added check for artifact versions pulled by project against ones declared in plugin dependencies. Change-Id: Ib7663eaa775fa6799ae11a3132fbd7ca080cb0e7 Signed-off-by: Martin Vitez --- .../plugin/it/YangToSourcesPluginTestIT.java | 7 + .../src/test/resources/InvalidVersion/pom.xml | 82 ++++++++++++ yang/yang-maven-plugin/pom.xml | 16 +++ .../yangtools/yang2sources/plugin/Util.java | 125 ++++++++++++++++++ .../plugin/YangToSourcesMojo.java | 17 +++ .../plugin/GenerateSourcesTest.java | 7 + 6 files changed, 254 insertions(+) create mode 100644 yang/yang-maven-plugin-it/src/test/resources/InvalidVersion/pom.xml diff --git a/yang/yang-maven-plugin-it/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/it/YangToSourcesPluginTestIT.java b/yang/yang-maven-plugin-it/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/it/YangToSourcesPluginTestIT.java index 72796c6752..daf737089d 100644 --- a/yang/yang-maven-plugin-it/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/it/YangToSourcesPluginTestIT.java +++ b/yang/yang-maven-plugin-it/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/it/YangToSourcesPluginTestIT.java @@ -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 index 0000000000..76c8f17105 --- /dev/null +++ b/yang/yang-maven-plugin-it/src/test/resources/InvalidVersion/pom.xml @@ -0,0 +1,82 @@ + + + + + 4.0.0 + + org.opendaylight.yangtools + 0.5-SNAPSHOT + test + + + + + + opendaylight-mirror + opendaylight-mirror + http://nexus.opendaylight.org/content/groups/public/ + + false + + + true + never + + + + + + org.opendaylight.yangtools + yang-common + 0.6.1 + + + + + + + + org.opendaylight.yangtools + yang-maven-plugin + ${it-project.version} + + + + generate-sources + + + ../files + false + + + + + + org.opendaylight.yangtools.yang2sources.spi.ResourceProviderTestImpl + + + outDir/ + + + + + + + + + org.opendaylight.yangtools + yang-maven-plugin-spi + ${it-project.version} + test-jar + + + + + + diff --git a/yang/yang-maven-plugin/pom.xml b/yang/yang-maven-plugin/pom.xml index 8ffa8204c2..61530777a8 100644 --- a/yang/yang-maven-plugin/pom.xml +++ b/yang/yang-maven-plugin/pom.xml @@ -68,6 +68,12 @@ org.codehaus.plexus plexus-slf4j-logging + + + google-collections + com.google.collections + + @@ -101,6 +107,16 @@ sisu-inject-plexus 2.5.0 + + org.sonatype.aether + aether-api + 1.13.1 + + + org.sonatype.aether + aether-util + 1.13.1 + diff --git a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/Util.java b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/Util.java index b1dee91efe..bcb7bc9b3c 100644 --- a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/Util.java +++ b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/Util.java @@ -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,24 @@ import java.util.zip.ZipFile; import org.apache.commons.io.FileUtils; import org.apache.maven.artifact.Artifact; +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.sonatype.aether.RepositorySystem; +import org.sonatype.aether.RepositorySystemSession; +import org.sonatype.aether.collection.CollectRequest; +import org.sonatype.aether.graph.DependencyFilter; +import org.sonatype.aether.repository.RemoteRepository; +import org.sonatype.aether.resolution.ArtifactResult; +import org.sonatype.aether.resolution.DependencyRequest; +import org.sonatype.aether.resolution.DependencyResolutionException; +import org.sonatype.aether.util.artifact.JavaScopes; +import org.sonatype.aether.util.filter.DependencyFilterUtils; import com.google.common.base.Preconditions; import com.google.common.collect.Lists; @@ -146,6 +159,118 @@ 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 log + * logger + * @param repoSystem + * repository system + * @param repoSession + * repository system session + * @param remoteRepos + * remote repositories + */ + static void checkClasspath(MavenProject project, Log log, RepositorySystem repoSystem, + RepositorySystemSession repoSession, List remoteRepos) { + 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> pluginDependencies = new HashMap<>(); + getPluginTransitiveDependencies(plugin, pluginDependencies, repoSystem, repoSession, remoteRepos, log); + + Set projectDependencies = project.getDependencyArtifacts(); + for (Map.Entry> entry : pluginDependencies + .entrySet()) { + checkArtifact(entry.getKey(), projectDependencies, log); + for (org.sonatype.aether.artifact.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 repoSession + * repository system session + * @param remoteRepos + * list of remote repositories + * @param log + * logger + */ + private static void getPluginTransitiveDependencies(Plugin plugin, + Map> map, + RepositorySystem repoSystem, RepositorySystemSession repoSession, List remoteRepos, + Log log) { + for (Dependency dep : plugin.getDependencies()) { + String artifactCoords = dep.getGroupId() + ":" + dep.getArtifactId() + ":" + dep.getVersion(); + org.sonatype.aether.artifact.Artifact artifact = new org.sonatype.aether.util.artifact.DefaultArtifact( + artifactCoords); + + if (!(map.containsKey(artifact))) { + DependencyFilter classpathFlter = DependencyFilterUtils.classpathFilter(JavaScopes.COMPILE); + CollectRequest collectRequest = new CollectRequest(); + collectRequest.setRoot(new org.sonatype.aether.graph.Dependency(artifact, JavaScopes.COMPILE)); + collectRequest.setRepositories(remoteRepos); + DependencyRequest dependencyRequest = new DependencyRequest(collectRequest, classpathFlter); + + List artifactResults; + try { + artifactResults = repoSystem.resolveDependencies(repoSession, dependencyRequest) + .getArtifactResults(); + List deps = new ArrayList<>(); + for (ArtifactResult ar : artifactResults) { + deps.add(ar.getArtifact()); + } + map.put(artifact, deps); + } catch (DependencyResolutionException e) { + log.warn(message("Failed to resolve plugin dependencies, version check skipped", + YangToSourcesProcessor.LOG_PREFIX)); + } + } + } + } + + /** + * 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(org.sonatype.aether.artifact.Artifact artifact, Collection dependencies, + Log log) { + for (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) { diff --git a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesMojo.java b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesMojo.java index 174e2acf5f..933b0d58e8 100644 --- a/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesMojo.java +++ b/yang/yang-maven-plugin/src/main/java/org/opendaylight/yangtools/yang2sources/plugin/YangToSourcesMojo.java @@ -27,6 +27,9 @@ import org.opendaylight.yangtools.yang.parser.impl.YangParserImpl; import org.opendaylight.yangtools.yang2sources.plugin.ConfigArg.CodeGeneratorArg; import org.opendaylight.yangtools.yang2sources.spi.CodeGenerator; import org.slf4j.impl.StaticLoggerBinder; +import org.sonatype.aether.RepositorySystem; +import org.sonatype.aether.RepositorySystemSession; +import org.sonatype.aether.repository.RemoteRepository; import org.sonatype.plexus.build.incremental.BuildContext; import com.google.common.annotations.VisibleForTesting; @@ -46,6 +49,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,6 +82,16 @@ public final class YangToSourcesMojo extends AbstractMojo { private YangToSourcesProcessor yangToSourcesProcessor; + @Component + private RepositorySystem repoSystem; + + @Parameter( readonly = true, defaultValue = "${repositorySystemSession}" ) + private RepositorySystemSession repoSession; + + @Parameter( readonly = true, defaultValue = "${project.remoteProjectRepositories}" ) + private List remoteRepos; + + public YangToSourcesMojo() { } @@ -94,6 +108,9 @@ public final class YangToSourcesMojo extends AbstractMojo { @Override public void execute() throws MojoExecutionException, MojoFailureException { StaticLoggerBinder.getSingleton().setMavenLog(this.getLog()); + + Util.checkClasspath(project, getLog(), repoSystem, repoSession, remoteRepos); + if (yangToSourcesProcessor == null) { List codeGeneratorArgs = processCodeGenerators(codeGenerators); diff --git a/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/GenerateSourcesTest.java b/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/GenerateSourcesTest.java index 3ab8a8c228..3389839e32 100644 --- a/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/GenerateSourcesTest.java +++ b/yang/yang-maven-plugin/src/test/java/org/opendaylight/yangtools/yang2sources/plugin/GenerateSourcesTest.java @@ -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); } -- 2.36.6