You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by kd...@apache.org on 2019/02/13 20:06:51 UTC
[nifi-maven] 04/20: NIFI-376: - Adding a new maven dependency for
printing the dependencies provided through a NAR. New features require at
least Maven 3.1.0.
This is an automated email from the ASF dual-hosted git repository.
kdoran pushed a commit to branch master
in repository https://gitbox.apache.org/repos/asf/nifi-maven.git
commit 7932897aec68a9292961d4ac37626fb84d672b11
Author: Matt Gilman <ma...@gmail.com>
AuthorDate: Wed Aug 19 13:35:07 2015 -0400
NIFI-376: - Adding a new maven dependency for printing the dependencies provided through a NAR. New features require at least Maven 3.1.0.
Signed-off-by: joewitt <jo...@apache.org>
---
README.md | 2 +-
pom.xml | 21 +-
.../apache/nifi/NarProvidedDependenciesMojo.java | 317 +++++++++++++++++++++
3 files changed, 336 insertions(+), 4 deletions(-)
diff --git a/README.md b/README.md
index 71772ac..a9c0f23 100644
--- a/README.md
+++ b/README.md
@@ -25,7 +25,7 @@ Apache NiFi NAR Maven Plugin helps to build NiFi Archive bundles to support the
## Requirements
* JDK 1.7 or higher
-* Apache Maven 3.0.5 or higher
+* Apache Maven 3.1.0 or higher
## Getting Started
diff --git a/pom.xml b/pom.xml
index 5d1778c..431d87c 100644
--- a/pom.xml
+++ b/pom.xml
@@ -23,7 +23,7 @@
</parent>
<groupId>org.apache.nifi</groupId>
<artifactId>nifi-nar-maven-plugin</artifactId>
- <version>1.0.2-SNAPSHOT</version>
+ <version>1.1.0-SNAPSHOT</version>
<packaging>maven-plugin</packaging>
<description>Apache NiFi Nar Maven Plugin</description>
<url>http://nifi.apache.org</url>
@@ -76,7 +76,7 @@
<properties>
<maven.compiler.source>1.7</maven.compiler.source>
<maven.compiler.target>1.7</maven.compiler.target>
- <maven.min-version>3.0.5</maven.min-version>
+ <maven.min-version>3.1.0</maven.min-version>
<project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
<project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
<inceptionYear>2014</inceptionYear>
@@ -365,7 +365,17 @@
<dependency>
<groupId>org.apache.maven</groupId>
<artifactId>maven-plugin-api</artifactId>
- <version>2.2.1</version>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-artifact</artifactId>
+ <version>3.1.0</version>
+ </dependency>
+ <dependency>
+ <groupId>org.apache.maven</groupId>
+ <artifactId>maven-compat</artifactId>
+ <version>3.1.0</version>
</dependency>
<dependency>
<groupId>org.apache.maven.plugins</groupId>
@@ -373,6 +383,11 @@
<type>maven-plugin</type>
<version>2.9</version>
</dependency>
+ <dependency>
+ <groupId>org.apache.maven.shared</groupId>
+ <artifactId>maven-dependency-tree</artifactId>
+ <version>2.2</version>
+ </dependency>
<dependency>
<!-- No code from maven-jar-plugin is actually used; it's included
just to simplify the dependencies list. -->
diff --git a/src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java b/src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java
new file mode 100644
index 0000000..63b2abd
--- /dev/null
+++ b/src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java
@@ -0,0 +1,317 @@
+/*
+ * 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.
+ */
+package org.apache.nifi;
+
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.handler.ArtifactHandler;
+import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
+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;
+import org.apache.maven.plugins.annotations.LifecyclePhase;
+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.plugins.annotations.Component;
+import org.apache.maven.project.DefaultProjectBuildingRequest;
+import org.apache.maven.project.ProjectBuilder;
+import org.apache.maven.project.ProjectBuildingException;
+import org.apache.maven.project.ProjectBuildingRequest;
+import org.apache.maven.project.ProjectBuildingResult;
+import org.apache.maven.shared.dependency.tree.DependencyNode;
+import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
+import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
+import org.apache.maven.shared.dependency.tree.traversal.DependencyNodeVisitor;
+import org.eclipse.aether.RepositorySystemSession;
+
+/**
+ * Generates the listing of dependencies that is provided by the NAR dependency of the current NAR. This is important as artifacts that bundle dependencies will
+ * not project those dependences using the traditional maven dependency plugin. This plugin will override that setting in order to print the dependencies being
+ * inherited at runtime.
+ */
+@Mojo(name = "provided-nar-dependencies", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = false, requiresDependencyResolution = ResolutionScope.RUNTIME)
+public class NarProvidedDependenciesMojo extends AbstractMojo {
+
+ private static final String NAR = "nar";
+
+ /**
+ * The Maven project.
+ */
+ @Parameter(defaultValue = "${project}", readonly = true, required = true)
+ private MavenProject project;
+
+ /**
+ * The local artifact repository.
+ */
+ @Parameter(defaultValue = "${localRepository}", readonly = true)
+ private ArtifactRepository localRepository;
+
+ /**
+ * The {@link RepositorySystemSession} used for obtaining the local and remote artifact repositories.
+ */
+ @Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
+ private RepositorySystemSession repoSession;
+
+ /**
+ * If specified, this parameter will cause the dependency tree to be written using the specified format. Currently supported format are: <code>tree</code>
+ * or <code>pom</code>.
+ */
+ @Parameter(property = "mode", defaultValue = "tree")
+ private String mode;
+
+ /**
+ * The dependency tree builder to use for verbose output.
+ */
+ @Component
+ private DependencyTreeBuilder dependencyTreeBuilder;
+
+ /**
+ * *
+ * The {@link ArtifactHandlerManager} into which any extension {@link ArtifactHandler} instances should have been injected when the extensions were loaded.
+ */
+ @Component
+ private ArtifactHandlerManager artifactHandlerManager;
+
+ /**
+ * The {@link ProjectBuilder} used to generate the {@link MavenProject} for the nar artifact the dependency tree is being generated for.
+ */
+ @Component
+ private ProjectBuilder projectBuilder;
+
+ /*
+ * @see org.apache.maven.plugin.Mojo#execute()
+ */
+ @Override
+ public void execute() throws MojoExecutionException, MojoFailureException {
+ try {
+ // find the nar dependency
+ Artifact narArtifact = null;
+ for (final Artifact artifact : project.getDependencyArtifacts()) {
+ if (NAR.equals(artifact.getType())) {
+ // ensure the project doesn't have two nar dependencies
+ if (narArtifact != null) {
+ throw new MojoExecutionException("Project can only have one NAR dependency.");
+ }
+
+ // record the nar dependency
+ narArtifact = artifact;
+ }
+ }
+
+ // ensure there is a nar dependency
+ if (narArtifact == null) {
+ throw new MojoExecutionException("Project does not have any NAR dependencies.");
+ }
+
+ // build the project for the nar artifact
+ final ProjectBuildingRequest narRequest = new DefaultProjectBuildingRequest();
+ narRequest.setRepositorySession(repoSession);
+ final ProjectBuildingResult narResult = projectBuilder.build(narArtifact, narRequest);
+
+ // get the artifact handler for excluding dependencies
+ final ArtifactHandler narHandler = excludesDependencies(narArtifact);
+ narArtifact.setArtifactHandler(narHandler);
+
+ // nar artifacts by nature includes dependencies, however this prevents the
+ // transitive dependencies from printing using tools like dependency:tree.
+ // here we are overriding the artifact handler for all nars so the
+ // dependencies can be listed. this is important because nar dependencies
+ // will be used as the parent classloader for this nar and seeing what
+ // dependencies are provided is critical.
+ final Map<String, ArtifactHandler> narHandlerMap = new HashMap<>();
+ narHandlerMap.put(NAR, narHandler);
+ artifactHandlerManager.addHandlers(narHandlerMap);
+
+ // get the dependency tree
+ final DependencyNode root = dependencyTreeBuilder.buildDependencyTree(narResult.getProject(), localRepository, null);
+
+ // write the appropriate output
+ DependencyNodeVisitor visitor = null;
+ if ("tree".equals(mode)) {
+ visitor = new TreeWriter();
+ } else if ("pom".equals(mode)) {
+ visitor = new PomWriter();
+ }
+
+ // ensure the mode was specified correctly
+ if (visitor == null) {
+ throw new MojoExecutionException("The specified mode is invalid. Supported options are 'tree' and 'pom'.");
+ }
+
+ // visit and print the results
+ root.accept(visitor);
+ getLog().info("--- Provided NAR Dependencies ---\n\n" + visitor.toString());
+ } catch (DependencyTreeBuilderException | ProjectBuildingException e) {
+ throw new MojoExecutionException("Cannot build project dependency tree", e);
+ }
+ }
+
+ /**
+ * Gets the Maven project used by this mojo.
+ *
+ * @return the Maven project
+ */
+ public MavenProject getProject() {
+ return project;
+ }
+
+ /**
+ * Creates a new ArtifactHandler for the specified Artifact that overrides the includeDependencies flag. When set, this flag prevents transitive
+ * dependencies from being printed in dependencies plugin.
+ *
+ * @param artifact The artifact
+ * @return The handler for the artifact
+ */
+ private ArtifactHandler excludesDependencies(final Artifact artifact) {
+ final ArtifactHandler orig = artifact.getArtifactHandler();
+
+ return new ArtifactHandler() {
+ @Override
+ public String getExtension() {
+ return orig.getExtension();
+ }
+
+ @Override
+ public String getDirectory() {
+ return orig.getDirectory();
+ }
+
+ @Override
+ public String getClassifier() {
+ return orig.getClassifier();
+ }
+
+ @Override
+ public String getPackaging() {
+ return orig.getPackaging();
+ }
+
+ // mark dependencies has excluded so they will appear in tree listing
+ @Override
+ public boolean isIncludesDependencies() {
+ return false;
+ }
+
+ @Override
+ public String getLanguage() {
+ return orig.getLanguage();
+ }
+
+ @Override
+ public boolean isAddedToClasspath() {
+ return orig.isAddedToClasspath();
+ }
+ };
+ }
+
+ /**
+ * Returns whether the specified dependency has test scope.
+ *
+ * @param node The dependency
+ * @return What the dependency is a test scoped dep
+ */
+ private boolean isTest(final DependencyNode node) {
+ return "test".equals(node.getArtifact().getScope());
+ }
+
+ /**
+ * A dependency visitor that builds a dependency tree.
+ */
+ private class TreeWriter implements DependencyNodeVisitor {
+
+ private final StringBuilder output = new StringBuilder();
+ private final Deque<DependencyNode> hierarchy = new ArrayDeque<>();
+
+ @Override
+ public boolean visit(DependencyNode node) {
+ // add this node
+ hierarchy.push(node);
+
+ // don't print test deps, but still add to hierarchy as they will
+ // be removed in endVisit below
+ if (isTest(node)) {
+ return false;
+ }
+
+ // build the padding
+ final StringBuilder pad = new StringBuilder();
+ for (int i = 0; i < hierarchy.size() - 1; i++) {
+ pad.append(" ");
+ }
+ pad.append("+- ");
+
+ // log it
+ output.append(pad).append(node.toNodeString()).append("\n");
+
+ return true;
+ }
+
+ @Override
+ public boolean endVisit(DependencyNode node) {
+ hierarchy.pop();
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return output.toString();
+ }
+ }
+
+ /**
+ * A dependency visitor that generates output that can be copied into a pom's dependency management section.
+ */
+ private class PomWriter implements DependencyNodeVisitor {
+
+ private final StringBuilder output = new StringBuilder();
+
+ @Override
+ public boolean visit(DependencyNode node) {
+ if (isTest(node)) {
+ return false;
+ }
+
+ final Artifact artifact = node.getArtifact();
+ if (!NAR.equals(artifact.getType())) {
+ output.append("<dependency>\n");
+ output.append(" <groupId>").append(artifact.getGroupId()).append("</groupId>\n");
+ output.append(" <artifactId>").append(artifact.getArtifactId()).append("</artifactId>\n");
+ output.append(" <version>").append(artifact.getVersion()).append("</version>\n");
+ output.append(" <scope>provided</scope>\n");
+ output.append("</dependency>\n");
+ }
+
+ return true;
+ }
+
+ @Override
+ public boolean endVisit(DependencyNode node) {
+ return true;
+ }
+
+ @Override
+ public String toString() {
+ return output.toString();
+ }
+ }
+}