--- /dev/null
+<?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>
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;
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;
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<RemoteRepository> 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<org.sonatype.aether.artifact.Artifact, List<org.sonatype.aether.artifact.Artifact>> pluginDependencies = new HashMap<>();
+ getPluginTransitiveDependencies(plugin, pluginDependencies, repoSystem, repoSession, remoteRepos, log);
+
+ Set<Artifact> projectDependencies = project.getDependencyArtifacts();
+ for (Map.Entry<org.sonatype.aether.artifact.Artifact, List<org.sonatype.aether.artifact.Artifact>> 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<org.sonatype.aether.artifact.Artifact, List<org.sonatype.aether.artifact.Artifact>> map,
+ RepositorySystem repoSystem, RepositorySystemSession repoSession, List<RemoteRepository> 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<ArtifactResult> artifactResults;
+ try {
+ artifactResults = repoSystem.resolveDependencies(repoSession, dependencyRequest)
+ .getArtifactResults();
+ List<org.sonatype.aether.artifact.Artifact> 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<Artifact> 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) {
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;
*/
@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
private YangToSourcesProcessor yangToSourcesProcessor;
+ @Component
+ private RepositorySystem repoSystem;
+
+ @Parameter( readonly = true, defaultValue = "${repositorySystemSession}" )
+ private RepositorySystemSession repoSession;
+
+ @Parameter( readonly = true, defaultValue = "${project.remoteProjectRepositories}" )
+ private List<RemoteRepository> remoteRepos;
+
+
public YangToSourcesMojo() {
}
@Override
public void execute() throws MojoExecutionException, MojoFailureException {
StaticLoggerBinder.getSingleton().setMavenLog(this.getLog());
+
+ Util.checkClasspath(project, getLog(), repoSystem, repoSession, remoteRepos);
+
if (yangToSourcesProcessor == null) {
List<CodeGeneratorArg> codeGeneratorArgs = processCodeGenerators(codeGenerators);