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:47 UTC

[nifi-maven] branch master updated (953ddf4 -> 438612e)

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

kdoran pushed a change to branch master
in repository https://gitbox.apache.org/repos/asf/nifi-maven.git.


    from 953ddf4  NIFI-5304 - Changed Lifecycle Phase Binding for Help Mojo
     new f9f372e  NIFI-5859: Build NAR Extension Definitions/docs at build time
     new 438612e  NIFI-5859

The 20 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.


Summary of changes:
 pom.xml                                            |  36 +-
 src/main/java/org/apache/nifi/NarMojo.java         | 346 ++++++++++++++++-
 .../extension/definition/ExtensionDefinition.java  |  39 ++
 .../nifi/extension/definition/ExtensionType.java   |  27 ++
 .../extension/definition/ServiceAPIDefinition.java |  27 ++
 .../extraction/ExtensionClassLoader.java           | 118 ++++++
 .../extraction/ExtensionClassLoaderFactory.java    | 413 +++++++++++++++++++++
 .../extraction/ExtensionDefinitionFactory.java     | 139 +++++++
 .../extraction/StandardExtensionDefinition.java    |  56 +++
 .../extraction/StandardServiceAPIDefinition.java   |  53 +++
 10 files changed, 1224 insertions(+), 30 deletions(-)
 create mode 100644 src/main/java/org/apache/nifi/extension/definition/ExtensionDefinition.java
 create mode 100644 src/main/java/org/apache/nifi/extension/definition/ExtensionType.java
 create mode 100644 src/main/java/org/apache/nifi/extension/definition/ServiceAPIDefinition.java
 create mode 100644 src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoader.java
 create mode 100644 src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoaderFactory.java
 create mode 100644 src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionDefinitionFactory.java
 create mode 100644 src/main/java/org/apache/nifi/extension/definition/extraction/StandardExtensionDefinition.java
 create mode 100644 src/main/java/org/apache/nifi/extension/definition/extraction/StandardServiceAPIDefinition.java


[nifi-maven] 16/20: NIFI-4216 Marked mojos as ThreadSafe

Posted by kd...@apache.org.
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 f2b7e413d464a9775223c9175414f70b5648c439
Author: Jan Hentschel <ja...@ultratendency.com>
AuthorDate: Sun Jul 8 18:36:13 2018 +0200

    NIFI-4216 Marked mojos as ThreadSafe
    
    This closes #6.
    
    Signed-off-by: Bryan Bende <bb...@apache.org>
---
 src/main/java/org/apache/nifi/NarMojo.java                     | 2 +-
 src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java | 2 +-
 2 files changed, 2 insertions(+), 2 deletions(-)

diff --git a/src/main/java/org/apache/nifi/NarMojo.java b/src/main/java/org/apache/nifi/NarMojo.java
index 124a978..4110fa6 100644
--- a/src/main/java/org/apache/nifi/NarMojo.java
+++ b/src/main/java/org/apache/nifi/NarMojo.java
@@ -78,7 +78,7 @@ import org.codehaus.plexus.util.StringUtils;
  * simplified to the use case of NarMojo.
  *
  */
-@Mojo(name = "nar", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = false, requiresDependencyResolution = ResolutionScope.RUNTIME)
+@Mojo(name = "nar", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true, requiresDependencyResolution = ResolutionScope.RUNTIME)
 public class NarMojo extends AbstractMojo {
 
     private static final String[] DEFAULT_EXCLUDES = new String[]{"**/package.html"};
diff --git a/src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java b/src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java
index 15da9ad..a9ec9b2 100644
--- a/src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java
+++ b/src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java
@@ -50,7 +50,7 @@ import java.util.Map;
  * 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)
+@Mojo(name = "provided-nar-dependencies", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true, requiresDependencyResolution = ResolutionScope.RUNTIME)
 public class NarProvidedDependenciesMojo extends AbstractMojo {
 
     private static final String NAR = "nar";


[nifi-maven] 02/20: NIFI-850

Posted by kd...@apache.org.
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 8ffd92311f55a391e9bcd2e91c6a635935c4f26e
Author: joewitt <jo...@apache.org>
AuthorDate: Sat Aug 15 12:23:11 2015 -0400

    NIFI-850
---
 DISCLAIMER                                        |  15 +
 LICENSE                                           | 202 +++++++
 NOTICE                                            |   5 +
 README.md                                         |  63 +++
 pom.xml                                           | 431 +++++++++++++++
 src/main/java/org/apache/nifi/NarMojo.java        | 613 ++++++++++++++++++++++
 src/main/resources/META-INF/plexus/components.xml |  52 ++
 7 files changed, 1381 insertions(+)

diff --git a/DISCLAIMER b/DISCLAIMER
new file mode 100644
index 0000000..0f8e7a1
--- /dev/null
+++ b/DISCLAIMER
@@ -0,0 +1,15 @@
+Apache NiFi is an effort undergoing incubation at the Apache Software
+Foundation (ASF), sponsored by the Apache Incubator PMC.
+
+Incubation is required of all newly accepted projects until a further review
+indicates that the infrastructure, communications, and decision making process
+have stabilized in a manner consistent with other successful ASF projects.
+
+While incubation status is not necessarily a reflection of the completeness
+or stability of the code, it does indicate that the project has yet to be
+fully endorsed by the ASF.
+
+For more information about the incubation status of the Apache NiFi project
+you can go to the following page:
+
+http://nifi.incubator.apache.org/
diff --git a/LICENSE b/LICENSE
new file mode 100644
index 0000000..7a4a3ea
--- /dev/null
+++ b/LICENSE
@@ -0,0 +1,202 @@
+
+                                 Apache License
+                           Version 2.0, January 2004
+                        http://www.apache.org/licenses/
+
+   TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION
+
+   1. Definitions.
+
+      "License" shall mean the terms and conditions for use, reproduction,
+      and distribution as defined by Sections 1 through 9 of this document.
+
+      "Licensor" shall mean the copyright owner or entity authorized by
+      the copyright owner that is granting the License.
+
+      "Legal Entity" shall mean the union of the acting entity and all
+      other entities that control, are controlled by, or are under common
+      control with that entity. For the purposes of this definition,
+      "control" means (i) the power, direct or indirect, to cause the
+      direction or management of such entity, whether by contract or
+      otherwise, or (ii) ownership of fifty percent (50%) or more of the
+      outstanding shares, or (iii) beneficial ownership of such entity.
+
+      "You" (or "Your") shall mean an individual or Legal Entity
+      exercising permissions granted by this License.
+
+      "Source" form shall mean the preferred form for making modifications,
+      including but not limited to software source code, documentation
+      source, and configuration files.
+
+      "Object" form shall mean any form resulting from mechanical
+      transformation or translation of a Source form, including but
+      not limited to compiled object code, generated documentation,
+      and conversions to other media types.
+
+      "Work" shall mean the work of authorship, whether in Source or
+      Object form, made available under the License, as indicated by a
+      copyright notice that is included in or attached to the work
+      (an example is provided in the Appendix below).
+
+      "Derivative Works" shall mean any work, whether in Source or Object
+      form, that is based on (or derived from) the Work and for which the
+      editorial revisions, annotations, elaborations, or other modifications
+      represent, as a whole, an original work of authorship. For the purposes
+      of this License, Derivative Works shall not include works that remain
+      separable from, or merely link (or bind by name) to the interfaces of,
+      the Work and Derivative Works thereof.
+
+      "Contribution" shall mean any work of authorship, including
+      the original version of the Work and any modifications or additions
+      to that Work or Derivative Works thereof, that is intentionally
+      submitted to Licensor for inclusion in the Work by the copyright owner
+      or by an individual or Legal Entity authorized to submit on behalf of
+      the copyright owner. For the purposes of this definition, "submitted"
+      means any form of electronic, verbal, or written communication sent
+      to the Licensor or its representatives, including but not limited to
+      communication on electronic mailing lists, source code control systems,
+      and issue tracking systems that are managed by, or on behalf of, the
+      Licensor for the purpose of discussing and improving the Work, but
+      excluding communication that is conspicuously marked or otherwise
+      designated in writing by the copyright owner as "Not a Contribution."
+
+      "Contributor" shall mean Licensor and any individual or Legal Entity
+      on behalf of whom a Contribution has been received by Licensor and
+      subsequently incorporated within the Work.
+
+   2. Grant of Copyright License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      copyright license to reproduce, prepare Derivative Works of,
+      publicly display, publicly perform, sublicense, and distribute the
+      Work and such Derivative Works in Source or Object form.
+
+   3. Grant of Patent License. Subject to the terms and conditions of
+      this License, each Contributor hereby grants to You a perpetual,
+      worldwide, non-exclusive, no-charge, royalty-free, irrevocable
+      (except as stated in this section) patent license to make, have made,
+      use, offer to sell, sell, import, and otherwise transfer the Work,
+      where such license applies only to those patent claims licensable
+      by such Contributor that are necessarily infringed by their
+      Contribution(s) alone or by combination of their Contribution(s)
+      with the Work to which such Contribution(s) was submitted. If You
+      institute patent litigation against any entity (including a
+      cross-claim or counterclaim in a lawsuit) alleging that the Work
+      or a Contribution incorporated within the Work constitutes direct
+      or contributory patent infringement, then any patent licenses
+      granted to You under this License for that Work shall terminate
+      as of the date such litigation is filed.
+
+   4. Redistribution. You may reproduce and distribute copies of the
+      Work or Derivative Works thereof in any medium, with or without
+      modifications, and in Source or Object form, provided that You
+      meet the following conditions:
+
+      (a) You must give any other recipients of the Work or
+          Derivative Works a copy of this License; and
+
+      (b) You must cause any modified files to carry prominent notices
+          stating that You changed the files; and
+
+      (c) You must retain, in the Source form of any Derivative Works
+          that You distribute, all copyright, patent, trademark, and
+          attribution notices from the Source form of the Work,
+          excluding those notices that do not pertain to any part of
+          the Derivative Works; and
+
+      (d) If the Work includes a "NOTICE" text file as part of its
+          distribution, then any Derivative Works that You distribute must
+          include a readable copy of the attribution notices contained
+          within such NOTICE file, excluding those notices that do not
+          pertain to any part of the Derivative Works, in at least one
+          of the following places: within a NOTICE text file distributed
+          as part of the Derivative Works; within the Source form or
+          documentation, if provided along with the Derivative Works; or,
+          within a display generated by the Derivative Works, if and
+          wherever such third-party notices normally appear. The contents
+          of the NOTICE file are for informational purposes only and
+          do not modify the License. You may add Your own attribution
+          notices within Derivative Works that You distribute, alongside
+          or as an addendum to the NOTICE text from the Work, provided
+          that such additional attribution notices cannot be construed
+          as modifying the License.
+
+      You may add Your own copyright statement to Your modifications and
+      may provide additional or different license terms and conditions
+      for use, reproduction, or distribution of Your modifications, or
+      for any such Derivative Works as a whole, provided Your use,
+      reproduction, and distribution of the Work otherwise complies with
+      the conditions stated in this License.
+
+   5. Submission of Contributions. Unless You explicitly state otherwise,
+      any Contribution intentionally submitted for inclusion in the Work
+      by You to the Licensor shall be under the terms and conditions of
+      this License, without any additional terms or conditions.
+      Notwithstanding the above, nothing herein shall supersede or modify
+      the terms of any separate license agreement you may have executed
+      with Licensor regarding such Contributions.
+
+   6. Trademarks. This License does not grant permission to use the trade
+      names, trademarks, service marks, or product names of the Licensor,
+      except as required for reasonable and customary use in describing the
+      origin of the Work and reproducing the content of the NOTICE file.
+
+   7. Disclaimer of Warranty. Unless required by applicable law or
+      agreed to in writing, Licensor provides the Work (and each
+      Contributor provides its Contributions) on an "AS IS" BASIS,
+      WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
+      implied, including, without limitation, any warranties or conditions
+      of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A
+      PARTICULAR PURPOSE. You are solely responsible for determining the
+      appropriateness of using or redistributing the Work and assume any
+      risks associated with Your exercise of permissions under this License.
+
+   8. Limitation of Liability. In no event and under no legal theory,
+      whether in tort (including negligence), contract, or otherwise,
+      unless required by applicable law (such as deliberate and grossly
+      negligent acts) or agreed to in writing, shall any Contributor be
+      liable to You for damages, including any direct, indirect, special,
+      incidental, or consequential damages of any character arising as a
+      result of this License or out of the use or inability to use the
+      Work (including but not limited to damages for loss of goodwill,
+      work stoppage, computer failure or malfunction, or any and all
+      other commercial damages or losses), even if such Contributor
+      has been advised of the possibility of such damages.
+
+   9. Accepting Warranty or Additional Liability. While redistributing
+      the Work or Derivative Works thereof, You may choose to offer,
+      and charge a fee for, acceptance of support, warranty, indemnity,
+      or other liability obligations and/or rights consistent with this
+      License. However, in accepting such obligations, You may act only
+      on Your own behalf and on Your sole responsibility, not on behalf
+      of any other Contributor, and only if You agree to indemnify,
+      defend, and hold each Contributor harmless for any liability
+      incurred by, or claims asserted against, such Contributor by reason
+      of your accepting any such warranty or additional liability.
+
+   END OF TERMS AND CONDITIONS
+
+   APPENDIX: How to apply the Apache License to your work.
+
+      To apply the Apache License to your work, attach the following
+      boilerplate notice, with the fields enclosed by brackets "[]"
+      replaced with your own identifying information. (Don't include
+      the brackets!)  The text should be enclosed in the appropriate
+      comment syntax for the file format. We also recommend that a
+      file or class name and description of purpose be included on the
+      same "printed page" as the copyright notice for easier
+      identification within third-party archives.
+
+   Copyright [yyyy] [name of copyright owner]
+
+   Licensed 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.
\ No newline at end of file
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..76a23fb
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,5 @@
+Apache NiFi
+Copyright 2014-2015 The Apache Software Foundation
+
+This product includes software developed at
+The Apache Software Foundation (http://www.apache.org/).
diff --git a/README.md b/README.md
new file mode 100644
index 0000000..71772ac
--- /dev/null
+++ b/README.md
@@ -0,0 +1,63 @@
+<!--
+  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.
+-->
+# Apache NiFi NAR Maven Plugin
+
+Apache NiFi NAR Maven Plugin helps to build NiFi Archive bundles to support the classloader isolation model of NiFi.
+
+## Table of Contents
+
+- [Requirements](#requirements)
+- [Getting Started](#getting-started)
+- [Getting Help](#getting-help)
+- [License](#license)
+
+## Requirements
+* JDK 1.7 or higher
+* Apache Maven 3.0.5 or higher
+
+## Getting Started
+
+Building the nifi-nar-maven-plugin module should be rare since it will be released infrequently compared to
+the main 'nifi' code tree.
+
+- Build with `mvn clean install`
+- Presuming you need to make use of changes to the nifi-nar-maven-plugin module, you should next
+  go to the [nifi](../nifi) directory and follow its instructions. 
+
+
+## Getting Help
+If you have questions, you can reach out to our mailing list: dev@nifi.incubator.apache.org
+([archive](http://mail-archives.apache.org/mod_mbox/incubator-nifi-dev)).
+We're also often available in IRC: #nifi on
+[irc.freenode.net](http://webchat.freenode.net/?channels=#nifi).
+
+
+## License
+
+Except as otherwise noted this software is licensed under the
+[Apache License, Version 2.0](http://www.apache.org/licenses/LICENSE-2.0.html)
+
+Licensed 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.
+
diff --git a/pom.xml b/pom.xml
new file mode 100644
index 0000000..5d1778c
--- /dev/null
+++ b/pom.xml
@@ -0,0 +1,431 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+<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>
+    <parent>
+        <groupId>org.apache</groupId>
+        <artifactId>apache</artifactId>
+        <version>17</version>
+        <relativePath />
+    </parent>
+    <groupId>org.apache.nifi</groupId>
+    <artifactId>nifi-nar-maven-plugin</artifactId>
+    <version>1.0.2-SNAPSHOT</version>
+    <packaging>maven-plugin</packaging>
+    <description>Apache NiFi Nar Maven Plugin</description>
+    <url>http://nifi.apache.org</url>
+    <organization>
+        <name>Apache NiFi Project</name>
+        <url>http://nifi.apache.org/</url>
+    </organization>
+    <licenses>
+        <license>
+            <name>Apache License, Version 2.0</name>
+            <url>http://www.apache.org/licenses/LICENSE-2.0</url>
+        </license>
+    </licenses>
+    <mailingLists>
+        <mailingList>
+            <name>Dev</name>
+            <subscribe>dev-subscribe@nifi.apache.org</subscribe>
+            <unsubscribe>dev-unsubscribe@nifi.apache.org</unsubscribe>
+            <post>dev@nifi.apache.org</post>
+            <archive>http://mail-archives.apache.org/mod_mbox/nifi-dev</archive>
+        </mailingList>
+        <mailingList>
+            <name>Users</name>
+            <subscribe>users-subscribe@nifi.apache.org</subscribe>
+            <unsubscribe>users-unsubscribe@nifi.apache.org</unsubscribe>
+            <post>users@nifi.apache.org</post>
+            <archive>http://mail-archives.apache.org/mod_mbox/nifi-users</archive>
+        </mailingList>
+        <mailingList>
+            <name>Commits</name>
+            <subscribe>commits-subscribe@nifi.apache.org</subscribe>
+            <unsubscribe>commits-unsubscribe@nifi.apache.org</unsubscribe>
+            <post>commits@nifi.apache.org</post>
+            <archive>http://mail-archives.apache.org/mod_mbox/nifi-commits</archive>
+        </mailingList>
+    </mailingLists>
+    <prerequisites>
+        <maven>${maven.min-version}</maven>
+    </prerequisites>
+    <scm>
+        <connection>scm:git:git://git.apache.org/nifi-maven.git</connection>
+        <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/nifi-maven.git</developerConnection>
+        <url>https://git-wip-us.apache.org/repos/asf?p=nifi-maven.git</url>
+        <tag>HEAD</tag>
+    </scm>
+    <issueManagement>
+        <system>JIRA</system>
+        <url>https://issues.apache.org/jira/browse/NIFI</url>
+    </issueManagement>
+    <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>
+        <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
+        <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
+        <inceptionYear>2014</inceptionYear>
+    </properties>    
+    <build>
+        <pluginManagement>
+            <plugins>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-compiler-plugin</artifactId>
+                    <version>3.2</version>
+                    <configuration>
+                        <fork>true</fork>
+                        <optimize>true</optimize>
+                        <showDeprecation>true</showDeprecation>
+                        <showWarnings>true</showWarnings>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-war-plugin</artifactId>
+                    <version>2.5</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-dependency-plugin</artifactId>
+                    <version>2.9</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-resources-plugin</artifactId>
+                    <version>2.7</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-surefire-plugin</artifactId>
+                    <version>2.18</version>
+                    <configuration>
+                        <redirectTestOutputToFile>true</redirectTestOutputToFile>
+                        <argLine>-Xmx1G</argLine>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-source-plugin</artifactId>
+                    <version>2.4</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-jar-plugin</artifactId>
+                    <version>2.5</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-javadoc-plugin</artifactId>
+                    <version>2.10.1</version>
+                    <configuration>
+                        <failOnError>false</failOnError>
+                        <quiet>true</quiet>
+                        <show>private</show>
+                        <encoding>UTF-8</encoding>
+                        <quiet>true</quiet>
+                        <javadocVersion>1.7</javadocVersion>
+                        <additionalJOption>-J-Xmx512m</additionalJOption>
+                    </configuration>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-release-plugin</artifactId>
+                    <version>2.5.1</version>
+                    <configuration>
+                        <useReleaseProfile>true</useReleaseProfile>
+                        <releaseProfiles>apache-release</releaseProfiles>
+                        <autoVersionSubmodules>true</autoVersionSubmodules>
+                        <goals>deploy</goals>
+                        <tagNameFormat>@{project.artifactId}-@{project.version}</tagNameFormat>
+                        <pushChanges>false</pushChanges>
+                        <localCheckout>true</localCheckout>
+                    </configuration>
+                    <executions>
+                        <execution>
+                            <id>default</id>
+                            <goals>
+                                <goal>perform</goal>
+                            </goals>
+                            <configuration>
+                                <pomFileName>pom.xml</pomFileName>
+                            </configuration>
+                        </execution>
+                    </executions>
+                </plugin>
+                <plugin>
+                    <groupId>org.codehaus.mojo</groupId>
+                    <artifactId>rpm-maven-plugin</artifactId>
+                    <version>2.1.1</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.antlr</groupId>
+                    <artifactId>antlr3-maven-plugin</artifactId>
+                    <version>3.5.2</version>
+                </plugin>
+                <plugin>
+                    <groupId>org.apache.maven.plugins</groupId>
+                    <artifactId>maven-checkstyle-plugin</artifactId>
+                    <version>2.15</version>
+                    <dependencies>
+                        <dependency>
+                            <groupId>com.puppycrawl.tools</groupId>
+                            <artifactId>checkstyle</artifactId>
+                            <version>6.5</version>
+                        </dependency>
+                    </dependencies>
+                </plugin>
+            </plugins>
+        </pluginManagement>
+        <plugins>
+            <plugin>
+                <groupId>org.sonatype.plugins</groupId>
+                <artifactId>nexus-staging-maven-plugin</artifactId>
+                <version>1.6.5</version>
+                <extensions>true</extensions>
+                <configuration>
+                    <serverId>repository.apache.org</serverId>
+                    <nexusUrl>https://repository.apache.org/</nexusUrl>
+                </configuration>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-enforcer-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>enforce-maven</id>
+                        <goals>
+                            <goal>enforce</goal>
+                        </goals>
+                        <configuration>
+                            <rules>
+                                <requireSameVersions>
+                                    <plugins>
+                                        <plugin>org.apache.maven.plugins:maven-surefire-plugin</plugin>
+                                        <plugin>org.apache.maven.plugins:maven-failsafe-plugin</plugin>
+                                        <plugin>org.apache.maven.plugins:maven-surefire-report-plugin</plugin>
+                                    </plugins>
+                                </requireSameVersions>
+                                <requireMavenVersion>
+                                    <version>${maven.min-version}</version>
+                                </requireMavenVersion>
+                            </rules>    
+                        </configuration>
+                    </execution>
+                </executions>
+            </plugin>
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-checkstyle-plugin</artifactId>
+                <configuration>
+                    <checkstyleRules>
+                        <module name="Checker">
+                            <property name="charset" value="UTF-8" />
+                            <property name="severity" value="warning" />
+                            <!-- Checks for whitespace                              -->
+                            <!-- See http://checkstyle.sf.net/config_whitespace.html -->
+                            <module name="FileTabCharacter">
+                                <property name="eachLine" value="true" />
+                            </module>
+                            <module name="TreeWalker">
+                                <module name="RegexpSinglelineJava">
+                                    <property name="format" value="\s+$" />
+                                    <property name="message" value="Line has trailing whitespace." />
+                                </module>
+                                <module name="RegexpSinglelineJava">
+                                    <property name="format" value="[@]see\s+[{][@]link" />
+                                    <property name="message" value="Javadoc @see does not need @link: pick one or the other." />
+                                </module>
+                                <module name="OuterTypeFilename" />
+                                <module name="LineLength">
+                                    <!-- needs extra, because Eclipse formatter ignores the ending left brace -->
+                                    <property name="max" value="200" />
+                                    <property name="ignorePattern" value="^package.*|^import.*|a href|href|http://|https://|ftp://" />
+                                </module>
+                                <module name="AvoidStarImport" />
+                                <module name="UnusedImports">
+                                    <property name="processJavadoc" value="true" />
+                                </module>
+                                <module name="NoLineWrap" />
+                                <module name="LeftCurly">
+                                    <property name="maxLineLength" value="160" />
+                                </module>
+                                <module name="RightCurly" />
+                                <module name="RightCurly">
+                                    <property name="option" value="alone" />
+                                    <property name="tokens" value="CLASS_DEF, METHOD_DEF, CTOR_DEF, LITERAL_FOR, LITERAL_WHILE, LITERAL_DO, STATIC_INIT, INSTANCE_INIT" />
+                                </module>
+                                <module name="SeparatorWrap">
+                                    <property name="tokens" value="DOT" />
+                                    <property name="option" value="nl" />
+                                </module>
+                                <module name="SeparatorWrap">
+                                    <property name="tokens" value="COMMA" />
+                                    <property name="option" value="EOL" />
+                                </module>
+                                <module name="PackageName">
+                                    <property name="format" value="^[a-z]+(\.[a-z][a-zA-Z0-9]*)*$" />
+                                </module>
+                                <module name="MethodTypeParameterName">
+                                    <property name="format" value="(^[A-Z][0-9]?)$|([A-Z][a-zA-Z0-9]*[T]$)" />
+                                </module>
+                                <module name="MethodParamPad" />
+                                <module name="OperatorWrap">
+                                    <property name="option" value="NL" />
+                                    <property name="tokens" value="BAND, BOR, BSR, BXOR, DIV, EQUAL, GE, GT, LAND, LE, LITERAL_INSTANCEOF, LOR, LT, MINUS, MOD, NOT_EQUAL, QUESTION, SL, SR, STAR " />
+                                </module>
+                                <module name="AnnotationLocation">
+                                    <property name="tokens" value="CLASS_DEF, INTERFACE_DEF, ENUM_DEF, METHOD_DEF, CTOR_DEF" />
+                                </module>
+                                <module name="AnnotationLocation">
+                                    <property name="tokens" value="VARIABLE_DEF" />
+                                    <property name="allowSamelineMultipleAnnotations" value="true" />
+                                </module>
+                                <module name="NonEmptyAtclauseDescription" />
+                                <module name="JavadocMethod">
+                                    <property name="allowMissingJavadoc" value="true" />
+                                    <property name="allowMissingParamTags" value="true" />
+                                    <property name="allowMissingThrowsTags" value="true" />
+                                    <property name="allowMissingReturnTag" value="true" />
+                                    <property name="allowedAnnotations" value="Override,Test,BeforeClass,AfterClass,Before,After" />
+                                    <property name="allowThrowsTagsForSubclasses" value="true" />
+                                </module>
+                                <module name="SingleLineJavadoc" />
+                            </module>
+                        </module>
+                    </checkstyleRules>
+                    <violationSeverity>warning</violationSeverity>
+                    <includeTestSourceDirectory>true</includeTestSourceDirectory>
+                    <excludes>**/HelpMojo.java</excludes>
+                </configuration>
+            </plugin>      
+            <plugin>
+                <groupId>org.apache.rat</groupId>
+                <artifactId>apache-rat-plugin</artifactId>
+                <configuration>
+                    <excludes>
+                        <exclude>nb-configuration.xml</exclude> <!-- courtesy excludes for netbeans users -->
+                        <exclude>nbactions.xml</exclude> <!-- courtesy excludes for netbeans users -->
+                        <exclude>DEPENDENCIES</exclude> <!-- auto generated file by apache's maven config while building sources.zip -->
+                    </excludes>
+                </configuration>
+                <dependencies>
+                    <!-- workaround for RAT-158 -->
+                    <dependency>
+                        <groupId>org.apache.maven.doxia</groupId>
+                        <artifactId>doxia-core</artifactId>
+                        <version>1.6</version>
+                        <exclusions>
+                            <exclusion>
+                                <groupId>xerces</groupId>
+                                <artifactId>xercesImpl</artifactId>
+                            </exclusion>
+                        </exclusions>
+                    </dependency>
+                </dependencies>
+            </plugin>             
+            <plugin>
+                <groupId>org.apache.maven.plugins</groupId>
+                <artifactId>maven-plugin-plugin</artifactId>
+                <executions>
+                    <execution>
+                        <id>default-descriptor</id>
+                        <goals>
+                            <goal>descriptor</goal>
+                        </goals>
+                        <phase>process-classes</phase>
+                    </execution>
+                    <execution>
+                        <id>help-descriptor</id>
+                        <goals>
+                            <goal>helpmojo</goal>
+                        </goals>
+                        <phase>process-classes</phase>
+                    </execution>
+                </executions>
+            </plugin>
+        </plugins>        
+    </build>
+    <dependencies>
+        <dependency>          
+            <groupId>org.apache.maven</groupId>
+            <artifactId>maven-plugin-api</artifactId>
+            <version>2.2.1</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-dependency-plugin</artifactId>
+            <type>maven-plugin</type>
+            <version>2.9</version>
+        </dependency>
+        <dependency>
+            <!-- No code from maven-jar-plugin is actually used; it's included
+            just to simplify the dependencies list.                     -->
+            <groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-jar-plugin</artifactId>
+            <version>2.5</version>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.maven.plugin-tools</groupId>
+            <artifactId>maven-plugin-annotations</artifactId>
+            <scope>provided</scope>
+            <version>3.3</version>
+        </dependency>
+    </dependencies>
+    <profiles>
+        <profile>
+            <!-- 
+            Checks style and licensing requirements.  This is a good idea to 
+            run for contributions and for the release process.  While it 
+            would be nice to run always these plugins can considerably slow
+            the build and have proven to create unstable builds in our
+            multi-module project and when building using multiple threads.
+            The stability issues seen with Checkstyle in multi-module builds
+            include false-positives and false negatives.-->
+            <id>contrib-check</id>
+            <build>
+                <plugins>
+                    <plugin>
+                        <groupId>org.apache.rat</groupId>
+                        <artifactId>apache-rat-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <goals>
+                                    <goal>check</goal>
+                                </goals>
+                                <phase>verify</phase>
+                            </execution>
+                        </executions>
+                    </plugin>
+                    <plugin>
+                        <groupId>org.apache.maven.plugins</groupId>
+                        <artifactId>maven-checkstyle-plugin</artifactId>
+                        <executions>
+                            <execution>
+                                <id>check-style</id>
+                                <goals>
+                                    <goal>check</goal>
+                                </goals>
+                            </execution>
+                        </executions>                
+                    </plugin>
+                </plugins>
+            </build>
+        </profile>
+    </profiles>    
+</project>
diff --git a/src/main/java/org/apache/nifi/NarMojo.java b/src/main/java/org/apache/nifi/NarMojo.java
new file mode 100644
index 0000000..0e32902
--- /dev/null
+++ b/src/main/java/org/apache/nifi/NarMojo.java
@@ -0,0 +1,613 @@
+/*
+ * 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.io.File;
+import java.io.IOException;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import org.apache.maven.archiver.MavenArchiveConfiguration;
+import org.apache.maven.archiver.MavenArchiver;
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DependencyResolutionRequiredException;
+import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.installer.ArtifactInstaller;
+import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
+import org.apache.maven.artifact.repository.ArtifactRepository;
+import org.apache.maven.artifact.repository.ArtifactRepositoryFactory;
+import org.apache.maven.artifact.resolver.ArtifactCollector;
+import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
+import org.apache.maven.artifact.resolver.ArtifactResolutionException;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.plugin.AbstractMojo;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.MojoFailureException;
+import org.apache.maven.plugin.dependency.utils.DependencyStatusSets;
+import org.apache.maven.plugin.dependency.utils.DependencyUtil;
+import org.apache.maven.plugin.dependency.utils.filters.DestFileFilter;
+import org.apache.maven.plugin.dependency.utils.resolvers.ArtifactsResolver;
+import org.apache.maven.plugin.dependency.utils.resolvers.DefaultArtifactsResolver;
+import org.apache.maven.plugin.dependency.utils.translators.ArtifactTranslator;
+import org.apache.maven.plugin.dependency.utils.translators.ClassifierTypeTranslator;
+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.execution.MavenSession;
+import org.apache.maven.plugins.annotations.Component;
+import org.apache.maven.project.MavenProjectHelper;
+import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
+import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
+import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
+import org.apache.maven.shared.artifact.filter.collection.ClassifierFilter;
+import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
+import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
+import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
+import org.apache.maven.shared.artifact.filter.collection.ProjectTransitivityFilter;
+import org.apache.maven.shared.artifact.filter.collection.TypeFilter;
+import org.codehaus.plexus.archiver.ArchiverException;
+import org.codehaus.plexus.archiver.jar.JarArchiver;
+import org.codehaus.plexus.archiver.jar.ManifestException;
+import org.codehaus.plexus.archiver.manager.ArchiverManager;
+import org.codehaus.plexus.util.FileUtils;
+import org.codehaus.plexus.util.StringUtils;
+
+/**
+ * Packages the current project as an Apache NiFi Archive (NAR).
+ *
+ * The following code is derived from maven-dependencies-plugin and
+ * maven-jar-plugin. The functionality of CopyDependenciesMojo and JarMojo was
+ * simplified to the use case of NarMojo.
+ *
+ */
+@Mojo(name = "nar", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = false, requiresDependencyResolution = ResolutionScope.RUNTIME)
+public class NarMojo extends AbstractMojo {
+
+    private static final String[] DEFAULT_EXCLUDES = new String[]{"**/package.html"};
+    private static final String[] DEFAULT_INCLUDES = new String[]{"**/**"};
+
+    /**
+     * POM
+     *
+     */
+    @Parameter(defaultValue = "${project}", readonly = true, required = true)
+    protected MavenProject project;
+
+    @Parameter(defaultValue = "${session}", readonly = true, required = true)
+    protected MavenSession session;
+
+    /**
+     * List of files to include. Specified as fileset patterns.
+     */
+    @Parameter(property = "includes")
+    protected String[] includes;
+    /**
+     * List of files to exclude. Specified as fileset patterns.
+     */
+    @Parameter(property = "excludes")
+    protected String[] excludes;
+    /**
+     * Name of the generated NAR.
+     *
+     */
+    @Parameter(alias = "narName", property = "nar.finalName", defaultValue = "${project.build.finalName}", required = true)
+    protected String finalName;
+
+    /**
+     * The Jar archiver.
+     *
+     * \@\component role="org.codehaus.plexus.archiver.Archiver" roleHint="jar"
+     */
+    @Component(role = org.codehaus.plexus.archiver.Archiver.class, hint = "jar")
+    private JarArchiver jarArchiver;
+    /**
+     * The archive configuration to use.
+     *
+     * See <a
+     * href="http://maven.apache.org/shared/maven-archiver/index.html">the
+     * documentation for Maven Archiver</a>.
+     *
+     */
+    @Parameter(property = "archive")
+    protected final MavenArchiveConfiguration archive = new MavenArchiveConfiguration();
+    /**
+     * Path to the default MANIFEST file to use. It will be used if
+     * <code>useDefaultManifestFile</code> is set to <code>true</code>.
+     *
+     */
+    @Parameter(property = "defaultManifestFiles", defaultValue = "${project.build.outputDirectory}/META-INF/MANIFEST.MF", readonly = true, required = true)
+    protected File defaultManifestFile;
+
+    /**
+     * Set this to <code>true</code> to enable the use of the
+     * <code>defaultManifestFile</code>.
+     *
+     * @since 2.2
+     */
+    @Parameter(property = "nar.useDefaultManifestFile", defaultValue = "false")
+    protected boolean useDefaultManifestFile;
+
+    @Component
+    protected MavenProjectHelper projectHelper;
+
+    /**
+     * Whether creating the archive should be forced.
+     *
+     */
+    @Parameter(property = "nar.forceCreation", defaultValue = "false")
+    protected boolean forceCreation;
+
+    /**
+     * Classifier to add to the artifact generated. If given, the artifact will
+     * be an attachment instead.
+     *
+     */
+    @Parameter(property = "classifier")
+    protected String classifier;
+
+    @Component
+    protected ArtifactInstaller installer;
+
+    @Component
+    protected ArtifactRepositoryFactory repositoryFactory;
+
+    /**
+     * This only applies if the classifier parameter is used.
+     *
+     */
+    @Parameter(property = "mdep.failOnMissingClassifierArtifact", defaultValue = "true", required = false)
+    protected boolean failOnMissingClassifierArtifact = true;
+
+    /**
+     * Comma Separated list of Types to include. Empty String indicates include
+     * everything (default).
+     *
+     */
+    @Parameter(property = "includeTypes", required = false)
+    protected String includeTypes;
+
+    /**
+     * Comma Separated list of Types to exclude. Empty String indicates don't
+     * exclude anything (default).
+     *
+     */
+    @Parameter(property = "excludeTypes", required = false)
+    protected String excludeTypes;
+
+    /**
+     * Scope to include. An Empty string indicates all scopes (default).
+     *
+     */
+    @Parameter(property = "includeScope", required = false)
+    protected String includeScope;
+
+    /**
+     * Scope to exclude. An Empty string indicates no scopes (default).
+     *
+     */
+    @Parameter(property = "excludeScope", required = false)
+    protected String excludeScope;
+
+    /**
+     * Comma Separated list of Classifiers to include. Empty String indicates
+     * include everything (default).
+     *
+     */
+    @Parameter(property = "includeClassifiers", required = false)
+    protected String includeClassifiers;
+
+    /**
+     * Comma Separated list of Classifiers to exclude. Empty String indicates
+     * don't exclude anything (default).
+     *
+     */
+    @Parameter(property = "excludeClassifiers", required = false)
+    protected String excludeClassifiers;
+
+    /**
+     * Specify classifier to look for. Example: sources
+     *
+     */
+    @Parameter(property = "classifier", required = false)
+    protected String copyDepClassifier;
+
+    /**
+     * Specify type to look for when constructing artifact based on classifier.
+     * Example: java-source,jar,war, nar
+     *
+     */
+    @Parameter(property = "type", required = false, defaultValue = "nar")
+    protected String type;
+
+    /**
+     * Comma separated list of Artifact names too exclude.
+     *
+     */
+    @Parameter(property = "excludeArtifacts", required = false)
+    protected String excludeArtifactIds;
+
+    /**
+     * Comma separated list of Artifact names to include.
+     *
+     */
+    @Parameter(property = "includeArtifacts", required = false)
+    protected String includeArtifactIds;
+
+    /**
+     * Comma separated list of GroupId Names to exclude.
+     *
+     */
+    @Parameter(property = "excludeArtifacts", required = false)
+    protected String excludeGroupIds;
+
+    /**
+     * Comma separated list of GroupIds to include.
+     *
+     */
+    @Parameter(property = "includeGroupIds", required = false)
+    protected String includeGroupIds;
+
+    /**
+     * Directory to store flag files
+     *
+     */
+    @Parameter(property = "markersDirectory", required = false, defaultValue = "${project.build.directory}/dependency-maven-plugin-markers")
+    protected File markersDirectory;
+
+    /**
+     * Overwrite release artifacts
+     *
+     */
+    @Parameter(property = "overWriteReleases", required = false)
+    protected boolean overWriteReleases;
+
+    /**
+     * Overwrite snapshot artifacts
+     *
+     */
+    @Parameter(property = "overWriteSnapshots", required = false)
+    protected boolean overWriteSnapshots;
+
+    /**
+     * Overwrite artifacts that don't exist or are older than the source.
+     *
+     */
+    @Parameter(property = "overWriteIfNewer", required = false, defaultValue = "true")
+    protected boolean overWriteIfNewer;
+
+    @Parameter(property = "projectBuildDirectory", required = false, defaultValue = "${project.build.directory}")
+    protected File projectBuildDirectory;
+
+    /**
+     * Used to look up Artifacts in the remote repository.
+     */
+    @Component
+    protected ArtifactFactory factory;
+
+    /**
+     * Used to look up Artifacts in the remote repository.
+     *
+     */
+    @Component
+    protected ArtifactResolver resolver;
+
+    /**
+     * Artifact collector, needed to resolve dependencies.
+     *
+     */
+    @Component(role = org.apache.maven.artifact.resolver.ArtifactCollector.class)
+    protected ArtifactCollector artifactCollector;
+
+    @Component(role = org.apache.maven.artifact.metadata.ArtifactMetadataSource.class)
+    protected ArtifactMetadataSource artifactMetadataSource;
+
+    /**
+     * Location of the local repository.
+     *
+     */
+    @Parameter(property = "localRepository", required = true, readonly = true)
+    protected ArtifactRepository local;
+
+    /**
+     * List of Remote Repositories used by the resolver
+     *
+     */
+    @Parameter(property = "project.remoteArtifactRepositories", required = true, readonly = true)
+    protected List remoteRepos;
+
+    /**
+     * To look up Archiver/UnArchiver implementations
+     *
+     */
+    @Component
+    protected ArchiverManager archiverManager;
+
+    /**
+     * Contains the full list of projects in the reactor.
+     *
+     */
+    @Parameter(property = "reactorProjects", required = true, readonly = true)
+    protected List reactorProjects;
+
+    /**
+     * If the plugin should be silent.
+     *
+     */
+    @Parameter(property = "silent", required = false, defaultValue = "false")
+    public boolean silent;
+
+    /**
+     * Output absolute filename for resolved artifacts
+     *
+     */
+    @Parameter(property = "outputAbsoluteArtifactFilename", defaultValue = "false", required = false)
+    protected boolean outputAbsoluteArtifactFilename;
+
+    @Override
+    public void execute() throws MojoExecutionException, MojoFailureException {
+        copyDependencies();
+        makeNar();
+    }
+
+    private void copyDependencies() throws MojoExecutionException {
+        DependencyStatusSets dss = getDependencySets(this.failOnMissingClassifierArtifact);
+        Set artifacts = dss.getResolvedDependencies();
+
+        for (Object artifactObj : artifacts) {
+            copyArtifact((Artifact) artifactObj);
+        }
+
+        artifacts = dss.getSkippedDependencies();
+        for (Object artifactOjb : artifacts) {
+            Artifact artifact = (Artifact) artifactOjb;
+            getLog().info(artifact.getFile().getName() + " already exists in destination.");
+        }
+    }
+
+    protected void copyArtifact(Artifact artifact) throws MojoExecutionException {
+        String destFileName = DependencyUtil.getFormattedFileName(artifact, false);
+        final File destDir = DependencyUtil.getFormattedOutputDirectory(false, false, false, false, false, getDependenciesDirectory(), artifact);
+        final File destFile = new File(destDir, destFileName);
+        copyFile(artifact.getFile(), destFile);
+    }
+
+    protected Artifact getResolvedPomArtifact(Artifact artifact) {
+        Artifact pomArtifact = this.factory.createArtifact(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion(), "", "pom");
+        // Resolve the pom artifact using repos
+        try {
+            this.resolver.resolve(pomArtifact, this.remoteRepos, this.local);
+        } catch (ArtifactResolutionException | ArtifactNotFoundException e) {
+            getLog().info(e.getMessage());
+        }
+        return pomArtifact;
+    }
+
+    protected ArtifactsFilter getMarkedArtifactFilter() {
+        return new DestFileFilter(this.overWriteReleases, this.overWriteSnapshots, this.overWriteIfNewer, false, false, false, false, false, getDependenciesDirectory());
+    }
+
+    protected DependencyStatusSets getDependencySets(boolean stopOnFailure) throws MojoExecutionException {
+        // add filters in well known order, least specific to most specific
+        FilterArtifacts filter = new FilterArtifacts();
+
+        filter.addFilter(new ProjectTransitivityFilter(project.getDependencyArtifacts(), false));
+        filter.addFilter(new ScopeFilter(this.includeScope, this.excludeScope));
+        filter.addFilter(new TypeFilter(this.includeTypes, this.excludeTypes));
+        filter.addFilter(new ClassifierFilter(this.includeClassifiers, this.excludeClassifiers));
+        filter.addFilter(new GroupIdFilter(this.includeGroupIds, this.excludeGroupIds));
+        filter.addFilter(new ArtifactIdFilter(this.includeArtifactIds, this.excludeArtifactIds));
+
+        // explicitly filter our nar dependencies
+        filter.addFilter(new TypeFilter("", "nar"));
+
+        // start with all artifacts.
+        Set artifacts = project.getArtifacts();
+
+        // perform filtering
+        try {
+            artifacts = filter.filter(artifacts);
+        } catch (ArtifactFilterException e) {
+            throw new MojoExecutionException(e.getMessage(), e);
+        }
+
+        // transform artifacts if classifier is set
+        final DependencyStatusSets status;
+        if (StringUtils.isNotEmpty(copyDepClassifier)) {
+            status = getClassifierTranslatedDependencies(artifacts, stopOnFailure);
+        } else {
+            status = filterMarkedDependencies(artifacts);
+        }
+
+        return status;
+    }
+
+    protected DependencyStatusSets getClassifierTranslatedDependencies(Set artifacts, boolean stopOnFailure) throws MojoExecutionException {
+        Set unResolvedArtifacts = new HashSet();
+        Set resolvedArtifacts = artifacts;
+        DependencyStatusSets status = new DependencyStatusSets();
+
+        // possibly translate artifacts into a new set of artifacts based on the
+        // classifier and type
+        // if this did something, we need to resolve the new artifacts
+        if (StringUtils.isNotEmpty(copyDepClassifier)) {
+            ArtifactTranslator translator = new ClassifierTypeTranslator(this.copyDepClassifier, this.type, this.factory);
+            artifacts = translator.translate(artifacts, getLog());
+
+            status = filterMarkedDependencies(artifacts);
+
+            // the unskipped artifacts are in the resolved set.
+            artifacts = status.getResolvedDependencies();
+
+            // resolve the rest of the artifacts
+            ArtifactsResolver artifactsResolver = new DefaultArtifactsResolver(this.resolver, this.local,
+                    this.remoteRepos, stopOnFailure);
+            resolvedArtifacts = artifactsResolver.resolve(artifacts, getLog());
+
+            // calculate the artifacts not resolved.
+            unResolvedArtifacts.addAll(artifacts);
+            unResolvedArtifacts.removeAll(resolvedArtifacts);
+        }
+
+        // return a bean of all 3 sets.
+        status.setResolvedDependencies(resolvedArtifacts);
+        status.setUnResolvedDependencies(unResolvedArtifacts);
+
+        return status;
+    }
+
+    protected DependencyStatusSets filterMarkedDependencies(Set artifacts) throws MojoExecutionException {
+        // remove files that have markers already
+        FilterArtifacts filter = new FilterArtifacts();
+        filter.clearFilters();
+        filter.addFilter(getMarkedArtifactFilter());
+
+        Set unMarkedArtifacts;
+        try {
+            unMarkedArtifacts = filter.filter(artifacts);
+        } catch (ArtifactFilterException e) {
+            throw new MojoExecutionException(e.getMessage(), e);
+        }
+
+        // calculate the skipped artifacts
+        Set skippedArtifacts = new HashSet();
+        skippedArtifacts.addAll(artifacts);
+        skippedArtifacts.removeAll(unMarkedArtifacts);
+
+        return new DependencyStatusSets(unMarkedArtifacts, null, skippedArtifacts);
+    }
+
+    protected void copyFile(File artifact, File destFile) throws MojoExecutionException {
+        try {
+            getLog().info("Copying " + (this.outputAbsoluteArtifactFilename ? artifact.getAbsolutePath() : artifact.getName()) + " to " + destFile);
+            FileUtils.copyFile(artifact, destFile);
+        } catch (Exception e) {
+            throw new MojoExecutionException("Error copying artifact from " + artifact + " to " + destFile, e);
+        }
+    }
+
+    private File getClassesDirectory() {
+        final File outputDirectory = projectBuildDirectory;
+        return new File(outputDirectory, "classes");
+    }
+
+    private File getDependenciesDirectory() {
+        return new File(getClassesDirectory(), "META-INF/bundled-dependencies");
+    }
+
+    private void makeNar() throws MojoExecutionException {
+        File narFile = createArchive();
+
+        if (classifier != null) {
+            projectHelper.attachArtifact(project, "nar", classifier, narFile);
+        } else {
+            project.getArtifact().setFile(narFile);
+        }
+    }
+
+    public File createArchive() throws MojoExecutionException {
+        final File outputDirectory = projectBuildDirectory;
+        File narFile = getNarFile(outputDirectory, finalName, classifier);
+        MavenArchiver archiver = new MavenArchiver();
+        archiver.setArchiver(jarArchiver);
+        archiver.setOutputFile(narFile);
+        archive.setForced(forceCreation);
+
+        try {
+            File contentDirectory = getClassesDirectory();
+            if (!contentDirectory.exists()) {
+                getLog().warn("NAR will be empty - no content was marked for inclusion!");
+            } else {
+                archiver.getArchiver().addDirectory(contentDirectory, getIncludes(), getExcludes());
+            }
+
+            File existingManifest = defaultManifestFile;
+            if (useDefaultManifestFile && existingManifest.exists() && archive.getManifestFile() == null) {
+                getLog().info("Adding existing MANIFEST to archive. Found under: " + existingManifest.getPath());
+                archive.setManifestFile(existingManifest);
+            }
+
+            // automatically add the artifact id to the manifest
+            archive.addManifestEntry("Nar-Id", project.getArtifactId());
+
+            // look for a nar dependency
+            String narDependency = getNarDependency();
+            if (narDependency != null) {
+                archive.addManifestEntry("Nar-Dependency-Id", narDependency);
+            }
+
+            archiver.createArchive(session, project, archive);
+            return narFile;
+        } catch (ArchiverException | MojoExecutionException | ManifestException | IOException | DependencyResolutionRequiredException e) {
+            throw new MojoExecutionException("Error assembling NAR", e);
+        }
+    }
+
+    private String[] getIncludes() {
+        if (includes != null && includes.length > 0) {
+            return includes;
+        }
+        return DEFAULT_INCLUDES;
+    }
+
+    private String[] getExcludes() {
+        if (excludes != null && excludes.length > 0) {
+            return excludes;
+        }
+        return DEFAULT_EXCLUDES;
+    }
+
+    protected File getNarFile(File basedir, String finalName, String classifier) {
+        if (classifier == null) {
+            classifier = "";
+        } else if (classifier.trim().length() > 0 && !classifier.startsWith("-")) {
+            classifier = "-" + classifier;
+        }
+
+        return new File(basedir, finalName + classifier + ".nar");
+    }
+
+    private String getNarDependency() throws MojoExecutionException {
+        String narDependency = null;
+
+        // get nar dependencies
+        FilterArtifacts filter = new FilterArtifacts();
+        filter.addFilter(new TypeFilter("nar", ""));
+
+        // start with all artifacts.
+        Set artifacts = project.getArtifacts();
+
+        // perform filtering
+        try {
+            artifacts = filter.filter(artifacts);
+        } catch (ArtifactFilterException e) {
+            throw new MojoExecutionException(e.getMessage(), e);
+        }
+
+        // ensure there is a single nar dependency
+        if (artifacts.size() > 1) {
+            throw new MojoExecutionException("Each NAR represents a ClassLoader. A NAR dependency allows that NAR's ClassLoader to be "
+                    + "used as the parent of this NAR's ClassLoader. As a result, only a single NAR dependency is allowed.");
+        } else if (artifacts.size() == 1) {
+            final Artifact artifact = (Artifact) artifacts.iterator().next();
+            narDependency = artifact.getArtifactId();
+        }
+
+        return narDependency;
+    }
+}
diff --git a/src/main/resources/META-INF/plexus/components.xml b/src/main/resources/META-INF/plexus/components.xml
new file mode 100644
index 0000000..ad2c3cb
--- /dev/null
+++ b/src/main/resources/META-INF/plexus/components.xml
@@ -0,0 +1,52 @@
+<?xml version="1.0"?>
+<!--
+  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.
+-->
+<component-set>
+    <components>
+        <component>
+            <role>org.apache.maven.lifecycle.mapping.LifecycleMapping</role>
+            <role-hint>nar</role-hint>
+            <implementation>org.apache.maven.lifecycle.mapping.DefaultLifecycleMapping</implementation>
+            <configuration>
+                <lifecycles>
+                    <lifecycle>
+                        <id>default</id>
+                        <phases>
+                            <process-resources>org.apache.maven.plugins:maven-resources-plugin:resources</process-resources>
+                            <compile>org.apache.maven.plugins:maven-compiler-plugin:compile</compile>
+                            <process-test-resources>org.apache.maven.plugins:maven-resources-plugin:testResources</process-test-resources>
+                            <test-compile>org.apache.maven.plugins:maven-compiler-plugin:testCompile</test-compile>
+                            <test>org.apache.maven.plugins:maven-surefire-plugin:test</test>
+                            <package>org.apache.nifi:nifi-nar-maven-plugin:nar</package>
+                            <install>org.apache.maven.plugins:maven-install-plugin:install</install>
+                            <deploy>org.apache.maven.plugins:maven-deploy-plugin:deploy</deploy>
+                        </phases>
+                    </lifecycle>
+                </lifecycles>
+            </configuration>
+        </component>
+        <component>
+            <role>org.apache.maven.artifact.handler.ArtifactHandler</role>
+            <role-hint>nar</role-hint>
+            <implementation>org.apache.maven.artifact.handler.DefaultArtifactHandler</implementation>
+            <configuration>
+                <type>nar</type>
+                <language>java</language>
+                <addedToClasspath>false</addedToClasspath>
+                <includesDependencies>true</includesDependencies>
+            </configuration>
+        </component>
+    </components>
+</component-set>


[nifi-maven] 15/20: NIFI-4930: Resolve issues when fetching nar files from artifact repositories like artifactory

Posted by kd...@apache.org.
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 5a74629467d11ddc6ac1ef07c246c4588bfd9bca
Author: Derek Straka <de...@asterius.io>
AuthorDate: Tue May 29 21:33:36 2018 -0400

    NIFI-4930: Resolve issues when fetching nar files from artifact repositories like artifactory
    
    The NAR Maven Plugin 1.2.0 is using artifact.getVersion() to determine the Nar-Dependency-Version, however this version number can be a timestamped snapshot version number if the dependency was downloaded from a remote repo. The Nar-Dependency-Version can then differ from the declared Nar-Version in the other JAR.
    
    This closes #3.
    
    Signed-off-by: Derek Straka <de...@asterius.io>
    Signed-off-by: Bryan Bende <bb...@apache.org>
---
 src/main/java/org/apache/nifi/NarMojo.java | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/src/main/java/org/apache/nifi/NarMojo.java b/src/main/java/org/apache/nifi/NarMojo.java
index 809eff4..124a978 100644
--- a/src/main/java/org/apache/nifi/NarMojo.java
+++ b/src/main/java/org/apache/nifi/NarMojo.java
@@ -702,7 +702,7 @@ public class NarMojo extends AbstractMojo {
         } else if (artifacts.size() == 1) {
             final Artifact artifact = (Artifact) artifacts.iterator().next();
 
-            narDependency = new NarDependency(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion());
+            narDependency = new NarDependency(artifact.getGroupId(), artifact.getArtifactId(), artifact.getBaseVersion());
         }
 
         return narDependency;


[nifi-maven] 03/20: NIFI-850

Posted by kd...@apache.org.
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 82d8f6173e743b6b9a9fe066946f76944e1e0eea
Author: joewitt <jo...@apache.org>
AuthorDate: Sat Aug 15 13:14:56 2015 -0400

    NIFI-850
---
 DISCLAIMER | 15 ---------------
 1 file changed, 15 deletions(-)

diff --git a/DISCLAIMER b/DISCLAIMER
deleted file mode 100644
index 0f8e7a1..0000000
--- a/DISCLAIMER
+++ /dev/null
@@ -1,15 +0,0 @@
-Apache NiFi is an effort undergoing incubation at the Apache Software
-Foundation (ASF), sponsored by the Apache Incubator PMC.
-
-Incubation is required of all newly accepted projects until a further review
-indicates that the infrastructure, communications, and decision making process
-have stabilized in a manner consistent with other successful ASF projects.
-
-While incubation status is not necessarily a reflection of the completeness
-or stability of the code, it does indicate that the project has yet to be
-fully endorsed by the ASF.
-
-For more information about the incubation status of the Apache NiFi project
-you can go to the following page:
-
-http://nifi.incubator.apache.org/


[nifi-maven] 07/20: NIFI-875 fixing incubator reference

Posted by kd...@apache.org.
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 a931303a81d25f8c9373c2d00ec3f219589ab444
Author: joewitt <jo...@apache.org>
AuthorDate: Sun Aug 23 22:40:49 2015 -0400

    NIFI-875 fixing incubator reference
---
 README.md | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/README.md b/README.md
index a9c0f23..91c44f2 100644
--- a/README.md
+++ b/README.md
@@ -38,8 +38,8 @@ the main 'nifi' code tree.
 
 
 ## Getting Help
-If you have questions, you can reach out to our mailing list: dev@nifi.incubator.apache.org
-([archive](http://mail-archives.apache.org/mod_mbox/incubator-nifi-dev)).
+If you have questions, you can reach out to our mailing list: dev@nifi.apache.org
+([archive](http://mail-archives.apache.org/mod_mbox/nifi-dev)).
 We're also often available in IRC: #nifi on
 [irc.freenode.net](http://webchat.freenode.net/?channels=#nifi).
 


[nifi-maven] 08/20: NIFI-3381 Updating NAR Maven Plugin to include group and versio for NAR and NAR dependencies, as well as additional build info when available

Posted by kd...@apache.org.
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 c5f32a706010ec2fbec51c9e6189e41a0fa47dd3
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Fri Jan 20 17:45:58 2017 -0500

    NIFI-3381 Updating NAR Maven Plugin to include group and versio for NAR and NAR dependencies, as well as additional build info when available
    
    Signed-off-by: Matt Gilman <ma...@gmail.com>
---
 src/main/java/org/apache/nifi/NarMojo.java | 75 +++++++++++++++++++++++++++---
 1 file changed, 69 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/apache/nifi/NarMojo.java b/src/main/java/org/apache/nifi/NarMojo.java
index 0e32902..a4f8f31 100644
--- a/src/main/java/org/apache/nifi/NarMojo.java
+++ b/src/main/java/org/apache/nifi/NarMojo.java
@@ -18,6 +18,8 @@ package org.apache.nifi;
 
 import java.io.File;
 import java.io.IOException;
+import java.text.SimpleDateFormat;
+import java.util.Date;
 import java.util.HashSet;
 import java.util.List;
 import java.util.Set;
@@ -82,6 +84,8 @@ public class NarMojo extends AbstractMojo {
     private static final String[] DEFAULT_EXCLUDES = new String[]{"**/package.html"};
     private static final String[] DEFAULT_INCLUDES = new String[]{"**/**"};
 
+    private static final String BUILD_TIMESTAMP_FORMAT = "yyyy-MM-dd'T'HH:mm:ss'Z'";
+
     /**
      * POM
      *
@@ -359,6 +363,15 @@ public class NarMojo extends AbstractMojo {
     @Parameter(property = "outputAbsoluteArtifactFilename", defaultValue = "false", required = false)
     protected boolean outputAbsoluteArtifactFilename;
 
+    @Parameter(property = "buildTag", defaultValue = "${project.scm.tag}", required = false)
+    protected String buildTag;
+
+    @Parameter(property = "buildBranch", defaultValue = "${buildBranch}", required = false)
+    protected String buildBranch;
+
+    @Parameter(property = "buildRevision", defaultValue = "${buildRevision}", required = false)
+    protected String buildRevision;
+
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
         copyDependencies();
@@ -542,15 +555,34 @@ public class NarMojo extends AbstractMojo {
                 archive.setManifestFile(existingManifest);
             }
 
-            // automatically add the artifact id to the manifest
+            // automatically add the artifact id, group id, and version to the manifest
             archive.addManifestEntry("Nar-Id", project.getArtifactId());
+            archive.addManifestEntry("Nar-Group", project.getGroupId());
+            archive.addManifestEntry("Nar-Version", project.getVersion());
 
             // look for a nar dependency
-            String narDependency = getNarDependency();
+            NarDependency narDependency = getNarDependency();
             if (narDependency != null) {
-                archive.addManifestEntry("Nar-Dependency-Id", narDependency);
+                archive.addManifestEntry("Nar-Dependency-Id", narDependency.getArtifactId());
+                archive.addManifestEntry("Nar-Dependency-Group", narDependency.getGroupId());
+                archive.addManifestEntry("Nar-Dependency-Version", narDependency.getVersion());
             }
 
+            // add build information when available
+
+            if (notEmpty(buildTag)) {
+                archive.addManifestEntry("Build-Tag", buildTag);
+            }
+            if (notEmpty(buildBranch)) {
+                archive.addManifestEntry("Build-Branch", buildBranch);
+            }
+            if (notEmpty(buildRevision)) {
+                archive.addManifestEntry("Build-Revision", buildRevision);
+            }
+
+            SimpleDateFormat dateFormat = new SimpleDateFormat(BUILD_TIMESTAMP_FORMAT);
+            archive.addManifestEntry("Build-Timestamp", dateFormat.format(new Date()));
+
             archiver.createArchive(session, project, archive);
             return narFile;
         } catch (ArchiverException | MojoExecutionException | ManifestException | IOException | DependencyResolutionRequiredException e) {
@@ -558,6 +590,10 @@ public class NarMojo extends AbstractMojo {
         }
     }
 
+    private boolean notEmpty(String value) {
+        return value != null && !value.isEmpty();
+    }
+
     private String[] getIncludes() {
         if (includes != null && includes.length > 0) {
             return includes;
@@ -582,8 +618,8 @@ public class NarMojo extends AbstractMojo {
         return new File(basedir, finalName + classifier + ".nar");
     }
 
-    private String getNarDependency() throws MojoExecutionException {
-        String narDependency = null;
+    private NarDependency getNarDependency() throws MojoExecutionException {
+        NarDependency narDependency = null;
 
         // get nar dependencies
         FilterArtifacts filter = new FilterArtifacts();
@@ -605,9 +641,36 @@ public class NarMojo extends AbstractMojo {
                     + "used as the parent of this NAR's ClassLoader. As a result, only a single NAR dependency is allowed.");
         } else if (artifacts.size() == 1) {
             final Artifact artifact = (Artifact) artifacts.iterator().next();
-            narDependency = artifact.getArtifactId();
+
+            narDependency = new NarDependency(artifact.getGroupId(), artifact.getArtifactId(), artifact.getVersion());
         }
 
         return narDependency;
     }
+
+    private static class NarDependency {
+
+        final String groupId;
+        final String artifactId;
+        final String version;
+
+        public NarDependency(String groupId, String artifactId, String version) {
+            this.groupId = groupId;
+            this.artifactId = artifactId;
+            this.version = version;
+        }
+
+        public String getGroupId() {
+            return groupId;
+        }
+
+        public String getArtifactId() {
+            return artifactId;
+        }
+
+        public String getVersion() {
+            return version;
+        }
+    }
+
 }


[nifi-maven] 13/20: NIFI-3597 prepare release nifi-nar-maven-plugin-1.2.0-RC1

Posted by kd...@apache.org.
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 d0c9d46d25a3eb8d3dbeb2783477b1a7c5b2f345
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Tue Mar 14 11:10:20 2017 -0400

    NIFI-3597 prepare release nifi-nar-maven-plugin-1.2.0-RC1
---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 6c0f01c..985a794 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.2.0-SNAPSHOT</version>
+    <version>1.2.0</version>
     <packaging>maven-plugin</packaging>
     <description>Apache NiFi Nar Maven Plugin</description>
     <url>http://nifi.apache.org</url>
@@ -67,7 +67,7 @@
         <connection>scm:git:git://git.apache.org/nifi-maven.git</connection>
         <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/nifi-maven.git</developerConnection>
         <url>https://git-wip-us.apache.org/repos/asf?p=nifi-maven.git</url>
-        <tag>HEAD</tag>
+        <tag>nifi-nar-maven-plugin-1.2.0-RC1</tag>
     </scm>
     <issueManagement>
         <system>JIRA</system>


[nifi-maven] 20/20: NIFI-5859

Posted by kd...@apache.org.
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 438612e8e30015441d3e5394d60067ccc75aa914
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Fri Feb 1 16:50:58 2019 -0500

    NIFI-5859
    
    - Removing unused code that was moved to nifi-api, refactored logic for traversing dependencies
    - Added option to fail build if doc generation fails through enforceDocGeneration property on plugin configuration
    
    This closes #8.
    
    Signed-off-by: Kevin Doran <kd...@apache.org>
---
 src/main/java/org/apache/nifi/NarMojo.java         |  36 ++---
 .../apache/nifi/PropertiesDefinitionWriter.java    |  75 ----------
 .../java/org/apache/nifi/XmlDefinitionWriter.java  | 165 ---------------------
 .../extension/definition/ExtensionDefinition.java  |  15 +-
 .../nifi/extension/definition/Restriction.java     |  29 ----
 .../nifi/extension/definition/Restrictions.java    |  31 ----
 .../extraction/ExtensionClassLoader.java           |  10 +-
 .../extraction/ExtensionClassLoaderFactory.java    |  93 +++++-------
 .../extraction/ExtensionDefinitionFactory.java     | 112 +-------------
 .../extraction/StandardExtensionDefinition.java    |  26 +---
 .../definition/extraction/StandardRestriction.java |  39 -----
 .../extraction/StandardRestrictions.java           |  42 ------
 12 files changed, 71 insertions(+), 602 deletions(-)

diff --git a/src/main/java/org/apache/nifi/NarMojo.java b/src/main/java/org/apache/nifi/NarMojo.java
index 85ebfcf..3627adf 100644
--- a/src/main/java/org/apache/nifi/NarMojo.java
+++ b/src/main/java/org/apache/nifi/NarMojo.java
@@ -34,7 +34,6 @@ import org.apache.maven.artifact.resolver.ArtifactResolver;
 import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
-import org.apache.maven.plugin.MojoFailureException;
 import org.apache.maven.plugin.dependency.utils.DependencyStatusSets;
 import org.apache.maven.plugin.dependency.utils.DependencyUtil;
 import org.apache.maven.plugin.dependency.utils.filters.DestFileFilter;
@@ -50,6 +49,7 @@ import org.apache.maven.plugins.annotations.ResolutionScope;
 import org.apache.maven.project.MavenProject;
 import org.apache.maven.project.MavenProjectHelper;
 import org.apache.maven.project.ProjectBuilder;
+import org.apache.maven.project.ProjectBuildingException;
 import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
 import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
 import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
@@ -76,19 +76,11 @@ import org.eclipse.aether.RepositorySystemSession;
 
 import javax.xml.stream.XMLOutputFactory;
 import javax.xml.stream.XMLStreamWriter;
-import java.io.BufferedOutputStream;
-import java.io.BufferedReader;
 import java.io.File;
-import java.io.FileInputStream;
-import java.io.FileNotFoundException;
 import java.io.FileOutputStream;
 import java.io.IOException;
 import java.io.InputStream;
-import java.io.InputStreamReader;
 import java.io.OutputStream;
-import java.io.Reader;
-import java.io.StringWriter;
-import java.io.Writer;
 import java.lang.reflect.Constructor;
 import java.lang.reflect.InvocationTargetException;
 import java.lang.reflect.Method;
@@ -479,6 +471,9 @@ public class NarMojo extends AbstractMojo {
     protected boolean cloneDuringInstanceClassLoading;
 
 
+    @Parameter(property = "enforceDocGeneration", defaultValue = "false", required = false)
+    protected boolean enforceDocGeneration;
+
     /**
      * The {@link RepositorySystemSession} used for obtaining the local and remote artifact repositories.
      */
@@ -501,7 +496,12 @@ public class NarMojo extends AbstractMojo {
         try {
             generateDocumentation();
         } catch (final Throwable t) { // Catch Throwable in case a linkage error such as NoClassDefFoundError occurs
-            getLog().warn("Could not generate extensions' documentation", t);
+            if (enforceDocGeneration) {
+                getLog().error("Could not generate extensions' documentation", t);
+                throw t;
+            } else {
+                getLog().warn("Could not generate extensions' documentation", t);
+            }
         }
 
         makeNar();
@@ -522,14 +522,17 @@ public class NarMojo extends AbstractMojo {
         try {
             extensionClassLoader = classLoaderFactory.createExtensionClassLoader();
         } catch (final Exception e) {
-            if (getLog().isDebugEnabled()) {
-                getLog().debug("Unable to create a ClassLoader for documenting extensions. If this NAR contains any NiFi Extensions, those extensions will not be documented.", e);
+            if (enforceDocGeneration) {
+                throw new MojoExecutionException("Failed to create Extension Documentation", e);
             } else {
-                getLog().warn("Unable to create a ClassLoader for documenting extensions. If this NAR contains any NiFi Extensions, those extensions will not be documented. " +
-                    "Enable mvn DEBUG output for more information (mvn -X).");
+                if (getLog().isDebugEnabled()) {
+                    getLog().debug("Unable to create a ClassLoader for documenting extensions. If this NAR contains any NiFi Extensions, those extensions will not be documented.", e);
+                } else {
+                    getLog().warn("Unable to create a ClassLoader for documenting extensions. If this NAR contains any NiFi Extensions, those extensions will not be documented. " +
+                            "Enable mvn DEBUG output for more information (mvn -X).");
+                }
+                return;
             }
-
-            return;
         }
 
 
@@ -715,7 +718,6 @@ public class NarMojo extends AbstractMojo {
             .log(getLog())
             .project(project)
             .projectBuilder(projectBuilder)
-            .remoteRepositories(remoteRepos)
             .repositorySession(repoSession)
             .artifactHandlerManager(artifactHandlerManager)
             .build();
diff --git a/src/main/java/org/apache/nifi/PropertiesDefinitionWriter.java b/src/main/java/org/apache/nifi/PropertiesDefinitionWriter.java
deleted file mode 100644
index 402d18c..0000000
--- a/src/main/java/org/apache/nifi/PropertiesDefinitionWriter.java
+++ /dev/null
@@ -1,75 +0,0 @@
-/*
- * 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 org.apache.nifi.extension.definition.ExtensionDefinition;
-import org.apache.nifi.extension.definition.Restriction;
-import org.apache.nifi.extension.definition.Restrictions;
-import org.apache.nifi.extension.definition.ServiceAPIDefinition;
-
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Objects;
-import java.util.Properties;
-
-public class PropertiesDefinitionWriter {
-
-    public void writeDefinition(final ExtensionDefinition definition, final File file) throws IOException {
-        Objects.requireNonNull(definition);
-
-        final String capabilityDescription = definition.getCapabilityDescription();
-
-        final Properties properties = new Properties();
-        if (capabilityDescription != null) {
-            properties.setProperty("capability.description", capabilityDescription);
-        }
-
-        int i=0;
-        for (final String tag : definition.getTags()) {
-            properties.setProperty("tags." + (i++), tag);
-        }
-
-        final Restrictions restrictions = definition.getRestrictions();
-        if (restrictions != null) {
-            final String restrictedDescription = restrictions.getGeneralRestrictionExplanation();
-
-            if (restrictedDescription != null) {
-                properties.setProperty("restricted.description", restrictedDescription);
-            }
-
-            for (final Restriction restriction : restrictions.getRestrictions()) {
-                properties.setProperty("restriction." + restriction.getIdentifier(), restriction.getExplanation());
-            }
-        }
-
-        int serviceIndex = 0;
-        for (final ServiceAPIDefinition apiDefinition : definition.getProvidedServiceAPIs()) {
-            properties.setProperty("service.definition." + serviceIndex + ".class", apiDefinition.getServiceAPIClassName());
-            properties.setProperty("service.definition." + serviceIndex + ".groupId", apiDefinition.getServiceGroupId());
-            properties.setProperty("service.definition." + serviceIndex + ".artifactId", apiDefinition.getServiceArtifactId());
-            properties.setProperty("service.definition." + serviceIndex + ".version", apiDefinition.getServiceVersion());
-
-            serviceIndex++;
-        }
-
-        try (final OutputStream fos = new FileOutputStream(file)) {
-            properties.store(fos, null);
-        }
-    }
-}
diff --git a/src/main/java/org/apache/nifi/XmlDefinitionWriter.java b/src/main/java/org/apache/nifi/XmlDefinitionWriter.java
deleted file mode 100644
index 3e91061..0000000
--- a/src/main/java/org/apache/nifi/XmlDefinitionWriter.java
+++ /dev/null
@@ -1,165 +0,0 @@
-/*
- * 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 org.apache.nifi.extension.definition.ExtensionDefinition;
-import org.apache.nifi.extension.definition.ExtensionType;
-import org.apache.nifi.extension.definition.Restriction;
-import org.apache.nifi.extension.definition.Restrictions;
-import org.apache.nifi.extension.definition.ServiceAPIDefinition;
-
-import javax.xml.stream.XMLOutputFactory;
-import javax.xml.stream.XMLStreamException;
-import javax.xml.stream.XMLStreamWriter;
-import java.io.File;
-import java.io.FileOutputStream;
-import java.io.IOException;
-import java.io.OutputStream;
-import java.util.Collection;
-import java.util.List;
-import java.util.Map;
-import java.util.Objects;
-import java.util.Set;
-import java.util.stream.Collectors;
-
-public class XmlDefinitionWriter {
-
-    public void writeDefinition(final Collection<ExtensionDefinition> definitions, final File file) throws IOException {
-        final Map<ExtensionType, List<ExtensionDefinition>> definitionMap = definitions.stream()
-            .collect(Collectors.groupingBy(ExtensionDefinition::getExtensionType));
-
-        writeDefinition(definitionMap, file);
-    }
-
-    public void writeDefinition(final Map<ExtensionType, ? extends Collection<ExtensionDefinition>> definitions, final File file) throws IOException {
-        Objects.requireNonNull(definitions);
-        Objects.requireNonNull(file);
-
-        if (definitions.isEmpty()) {
-            return;
-        }
-
-        try (final OutputStream fileOut = new FileOutputStream(file)) {
-             final XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(fileOut, "UTF-8");
-             try {
-                 writer.writeStartElement("extensions");
-
-                 writer.writeStartElement("processors");
-                 writeDefinitions(ExtensionType.PROCESSOR, definitions.get(ExtensionType.PROCESSOR), writer);
-                 writer.writeEndElement();
-
-                 writer.writeStartElement("controllerServices");
-                 writeDefinitions(ExtensionType.CONTROLLER_SERVICE, definitions.get(ExtensionType.CONTROLLER_SERVICE), writer);
-                 writer.writeEndElement();
-
-                 writer.writeStartElement("reportingTasks");
-                 writeDefinitions(ExtensionType.REPORTING_TASK, definitions.get(ExtensionType.REPORTING_TASK), writer);
-                 writer.writeEndElement();
-
-                 writer.writeEndElement();
-             } finally {
-                 writer.close();
-             }
-        } catch (XMLStreamException e) {
-            throw new IOException(e);
-        }
-    }
-
-    private void writeDefinitions(final ExtensionType extensionType, final Collection<ExtensionDefinition> definitions, final XMLStreamWriter writer) throws XMLStreamException {
-        if (definitions == null) {
-            return;
-        }
-
-        final String tagName;
-        switch (extensionType) {
-            case PROCESSOR:
-                tagName = "processor";
-                break;
-            case CONTROLLER_SERVICE:
-                tagName = "controllerService";
-                break;
-            case REPORTING_TASK:
-                tagName = "reportingTask";
-                break;
-            default:
-                throw new AssertionError("Encountered unknown Extension Type " + extensionType);
-        }
-
-        for (final ExtensionDefinition definition : definitions) {
-            writer.writeStartElement(tagName);
-
-            writeTextElement(writer, "name", definition.getExtensionName());
-            writeTextElement(writer, "description", definition.getCapabilityDescription());
-
-            writer.writeStartElement("tags");
-            for (final String tag : definition.getTags()) {
-                writeTextElement(writer, "tag", tag);
-            }
-            writer.writeEndElement();
-
-            final Restrictions restrictions = definition.getRestrictions();
-            if (restrictions == null) {
-                writer.writeEmptyElement("restrictions");
-            } else {
-                writer.writeStartElement("restrictions");
-
-                writeTextElement(writer, "explanation", restrictions.getGeneralRestrictionExplanation());
-                final Set<Restriction> specificRestrictions = restrictions.getRestrictions();
-                for (final Restriction restriction : specificRestrictions) {
-                    writer.writeStartElement("restriction");
-                    writeTextElement(writer, "identifier", restriction.getIdentifier());
-                    writeTextElement(writer, "explanation", restriction.getExplanation());
-                    writer.writeEndElement();
-                }
-
-                writer.writeEndElement();
-            }
-
-            if (extensionType == ExtensionType.CONTROLLER_SERVICE) {
-                writer.writeStartElement("providedServiceAPIs");
-
-                final Set<ServiceAPIDefinition> serviceDefinitions = definition.getProvidedServiceAPIs();
-                if (serviceDefinitions != null) {
-                    for (final ServiceAPIDefinition serviceDefinition : serviceDefinitions) {
-                        writer.writeStartElement("service");
-
-                        writeTextElement(writer, "className", serviceDefinition.getServiceAPIClassName());
-                        writeTextElement(writer, "groupId", serviceDefinition.getServiceGroupId());
-                        writeTextElement(writer, "artifactId", serviceDefinition.getServiceArtifactId());
-                        writeTextElement(writer, "version", serviceDefinition.getServiceVersion());
-
-                        writer.writeEndElement();
-                    }
-                }
-
-                writer.writeEndElement();
-            }
-
-            writer.writeEndElement();
-        }
-    }
-
-    private void writeTextElement(final XMLStreamWriter writer, final String tagName, final String text) throws XMLStreamException {
-        writer.writeStartElement(tagName);
-
-        if (text != null) {
-            writer.writeCharacters(text);
-        }
-
-        writer.writeEndElement();
-    }
-}
diff --git a/src/main/java/org/apache/nifi/extension/definition/ExtensionDefinition.java b/src/main/java/org/apache/nifi/extension/definition/ExtensionDefinition.java
index 8c0bc40..cbff75e 100644
--- a/src/main/java/org/apache/nifi/extension/definition/ExtensionDefinition.java
+++ b/src/main/java/org/apache/nifi/extension/definition/ExtensionDefinition.java
@@ -19,20 +19,6 @@ package org.apache.nifi.extension.definition;
 import java.util.Set;
 
 public interface ExtensionDefinition {
-    /**
-     * @return the extension's capability description
-     */
-    String getCapabilityDescription();
-
-    /**
-     * @return the set of Tags associated with the extension
-     */
-    Set<String> getTags();
-
-    /**
-     * @return the Restrictions that are placed on the Extension
-     */
-    Restrictions getRestrictions();
 
     /**
      * @return the type of Extension
@@ -49,4 +35,5 @@ public interface ExtensionDefinition {
      * @return the name of the Extension
      */
     String getExtensionName();
+
 }
diff --git a/src/main/java/org/apache/nifi/extension/definition/Restriction.java b/src/main/java/org/apache/nifi/extension/definition/Restriction.java
deleted file mode 100644
index 9b5064c..0000000
--- a/src/main/java/org/apache/nifi/extension/definition/Restriction.java
+++ /dev/null
@@ -1,29 +0,0 @@
-/*
- * 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.extension.definition;
-
-public interface Restriction {
-    /**
-     * @return the Restriction identifier used by NiFi
-     */
-    String getIdentifier();
-
-    /**
-     * @return an Explanation of why the Restriction exists.
-     */
-    String getExplanation();
-}
diff --git a/src/main/java/org/apache/nifi/extension/definition/Restrictions.java b/src/main/java/org/apache/nifi/extension/definition/Restrictions.java
deleted file mode 100644
index 5e098fb..0000000
--- a/src/main/java/org/apache/nifi/extension/definition/Restrictions.java
+++ /dev/null
@@ -1,31 +0,0 @@
-/*
- * 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.extension.definition;
-
-import java.util.Set;
-
-public interface Restrictions {
-    /**
-     * @return if the extension has a General Restriction on it, this explains why the Restriction is in place.
-     */
-    String getGeneralRestrictionExplanation();
-
-    /**
-     * @return the set of all specific Restrictions that are placed on this extension.
-     */
-    Set<Restriction> getRestrictions();
-}
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoader.java b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoader.java
index 12f02ac..cdc531a 100644
--- a/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoader.java
+++ b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoader.java
@@ -34,7 +34,9 @@ public class ExtensionClassLoader extends URLClassLoader {
         this.urls = urls;
         this.narArtifact = narArtifact;
         this.allArtifacts = new ArrayList<>(otherArtifacts);
-        allArtifacts.add(narArtifact);
+        if (narArtifact != null) {
+            allArtifacts.add(narArtifact);
+        }
     }
 
     public ExtensionClassLoader(final URL[] urls, final Artifact narArtifact, final Collection<Artifact> otherArtifacts) {
@@ -42,7 +44,9 @@ public class ExtensionClassLoader extends URLClassLoader {
         this.urls = urls;
         this.narArtifact = narArtifact;
         this.allArtifacts = new ArrayList<>(otherArtifacts);
-        allArtifacts.add(narArtifact);
+        if (narArtifact != null) {
+            allArtifacts.add(narArtifact);
+        }
     }
 
     public String getNiFiApiVersion() {
@@ -55,7 +59,7 @@ public class ExtensionClassLoader extends URLClassLoader {
 
         final ClassLoader parent = getParent();
         if (parent instanceof ExtensionClassLoader) {
-            ((ExtensionClassLoader) parent).getNiFiApiVersion();
+            return ((ExtensionClassLoader) parent).getNiFiApiVersion();
         }
 
         return null;
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoaderFactory.java b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoaderFactory.java
index 7b2e5f7..1147698 100644
--- a/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoaderFactory.java
+++ b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoaderFactory.java
@@ -42,13 +42,14 @@ import org.eclipse.aether.RepositorySystemSession;
 import java.io.File;
 import java.net.MalformedURLException;
 import java.net.URL;
-import java.net.URLClassLoader;
 import java.util.ArrayList;
 import java.util.Collections;
+import java.util.Comparator;
 import java.util.HashSet;
 import java.util.Iterator;
 import java.util.List;
 import java.util.Set;
+import java.util.TreeSet;
 
 public class ExtensionClassLoaderFactory {
     private final Log log;
@@ -56,7 +57,6 @@ public class ExtensionClassLoaderFactory {
     private final RepositorySystemSession repoSession;
     private final ProjectBuilder projectBuilder;
     private final ArtifactRepository localRepo;
-    private final List<ArtifactRepository> remoteRepos;
     private final DependencyTreeBuilder dependencyTreeBuilder;
     private final ArtifactResolver artifactResolver;
     private final ArtifactHandlerManager artifactHandlerManager;
@@ -67,7 +67,6 @@ public class ExtensionClassLoaderFactory {
         this.repoSession = builder.repositorySession;
         this.projectBuilder = builder.projectBuilder;
         this.localRepo = builder.localRepo;
-        this.remoteRepos = new ArrayList<>(builder.remoteRepos);
         this.dependencyTreeBuilder = builder.dependencyTreeBuilder;
         this.artifactResolver = builder.artifactResolver;
         this.artifactHandlerManager = builder.artifactHandlerManager;
@@ -77,25 +76,18 @@ public class ExtensionClassLoaderFactory {
         return log;
     }
 
-    public ExtensionClassLoader createExtensionClassLoader() throws MojoExecutionException {
-        final Set<Artifact> artifacts = new HashSet<>();
-        gatherArtifacts(project, artifacts);
-
-        getLog().debug("Project artifacts: ");
-        artifacts.forEach(artifact -> getLog().debug(artifact.toString()));
-
+    public ExtensionClassLoader createExtensionClassLoader() throws MojoExecutionException, ProjectBuildingException {
         final Artifact narArtifact = project.getArtifact();
+        final Set<Artifact> narArtifacts = getNarDependencies(narArtifact);
 
-        final VersionLookup versionLookup = (group, artifact) -> {
-            try {
-                return determineProvidedEntityVersion(artifacts, group, artifact);
-            } catch (final Exception e) {
-                throw new RuntimeException("Failed to determine provided version of NiFi dependencies", e);
-            }
-        };
+        final ArtifactsHolder artifactsHolder = new ArtifactsHolder();
+        artifactsHolder.addArtifacts(narArtifacts);
+
+        getLog().debug("Project artifacts: ");
+        narArtifacts.forEach(artifact -> getLog().debug(artifact.getArtifactId()));
 
-        final ClassLoader parentClassLoader = createClassLoader(artifacts, versionLookup);
-        final ExtensionClassLoader classLoader = createClassLoader(artifacts, parentClassLoader, narArtifact);
+        final ExtensionClassLoader parentClassLoader = createClassLoader(narArtifacts, artifactsHolder);
+        final ExtensionClassLoader classLoader = createClassLoader(narArtifacts, parentClassLoader, narArtifact);
 
         if (getLog().isDebugEnabled()) {
             getLog().debug("Full ClassLoader is:\n" + classLoader.toTree());
@@ -104,15 +96,19 @@ public class ExtensionClassLoaderFactory {
         return classLoader;
     }
 
-    private ClassLoader createClassLoader(final Set<Artifact> artifacts, final VersionLookup versionLookup) throws MojoExecutionException {
+    private ExtensionClassLoader createClassLoader(final Set<Artifact> artifacts, final ArtifactsHolder artifactsHolder)
+            throws MojoExecutionException, ProjectBuildingException {
+
         final Artifact nar = removeNarArtifact(artifacts);
         if (nar == null) {
-            final ClassLoader providedEntityClassLoader = createProvidedEntitiesClassLoader(versionLookup);
-            return createUrlClassLoader(artifacts, providedEntityClassLoader);
+            final ExtensionClassLoader providedEntityClassLoader = createProvidedEntitiesClassLoader(artifactsHolder);
+            return createClassLoader(artifacts, providedEntityClassLoader, null);
         }
 
         final Set<Artifact> narDependencies = getNarDependencies(nar);
-        return createClassLoader(narDependencies, createClassLoader(narDependencies, versionLookup), nar);
+        artifactsHolder.addArtifacts(narDependencies);
+
+        return createClassLoader(narDependencies, createClassLoader(narDependencies, artifactsHolder), nar);
     }
 
 
@@ -141,7 +137,7 @@ public class ExtensionClassLoaderFactory {
         narRequest.setRepositorySession(repoSession);
         narRequest.setSystemProperties(System.getProperties());
 
-        final Set<Artifact> narDependencies = new HashSet<>();
+        final Set<Artifact> narDependencies = new TreeSet<>();
 
         try {
             final ProjectBuildingResult narResult = projectBuilder.build(narArtifact, narRequest);
@@ -213,7 +209,6 @@ public class ExtensionClassLoaderFactory {
 
         final ArtifactResolutionRequest request = new ArtifactResolutionRequest();
         request.setLocalRepository(localRepo);
-        request.setRemoteRepositories(remoteRepos);
         request.setArtifact(artifact);
 
         final ArtifactResolutionResult result = artifactResolver.resolve(request);
@@ -241,15 +236,17 @@ public class ExtensionClassLoaderFactory {
         return sorted.get(0);
     }
 
-    private ClassLoader createProvidedEntitiesClassLoader(final VersionLookup versionLookup) throws MojoExecutionException {
-        final String nifiApiVersion = versionLookup.getVersion("org.apache.nifi", "nifi-api");
+    private ExtensionClassLoader createProvidedEntitiesClassLoader(final ArtifactsHolder artifactsHolder)
+            throws MojoExecutionException, ProjectBuildingException {
+
+        final String nifiApiVersion = determineProvidedEntityVersion(artifactsHolder.getAllArtifacts(), "org.apache.nifi", "nifi-api");
         if (nifiApiVersion == null) {
             throw new MojoExecutionException("Could not find any dependency, provided or otherwise, on [org.apache.nifi:nifi-api]");
         } else {
             getLog().info("Found a dependency on version " + nifiApiVersion + " of NiFi API");
         }
 
-        final String slf4jApiVersion = versionLookup.getVersion("org.slf4j", "slf4j-api");
+        final String slf4jApiVersion = determineProvidedEntityVersion(artifactsHolder.getAllArtifacts(),"org.slf4j", "slf4j-api");
 
         final Artifact nifiApiArtifact = getProvidedArtifact("org.apache.nifi", "nifi-api", nifiApiVersion);
         final Artifact nifiFrameworkApiArtifact = getProvidedArtifact("org.apache.nifi", "nifi-framework-api", nifiApiArtifact.getVersion());
@@ -262,23 +259,10 @@ public class ExtensionClassLoaderFactory {
         providedArtifacts.add(slf4jArtifact);
 
         getLog().debug("Creating Provided Entities Class Loader with artifacts: " + providedArtifacts);
-        return createUrlClassLoader(providedArtifacts, null);
+        return createClassLoader(providedArtifacts, null, null);
     }
 
-    private ClassLoader createUrlClassLoader(final Set<Artifact> artifacts, final ClassLoader parent) throws MojoExecutionException {
-        final Set<URL> urls = new HashSet<>();
-        for (final Artifact artifact : artifacts) {
-            final Set<URL> artifactUrls = toURLs(artifact);
-            urls.addAll(artifactUrls);
-        }
-
-        getLog().debug("Creating class loader with following dependencies: " + urls);
-
-        final URL[] urlArray = urls.toArray(new URL[0]);
-        return new URLClassLoader(urlArray, parent);
-    }
-
-    private ExtensionClassLoader createClassLoader(final Set<Artifact> artifacts, final ClassLoader parent, final Artifact narArtifact) throws MojoExecutionException {
+    private ExtensionClassLoader createClassLoader(final Set<Artifact> artifacts, final ExtensionClassLoader parent, final Artifact narArtifact) throws MojoExecutionException {
         final Set<URL> urls = new HashSet<>();
         for (final Artifact artifact : artifacts) {
             final Set<URL> artifactUrls = toURLs(artifact);
@@ -330,7 +314,6 @@ public class ExtensionClassLoaderFactory {
 
             final ArtifactResolutionRequest request = new ArtifactResolutionRequest();
             request.setLocalRepository(localRepo);
-            request.setRemoteRepositories(remoteRepos);
             request.setArtifact(artifact);
 
             final ArtifactResolutionResult result = artifactResolver.resolve(request);
@@ -338,7 +321,7 @@ public class ExtensionClassLoaderFactory {
                 throw new MojoExecutionException("Could not resolve local dependency " + artifact);
             }
 
-            getLog().info("Resolved Artifact " + artifact + " to " + result.getArtifacts());
+            getLog().debug("Resolved Artifact " + artifact + " to " + result.getArtifacts());
 
             for (final Artifact resolved : result.getArtifacts()) {
                 urls.addAll(toURLs(resolved));
@@ -362,7 +345,6 @@ public class ExtensionClassLoaderFactory {
         private Log log;
         private MavenProject project;
         private ArtifactRepository localRepo;
-        private List<ArtifactRepository> remoteRepos;
         private DependencyTreeBuilder dependencyTreeBuilder;
         private ArtifactResolver artifactResolver;
         private ProjectBuilder projectBuilder;
@@ -389,11 +371,6 @@ public class ExtensionClassLoaderFactory {
             return this;
         }
 
-        public Builder remoteRepositories(final List<ArtifactRepository> remoteRepos) {
-            this.remoteRepos = remoteRepos;
-            return this;
-        }
-
         public Builder dependencyTreeBuilder(final DependencyTreeBuilder dependencyTreeBuilder) {
             this.dependencyTreeBuilder = dependencyTreeBuilder;
             return this;
@@ -419,8 +396,18 @@ public class ExtensionClassLoaderFactory {
         }
     }
 
+    private static class ArtifactsHolder {
 
-    private interface VersionLookup {
-        String getVersion(String groupId, String artifactId);
+        private Set<Artifact> allArtifacts = new TreeSet<>();
+
+        public void addArtifacts(final Set<Artifact> artifacts) {
+            if (artifacts != null) {
+                allArtifacts.addAll(artifacts);
+            }
+        }
+
+        public Set<Artifact> getAllArtifacts() {
+            return allArtifacts;
+        }
     }
 }
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionDefinitionFactory.java b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionDefinitionFactory.java
index d0aee68..6203493 100644
--- a/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionDefinitionFactory.java
+++ b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionDefinitionFactory.java
@@ -17,11 +17,8 @@
 package org.apache.nifi.extension.definition.extraction;
 
 import org.apache.maven.artifact.Artifact;
-import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.nifi.extension.definition.ExtensionDefinition;
 import org.apache.nifi.extension.definition.ExtensionType;
-import org.apache.nifi.extension.definition.Restriction;
-import org.apache.nifi.extension.definition.Restrictions;
 import org.apache.nifi.extension.definition.ServiceAPIDefinition;
 
 import java.io.BufferedReader;
@@ -29,9 +26,6 @@ import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStreamReader;
 import java.io.Reader;
-import java.lang.annotation.Annotation;
-import java.lang.reflect.InvocationTargetException;
-import java.lang.reflect.Method;
 import java.net.URL;
 import java.util.Collections;
 import java.util.Enumeration;
@@ -39,8 +33,6 @@ import java.util.HashMap;
 import java.util.HashSet;
 import java.util.Map;
 import java.util.Set;
-import java.util.stream.Collectors;
-import java.util.stream.Stream;
 
 public class ExtensionDefinitionFactory {
     private static final String SERVICES_DIRECTORY = "META-INF/services/";
@@ -78,17 +70,10 @@ public class ExtensionDefinitionFactory {
         return definitions;
     }
 
-    private ExtensionDefinition createExtensionDefinition(final ExtensionType extensionType, final String className) throws ClassNotFoundException,
-                IllegalAccessException, NoSuchMethodException, InvocationTargetException {
-
+    private ExtensionDefinition createExtensionDefinition(final ExtensionType extensionType, final String className) throws ClassNotFoundException {
         final Class<?> extensionClass = Class.forName(className, false, extensionClassLoader);
-
-        final String capabilityDescription = getCapabilityDescription(extensionClass);
-        final Set<String> tags = getTags(extensionClass);
-        final Restrictions restrictions = getRestrictions(extensionClass);
         final Set<ServiceAPIDefinition> serviceApis = getProvidedServiceAPIs(extensionType, extensionClass);
-
-        return new StandardExtensionDefinition(extensionType, className, capabilityDescription, tags, restrictions, serviceApis);
+        return new StandardExtensionDefinition(extensionType, className, serviceApis);
     }
 
     private Set<ServiceAPIDefinition> getProvidedServiceAPIs(final ExtensionType extensionType, final Class<?> extensionClass) throws ClassNotFoundException {
@@ -116,99 +101,6 @@ public class ExtensionDefinitionFactory {
         return serviceApis;
     }
 
-    private Restrictions getRestrictions(final Class<?> extensionClass) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
-        final String restrictedDescription = getRestrictedDescription(extensionClass);
-        final Map<String, String> specificRestrictions = getSpecificRestrictions(extensionClass);
-
-        final boolean hasRestriction = restrictedDescription != null || !specificRestrictions.isEmpty();
-        final Restrictions restrictions;
-        if (!hasRestriction) {
-            return null;
-        }
-
-        final Set<Restriction> restrictionSet = new HashSet<>();
-        for (final Map.Entry<String, String> specificRestriction : specificRestrictions.entrySet()) {
-            restrictionSet.add(new StandardRestriction(specificRestriction.getKey(), specificRestriction.getValue()));
-        }
-
-        return new StandardRestrictions(restrictedDescription, restrictionSet);
-    }
-
-
-    private String getCapabilityDescription(final Class<?> extensionClass) throws InvocationTargetException,
-                IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
-
-        final Class capabilityDescriptionClass = Class.forName("org.apache.nifi.annotation.documentation.CapabilityDescription", false, extensionClass.getClassLoader());
-        final Method valueMethod = capabilityDescriptionClass.getMethod("value");
-
-        final Annotation capabilityDescriptionAnnotation = extensionClass.getAnnotation(capabilityDescriptionClass);
-        if (capabilityDescriptionAnnotation == null) {
-            return null;
-        }
-
-        final String capabilityDescriptionText = (String) valueMethod.invoke(capabilityDescriptionAnnotation);
-        return capabilityDescriptionText;
-    }
-
-
-    private Set<String> getTags(final Class<?> extensionClass) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
-        final Class tagsClass = Class.forName("org.apache.nifi.annotation.documentation.Tags", false, extensionClass.getClassLoader());
-        final Method valueMethod = tagsClass.getMethod("value");
-
-        final Annotation tagsAnnotation = extensionClass.getAnnotation(tagsClass);
-        if (tagsAnnotation == null) {
-            return Collections.emptySet();
-        }
-
-        final String[] tags = (String[]) valueMethod.invoke(tagsAnnotation);
-        return Stream.of(tags).collect(Collectors.<String>toSet());
-    }
-
-
-    private Map<String, String> getSpecificRestrictions(final Class<?> extensionClass) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
-        final Class restrictedClass = Class.forName("org.apache.nifi.annotation.behavior.Restricted", false, extensionClass.getClassLoader());
-        final Class restrictionClass = Class.forName("org.apache.nifi.annotation.behavior.Restriction", false, extensionClass.getClassLoader());
-        final Class requiredPermissionClass = Class.forName("org.apache.nifi.components.RequiredPermission", false, extensionClass.getClassLoader());
-
-        final Method restrictionsMethod = restrictedClass.getMethod("restrictions");
-        final Method explanationMethod = restrictionClass.getMethod("explanation");
-        final Method requiredPermissionMethod = restrictionClass.getMethod("requiredPermission");
-        final Method getPermissionIdentifierMethod = requiredPermissionClass.getMethod("getPermissionIdentifier");
-
-        final Annotation restrictionAnnotation = restrictedClass.getAnnotation(restrictedClass);
-        if (restrictionAnnotation == null) {
-            return edu.emory.mathcs.backport.java.util.Collections.emptyMap();
-        }
-
-        final Object[] restrictionsArray = (Object[]) restrictionsMethod.invoke(restrictionAnnotation);
-
-        final Map<String, String> restrictions = new HashMap<>();
-        for (final Object restriction : restrictionsArray) {
-            final String explanation = (String) explanationMethod.invoke(restriction);
-
-            final Object requiredPermission = requiredPermissionMethod.invoke(restriction);
-            final String requiredPermissionId = (String) getPermissionIdentifierMethod.invoke(requiredPermission);
-
-            restrictions.put(requiredPermissionId, explanation);
-        }
-
-        return restrictions;
-    }
-
-    private String getRestrictedDescription(final Class<?> extensionClass) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
-        final Class restrictedClass = Class.forName("org.apache.nifi.annotation.behavior.Restricted", false, extensionClass.getClassLoader());
-        final Method valueMethod = restrictedClass.getMethod("value");
-
-        final Annotation restrictedAnnotation = extensionClass.getAnnotation(restrictedClass);
-        if (restrictedAnnotation == null) {
-            return null;
-        }
-
-        return (String) valueMethod.invoke(restrictedAnnotation);
-    }
-
-
-
     private Set<String> discoverClassNames(final String extensionType) throws IOException {
         final Set<String> classNames = new HashSet<>();
 
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/StandardExtensionDefinition.java b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardExtensionDefinition.java
index dadb747..fe19757 100644
--- a/src/main/java/org/apache/nifi/extension/definition/extraction/StandardExtensionDefinition.java
+++ b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardExtensionDefinition.java
@@ -18,45 +18,23 @@ package org.apache.nifi.extension.definition.extraction;
 
 import org.apache.nifi.extension.definition.ExtensionDefinition;
 import org.apache.nifi.extension.definition.ExtensionType;
-import org.apache.nifi.extension.definition.Restrictions;
 import org.apache.nifi.extension.definition.ServiceAPIDefinition;
 
 import java.util.Set;
 
 public class StandardExtensionDefinition implements ExtensionDefinition {
-    private final String capabilityDescription;
-    private final Set<String> tags;
-    private final Restrictions restrictions;
+
     private final ExtensionType extensionType;
     private final String extensionName;
     private final Set<ServiceAPIDefinition> providedServiceApis;
 
-    public StandardExtensionDefinition(final ExtensionType extensionType, final String extensionName, final String capabilityDescription, final Set<String> tags, final Restrictions restrictions,
-                                       final Set<ServiceAPIDefinition> providedServiceApis) {
+    public StandardExtensionDefinition(final ExtensionType extensionType, final String extensionName, final Set<ServiceAPIDefinition> providedServiceApis) {
         this.extensionType = extensionType;
         this.extensionName = extensionName;
-        this.capabilityDescription = capabilityDescription;
-        this.tags = tags;
-        this.restrictions = restrictions;
         this.providedServiceApis = providedServiceApis;
     }
 
     @Override
-    public String getCapabilityDescription() {
-        return capabilityDescription;
-    }
-
-    @Override
-    public Set<String> getTags() {
-        return tags;
-    }
-
-    @Override
-    public Restrictions getRestrictions() {
-        return restrictions;
-    }
-
-    @Override
     public ExtensionType getExtensionType() {
         return extensionType;
     }
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestriction.java b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestriction.java
deleted file mode 100644
index 6825d5b..0000000
--- a/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestriction.java
+++ /dev/null
@@ -1,39 +0,0 @@
-/*
- * 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.extension.definition.extraction;
-
-import org.apache.nifi.extension.definition.Restriction;
-
-public class StandardRestriction implements Restriction {
-    private final String identifier;
-    private final String explanation;
-
-    public StandardRestriction(final String identifier, final String explanation) {
-        this.identifier = identifier;
-        this.explanation = explanation;
-    }
-
-    @Override
-    public String getIdentifier() {
-        return identifier;
-    }
-
-    @Override
-    public String getExplanation() {
-        return explanation;
-    }
-}
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestrictions.java b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestrictions.java
deleted file mode 100644
index 97fa9ba..0000000
--- a/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestrictions.java
+++ /dev/null
@@ -1,42 +0,0 @@
-/*
- * 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.extension.definition.extraction;
-
-import org.apache.nifi.extension.definition.Restriction;
-import org.apache.nifi.extension.definition.Restrictions;
-
-import java.util.Set;
-
-public class StandardRestrictions implements Restrictions {
-    private final String generalRestrictionExplanation;
-    private final Set<Restriction> restrictions;
-
-    public StandardRestrictions(final String generalRestrictionExplanation, final Set<Restriction> restrictions) {
-        this.generalRestrictionExplanation = generalRestrictionExplanation;
-        this.restrictions = restrictions;
-    }
-
-    @Override
-    public String getGeneralRestrictionExplanation() {
-        return generalRestrictionExplanation;
-    }
-
-    @Override
-    public Set<Restriction> getRestrictions() {
-        return restrictions;
-    }
-}


[nifi-maven] 11/20: NIFI-3589 Add MANIFEST entry to allow specifying that resources should be cloned during instance class loading

Posted by kd...@apache.org.
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 76e0f54496c08fa0aaa2d15d45cba2f536b249dc
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Mon Mar 13 11:35:45 2017 -0400

    NIFI-3589 Add MANIFEST entry to allow specifying that resources should be cloned during instance class loading
    
    Signed-off-by: Matt Gilman <ma...@gmail.com>
---
 src/main/java/org/apache/nifi/NarMojo.java | 10 ++++++++++
 1 file changed, 10 insertions(+)

diff --git a/src/main/java/org/apache/nifi/NarMojo.java b/src/main/java/org/apache/nifi/NarMojo.java
index 351c23d..809eff4 100644
--- a/src/main/java/org/apache/nifi/NarMojo.java
+++ b/src/main/java/org/apache/nifi/NarMojo.java
@@ -418,6 +418,14 @@ public class NarMojo extends AbstractMojo {
     @Parameter(property = "buildRevision", defaultValue = "${buildRevision}", required = false)
     protected String buildRevision;
 
+    /**
+     * Allows a NAR to specify if it's resources should be cloned when a component that depends on this NAR
+     * is performing class loader isolation.
+     */
+    @Parameter(property = "cloneDuringInstanceClassLoading", defaultValue = "false", required = false)
+    protected boolean cloneDuringInstanceClassLoading;
+
+
     @Override
     public void execute() throws MojoExecutionException, MojoFailureException {
         copyDependencies();
@@ -633,6 +641,8 @@ public class NarMojo extends AbstractMojo {
             SimpleDateFormat dateFormat = new SimpleDateFormat(BUILD_TIMESTAMP_FORMAT);
             archive.addManifestEntry("Build-Timestamp", dateFormat.format(new Date()));
 
+            archive.addManifestEntry("Clone-During-Instance-Class-Loading", String.valueOf(cloneDuringInstanceClassLoading));
+
             archiver.createArchive(session, project, archive);
             return narFile;
         } catch (ArchiverException | MojoExecutionException | ManifestException | IOException | DependencyResolutionRequiredException e) {


[nifi-maven] 05/20: NIFI-875 prepare release nifi-nar-maven-plugin-1.1.0-RC1

Posted by kd...@apache.org.
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 80841130461e8346c0bd643b4097b36bf005b3a2
Author: Matt Gilman <ma...@gmail.com>
AuthorDate: Wed Aug 19 22:17:52 2015 -0400

    NIFI-875 prepare release nifi-nar-maven-plugin-1.1.0-RC1
---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 431d87c..a5d1cf4 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.1.0-SNAPSHOT</version>
+    <version>1.1.0</version>
     <packaging>maven-plugin</packaging>
     <description>Apache NiFi Nar Maven Plugin</description>
     <url>http://nifi.apache.org</url>
@@ -67,7 +67,7 @@
         <connection>scm:git:git://git.apache.org/nifi-maven.git</connection>
         <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/nifi-maven.git</developerConnection>
         <url>https://git-wip-us.apache.org/repos/asf?p=nifi-maven.git</url>
-        <tag>HEAD</tag>
+        <tag>nifi-nar-maven-plugin-1.1.0-RC1</tag>
     </scm>
     <issueManagement>
         <system>JIRA</system>


[nifi-maven] 01/20: NIFI-850 initial commit

Posted by kd...@apache.org.
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 75101ae09170e2e9ad4b94ba2efc1b033d9e3c10
Author: joewitt <jo...@apache.org>
AuthorDate: Thu Aug 13 12:51:02 2015 -0400

    NIFI-850 initial commit
---
 .gitignore | 16 ++++++++++++++++
 1 file changed, 16 insertions(+)

diff --git a/.gitignore b/.gitignore
new file mode 100644
index 0000000..a2e04fa
--- /dev/null
+++ b/.gitignore
@@ -0,0 +1,16 @@
+target
+.project
+.settings
+.classpath
+nbactions.xml
+nb-configuration.xml
+.DS_Store
+.metadata
+.recommenders
+
+# Intellij
+.idea/
+*.iml
+*.iws
+*~
+


[nifi-maven] 18/20: NIFI-5304 - Changed Lifecycle Phase Binding for Help Mojo

Posted by kd...@apache.org.
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 953ddf4db63509dc9c2c4cb531af0324626ac6dc
Author: Martin Payne <de...@martinpayne.me.uk>
AuthorDate: Wed Jun 13 06:48:53 2018 +0100

    NIFI-5304 - Changed Lifecycle Phase Binding for Help Mojo
    
    Moved Maven Plugin Plugin help Mojo from "process-classes" to
    "generate-sources" lifecycle phase to ensure the help Mojo is included
    in the built plugin.
    
    This closes #5.
    
    Signed-off-by: Bryan Bende <bb...@apache.org>
---
 pom.xml | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/pom.xml b/pom.xml
index 9a31087..daa17cb 100644
--- a/pom.xml
+++ b/pom.xml
@@ -355,7 +355,7 @@
                         <goals>
                             <goal>helpmojo</goal>
                         </goals>
-                        <phase>process-classes</phase>
+                        <phase>generate-sources</phase>
                     </execution>
                 </executions>
             </plugin>


[nifi-maven] 09/20: NIFI-1450: - Ensuring that system properties are relayed so that the disable doclint profile is not activated.

Posted by kd...@apache.org.
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 4e6d1a3ab566d0177a6fb33aa0c8d824f14d360e
Author: Matt Gilman <ma...@gmail.com>
AuthorDate: Mon Jan 23 10:11:25 2017 -0500

    NIFI-1450: - Ensuring that system properties are relayed so that the disable doclint profile is not activated.
    
    This closes #1.
    
    Signed-off-by: Bryan Bende <bb...@apache.org>
---
 pom.xml                                                    |  2 +-
 .../java/org/apache/nifi/NarProvidedDependenciesMojo.java  | 14 ++++++++------
 2 files changed, 9 insertions(+), 7 deletions(-)

diff --git a/pom.xml b/pom.xml
index 5962163..6c0f01c 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.1.1-SNAPSHOT</version>
+    <version>1.2.0-SNAPSHOT</version>
     <packaging>maven-plugin</packaging>
     <description>Apache NiFi Nar Maven Plugin</description>
     <url>http://nifi.apache.org</url>
diff --git a/src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java b/src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java
index 63b2abd..15da9ad 100644
--- a/src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java
+++ b/src/main/java/org/apache/nifi/NarProvidedDependenciesMojo.java
@@ -16,10 +16,6 @@
  */
 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;
@@ -27,13 +23,13 @@ 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.Component;
 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.MavenProject;
 import org.apache.maven.project.ProjectBuilder;
 import org.apache.maven.project.ProjectBuildingException;
 import org.apache.maven.project.ProjectBuildingRequest;
@@ -44,6 +40,11 @@ import org.apache.maven.shared.dependency.tree.DependencyTreeBuilderException;
 import org.apache.maven.shared.dependency.tree.traversal.DependencyNodeVisitor;
 import org.eclipse.aether.RepositorySystemSession;
 
+import java.util.ArrayDeque;
+import java.util.Deque;
+import java.util.HashMap;
+import java.util.Map;
+
 /**
  * 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
@@ -126,6 +127,7 @@ public class NarProvidedDependenciesMojo extends AbstractMojo {
             // build the project for the nar artifact
             final ProjectBuildingRequest narRequest = new DefaultProjectBuildingRequest();
             narRequest.setRepositorySession(repoSession);
+            narRequest.setSystemProperties(System.getProperties());
             final ProjectBuildingResult narResult = projectBuilder.build(narArtifact, narRequest);
 
             // get the artifact handler for excluding dependencies


[nifi-maven] 19/20: NIFI-5859: Build NAR Extension Definitions/docs at build time

Posted by kd...@apache.org.
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 f9f372e731441f1288933111586a937bbae3a65a
Author: Mark Payne <ma...@hotmail.com>
AuthorDate: Wed Nov 14 15:09:25 2018 -0500

    NIFI-5859: Build NAR Extension Definitions/docs at build time
---
 pom.xml                                            |  36 +-
 src/main/java/org/apache/nifi/NarMojo.java         | 342 ++++++++++++++++-
 .../apache/nifi/PropertiesDefinitionWriter.java    |  75 ++++
 .../java/org/apache/nifi/XmlDefinitionWriter.java  | 165 ++++++++
 .../extension/definition/ExtensionDefinition.java  |  52 +++
 .../nifi/extension/definition/ExtensionType.java   |  27 ++
 .../nifi/extension/definition/Restriction.java     |  29 ++
 .../nifi/extension/definition/Restrictions.java    |  31 ++
 .../extension/definition/ServiceAPIDefinition.java |  27 ++
 .../extraction/ExtensionClassLoader.java           | 114 ++++++
 .../extraction/ExtensionClassLoaderFactory.java    | 426 +++++++++++++++++++++
 .../extraction/ExtensionDefinitionFactory.java     | 247 ++++++++++++
 .../extraction/StandardExtensionDefinition.java    |  78 ++++
 .../definition/extraction/StandardRestriction.java |  39 ++
 .../extraction/StandardRestrictions.java           |  42 ++
 .../extraction/StandardServiceAPIDefinition.java   |  53 +++
 16 files changed, 1754 insertions(+), 29 deletions(-)

diff --git a/pom.xml b/pom.xml
index daa17cb..35f54ab 100644
--- a/pom.xml
+++ b/pom.xml
@@ -80,7 +80,7 @@
         <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding>
         <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding>
         <inceptionYear>2014</inceptionYear>
-    </properties>    
+    </properties>
     <build>
         <pluginManagement>
             <plugins>
@@ -224,7 +224,7 @@
                                 <requireMavenVersion>
                                     <version>${maven.min-version}</version>
                                 </requireMavenVersion>
-                            </rules>    
+                            </rules>
                         </configuration>
                     </execution>
                 </executions>
@@ -313,7 +313,7 @@
                     <includeTestSourceDirectory>true</includeTestSourceDirectory>
                     <excludes>**/HelpMojo.java</excludes>
                 </configuration>
-            </plugin>      
+            </plugin>
             <plugin>
                 <groupId>org.apache.rat</groupId>
                 <artifactId>apache-rat-plugin</artifactId>
@@ -338,7 +338,7 @@
                         </exclusions>
                     </dependency>
                 </dependencies>
-            </plugin>             
+            </plugin>
             <plugin>
                 <groupId>org.apache.maven.plugins</groupId>
                 <artifactId>maven-plugin-plugin</artifactId>
@@ -358,21 +358,27 @@
                         <phase>generate-sources</phase>
                     </execution>
                 </executions>
-            </plugin>
-        </plugins>        
+            </plugin><plugin><groupId>org.apache.maven.plugins</groupId>
+            <artifactId>maven-compiler-plugin</artifactId>
+            <configuration>
+                <source>8</source>
+                <target>8</target>
+            </configuration>
+        </plugin>
+        </plugins>
     </build>
     <dependencies>
-        <dependency>          
+        <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-plugin-api</artifactId>
             <version>3.1.1</version>
         </dependency>
-        <dependency>          
+        <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-artifact</artifactId>
             <version>3.1.1</version>
         </dependency>
-        <dependency>          
+        <dependency>
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-compat</artifactId>
             <version>3.1.1</version>
@@ -383,7 +389,7 @@
             <type>maven-plugin</type>
             <version>2.9</version>
         </dependency>
-        <dependency>          
+        <dependency>
             <groupId>org.apache.maven.shared</groupId>
             <artifactId>maven-dependency-tree</artifactId>
             <version>2.2</version>
@@ -404,9 +410,9 @@
     </dependencies>
     <profiles>
         <profile>
-            <!-- 
-            Checks style and licensing requirements.  This is a good idea to 
-            run for contributions and for the release process.  While it 
+            <!--
+            Checks style and licensing requirements.  This is a good idea to
+            run for contributions and for the release process.  While it
             would be nice to run always these plugins can considerably slow
             the build and have proven to create unstable builds in our
             multi-module project and when building using multiple threads.
@@ -437,10 +443,10 @@
                                     <goal>check</goal>
                                 </goals>
                             </execution>
-                        </executions>                
+                        </executions>
                     </plugin>
                 </plugins>
             </build>
         </profile>
-    </profiles>    
+    </profiles>
 </project>
diff --git a/src/main/java/org/apache/nifi/NarMojo.java b/src/main/java/org/apache/nifi/NarMojo.java
index 4110fa6..85ebfcf 100644
--- a/src/main/java/org/apache/nifi/NarMojo.java
+++ b/src/main/java/org/apache/nifi/NarMojo.java
@@ -16,18 +16,13 @@
  */
 package org.apache.nifi;
 
-import java.io.File;
-import java.io.IOException;
-import java.text.SimpleDateFormat;
-import java.util.Date;
-import java.util.HashSet;
-import java.util.List;
-import java.util.Set;
 import org.apache.maven.archiver.MavenArchiveConfiguration;
 import org.apache.maven.archiver.MavenArchiver;
 import org.apache.maven.artifact.Artifact;
 import org.apache.maven.artifact.DependencyResolutionRequiredException;
 import org.apache.maven.artifact.factory.ArtifactFactory;
+import org.apache.maven.artifact.handler.ArtifactHandler;
+import org.apache.maven.artifact.handler.manager.ArtifactHandlerManager;
 import org.apache.maven.artifact.installer.ArtifactInstaller;
 import org.apache.maven.artifact.metadata.ArtifactMetadataSource;
 import org.apache.maven.artifact.repository.ArtifactRepository;
@@ -36,6 +31,7 @@ import org.apache.maven.artifact.resolver.ArtifactCollector;
 import org.apache.maven.artifact.resolver.ArtifactNotFoundException;
 import org.apache.maven.artifact.resolver.ArtifactResolutionException;
 import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.execution.MavenSession;
 import org.apache.maven.plugin.AbstractMojo;
 import org.apache.maven.plugin.MojoExecutionException;
 import org.apache.maven.plugin.MojoFailureException;
@@ -46,29 +42,70 @@ import org.apache.maven.plugin.dependency.utils.resolvers.ArtifactsResolver;
 import org.apache.maven.plugin.dependency.utils.resolvers.DefaultArtifactsResolver;
 import org.apache.maven.plugin.dependency.utils.translators.ArtifactTranslator;
 import org.apache.maven.plugin.dependency.utils.translators.ClassifierTypeTranslator;
+import org.apache.maven.plugins.annotations.Component;
 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.execution.MavenSession;
-import org.apache.maven.plugins.annotations.Component;
 import org.apache.maven.project.MavenProjectHelper;
+import org.apache.maven.project.ProjectBuilder;
 import org.apache.maven.shared.artifact.filter.collection.ArtifactFilterException;
 import org.apache.maven.shared.artifact.filter.collection.ArtifactIdFilter;
 import org.apache.maven.shared.artifact.filter.collection.ArtifactsFilter;
 import org.apache.maven.shared.artifact.filter.collection.ClassifierFilter;
 import org.apache.maven.shared.artifact.filter.collection.FilterArtifacts;
 import org.apache.maven.shared.artifact.filter.collection.GroupIdFilter;
-import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
 import org.apache.maven.shared.artifact.filter.collection.ProjectTransitivityFilter;
+import org.apache.maven.shared.artifact.filter.collection.ScopeFilter;
 import org.apache.maven.shared.artifact.filter.collection.TypeFilter;
+import org.apache.maven.shared.dependency.tree.DependencyTreeBuilder;
+import org.apache.nifi.extension.definition.ExtensionDefinition;
+import org.apache.nifi.extension.definition.ExtensionType;
+import org.apache.nifi.extension.definition.ServiceAPIDefinition;
+import org.apache.nifi.extension.definition.extraction.ExtensionClassLoader;
+import org.apache.nifi.extension.definition.extraction.ExtensionClassLoaderFactory;
+import org.apache.nifi.extension.definition.extraction.ExtensionDefinitionFactory;
 import org.codehaus.plexus.archiver.ArchiverException;
 import org.codehaus.plexus.archiver.jar.JarArchiver;
 import org.codehaus.plexus.archiver.jar.ManifestException;
 import org.codehaus.plexus.archiver.manager.ArchiverManager;
 import org.codehaus.plexus.util.FileUtils;
 import org.codehaus.plexus.util.StringUtils;
+import org.eclipse.aether.RepositorySystemSession;
+
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.BufferedOutputStream;
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.FileNotFoundException;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.OutputStream;
+import java.io.Reader;
+import java.io.StringWriter;
+import java.io.Writer;
+import java.lang.reflect.Constructor;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URISyntaxException;
+import java.net.URL;
+import java.nio.file.Files;
+import java.text.SimpleDateFormat;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Date;
+import java.util.Enumeration;
+import java.util.HashSet;
+import java.util.List;
+import java.util.Set;
+import java.util.jar.JarEntry;
+import java.util.jar.JarFile;
+import java.util.stream.Collectors;
 
 /**
  * Packages the current project as an Apache NiFi Archive (NAR).
@@ -80,6 +117,8 @@ import org.codehaus.plexus.util.StringUtils;
  */
 @Mojo(name = "nar", defaultPhase = LifecyclePhase.PACKAGE, threadSafe = true, requiresDependencyResolution = ResolutionScope.RUNTIME)
 public class NarMojo extends AbstractMojo {
+    private static final String SERVICES_DIRECTORY = "META-INF/services/";
+    private static final String DOCUMENTATION_WRITER_CLASS_NAME = "org.apache.nifi.documentation.xml.XmlDocumentationWriter";
 
     private static final String[] DEFAULT_EXCLUDES = new String[]{"**/package.html"};
     private static final String[] DEFAULT_INCLUDES = new String[]{"**/**"};
@@ -357,6 +396,20 @@ public class NarMojo extends AbstractMojo {
     public boolean silent;
 
     /**
+     * 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;
+
+
+    /**
      * Output absolute filename for resolved artifacts
      *
      */
@@ -426,12 +479,260 @@ public class NarMojo extends AbstractMojo {
     protected boolean cloneDuringInstanceClassLoading;
 
 
+    /**
+     * The {@link RepositorySystemSession} used for obtaining the local and remote artifact repositories.
+     */
+    @Parameter(defaultValue = "${repositorySystemSession}", readonly = true)
+    private RepositorySystemSession repoSession;
+
+
+    /**
+     * The {@link ProjectBuilder} used to generate the {@link MavenProject} for the nar artifact the dependency tree is being generated for.
+     */
+    @Component
+    private ProjectBuilder projectBuilder;
+
+
+
     @Override
-    public void execute() throws MojoExecutionException, MojoFailureException {
+    public void execute() throws MojoExecutionException {
         copyDependencies();
+
+        try {
+            generateDocumentation();
+        } catch (final Throwable t) { // Catch Throwable in case a linkage error such as NoClassDefFoundError occurs
+            getLog().warn("Could not generate extensions' documentation", t);
+        }
+
         makeNar();
     }
 
+    private File getExtensionsDocumentationFile() {
+        final File directory = new File(projectBuildDirectory, "META-INF/docs");
+        return new File(directory, "extension-docs.xml");
+    }
+
+    private void generateDocumentation() throws MojoExecutionException {
+        getLog().info("Generating documentation for NiFi extensions in the NAR...");
+
+        // Create the ClassLoader for the NAR
+        final ExtensionClassLoaderFactory classLoaderFactory = createClassLoaderFactory();
+
+        final ExtensionClassLoader extensionClassLoader;
+        try {
+            extensionClassLoader = classLoaderFactory.createExtensionClassLoader();
+        } catch (final Exception e) {
+            if (getLog().isDebugEnabled()) {
+                getLog().debug("Unable to create a ClassLoader for documenting extensions. If this NAR contains any NiFi Extensions, those extensions will not be documented.", e);
+            } else {
+                getLog().warn("Unable to create a ClassLoader for documenting extensions. If this NAR contains any NiFi Extensions, those extensions will not be documented. " +
+                    "Enable mvn DEBUG output for more information (mvn -X).");
+            }
+
+            return;
+        }
+
+
+        final File docsFile = getExtensionsDocumentationFile();
+        createDirectory(docsFile.getParentFile());
+
+        final File additionalDetailsDir = new File(docsFile.getParentFile(), "additional-details");
+        createDirectory(additionalDetailsDir);
+
+        try (final OutputStream out = new FileOutputStream(docsFile)) {
+
+            final XMLStreamWriter xmlWriter = XMLOutputFactory.newInstance().createXMLStreamWriter(out, "UTF-8");
+            try {
+                xmlWriter.writeStartElement("extensions");
+
+                final String nifiApiVersion = extensionClassLoader.getNiFiApiVersion();
+                xmlWriter.writeStartElement("nifiApiVersion");
+                xmlWriter.writeCharacters(nifiApiVersion);
+                xmlWriter.writeEndElement();
+
+                final Class<?> docWriterClass;
+                try {
+                    docWriterClass = Class.forName(DOCUMENTATION_WRITER_CLASS_NAME, false, extensionClassLoader);
+                } catch (ClassNotFoundException e) {
+                    getLog().warn("Cannot locate class " + DOCUMENTATION_WRITER_CLASS_NAME + ", so no documentation will be generated for the extensions in this NAR");
+                    return;
+                }
+
+                getLog().debug("Creating Extension Definition Factory for NiFi API version " + nifiApiVersion);
+
+                final ExtensionDefinitionFactory extensionDefinitionFactory = new ExtensionDefinitionFactory(extensionClassLoader);
+
+                final ClassLoader currentContextClassLoader = Thread.currentThread().getContextClassLoader();
+                try {
+                    Thread.currentThread().setContextClassLoader(extensionClassLoader);
+
+                    final Set<ExtensionDefinition> processorDefinitions = extensionDefinitionFactory.discoverExtensions(ExtensionType.PROCESSOR);
+                    writeDocumentation(processorDefinitions, extensionClassLoader, docWriterClass, xmlWriter, additionalDetailsDir);
+
+                    final Set<ExtensionDefinition> controllerServiceDefinitions = extensionDefinitionFactory.discoverExtensions(ExtensionType.CONTROLLER_SERVICE);
+                    writeDocumentation(controllerServiceDefinitions, extensionClassLoader, docWriterClass, xmlWriter, additionalDetailsDir);
+
+                    final Set<ExtensionDefinition> reportingTaskDefinitions = extensionDefinitionFactory.discoverExtensions(ExtensionType.REPORTING_TASK);
+                    writeDocumentation(reportingTaskDefinitions, extensionClassLoader, docWriterClass, xmlWriter, additionalDetailsDir);
+                } finally {
+                    if (currentContextClassLoader != null) {
+                        Thread.currentThread().setContextClassLoader(currentContextClassLoader);
+                    }
+                }
+
+                xmlWriter.writeEndElement();
+            } finally {
+                xmlWriter.close();
+            }
+        } catch (final Exception ioe) {
+            throw new MojoExecutionException("Failed to create Extension Documentation", ioe);
+        }
+    }
+
+    private void writeDocumentation(final Set<ExtensionDefinition> extensionDefinitions, final ExtensionClassLoader classLoader,
+                                    final Class<?> docWriterClass, final XMLStreamWriter xmlWriter, final File additionalDetailsDir)
+        throws InvocationTargetException, NoSuchMethodException, ClassNotFoundException, InstantiationException, IllegalAccessException, IOException {
+
+        for (final ExtensionDefinition definition : extensionDefinitions) {
+            writeDocumentation(definition, classLoader, docWriterClass, xmlWriter);
+        }
+
+        final Set<String> extensionNames = extensionDefinitions.stream()
+            .map(ExtensionDefinition::getExtensionName)
+            .collect(Collectors.toSet());
+
+        try {
+            writeAdditionalDetails(classLoader, extensionNames, additionalDetailsDir);
+        } catch (final Exception e) {
+            throw new IOException("Unable to extract Additional Details", e);
+        }
+
+    }
+
+    private void writeDocumentation(final ExtensionDefinition extensionDefinition, final ExtensionClassLoader classLoader,
+                                    final Class<?> docWriterClass, final XMLStreamWriter xmlWriter)
+        throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException, ClassNotFoundException, IOException {
+
+        getLog().debug("Generating documentation for " + extensionDefinition.getExtensionName() + " using ClassLoader:\n" + classLoader.toTree());
+        final Object docWriter = docWriterClass.getConstructor(XMLStreamWriter.class).newInstance(xmlWriter);
+        final Class<?> configurableComponentClass = Class.forName("org.apache.nifi.components.ConfigurableComponent", false, classLoader);
+
+        final Class<?> extensionClass = Class.forName(extensionDefinition.getExtensionName(), false, classLoader);
+        final Object extensionInstance = extensionClass.newInstance();
+
+        final Set<ServiceAPIDefinition> serviceDefinitions = extensionDefinition.getProvidedServiceAPIs();
+
+        if (serviceDefinitions == null || serviceDefinitions.isEmpty()) {
+            final Method writeMethod = docWriterClass.getMethod("write", configurableComponentClass);
+            writeMethod.invoke(docWriter, extensionInstance);
+        } else {
+            final Class<?> providedServiceApiClass = Class.forName("org.apache.nifi.documentation.StandardProvidedServiceAPI", false, classLoader);
+            final Constructor<?> ctr = providedServiceApiClass.getConstructor(String.class, String.class, String.class, String.class);
+
+            final List<Object> providedServices = new ArrayList<>();
+
+            for (final ServiceAPIDefinition definition : serviceDefinitions) {
+                final Object serviceApi = ctr.newInstance(definition.getServiceAPIClassName(), definition.getServiceGroupId(), definition.getServiceArtifactId(), definition.getServiceVersion());
+                providedServices.add(serviceApi);
+            }
+
+            final Method writeMethod = docWriterClass.getMethod("write", configurableComponentClass, Collection.class);
+            writeMethod.invoke(docWriter, extensionInstance, providedServices);
+        }
+    }
+
+    private void writeAdditionalDetails(final ExtensionClassLoader classLoader, final Set<String> extensionNames, final File additionalDetailsDir)
+        throws URISyntaxException, IOException, MojoExecutionException {
+
+        for (final URL url : classLoader.getURLs()) {
+            final File file = new File(url.toURI());
+            final String filename = file.getName();
+            if (!filename.endsWith(".jar")) {
+                continue;
+            }
+
+            writeAdditionalDetails(file, extensionNames, additionalDetailsDir);
+        }
+    }
+
+    private void writeAdditionalDetails(final File file, final Set<String> extensionNames, final File additionalDetailsDir) throws IOException, MojoExecutionException {
+        final JarFile jarFile = new JarFile(file);
+
+        for (final Enumeration<JarEntry> jarEnumeration = jarFile.entries(); jarEnumeration.hasMoreElements();) {
+            final JarEntry jarEntry = jarEnumeration.nextElement();
+
+            final String entryName = jarEntry.getName();
+            if (!entryName.startsWith("docs/")) {
+                continue;
+            }
+
+            final int nextSlashIndex = entryName.indexOf("/", 5);
+            if (nextSlashIndex < 0) {
+                continue;
+            }
+
+            final String componentName = entryName.substring(5, nextSlashIndex);
+            if (!extensionNames.contains(componentName)) {
+                continue;
+            }
+
+            if (jarEntry.isDirectory()) {
+                continue;
+            }
+
+            if (entryName.length() < nextSlashIndex + 1) {
+                continue;
+            }
+
+            getLog().debug("Found file " + entryName + " in " + file + " that consists of documentation for " + componentName);
+            final File componentDirectory = new File(additionalDetailsDir, componentName);
+            final String remainingPath = entryName.substring(nextSlashIndex + 1);
+            final File destinationFile = new File(componentDirectory, remainingPath);
+
+            createDirectory(destinationFile.getParentFile());
+
+            try (final InputStream in = jarFile.getInputStream(jarEntry);
+                 final OutputStream out = new FileOutputStream(destinationFile)) {
+                copy(in, out);
+            }
+        }
+    }
+
+    private void copy(final InputStream in, final OutputStream out) throws IOException {
+        final byte[] buffer = new byte[8192];
+        int len;
+        while ((len = in.read(buffer)) >= 0) {
+            out.write(buffer, 0, len);
+        }
+    }
+
+
+    private ExtensionClassLoaderFactory createClassLoaderFactory() {
+        return new ExtensionClassLoaderFactory.Builder()
+            .artifactResolver(resolver)
+            .dependencyTreeBuilder(dependencyTreeBuilder)
+            .localRepository(local)
+            .log(getLog())
+            .project(project)
+            .projectBuilder(projectBuilder)
+            .remoteRepositories(remoteRepos)
+            .repositorySession(repoSession)
+            .artifactHandlerManager(artifactHandlerManager)
+            .build();
+    }
+
+
+    private void createDirectory(final File file) throws MojoExecutionException {
+        if (!file.exists()) {
+            try {
+                Files.createDirectories(file.toPath());
+            } catch (IOException e) {
+                throw new MojoExecutionException("Could not create directory " + file, e);
+            }
+        }
+    }
+
+
     private void copyDependencies() throws MojoExecutionException {
         DependencyStatusSets dss = getDependencySets(this.failOnMissingClassifierArtifact);
         Set artifacts = dss.getResolvedDependencies();
@@ -443,7 +744,7 @@ public class NarMojo extends AbstractMojo {
         artifacts = dss.getSkippedDependencies();
         for (Object artifactOjb : artifacts) {
             Artifact artifact = (Artifact) artifactOjb;
-            getLog().info(artifact.getFile().getName() + " already exists in destination.");
+            getLog().debug(artifact.getFile().getName() + " already exists in destination.");
         }
     }
 
@@ -469,6 +770,7 @@ public class NarMojo extends AbstractMojo {
         return new DestFileFilter(this.overWriteReleases, this.overWriteSnapshots, this.overWriteIfNewer, false, false, false, false, false, getDependenciesDirectory());
     }
 
+
     protected DependencyStatusSets getDependencySets(boolean stopOnFailure) throws MojoExecutionException {
         // add filters in well known order, least specific to most specific
         FilterArtifacts filter = new FilterArtifacts();
@@ -597,10 +899,22 @@ public class NarMojo extends AbstractMojo {
 
         try {
             File contentDirectory = getClassesDirectory();
-            if (!contentDirectory.exists()) {
+            if (contentDirectory.exists()) {
+                archiver.getArchiver().addDirectory(contentDirectory, getIncludes(), getExcludes());
+            } else {
                 getLog().warn("NAR will be empty - no content was marked for inclusion!");
+            }
+
+            File extensionDocsFile = getExtensionsDocumentationFile();
+            if (extensionDocsFile.exists()) {
+                archiver.getArchiver().addFile(extensionDocsFile, "META-INF/docs/" + extensionDocsFile.getName());
             } else {
-                archiver.getArchiver().addDirectory(contentDirectory, getIncludes(), getExcludes());
+                getLog().warn("NAR will not contain any Extensions' documentation - no META-INF/" + extensionDocsFile.getName() + " file found!");
+            }
+
+            File additionalDetailsDirectory = new File(getExtensionsDocumentationFile().getParentFile(), "additional-details");
+            if (additionalDetailsDirectory.exists()) {
+                archiver.getArchiver().addDirectory(additionalDetailsDirectory, "META-INF/docs/additional-details/");
             }
 
             File existingManifest = defaultManifestFile;
diff --git a/src/main/java/org/apache/nifi/PropertiesDefinitionWriter.java b/src/main/java/org/apache/nifi/PropertiesDefinitionWriter.java
new file mode 100644
index 0000000..402d18c
--- /dev/null
+++ b/src/main/java/org/apache/nifi/PropertiesDefinitionWriter.java
@@ -0,0 +1,75 @@
+/*
+ * 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 org.apache.nifi.extension.definition.ExtensionDefinition;
+import org.apache.nifi.extension.definition.Restriction;
+import org.apache.nifi.extension.definition.Restrictions;
+import org.apache.nifi.extension.definition.ServiceAPIDefinition;
+
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Objects;
+import java.util.Properties;
+
+public class PropertiesDefinitionWriter {
+
+    public void writeDefinition(final ExtensionDefinition definition, final File file) throws IOException {
+        Objects.requireNonNull(definition);
+
+        final String capabilityDescription = definition.getCapabilityDescription();
+
+        final Properties properties = new Properties();
+        if (capabilityDescription != null) {
+            properties.setProperty("capability.description", capabilityDescription);
+        }
+
+        int i=0;
+        for (final String tag : definition.getTags()) {
+            properties.setProperty("tags." + (i++), tag);
+        }
+
+        final Restrictions restrictions = definition.getRestrictions();
+        if (restrictions != null) {
+            final String restrictedDescription = restrictions.getGeneralRestrictionExplanation();
+
+            if (restrictedDescription != null) {
+                properties.setProperty("restricted.description", restrictedDescription);
+            }
+
+            for (final Restriction restriction : restrictions.getRestrictions()) {
+                properties.setProperty("restriction." + restriction.getIdentifier(), restriction.getExplanation());
+            }
+        }
+
+        int serviceIndex = 0;
+        for (final ServiceAPIDefinition apiDefinition : definition.getProvidedServiceAPIs()) {
+            properties.setProperty("service.definition." + serviceIndex + ".class", apiDefinition.getServiceAPIClassName());
+            properties.setProperty("service.definition." + serviceIndex + ".groupId", apiDefinition.getServiceGroupId());
+            properties.setProperty("service.definition." + serviceIndex + ".artifactId", apiDefinition.getServiceArtifactId());
+            properties.setProperty("service.definition." + serviceIndex + ".version", apiDefinition.getServiceVersion());
+
+            serviceIndex++;
+        }
+
+        try (final OutputStream fos = new FileOutputStream(file)) {
+            properties.store(fos, null);
+        }
+    }
+}
diff --git a/src/main/java/org/apache/nifi/XmlDefinitionWriter.java b/src/main/java/org/apache/nifi/XmlDefinitionWriter.java
new file mode 100644
index 0000000..3e91061
--- /dev/null
+++ b/src/main/java/org/apache/nifi/XmlDefinitionWriter.java
@@ -0,0 +1,165 @@
+/*
+ * 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 org.apache.nifi.extension.definition.ExtensionDefinition;
+import org.apache.nifi.extension.definition.ExtensionType;
+import org.apache.nifi.extension.definition.Restriction;
+import org.apache.nifi.extension.definition.Restrictions;
+import org.apache.nifi.extension.definition.ServiceAPIDefinition;
+
+import javax.xml.stream.XMLOutputFactory;
+import javax.xml.stream.XMLStreamException;
+import javax.xml.stream.XMLStreamWriter;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.OutputStream;
+import java.util.Collection;
+import java.util.List;
+import java.util.Map;
+import java.util.Objects;
+import java.util.Set;
+import java.util.stream.Collectors;
+
+public class XmlDefinitionWriter {
+
+    public void writeDefinition(final Collection<ExtensionDefinition> definitions, final File file) throws IOException {
+        final Map<ExtensionType, List<ExtensionDefinition>> definitionMap = definitions.stream()
+            .collect(Collectors.groupingBy(ExtensionDefinition::getExtensionType));
+
+        writeDefinition(definitionMap, file);
+    }
+
+    public void writeDefinition(final Map<ExtensionType, ? extends Collection<ExtensionDefinition>> definitions, final File file) throws IOException {
+        Objects.requireNonNull(definitions);
+        Objects.requireNonNull(file);
+
+        if (definitions.isEmpty()) {
+            return;
+        }
+
+        try (final OutputStream fileOut = new FileOutputStream(file)) {
+             final XMLStreamWriter writer = XMLOutputFactory.newInstance().createXMLStreamWriter(fileOut, "UTF-8");
+             try {
+                 writer.writeStartElement("extensions");
+
+                 writer.writeStartElement("processors");
+                 writeDefinitions(ExtensionType.PROCESSOR, definitions.get(ExtensionType.PROCESSOR), writer);
+                 writer.writeEndElement();
+
+                 writer.writeStartElement("controllerServices");
+                 writeDefinitions(ExtensionType.CONTROLLER_SERVICE, definitions.get(ExtensionType.CONTROLLER_SERVICE), writer);
+                 writer.writeEndElement();
+
+                 writer.writeStartElement("reportingTasks");
+                 writeDefinitions(ExtensionType.REPORTING_TASK, definitions.get(ExtensionType.REPORTING_TASK), writer);
+                 writer.writeEndElement();
+
+                 writer.writeEndElement();
+             } finally {
+                 writer.close();
+             }
+        } catch (XMLStreamException e) {
+            throw new IOException(e);
+        }
+    }
+
+    private void writeDefinitions(final ExtensionType extensionType, final Collection<ExtensionDefinition> definitions, final XMLStreamWriter writer) throws XMLStreamException {
+        if (definitions == null) {
+            return;
+        }
+
+        final String tagName;
+        switch (extensionType) {
+            case PROCESSOR:
+                tagName = "processor";
+                break;
+            case CONTROLLER_SERVICE:
+                tagName = "controllerService";
+                break;
+            case REPORTING_TASK:
+                tagName = "reportingTask";
+                break;
+            default:
+                throw new AssertionError("Encountered unknown Extension Type " + extensionType);
+        }
+
+        for (final ExtensionDefinition definition : definitions) {
+            writer.writeStartElement(tagName);
+
+            writeTextElement(writer, "name", definition.getExtensionName());
+            writeTextElement(writer, "description", definition.getCapabilityDescription());
+
+            writer.writeStartElement("tags");
+            for (final String tag : definition.getTags()) {
+                writeTextElement(writer, "tag", tag);
+            }
+            writer.writeEndElement();
+
+            final Restrictions restrictions = definition.getRestrictions();
+            if (restrictions == null) {
+                writer.writeEmptyElement("restrictions");
+            } else {
+                writer.writeStartElement("restrictions");
+
+                writeTextElement(writer, "explanation", restrictions.getGeneralRestrictionExplanation());
+                final Set<Restriction> specificRestrictions = restrictions.getRestrictions();
+                for (final Restriction restriction : specificRestrictions) {
+                    writer.writeStartElement("restriction");
+                    writeTextElement(writer, "identifier", restriction.getIdentifier());
+                    writeTextElement(writer, "explanation", restriction.getExplanation());
+                    writer.writeEndElement();
+                }
+
+                writer.writeEndElement();
+            }
+
+            if (extensionType == ExtensionType.CONTROLLER_SERVICE) {
+                writer.writeStartElement("providedServiceAPIs");
+
+                final Set<ServiceAPIDefinition> serviceDefinitions = definition.getProvidedServiceAPIs();
+                if (serviceDefinitions != null) {
+                    for (final ServiceAPIDefinition serviceDefinition : serviceDefinitions) {
+                        writer.writeStartElement("service");
+
+                        writeTextElement(writer, "className", serviceDefinition.getServiceAPIClassName());
+                        writeTextElement(writer, "groupId", serviceDefinition.getServiceGroupId());
+                        writeTextElement(writer, "artifactId", serviceDefinition.getServiceArtifactId());
+                        writeTextElement(writer, "version", serviceDefinition.getServiceVersion());
+
+                        writer.writeEndElement();
+                    }
+                }
+
+                writer.writeEndElement();
+            }
+
+            writer.writeEndElement();
+        }
+    }
+
+    private void writeTextElement(final XMLStreamWriter writer, final String tagName, final String text) throws XMLStreamException {
+        writer.writeStartElement(tagName);
+
+        if (text != null) {
+            writer.writeCharacters(text);
+        }
+
+        writer.writeEndElement();
+    }
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/ExtensionDefinition.java b/src/main/java/org/apache/nifi/extension/definition/ExtensionDefinition.java
new file mode 100644
index 0000000..8c0bc40
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/ExtensionDefinition.java
@@ -0,0 +1,52 @@
+/*
+ * 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.extension.definition;
+
+import java.util.Set;
+
+public interface ExtensionDefinition {
+    /**
+     * @return the extension's capability description
+     */
+    String getCapabilityDescription();
+
+    /**
+     * @return the set of Tags associated with the extension
+     */
+    Set<String> getTags();
+
+    /**
+     * @return the Restrictions that are placed on the Extension
+     */
+    Restrictions getRestrictions();
+
+    /**
+     * @return the type of Extension
+     */
+    ExtensionType getExtensionType();
+
+    /**
+     * @return the Set of all Services API's that this extension provides. Note that this will be an empty set for
+     * any Extension for which {@link #getExtensionType()} is not {@link ExtensionType#CONTROLLER_SERVICE}.
+     */
+    Set<ServiceAPIDefinition> getProvidedServiceAPIs();
+
+    /**
+     * @return the name of the Extension
+     */
+    String getExtensionName();
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/ExtensionType.java b/src/main/java/org/apache/nifi/extension/definition/ExtensionType.java
new file mode 100644
index 0000000..55f76f5
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/ExtensionType.java
@@ -0,0 +1,27 @@
+/*
+ * 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.extension.definition;
+
+public enum ExtensionType {
+
+    PROCESSOR,
+
+    CONTROLLER_SERVICE,
+
+    REPORTING_TASK;
+
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/Restriction.java b/src/main/java/org/apache/nifi/extension/definition/Restriction.java
new file mode 100644
index 0000000..9b5064c
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/Restriction.java
@@ -0,0 +1,29 @@
+/*
+ * 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.extension.definition;
+
+public interface Restriction {
+    /**
+     * @return the Restriction identifier used by NiFi
+     */
+    String getIdentifier();
+
+    /**
+     * @return an Explanation of why the Restriction exists.
+     */
+    String getExplanation();
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/Restrictions.java b/src/main/java/org/apache/nifi/extension/definition/Restrictions.java
new file mode 100644
index 0000000..5e098fb
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/Restrictions.java
@@ -0,0 +1,31 @@
+/*
+ * 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.extension.definition;
+
+import java.util.Set;
+
+public interface Restrictions {
+    /**
+     * @return if the extension has a General Restriction on it, this explains why the Restriction is in place.
+     */
+    String getGeneralRestrictionExplanation();
+
+    /**
+     * @return the set of all specific Restrictions that are placed on this extension.
+     */
+    Set<Restriction> getRestrictions();
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/ServiceAPIDefinition.java b/src/main/java/org/apache/nifi/extension/definition/ServiceAPIDefinition.java
new file mode 100644
index 0000000..0167f40
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/ServiceAPIDefinition.java
@@ -0,0 +1,27 @@
+/*
+ * 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.extension.definition;
+
+public interface ServiceAPIDefinition {
+    String getServiceAPIClassName();
+
+    String getServiceGroupId();
+
+    String getServiceArtifactId();
+
+    String getServiceVersion();
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoader.java b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoader.java
new file mode 100644
index 0000000..12f02ac
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoader.java
@@ -0,0 +1,114 @@
+/*
+ * 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.extension.definition.extraction;
+
+import org.apache.maven.artifact.Artifact;
+
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.Collection;
+
+public class ExtensionClassLoader extends URLClassLoader {
+    private final URL[] urls;
+    private final Artifact narArtifact;
+    private final Collection<Artifact> allArtifacts;
+
+    public ExtensionClassLoader(final URL[] urls, final ClassLoader parent, final Artifact narArtifact, final Collection<Artifact> otherArtifacts) {
+        super(urls, parent);
+        this.urls = urls;
+        this.narArtifact = narArtifact;
+        this.allArtifacts = new ArrayList<>(otherArtifacts);
+        allArtifacts.add(narArtifact);
+    }
+
+    public ExtensionClassLoader(final URL[] urls, final Artifact narArtifact, final Collection<Artifact> otherArtifacts) {
+        super(urls);
+        this.urls = urls;
+        this.narArtifact = narArtifact;
+        this.allArtifacts = new ArrayList<>(otherArtifacts);
+        allArtifacts.add(narArtifact);
+    }
+
+    public String getNiFiApiVersion() {
+        final Collection<Artifact> artifacts = getAllArtifacts();
+        for (final Artifact artifact : artifacts) {
+            if (artifact.getArtifactId().equals("nifi-api") && artifact.getGroupId().equals("org.apache.nifi")) {
+                return artifact.getVersion();
+            }
+        }
+
+        final ClassLoader parent = getParent();
+        if (parent instanceof ExtensionClassLoader) {
+            ((ExtensionClassLoader) parent).getNiFiApiVersion();
+        }
+
+        return null;
+    }
+
+    public Artifact getNarArtifact() {
+        return narArtifact;
+    }
+
+    public Collection<Artifact> getAllArtifacts() {
+        return allArtifacts;
+    }
+
+    @Override
+    public String toString() {
+        return "ExtensionClassLoader[" + narArtifact + ", Dependencies=" + Arrays.asList(urls) + "]";
+    }
+
+    public String toTree() {
+        final StringBuilder sb = new StringBuilder();
+        sb.append("ClassLoader for ").append(narArtifact).append(" with nifi-api version ").append(getNiFiApiVersion()).append(":\n");
+
+        for (final URL url : urls) {
+            sb.append(url).append("\n");
+        }
+
+        final ClassLoader parent = getParent();
+        if (parent instanceof ExtensionClassLoader) {
+            sb.append("\n\n-------- Parent:\n");
+            sb.append(((ExtensionClassLoader) parent).toTree());
+        } else if (parent instanceof URLClassLoader) {
+            sb.append(toTree((URLClassLoader) parent));
+        }
+
+        return sb.toString();
+    }
+
+    private String toTree(final URLClassLoader classLoader) {
+        final StringBuilder sb = new StringBuilder();
+
+        sb.append("\n\n-------- Parent:\n");
+        final URL[] urls = classLoader.getURLs();
+
+        for (final URL url : urls) {
+            sb.append(url).append("\n");
+        }
+
+        final ClassLoader parent = classLoader.getParent();
+        if (parent instanceof URLClassLoader) {
+            final URLClassLoader urlParent = (URLClassLoader) parent;
+            sb.append(toTree(urlParent));
+        }
+
+        return sb.toString();
+    }
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoaderFactory.java b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoaderFactory.java
new file mode 100644
index 0000000..7b2e5f7
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionClassLoaderFactory.java
@@ -0,0 +1,426 @@
+/*
+ * 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.extension.definition.extraction;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.artifact.DefaultArtifact;
+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.artifact.resolver.ArtifactResolutionRequest;
+import org.apache.maven.artifact.resolver.ArtifactResolutionResult;
+import org.apache.maven.artifact.resolver.ArtifactResolver;
+import org.apache.maven.artifact.versioning.VersionRange;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.maven.plugin.logging.Log;
+import org.apache.maven.project.DefaultProjectBuildingRequest;
+import org.apache.maven.project.MavenProject;
+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;
+
+import java.io.File;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.net.URLClassLoader;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.List;
+import java.util.Set;
+
+public class ExtensionClassLoaderFactory {
+    private final Log log;
+    private final MavenProject project;
+    private final RepositorySystemSession repoSession;
+    private final ProjectBuilder projectBuilder;
+    private final ArtifactRepository localRepo;
+    private final List<ArtifactRepository> remoteRepos;
+    private final DependencyTreeBuilder dependencyTreeBuilder;
+    private final ArtifactResolver artifactResolver;
+    private final ArtifactHandlerManager artifactHandlerManager;
+
+    private ExtensionClassLoaderFactory(final Builder builder) {
+        this.log = builder.log;
+        this.project = builder.project;
+        this.repoSession = builder.repositorySession;
+        this.projectBuilder = builder.projectBuilder;
+        this.localRepo = builder.localRepo;
+        this.remoteRepos = new ArrayList<>(builder.remoteRepos);
+        this.dependencyTreeBuilder = builder.dependencyTreeBuilder;
+        this.artifactResolver = builder.artifactResolver;
+        this.artifactHandlerManager = builder.artifactHandlerManager;
+    }
+
+    private Log getLog() {
+        return log;
+    }
+
+    public ExtensionClassLoader createExtensionClassLoader() throws MojoExecutionException {
+        final Set<Artifact> artifacts = new HashSet<>();
+        gatherArtifacts(project, artifacts);
+
+        getLog().debug("Project artifacts: ");
+        artifacts.forEach(artifact -> getLog().debug(artifact.toString()));
+
+        final Artifact narArtifact = project.getArtifact();
+
+        final VersionLookup versionLookup = (group, artifact) -> {
+            try {
+                return determineProvidedEntityVersion(artifacts, group, artifact);
+            } catch (final Exception e) {
+                throw new RuntimeException("Failed to determine provided version of NiFi dependencies", e);
+            }
+        };
+
+        final ClassLoader parentClassLoader = createClassLoader(artifacts, versionLookup);
+        final ExtensionClassLoader classLoader = createClassLoader(artifacts, parentClassLoader, narArtifact);
+
+        if (getLog().isDebugEnabled()) {
+            getLog().debug("Full ClassLoader is:\n" + classLoader.toTree());
+        }
+
+        return classLoader;
+    }
+
+    private ClassLoader createClassLoader(final Set<Artifact> artifacts, final VersionLookup versionLookup) throws MojoExecutionException {
+        final Artifact nar = removeNarArtifact(artifacts);
+        if (nar == null) {
+            final ClassLoader providedEntityClassLoader = createProvidedEntitiesClassLoader(versionLookup);
+            return createUrlClassLoader(artifacts, providedEntityClassLoader);
+        }
+
+        final Set<Artifact> narDependencies = getNarDependencies(nar);
+        return createClassLoader(narDependencies, createClassLoader(narDependencies, versionLookup), nar);
+    }
+
+
+    private Artifact removeNarArtifact(final Set<Artifact> artifacts) {
+        final Iterator<Artifact> itr = artifacts.iterator();
+        while (itr.hasNext()) {
+            final Artifact artifact = itr.next();
+
+            if (artifact.equals(project.getArtifact())) {
+                continue;
+            }
+
+            if ("nar".equalsIgnoreCase(artifact.getType())) {
+                getLog().info("Found NAR dependency of " + artifact);
+                itr.remove();
+
+                return artifact;
+            }
+        }
+
+        return null;
+    }
+
+    private Set<Artifact> getNarDependencies(final Artifact narArtifact) throws MojoExecutionException {
+        final ProjectBuildingRequest narRequest = new DefaultProjectBuildingRequest();
+        narRequest.setRepositorySession(repoSession);
+        narRequest.setSystemProperties(System.getProperties());
+
+        final Set<Artifact> narDependencies = new HashSet<>();
+
+        try {
+            final ProjectBuildingResult narResult = projectBuilder.build(narArtifact, narRequest);
+            gatherArtifacts(narResult.getProject(), narDependencies);
+            narDependencies.remove(narArtifact);
+            narDependencies.remove(project.getArtifact());
+
+            getLog().debug("Found NAR dependency of " + narArtifact + ", which resolved to the following artifacts: " + narDependencies);
+        } catch (ProjectBuildingException e) {
+            throw new MojoExecutionException("Could not build parent nar project");
+        }
+
+        return narDependencies;
+    }
+
+    private String determineProvidedEntityVersion(final Set<Artifact> artifacts, final String groupId, final String artifactId) throws ProjectBuildingException, MojoExecutionException {
+        getLog().debug("Determining provided entities for " + groupId + ":" + artifactId);
+
+        for (final Artifact artifact : artifacts) {
+            if (artifact.getGroupId().equals(groupId) && artifact.getArtifactId().equals(artifactId)) {
+                return artifact.getVersion();
+            }
+        }
+
+        return findProvidedDependencyVersion(artifacts, groupId, artifactId);
+    }
+
+    private String findProvidedDependencyVersion(final Set<Artifact> artifacts, final String groupId, final String artifactId) throws ProjectBuildingException, MojoExecutionException {
+        final ProjectBuildingRequest narRequest = new DefaultProjectBuildingRequest();
+        narRequest.setRepositorySession(repoSession);
+        narRequest.setSystemProperties(System.getProperties());
+
+        for (final Artifact artifact : artifacts) {
+            final Set<Artifact> artifactDependencies = new HashSet<>();
+
+            try {
+                final ProjectBuildingResult projectResult = projectBuilder.build(artifact, narRequest);
+                gatherArtifacts(projectResult.getProject(), artifactDependencies);
+
+                getLog().debug("For Artifact " + artifact + ", found the following dependencies:");
+                artifactDependencies.forEach(dep -> getLog().debug(dep.toString()));
+
+                for (final Artifact dependency : artifactDependencies) {
+                    if (dependency.getGroupId().equals(groupId) && dependency.getArtifactId().equals(artifactId)) {
+                        getLog().debug("Found version of " + groupId + ":" + artifactId + " to be " + artifact.getVersion());
+                        return artifact.getVersion();
+                    }
+                }
+            } catch (final Exception e) {
+                getLog().warn("Unable to construct Maven Project for " + artifact + " when attempting to determine the expected version of NiFi API");
+                getLog().debug("Unable to construct Maven Project for " + artifact + " when attempting to determine the expected version of NiFi API", e);
+            }
+        }
+
+        return null;
+    }
+
+    private Artifact getProvidedArtifact(final String groupId, final String artifactId, final String version) throws MojoExecutionException {
+        final ArtifactHandler handler = artifactHandlerManager.getArtifactHandler("jar");
+
+        final VersionRange versionRange;
+        try {
+            versionRange = VersionRange.createFromVersionSpec(version);
+        } catch (final Exception e) {
+            throw new MojoExecutionException("Could not determine appropriate version for Provided Artifact " + groupId + ":" + artifactId, e);
+        }
+
+        final Artifact artifact = new DefaultArtifact(groupId, artifactId, versionRange, null, "jar", null, handler);
+
+        final ArtifactResolutionRequest request = new ArtifactResolutionRequest();
+        request.setLocalRepository(localRepo);
+        request.setRemoteRepositories(remoteRepos);
+        request.setArtifact(artifact);
+
+        final ArtifactResolutionResult result = artifactResolver.resolve(request);
+        if (!result.isSuccess()) {
+            final List<Exception> exceptions = result.getExceptions();
+
+            final MojoExecutionException exception = new MojoExecutionException("Could not resolve local dependency " + artifact);
+            if (exceptions != null) {
+                for (final Exception e : exceptions) {
+                    exception.addSuppressed(e);
+                }
+            }
+
+            throw exception;
+        }
+
+        final Set<Artifact> artifacts = result.getArtifacts();
+        if (artifacts.isEmpty()) {
+            throw new MojoExecutionException("Could not resolve any artifacts for dependency " + artifact);
+        }
+
+        final List<Artifact> sorted = new ArrayList<>(artifacts);
+        Collections.sort(sorted);
+
+        return sorted.get(0);
+    }
+
+    private ClassLoader createProvidedEntitiesClassLoader(final VersionLookup versionLookup) throws MojoExecutionException {
+        final String nifiApiVersion = versionLookup.getVersion("org.apache.nifi", "nifi-api");
+        if (nifiApiVersion == null) {
+            throw new MojoExecutionException("Could not find any dependency, provided or otherwise, on [org.apache.nifi:nifi-api]");
+        } else {
+            getLog().info("Found a dependency on version " + nifiApiVersion + " of NiFi API");
+        }
+
+        final String slf4jApiVersion = versionLookup.getVersion("org.slf4j", "slf4j-api");
+
+        final Artifact nifiApiArtifact = getProvidedArtifact("org.apache.nifi", "nifi-api", nifiApiVersion);
+        final Artifact nifiFrameworkApiArtifact = getProvidedArtifact("org.apache.nifi", "nifi-framework-api", nifiApiArtifact.getVersion());
+
+        final Artifact slf4jArtifact = getProvidedArtifact("org.slf4j", "slf4j-api", slf4jApiVersion);
+
+        final Set<Artifact> providedArtifacts = new HashSet<>();
+        providedArtifacts.add(nifiApiArtifact);
+        providedArtifacts.add(nifiFrameworkApiArtifact);
+        providedArtifacts.add(slf4jArtifact);
+
+        getLog().debug("Creating Provided Entities Class Loader with artifacts: " + providedArtifacts);
+        return createUrlClassLoader(providedArtifacts, null);
+    }
+
+    private ClassLoader createUrlClassLoader(final Set<Artifact> artifacts, final ClassLoader parent) throws MojoExecutionException {
+        final Set<URL> urls = new HashSet<>();
+        for (final Artifact artifact : artifacts) {
+            final Set<URL> artifactUrls = toURLs(artifact);
+            urls.addAll(artifactUrls);
+        }
+
+        getLog().debug("Creating class loader with following dependencies: " + urls);
+
+        final URL[] urlArray = urls.toArray(new URL[0]);
+        return new URLClassLoader(urlArray, parent);
+    }
+
+    private ExtensionClassLoader createClassLoader(final Set<Artifact> artifacts, final ClassLoader parent, final Artifact narArtifact) throws MojoExecutionException {
+        final Set<URL> urls = new HashSet<>();
+        for (final Artifact artifact : artifacts) {
+            final Set<URL> artifactUrls = toURLs(artifact);
+            urls.addAll(artifactUrls);
+        }
+
+        getLog().debug("Creating class loader with following dependencies: " + urls);
+
+        final URL[] urlArray = urls.toArray(new URL[0]);
+        if (parent == null) {
+            return new ExtensionClassLoader(urlArray, narArtifact, artifacts);
+        } else {
+            return new ExtensionClassLoader(urlArray, parent, narArtifact, artifacts);
+        }
+    }
+
+
+    private void gatherArtifacts(final MavenProject mavenProject, final Set<Artifact> artifacts) throws MojoExecutionException {
+        final DependencyNodeVisitor nodeVisitor = new DependencyNodeVisitor() {
+            @Override
+            public boolean visit(final DependencyNode dependencyNode) {
+                final Artifact artifact = dependencyNode.getArtifact();
+                artifacts.add(artifact);
+                return true;
+            }
+
+            @Override
+            public boolean endVisit(final DependencyNode dependencyNode) {
+                return true;
+            }
+        };
+
+        try {
+            final DependencyNode depNode = dependencyTreeBuilder.buildDependencyTree(mavenProject, localRepo, null);
+            depNode.accept(nodeVisitor);
+        } catch (DependencyTreeBuilderException e) {
+            throw new MojoExecutionException("Failed to build dependency tree", e);
+        }
+    }
+
+
+
+    private Set<URL> toURLs(final Artifact artifact) throws MojoExecutionException {
+        final Set<URL> urls = new HashSet<>();
+
+        final File artifactFile = artifact.getFile();
+        if (artifactFile == null) {
+            getLog().debug("Attempting to resolve Artifact " + artifact + " because it has no File associated with it");
+
+            final ArtifactResolutionRequest request = new ArtifactResolutionRequest();
+            request.setLocalRepository(localRepo);
+            request.setRemoteRepositories(remoteRepos);
+            request.setArtifact(artifact);
+
+            final ArtifactResolutionResult result = artifactResolver.resolve(request);
+            if (!result.isSuccess()) {
+                throw new MojoExecutionException("Could not resolve local dependency " + artifact);
+            }
+
+            getLog().info("Resolved Artifact " + artifact + " to " + result.getArtifacts());
+
+            for (final Artifact resolved : result.getArtifacts()) {
+                urls.addAll(toURLs(resolved));
+            }
+        } else {
+            try {
+                final URL url = artifact.getFile().toURI().toURL();
+                getLog().debug("Adding URL " + url + " to ClassLoader");
+                urls.add(url);
+            } catch (final MalformedURLException mue) {
+                throw new MojoExecutionException("Failed to convert File " + artifact.getFile() + " into URL", mue);
+            }
+        }
+
+        return urls;
+    }
+
+
+
+    public static class Builder {
+        private Log log;
+        private MavenProject project;
+        private ArtifactRepository localRepo;
+        private List<ArtifactRepository> remoteRepos;
+        private DependencyTreeBuilder dependencyTreeBuilder;
+        private ArtifactResolver artifactResolver;
+        private ProjectBuilder projectBuilder;
+        private RepositorySystemSession repositorySession;
+        private ArtifactHandlerManager artifactHandlerManager;
+
+        public Builder log(final Log log) {
+            this.log = log;
+            return this;
+        }
+
+        public Builder projectBuilder(final ProjectBuilder projectBuilder) {
+            this.projectBuilder = projectBuilder;
+            return this;
+        }
+
+        public Builder project(final MavenProject project) {
+            this.project = project;
+            return this;
+        }
+
+        public Builder localRepository(final ArtifactRepository localRepo) {
+            this.localRepo = localRepo;
+            return this;
+        }
+
+        public Builder remoteRepositories(final List<ArtifactRepository> remoteRepos) {
+            this.remoteRepos = remoteRepos;
+            return this;
+        }
+
+        public Builder dependencyTreeBuilder(final DependencyTreeBuilder dependencyTreeBuilder) {
+            this.dependencyTreeBuilder = dependencyTreeBuilder;
+            return this;
+        }
+
+        public Builder artifactResolver(final ArtifactResolver resolver) {
+            this.artifactResolver = resolver;
+            return this;
+        }
+
+        public Builder repositorySession(final RepositorySystemSession repositorySession) {
+            this.repositorySession = repositorySession;
+            return this;
+        }
+
+        public Builder artifactHandlerManager(final ArtifactHandlerManager artifactHandlerManager) {
+            this.artifactHandlerManager = artifactHandlerManager;
+            return this;
+        }
+
+        public ExtensionClassLoaderFactory build() {
+            return new ExtensionClassLoaderFactory(this);
+        }
+    }
+
+
+    private interface VersionLookup {
+        String getVersion(String groupId, String artifactId);
+    }
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionDefinitionFactory.java b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionDefinitionFactory.java
new file mode 100644
index 0000000..d0aee68
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/extraction/ExtensionDefinitionFactory.java
@@ -0,0 +1,247 @@
+/*
+ * 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.extension.definition.extraction;
+
+import org.apache.maven.artifact.Artifact;
+import org.apache.maven.plugin.MojoExecutionException;
+import org.apache.nifi.extension.definition.ExtensionDefinition;
+import org.apache.nifi.extension.definition.ExtensionType;
+import org.apache.nifi.extension.definition.Restriction;
+import org.apache.nifi.extension.definition.Restrictions;
+import org.apache.nifi.extension.definition.ServiceAPIDefinition;
+
+import java.io.BufferedReader;
+import java.io.IOException;
+import java.io.InputStream;
+import java.io.InputStreamReader;
+import java.io.Reader;
+import java.lang.annotation.Annotation;
+import java.lang.reflect.InvocationTargetException;
+import java.lang.reflect.Method;
+import java.net.URL;
+import java.util.Collections;
+import java.util.Enumeration;
+import java.util.HashMap;
+import java.util.HashSet;
+import java.util.Map;
+import java.util.Set;
+import java.util.stream.Collectors;
+import java.util.stream.Stream;
+
+public class ExtensionDefinitionFactory {
+    private static final String SERVICES_DIRECTORY = "META-INF/services/";
+
+    private static final Map<ExtensionType, String> INTERFACE_NAMES = new HashMap<>();
+    static {
+        INTERFACE_NAMES.put(ExtensionType.PROCESSOR, "org.apache.nifi.processor.Processor");
+        INTERFACE_NAMES.put(ExtensionType.CONTROLLER_SERVICE, "org.apache.nifi.controller.ControllerService");
+        INTERFACE_NAMES.put(ExtensionType.REPORTING_TASK, "org.apache.nifi.reporting.ReportingTask");
+    }
+
+    private final ClassLoader extensionClassLoader;
+
+    public ExtensionDefinitionFactory(final ClassLoader classLoader) {
+        this.extensionClassLoader = classLoader;
+    }
+
+    public Set<ExtensionDefinition> discoverExtensions(final ExtensionType extensionType) throws IOException {
+        final String interfaceName = INTERFACE_NAMES.get(extensionType);
+        final Set<String> classNames = discoverClassNames(interfaceName);
+
+        if (classNames.isEmpty()) {
+            return Collections.emptySet();
+        }
+
+        final Set<ExtensionDefinition> definitions = new HashSet<>();
+        for (final String className : classNames) {
+            try {
+                definitions.add(createExtensionDefinition(extensionType, className));
+            } catch (final Exception e) {
+                throw new IOException("Failed to create Extension Definition for " + extensionType + " " + className, e);
+            }
+        }
+
+        return definitions;
+    }
+
+    private ExtensionDefinition createExtensionDefinition(final ExtensionType extensionType, final String className) throws ClassNotFoundException,
+                IllegalAccessException, NoSuchMethodException, InvocationTargetException {
+
+        final Class<?> extensionClass = Class.forName(className, false, extensionClassLoader);
+
+        final String capabilityDescription = getCapabilityDescription(extensionClass);
+        final Set<String> tags = getTags(extensionClass);
+        final Restrictions restrictions = getRestrictions(extensionClass);
+        final Set<ServiceAPIDefinition> serviceApis = getProvidedServiceAPIs(extensionType, extensionClass);
+
+        return new StandardExtensionDefinition(extensionType, className, capabilityDescription, tags, restrictions, serviceApis);
+    }
+
+    private Set<ServiceAPIDefinition> getProvidedServiceAPIs(final ExtensionType extensionType, final Class<?> extensionClass) throws ClassNotFoundException {
+        if (extensionType != ExtensionType.CONTROLLER_SERVICE) {
+            return Collections.emptySet();
+        }
+
+        final Set<ServiceAPIDefinition> serviceApis = new HashSet<>();
+        final Class<?> controllerServiceClass = Class.forName("org.apache.nifi.controller.ControllerService", false, extensionClassLoader);
+
+        for (final Class<?> implementedInterface : extensionClass.getInterfaces()) {
+            if (controllerServiceClass.isAssignableFrom(implementedInterface)) {
+                final ClassLoader interfaceClassLoader = implementedInterface.getClassLoader();
+                if (interfaceClassLoader instanceof ExtensionClassLoader) {
+                    final Artifact interfaceNarArtifact = ((ExtensionClassLoader) interfaceClassLoader).getNarArtifact();
+
+                    final ServiceAPIDefinition serviceDefinition = new StandardServiceAPIDefinition(implementedInterface.getName(),
+                        interfaceNarArtifact.getGroupId(), interfaceNarArtifact.getArtifactId(), interfaceNarArtifact.getVersion());
+
+                    serviceApis.add(serviceDefinition);
+                }
+            }
+        }
+
+        return serviceApis;
+    }
+
+    private Restrictions getRestrictions(final Class<?> extensionClass) throws ClassNotFoundException, NoSuchMethodException, IllegalAccessException, InvocationTargetException {
+        final String restrictedDescription = getRestrictedDescription(extensionClass);
+        final Map<String, String> specificRestrictions = getSpecificRestrictions(extensionClass);
+
+        final boolean hasRestriction = restrictedDescription != null || !specificRestrictions.isEmpty();
+        final Restrictions restrictions;
+        if (!hasRestriction) {
+            return null;
+        }
+
+        final Set<Restriction> restrictionSet = new HashSet<>();
+        for (final Map.Entry<String, String> specificRestriction : specificRestrictions.entrySet()) {
+            restrictionSet.add(new StandardRestriction(specificRestriction.getKey(), specificRestriction.getValue()));
+        }
+
+        return new StandardRestrictions(restrictedDescription, restrictionSet);
+    }
+
+
+    private String getCapabilityDescription(final Class<?> extensionClass) throws InvocationTargetException,
+                IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
+
+        final Class capabilityDescriptionClass = Class.forName("org.apache.nifi.annotation.documentation.CapabilityDescription", false, extensionClass.getClassLoader());
+        final Method valueMethod = capabilityDescriptionClass.getMethod("value");
+
+        final Annotation capabilityDescriptionAnnotation = extensionClass.getAnnotation(capabilityDescriptionClass);
+        if (capabilityDescriptionAnnotation == null) {
+            return null;
+        }
+
+        final String capabilityDescriptionText = (String) valueMethod.invoke(capabilityDescriptionAnnotation);
+        return capabilityDescriptionText;
+    }
+
+
+    private Set<String> getTags(final Class<?> extensionClass) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
+        final Class tagsClass = Class.forName("org.apache.nifi.annotation.documentation.Tags", false, extensionClass.getClassLoader());
+        final Method valueMethod = tagsClass.getMethod("value");
+
+        final Annotation tagsAnnotation = extensionClass.getAnnotation(tagsClass);
+        if (tagsAnnotation == null) {
+            return Collections.emptySet();
+        }
+
+        final String[] tags = (String[]) valueMethod.invoke(tagsAnnotation);
+        return Stream.of(tags).collect(Collectors.<String>toSet());
+    }
+
+
+    private Map<String, String> getSpecificRestrictions(final Class<?> extensionClass) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
+        final Class restrictedClass = Class.forName("org.apache.nifi.annotation.behavior.Restricted", false, extensionClass.getClassLoader());
+        final Class restrictionClass = Class.forName("org.apache.nifi.annotation.behavior.Restriction", false, extensionClass.getClassLoader());
+        final Class requiredPermissionClass = Class.forName("org.apache.nifi.components.RequiredPermission", false, extensionClass.getClassLoader());
+
+        final Method restrictionsMethod = restrictedClass.getMethod("restrictions");
+        final Method explanationMethod = restrictionClass.getMethod("explanation");
+        final Method requiredPermissionMethod = restrictionClass.getMethod("requiredPermission");
+        final Method getPermissionIdentifierMethod = requiredPermissionClass.getMethod("getPermissionIdentifier");
+
+        final Annotation restrictionAnnotation = restrictedClass.getAnnotation(restrictedClass);
+        if (restrictionAnnotation == null) {
+            return edu.emory.mathcs.backport.java.util.Collections.emptyMap();
+        }
+
+        final Object[] restrictionsArray = (Object[]) restrictionsMethod.invoke(restrictionAnnotation);
+
+        final Map<String, String> restrictions = new HashMap<>();
+        for (final Object restriction : restrictionsArray) {
+            final String explanation = (String) explanationMethod.invoke(restriction);
+
+            final Object requiredPermission = requiredPermissionMethod.invoke(restriction);
+            final String requiredPermissionId = (String) getPermissionIdentifierMethod.invoke(requiredPermission);
+
+            restrictions.put(requiredPermissionId, explanation);
+        }
+
+        return restrictions;
+    }
+
+    private String getRestrictedDescription(final Class<?> extensionClass) throws InvocationTargetException, IllegalAccessException, NoSuchMethodException, ClassNotFoundException {
+        final Class restrictedClass = Class.forName("org.apache.nifi.annotation.behavior.Restricted", false, extensionClass.getClassLoader());
+        final Method valueMethod = restrictedClass.getMethod("value");
+
+        final Annotation restrictedAnnotation = extensionClass.getAnnotation(restrictedClass);
+        if (restrictedAnnotation == null) {
+            return null;
+        }
+
+        return (String) valueMethod.invoke(restrictedAnnotation);
+    }
+
+
+
+    private Set<String> discoverClassNames(final String extensionType) throws IOException {
+        final Set<String> classNames = new HashSet<>();
+
+        final Enumeration<URL> resources = extensionClassLoader.getResources(SERVICES_DIRECTORY + extensionType);
+
+        while (resources.hasMoreElements()) {
+            final URL resourceUrl = resources.nextElement();
+            classNames.addAll(discoverClassNames(extensionClassLoader, resourceUrl));
+        }
+
+        return classNames;
+    }
+
+    private Set<String> discoverClassNames(final ClassLoader classLoader, final URL serviceUrl) throws IOException {
+        final Set<String> classNames = new HashSet<>();
+
+        try (final InputStream in = serviceUrl.openStream();
+             final Reader rawReader = new InputStreamReader(in);
+             final BufferedReader reader = new BufferedReader(rawReader)) {
+
+            String line;
+            while ((line = reader.readLine()) != null) {
+                line = line.trim();
+
+                if (line.isEmpty() || line.startsWith("#")) {
+                    continue;
+                }
+
+                classNames.add(line);
+            }
+        }
+
+        return classNames;
+    }
+
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/StandardExtensionDefinition.java b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardExtensionDefinition.java
new file mode 100644
index 0000000..dadb747
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardExtensionDefinition.java
@@ -0,0 +1,78 @@
+/*
+ * 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.extension.definition.extraction;
+
+import org.apache.nifi.extension.definition.ExtensionDefinition;
+import org.apache.nifi.extension.definition.ExtensionType;
+import org.apache.nifi.extension.definition.Restrictions;
+import org.apache.nifi.extension.definition.ServiceAPIDefinition;
+
+import java.util.Set;
+
+public class StandardExtensionDefinition implements ExtensionDefinition {
+    private final String capabilityDescription;
+    private final Set<String> tags;
+    private final Restrictions restrictions;
+    private final ExtensionType extensionType;
+    private final String extensionName;
+    private final Set<ServiceAPIDefinition> providedServiceApis;
+
+    public StandardExtensionDefinition(final ExtensionType extensionType, final String extensionName, final String capabilityDescription, final Set<String> tags, final Restrictions restrictions,
+                                       final Set<ServiceAPIDefinition> providedServiceApis) {
+        this.extensionType = extensionType;
+        this.extensionName = extensionName;
+        this.capabilityDescription = capabilityDescription;
+        this.tags = tags;
+        this.restrictions = restrictions;
+        this.providedServiceApis = providedServiceApis;
+    }
+
+    @Override
+    public String getCapabilityDescription() {
+        return capabilityDescription;
+    }
+
+    @Override
+    public Set<String> getTags() {
+        return tags;
+    }
+
+    @Override
+    public Restrictions getRestrictions() {
+        return restrictions;
+    }
+
+    @Override
+    public ExtensionType getExtensionType() {
+        return extensionType;
+    }
+
+    @Override
+    public Set<ServiceAPIDefinition> getProvidedServiceAPIs() {
+        return providedServiceApis;
+    }
+
+    @Override
+    public String getExtensionName() {
+        return extensionName;
+    }
+
+    @Override
+    public String toString() {
+        return "ExtensionDefinition[type=" + getExtensionType() + ", name=" + getExtensionName() + "]";
+    }
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestriction.java b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestriction.java
new file mode 100644
index 0000000..6825d5b
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestriction.java
@@ -0,0 +1,39 @@
+/*
+ * 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.extension.definition.extraction;
+
+import org.apache.nifi.extension.definition.Restriction;
+
+public class StandardRestriction implements Restriction {
+    private final String identifier;
+    private final String explanation;
+
+    public StandardRestriction(final String identifier, final String explanation) {
+        this.identifier = identifier;
+        this.explanation = explanation;
+    }
+
+    @Override
+    public String getIdentifier() {
+        return identifier;
+    }
+
+    @Override
+    public String getExplanation() {
+        return explanation;
+    }
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestrictions.java b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestrictions.java
new file mode 100644
index 0000000..97fa9ba
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardRestrictions.java
@@ -0,0 +1,42 @@
+/*
+ * 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.extension.definition.extraction;
+
+import org.apache.nifi.extension.definition.Restriction;
+import org.apache.nifi.extension.definition.Restrictions;
+
+import java.util.Set;
+
+public class StandardRestrictions implements Restrictions {
+    private final String generalRestrictionExplanation;
+    private final Set<Restriction> restrictions;
+
+    public StandardRestrictions(final String generalRestrictionExplanation, final Set<Restriction> restrictions) {
+        this.generalRestrictionExplanation = generalRestrictionExplanation;
+        this.restrictions = restrictions;
+    }
+
+    @Override
+    public String getGeneralRestrictionExplanation() {
+        return generalRestrictionExplanation;
+    }
+
+    @Override
+    public Set<Restriction> getRestrictions() {
+        return restrictions;
+    }
+}
diff --git a/src/main/java/org/apache/nifi/extension/definition/extraction/StandardServiceAPIDefinition.java b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardServiceAPIDefinition.java
new file mode 100644
index 0000000..eb11a2d
--- /dev/null
+++ b/src/main/java/org/apache/nifi/extension/definition/extraction/StandardServiceAPIDefinition.java
@@ -0,0 +1,53 @@
+/*
+ * 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.extension.definition.extraction;
+
+import org.apache.nifi.extension.definition.ServiceAPIDefinition;
+
+public class StandardServiceAPIDefinition implements ServiceAPIDefinition {
+    private final String serviceAPIClassName;
+    private final String serviceGroupId;
+    private final String serviceArtifactId;
+    private final String serviceVersion;
+
+    public StandardServiceAPIDefinition(final String serviceAPIClassName, final String serviceGroupId, final String serviceArtifactId, final String serviceVersion) {
+        this.serviceAPIClassName = serviceAPIClassName;
+        this.serviceGroupId = serviceGroupId;
+        this.serviceArtifactId = serviceArtifactId;
+        this.serviceVersion = serviceVersion;
+    }
+
+    @Override
+    public String getServiceAPIClassName() {
+        return serviceAPIClassName;
+    }
+
+    @Override
+    public String getServiceGroupId() {
+        return serviceGroupId;
+    }
+
+    @Override
+    public String getServiceArtifactId() {
+        return serviceArtifactId;
+    }
+
+    @Override
+    public String getServiceVersion() {
+        return serviceVersion;
+    }
+}


[nifi-maven] 10/20: NIFI-3381 Adding optional properties to override narGroup, narId, narVersion, narDependencyGroup, narDependencyId, narDependencyVersion so users can use a different versioning scheme than the Maven artifacts

Posted by kd...@apache.org.
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 33e1ae0356136641247450b9034dd36ccf33ff08
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Wed Feb 1 14:27:57 2017 -0500

    NIFI-3381 Adding optional properties to override narGroup, narId, narVersion, narDependencyGroup, narDependencyId, narDependencyVersion so users can use a different versioning scheme than the Maven artifacts
    
    Signed-off-by: Matt Gilman <ma...@gmail.com>
---
 src/main/java/org/apache/nifi/NarMojo.java | 62 +++++++++++++++++++++++++++---
 1 file changed, 56 insertions(+), 6 deletions(-)

diff --git a/src/main/java/org/apache/nifi/NarMojo.java b/src/main/java/org/apache/nifi/NarMojo.java
index a4f8f31..351c23d 100644
--- a/src/main/java/org/apache/nifi/NarMojo.java
+++ b/src/main/java/org/apache/nifi/NarMojo.java
@@ -363,6 +363,52 @@ public class NarMojo extends AbstractMojo {
     @Parameter(property = "outputAbsoluteArtifactFilename", defaultValue = "false", required = false)
     protected boolean outputAbsoluteArtifactFilename;
 
+    /* The values to use for populating the Nar-Group, Nar-Id, and Nar-Version in the MANIFEST file. By default
+     * these values will be set to the standard Maven project equivalents, but they may be overridden through properties.
+     *
+     * For example if the pom.xml for the nifi-test-nar contained the following:
+     *
+     *    <groupId>org.apache.nifi</groupId>
+     *    <artifactId>nifi-test-nar</artifactId>
+     *    <version>1.0</version>
+     *
+     *    <properties>
+     *       <narGroup>org.apache.nifi.overridden</narGroup>
+     *       <narId>nifi-overridden-test-nar</narId>
+     *       <narVersion>2.0</narVersion>
+     *   </properties>
+     *
+     * It would produce a MANIFEST with:
+     *
+     *   Nar-Id: nifi-overridden-test-nar
+     *   Nar-Group: org.apache.nifi.overridden
+     *   Nar-Version: 2.0
+     *
+    */
+
+    @Parameter(property = "narGroup", defaultValue = "${project.groupId}", required = true)
+    protected String narGroup;
+
+    @Parameter(property = "narId", defaultValue = "${project.artifactId}", required = true)
+    protected String narId;
+
+    @Parameter(property = "narVersion", defaultValue = "${project.version}", required = true)
+    protected String narVersion;
+
+    @Parameter(property = "narDependencyGroup", required = false)
+    protected String narDependencyGroup = null;
+
+    @Parameter(property = "narDependencyId", required = false)
+    protected String narDependencyId = null;
+
+    @Parameter(property = "narDependencyVersion", required = false)
+    protected String narDependencyVersion = null;
+
+
+    /**
+     * Build info to be populated in MANIFEST.
+     */
+
     @Parameter(property = "buildTag", defaultValue = "${project.scm.tag}", required = false)
     protected String buildTag;
 
@@ -556,16 +602,20 @@ public class NarMojo extends AbstractMojo {
             }
 
             // automatically add the artifact id, group id, and version to the manifest
-            archive.addManifestEntry("Nar-Id", project.getArtifactId());
-            archive.addManifestEntry("Nar-Group", project.getGroupId());
-            archive.addManifestEntry("Nar-Version", project.getVersion());
+            archive.addManifestEntry("Nar-Id", narId);
+            archive.addManifestEntry("Nar-Group", narGroup);
+            archive.addManifestEntry("Nar-Version", narVersion);
 
             // look for a nar dependency
             NarDependency narDependency = getNarDependency();
             if (narDependency != null) {
-                archive.addManifestEntry("Nar-Dependency-Id", narDependency.getArtifactId());
-                archive.addManifestEntry("Nar-Dependency-Group", narDependency.getGroupId());
-                archive.addManifestEntry("Nar-Dependency-Version", narDependency.getVersion());
+                final String narDependencyGroup = notEmpty(this.narDependencyGroup) ? this.narDependencyGroup : narDependency.getGroupId();
+                final String narDependencyId = notEmpty(this.narDependencyId) ? this.narDependencyId : narDependency.getArtifactId();
+                final String narDependencyVersion = notEmpty(this.narDependencyVersion) ? this.narDependencyVersion : narDependency.getVersion();
+
+                archive.addManifestEntry("Nar-Dependency-Group", narDependencyGroup);
+                archive.addManifestEntry("Nar-Dependency-Id", narDependencyId);
+                archive.addManifestEntry("Nar-Dependency-Version", narDependencyVersion);
             }
 
             // add build information when available


[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.

Posted by kd...@apache.org.
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();
+        }
+    }
+}


[nifi-maven] 17/20: NIFI-5277 nifi-nar-maven-plugin is built against buggy maven version

Posted by kd...@apache.org.
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 d0210b95795d578551c967ace2e94b8e39ba3f31
Author: Paul Millar <pa...@desy.de>
AuthorDate: Thu Jun 7 10:00:09 2018 +0200

    NIFI-5277 nifi-nar-maven-plugin is built against buggy maven version
    
    This closes #4.
    
    Signed-off-by: Paul Millar <pa...@desy.de>
    Signed-off-by: Bryan Bende <bb...@apache.org>
---
 pom.xml | 6 +++---
 1 file changed, 3 insertions(+), 3 deletions(-)

diff --git a/pom.xml b/pom.xml
index 02bf53c..9a31087 100644
--- a/pom.xml
+++ b/pom.xml
@@ -365,17 +365,17 @@
         <dependency>          
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-plugin-api</artifactId>
-            <version>3.1.0</version>
+            <version>3.1.1</version>
         </dependency>
         <dependency>          
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-artifact</artifactId>
-            <version>3.1.0</version>
+            <version>3.1.1</version>
         </dependency>
         <dependency>          
             <groupId>org.apache.maven</groupId>
             <artifactId>maven-compat</artifactId>
-            <version>3.1.0</version>
+            <version>3.1.1</version>
         </dependency>
         <dependency>
             <groupId>org.apache.maven.plugins</groupId>


[nifi-maven] 06/20: NIFI-875 prepare for next development iteration

Posted by kd...@apache.org.
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 83e10569303539131fa902b8b1ab53e49daab37b
Author: Matt Gilman <ma...@gmail.com>
AuthorDate: Wed Aug 19 22:18:02 2015 -0400

    NIFI-875 prepare for next development iteration
---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index a5d1cf4..5962163 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.1.0</version>
+    <version>1.1.1-SNAPSHOT</version>
     <packaging>maven-plugin</packaging>
     <description>Apache NiFi Nar Maven Plugin</description>
     <url>http://nifi.apache.org</url>
@@ -67,7 +67,7 @@
         <connection>scm:git:git://git.apache.org/nifi-maven.git</connection>
         <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/nifi-maven.git</developerConnection>
         <url>https://git-wip-us.apache.org/repos/asf?p=nifi-maven.git</url>
-        <tag>nifi-nar-maven-plugin-1.1.0-RC1</tag>
+        <tag>HEAD</tag>
     </scm>
     <issueManagement>
         <system>JIRA</system>


[nifi-maven] 14/20: NIFI-3597 prepare for next development iteration

Posted by kd...@apache.org.
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 fc124e5913019d219b1b7dbf3201713fe3290455
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Tue Mar 14 11:10:30 2017 -0400

    NIFI-3597 prepare for next development iteration
---
 pom.xml | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/pom.xml b/pom.xml
index 985a794..02bf53c 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.2.0</version>
+    <version>1.2.1-SNAPSHOT</version>
     <packaging>maven-plugin</packaging>
     <description>Apache NiFi Nar Maven Plugin</description>
     <url>http://nifi.apache.org</url>
@@ -67,7 +67,7 @@
         <connection>scm:git:git://git.apache.org/nifi-maven.git</connection>
         <developerConnection>scm:git:https://git-wip-us.apache.org/repos/asf/nifi-maven.git</developerConnection>
         <url>https://git-wip-us.apache.org/repos/asf?p=nifi-maven.git</url>
-        <tag>nifi-nar-maven-plugin-1.2.0-RC1</tag>
+        <tag>HEAD</tag>
     </scm>
     <issueManagement>
         <system>JIRA</system>


[nifi-maven] 12/20: Updating NOTICE to current year (2017)

Posted by kd...@apache.org.
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 d424f0f28da6478d6f31f40d956ef296c9b9b6d4
Author: Bryan Bende <bb...@apache.org>
AuthorDate: Tue Mar 14 11:01:06 2017 -0400

    Updating NOTICE to current year (2017)
---
 NOTICE | 2 +-
 1 file changed, 1 insertion(+), 1 deletion(-)

diff --git a/NOTICE b/NOTICE
index 76a23fb..6d192c1 100644
--- a/NOTICE
+++ b/NOTICE
@@ -1,5 +1,5 @@
 Apache NiFi
-Copyright 2014-2015 The Apache Software Foundation
+Copyright 2014-2017 The Apache Software Foundation
 
 This product includes software developed at
 The Apache Software Foundation (http://www.apache.org/).