You are viewing a plain text version of this content. The canonical link for it is here.
Posted to commits@nifi.apache.org by ma...@apache.org on 2017/03/24 15:10:54 UTC

[07/17] nifi git commit: NIFI-3380 Bumping NAR plugin to 1.2.0-SNAPSHOT development to leverage changes from master, adding buildnumber-maven-plugin to nifi-nar-bundles to properly set build info in MANIFEST of NARs - Refactoring NarDetails to include al

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-properties-loader/src/test/resources/conf/nifi_with_sensitive_properties_unprotected_extra_line.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-properties-loader/src/test/resources/conf/nifi_with_sensitive_properties_unprotected_extra_line.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-properties-loader/src/test/resources/conf/nifi_with_sensitive_properties_unprotected_extra_line.properties
index 4ad5784..1e308bf 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-properties-loader/src/test/resources/conf/nifi_with_sensitive_properties_unprotected_extra_line.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-properties-loader/src/test/resources/conf/nifi_with_sensitive_properties_unprotected_extra_line.properties
@@ -14,7 +14,6 @@
 # limitations under the License.
 
 # Core Properties #
-nifi.version=nifi-test 3.0.0
 nifi.flow.configuration.file=./target/flow.xml.gz
 nifi.flow.configuration.archive.dir=./target/archive/
 nifi.flowcontroller.autoResumeState=true

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml
index cecfabf..b8d3ad9 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/pom.xml
@@ -29,7 +29,6 @@
         <nifi.jvm.permgen.mb>128</nifi.jvm.permgen.mb>
         <nifi.run.as />
         <!-- nifi.properties: core properties -->
-        <nifi.version>${project.version}</nifi.version>
         <nifi.flowcontroller.autoResumeState>true</nifi.flowcontroller.autoResumeState>
         <nifi.flowcontroller.graceful.shutdown.period>10 sec</nifi.flowcontroller.graceful.shutdown.period>
         <nifi.flowservice.writedelay.interval>500 ms</nifi.flowservice.writedelay.interval>
@@ -174,13 +173,6 @@
         <nifi.kerberos.spnego.principal />
         <nifi.kerberos.spnego.keytab.location />
         <nifi.kerberos.spnego.authentication.expiration>12 hours</nifi.kerberos.spnego.authentication.expiration>
-
-        <!-- nifi.properties: build info -->
-        <nifi.build.tag>${project.scm.tag}</nifi.build.tag>
-        <nifi.build.timestamp>${maven.build.timestamp}</nifi.build.timestamp>
-        <!-- buildRevision and buildBranch provided by buildnumber-maven-plugin or build-info-read-properties profile -->
-        <nifi.build.branch>${buildBranch}</nifi.build.branch>
-        <nifi.build.revision>${buildRevision}</nifi.build.revision>
     </properties>
     <build>
         <plugins>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties
index 4a93828..62b4c8f 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-resources/src/main/resources/conf/nifi.properties
@@ -14,7 +14,6 @@
 # limitations under the License.
 
 # Core Properties #
-nifi.version=${nifi.version}
 nifi.flow.configuration.file=${nifi.flow.configuration.file}
 nifi.flow.configuration.archive.enabled=${nifi.flow.configuration.archive.enabled}
 nifi.flow.configuration.archive.dir=${nifi.flow.configuration.archive.dir}
@@ -198,10 +197,4 @@ nifi.kerberos.spnego.authentication.expiration=${nifi.kerberos.spnego.authentica
 
 # external properties files for variable registry
 # supports a comma delimited list of file locations
-nifi.variable.registry.properties=
-
-# Build info
-nifi.build.tag=${nifi.build.tag}
-nifi.build.branch=${nifi.build.branch}
-nifi.build.revision=${nifi.build.revision}
-nifi.build.timestamp=${nifi.build.timestamp}
\ No newline at end of file
+nifi.variable.registry.properties=
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/pom.xml
index 76c0131..44ec7ea 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/pom.xml
@@ -24,6 +24,11 @@
     <dependencies>
         <dependency>
             <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-framework-api</artifactId>
+            <scope>compile</scope>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-nar-utils</artifactId>
             <scope>compile</scope>
         </dependency>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/main/java/org/apache/nifi/NiFi.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/main/java/org/apache/nifi/NiFi.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/main/java/org/apache/nifi/NiFi.java
index 0488823..32cbeba 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/main/java/org/apache/nifi/NiFi.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/main/java/org/apache/nifi/NiFi.java
@@ -16,6 +16,18 @@
  */
 package org.apache.nifi;
 
+import org.apache.nifi.bundle.Bundle;
+import org.apache.nifi.documentation.DocGenerator;
+import org.apache.nifi.nar.ExtensionManager;
+import org.apache.nifi.nar.ExtensionMapping;
+import org.apache.nifi.nar.NarClassLoaders;
+import org.apache.nifi.nar.NarUnpacker;
+import org.apache.nifi.util.FileUtils;
+import org.apache.nifi.util.NiFiProperties;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.slf4j.bridge.SLF4JBridgeHandler;
+
 import java.io.File;
 import java.io.IOException;
 import java.lang.Thread.UncaughtExceptionHandler;
@@ -30,6 +42,7 @@ import java.nio.file.Paths;
 import java.util.ArrayList;
 import java.util.Arrays;
 import java.util.List;
+import java.util.Set;
 import java.util.Timer;
 import java.util.TimerTask;
 import java.util.concurrent.Executors;
@@ -40,17 +53,6 @@ import java.util.concurrent.TimeUnit;
 import java.util.concurrent.atomic.AtomicInteger;
 import java.util.concurrent.atomic.AtomicLong;
 
-import org.apache.nifi.documentation.DocGenerator;
-import org.apache.nifi.nar.ExtensionManager;
-import org.apache.nifi.nar.ExtensionMapping;
-import org.apache.nifi.nar.NarClassLoaders;
-import org.apache.nifi.nar.NarUnpacker;
-import org.apache.nifi.util.FileUtils;
-import org.apache.nifi.util.NiFiProperties;
-import org.slf4j.Logger;
-import org.slf4j.LoggerFactory;
-import org.slf4j.bridge.SLF4JBridgeHandler;
-
 public class NiFi {
 
     private static final Logger LOGGER = LoggerFactory.getLogger(NiFi.class);
@@ -124,31 +126,34 @@ public class NiFi {
         SLF4JBridgeHandler.removeHandlersForRootLogger();
         SLF4JBridgeHandler.install();
 
+        final Bundle systemBundle = ExtensionManager.createSystemBundle(properties);
+
         // expand the nars
-        final ExtensionMapping extensionMapping = NarUnpacker.unpackNars(properties);
+        final ExtensionMapping extensionMapping = NarUnpacker.unpackNars(properties, systemBundle);
 
         // load the extensions classloaders
         NarClassLoaders.getInstance().init(properties.getFrameworkWorkingDirectory(), properties.getExtensionsWorkingDirectory());
 
         // load the framework classloader
-        final ClassLoader frameworkClassLoader = NarClassLoaders.getInstance().getFrameworkClassLoader();
+        final ClassLoader frameworkClassLoader = NarClassLoaders.getInstance().getFrameworkBundle().getClassLoader();
         if (frameworkClassLoader == null) {
             throw new IllegalStateException("Unable to find the framework NAR ClassLoader.");
         }
 
         // discover the extensions
-        ExtensionManager.discoverExtensions(NarClassLoaders.getInstance().getExtensionClassLoaders());
+        final Set<Bundle> narBundles = NarClassLoaders.getInstance().getBundles();
+        ExtensionManager.discoverExtensions(systemBundle, narBundles);
         ExtensionManager.logClassLoaderMapping();
 
-        DocGenerator.generate(properties);
+        DocGenerator.generate(properties, extensionMapping);
 
         // load the server from the framework classloader
         Thread.currentThread().setContextClassLoader(frameworkClassLoader);
         Class<?> jettyServer = Class.forName("org.apache.nifi.web.server.JettyServer", true, frameworkClassLoader);
-        Constructor<?> jettyConstructor = jettyServer.getConstructor(NiFiProperties.class);
+        Constructor<?> jettyConstructor = jettyServer.getConstructor(NiFiProperties.class, Set.class);
 
         final long startTime = System.nanoTime();
-        nifiServer = (NiFiServer) jettyConstructor.newInstance(properties);
+        nifiServer = (NiFiServer) jettyConstructor.newInstance(properties, narBundles);
         nifiServer.setExtensionMapping(extensionMapping);
 
         if (shutdown) {

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi.properties
index f341c01..ff190d4 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi.properties
@@ -14,7 +14,6 @@
 # limitations under the License.
 
 # Core Properties #
-nifi.version=1.0.0-SNAPSHOT
 nifi.flow.configuration.file=./target/conf/flow.xml.gz
 nifi.flow.configuration.archive.enabled=true
 nifi.flow.configuration.archive.dir=./target/conf/archive/

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi_with_sensitive_properties_protected_aes.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi_with_sensitive_properties_protected_aes.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi_with_sensitive_properties_protected_aes.properties
index cbc9382..6dd949b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi_with_sensitive_properties_protected_aes.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi_with_sensitive_properties_protected_aes.properties
@@ -14,7 +14,6 @@
 # limitations under the License.
 
 # Core Properties #
-nifi.version=1.0.0-SNAPSHOT
 nifi.flow.configuration.file=./target/conf/flow.xml.gz
 nifi.flow.configuration.archive.enabled=true
 nifi.flow.configuration.archive.dir=./target/conf/archive/

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi_with_sensitive_properties_protected_aes_different_key.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi_with_sensitive_properties_protected_aes_different_key.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi_with_sensitive_properties_protected_aes_different_key.properties
index f170d7e..9c52fe6 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi_with_sensitive_properties_protected_aes_different_key.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-runtime/src/test/resources/NiFiProperties/conf/nifi_with_sensitive_properties_protected_aes_different_key.properties
@@ -14,7 +14,6 @@
 # limitations under the License.
 
 # Core Properties #
-nifi.version=1.0.0-SNAPSHOT
 nifi.flow.configuration.file=./target/conf/flow.xml.gz
 nifi.flow.configuration.archive.enabled=true
 nifi.flow.configuration.archive.dir=./target/conf/archive/

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/resources/nifi.properties
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/resources/nifi.properties b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/resources/nifi.properties
index 5b1134b..4709c21 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/resources/nifi.properties
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-site-to-site/src/test/resources/nifi.properties
@@ -25,7 +25,6 @@ nifi.flowfile.repository.checkpoint.millis=120000
 nifi.content.repository.directory.default=./content_repository
 nifi.provenance.repository.capacity=25000
 nifi.templates.directory=./conf/templates
-nifi.version=nifi 0.2.1-SNAPSHOT
 nifi.ui.banner.text=DEFAULT BANNER
 nifi.ui.autorefresh.interval.seconds=30
 nifi.flowcontroller.autoStartProcessors=true

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/pom.xml
new file mode 100644
index 0000000..fd3e5a4
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/pom.xml
@@ -0,0 +1,40 @@
+<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">
+    <!--
+      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.
+    -->
+    <modelVersion>4.0.0</modelVersion>
+    <parent>
+        <groupId>org.apache.nifi</groupId>
+        <artifactId>nifi-standard-bundle</artifactId>
+        <version>1.2.0-SNAPSHOT</version>
+    </parent>
+    <groupId>org.apache.nifi</groupId>
+    <artifactId>nifi-standard-prioritizers</artifactId>
+    <packaging>jar</packaging>
+    <dependencies>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-api</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-utils</artifactId>
+        </dependency>
+        <dependency>
+            <groupId>org.apache.nifi</groupId>
+            <artifactId>nifi-mock</artifactId>
+            <scope>test</scope>
+        </dependency>
+    </dependencies>
+</project>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/FirstInFirstOutPrioritizer.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/FirstInFirstOutPrioritizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/FirstInFirstOutPrioritizer.java
new file mode 100644
index 0000000..08437c7
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/FirstInFirstOutPrioritizer.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.prioritizer;
+
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.flowfile.FlowFilePrioritizer;
+
+public class FirstInFirstOutPrioritizer implements FlowFilePrioritizer {
+
+    @Override
+    public int compare(final FlowFile o1, final FlowFile o2) {
+        if (o1 == null && o2 == null) {
+            return 0;
+        } else if (o2 == null) {
+            return -1;
+        } else if (o1 == null) {
+            return 1;
+        }
+
+        final int dateComparison = o1.getLastQueueDate().compareTo(o2.getLastQueueDate());
+        if (dateComparison != 0) {
+            return dateComparison;
+        }
+
+        return Long.compare(o1.getQueueDateIndex(), o2.getQueueDateIndex());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/NewestFlowFileFirstPrioritizer.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/NewestFlowFileFirstPrioritizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/NewestFlowFileFirstPrioritizer.java
new file mode 100644
index 0000000..4893cf0
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/NewestFlowFileFirstPrioritizer.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.prioritizer;
+
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.flowfile.FlowFilePrioritizer;
+
+public class NewestFlowFileFirstPrioritizer implements FlowFilePrioritizer {
+
+    @Override
+    public int compare(final FlowFile o1, final FlowFile o2) {
+        if (o1 == null && o2 == null) {
+            return 0;
+        } else if (o2 == null) {
+            return -1;
+        } else if (o1 == null) {
+            return 1;
+        }
+
+        final int lineageDateCompare = Long.compare(o2.getLineageStartDate(), o1.getLineageStartDate());
+        if (lineageDateCompare != 0) {
+            return lineageDateCompare;
+        }
+
+        return Long.compare(o2.getLineageStartIndex(), o1.getLineageStartIndex());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/OldestFlowFileFirstPrioritizer.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/OldestFlowFileFirstPrioritizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/OldestFlowFileFirstPrioritizer.java
new file mode 100644
index 0000000..386d912
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/OldestFlowFileFirstPrioritizer.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.prioritizer;
+
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.flowfile.FlowFilePrioritizer;
+
+public class OldestFlowFileFirstPrioritizer implements FlowFilePrioritizer {
+
+    @Override
+    public int compare(final FlowFile o1, final FlowFile o2) {
+        if (o1 == null && o2 == null) {
+            return 0;
+        } else if (o2 == null) {
+            return -1;
+        } else if (o1 == null) {
+            return 1;
+        }
+
+        final int lineageDateCompare = Long.compare(o1.getLineageStartDate(), o2.getLineageStartDate());
+        if (lineageDateCompare != 0) {
+            return lineageDateCompare;
+        }
+
+        return Long.compare(o1.getLineageStartIndex(), o2.getLineageStartIndex());
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/PriorityAttributePrioritizer.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/PriorityAttributePrioritizer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/PriorityAttributePrioritizer.java
new file mode 100644
index 0000000..3d27930
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/java/org/apache/nifi/prioritizer/PriorityAttributePrioritizer.java
@@ -0,0 +1,86 @@
+/*
+ * 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.prioritizer;
+
+import java.util.regex.Pattern;
+
+import org.apache.nifi.flowfile.FlowFile;
+import org.apache.nifi.flowfile.FlowFilePrioritizer;
+import org.apache.nifi.flowfile.attributes.CoreAttributes;
+
+/**
+ * This prioritizer checks each FlowFile for a "priority" attribute and lets
+ * that attribute determine the priority.
+ *
+ * 1. if neither FlowFile has a "priority" attribute then order will be
+ * FirstInFirstOut 2. if one FlowFile has a "priority" attribute and the other
+ * does not, then the one with the attribute wins 3. if one or both "priority"
+ * attributes is an integer, then the lowest number wins 4. the "priority"
+ * attributes are compared lexicographically and the lowest wins
+ */
+public class PriorityAttributePrioritizer implements FlowFilePrioritizer {
+
+    private static final Pattern intPattern = Pattern.compile("-?\\d+");
+
+    @Override
+    public int compare(FlowFile o1, FlowFile o2) {
+        if (o1 == null && o2 == null) {
+            return 0;
+        } else if (o2 == null) {
+            return -1;
+        } else if (o1 == null) {
+            return 1;
+        }
+
+        String o1Priority = o1.getAttribute(CoreAttributes.PRIORITY.key());
+        String o2Priority = o2.getAttribute(CoreAttributes.PRIORITY.key());
+        if (o1Priority == null && o2Priority == null) {
+            return -1; // this is not 0 to match FirstInFirstOut
+        } else if (o2Priority == null) {
+            return -1;
+        } else if (o1Priority == null) {
+            return 1;
+        }
+
+        // priority exists on both FlowFiles
+        if (intPattern.matcher(o1Priority.trim()).matches()) {
+            if (intPattern.matcher(o2Priority.trim()).matches()) {
+                try {
+                    // both o1Priority and o2Priority are numbers
+                    long o1num = Long.parseLong(o1Priority.trim());
+                    long o2num = Long.parseLong(o2Priority.trim());
+                    return o1num < o2num ? -1 : (o1num > o2num ? 1 : 0);
+                } catch (NumberFormatException e) {
+                    // not a long after regex matched
+                    return 0;
+                }
+            } else {
+                // o1Priority is a number, o2Priority is not, o1 wins
+                return -1;
+            }
+        } else {
+            if (intPattern.matcher(o2Priority.trim()).matches()) {
+                // o2Priority is a number, o1Priority is not, o2 wins
+                return 1;
+            } else {
+                // neither o1Priority nor o2Priority are numbers
+                return o1Priority.compareTo(o2Priority);
+            }
+        }
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/resources/META-INF/services/org.apache.nifi.flowfile.FlowFilePrioritizer
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/resources/META-INF/services/org.apache.nifi.flowfile.FlowFilePrioritizer b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/resources/META-INF/services/org.apache.nifi.flowfile.FlowFilePrioritizer
new file mode 100644
index 0000000..1c3cd25
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/main/resources/META-INF/services/org.apache.nifi.flowfile.FlowFilePrioritizer
@@ -0,0 +1,18 @@
+# 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.
+org.apache.nifi.prioritizer.FirstInFirstOutPrioritizer
+org.apache.nifi.prioritizer.NewestFlowFileFirstPrioritizer
+org.apache.nifi.prioritizer.OldestFlowFileFirstPrioritizer
+org.apache.nifi.prioritizer.PriorityAttributePrioritizer
\ No newline at end of file

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/NewestFirstPrioritizerTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/NewestFirstPrioritizerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/NewestFirstPrioritizerTest.java
new file mode 100644
index 0000000..37364e5
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/NewestFirstPrioritizerTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.prioritizer;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.nifi.processor.AbstractProcessor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Processor;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.util.MockFlowFile;
+import org.apache.nifi.util.MockProcessSession;
+import org.apache.nifi.util.SharedSessionState;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class NewestFirstPrioritizerTest {
+
+    @Test
+    public void testPrioritizer() throws InstantiationException, IllegalAccessException {
+        final Processor processor = new SimpleProcessor();
+        final AtomicLong idGenerator = new AtomicLong(0L);
+        final MockProcessSession session = new MockProcessSession(new SharedSessionState(processor, idGenerator), Mockito.mock(Processor.class));
+
+        final MockFlowFile flowFile1 = session.create();
+        try {
+            Thread.sleep(2); // guarantee the FlowFile entryDate for flowFile2 is different than flowFile1
+        } catch (final InterruptedException e) {
+        }
+        final MockFlowFile flowFile2 = session.create();
+
+        final NewestFlowFileFirstPrioritizer prioritizer = new NewestFlowFileFirstPrioritizer();
+        Assert.assertEquals(0, prioritizer.compare(null, null));
+        Assert.assertEquals(-1, prioritizer.compare(flowFile1, null));
+        Assert.assertEquals(1, prioritizer.compare(null, flowFile1));
+        Assert.assertEquals(0, prioritizer.compare(flowFile1, flowFile1));
+        Assert.assertEquals(0, prioritizer.compare(flowFile2, flowFile2));
+        Assert.assertEquals(1, prioritizer.compare(flowFile1, flowFile2));
+        Assert.assertEquals(-1, prioritizer.compare(flowFile2, flowFile1));
+    }
+
+    public class SimpleProcessor extends AbstractProcessor {
+
+        @Override
+        public void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException {
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/OldestFirstPrioritizerTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/OldestFirstPrioritizerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/OldestFirstPrioritizerTest.java
new file mode 100644
index 0000000..68a8d7d
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/OldestFirstPrioritizerTest.java
@@ -0,0 +1,66 @@
+/*
+ * 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.prioritizer;
+
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.nifi.processor.AbstractProcessor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Processor;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.util.MockFlowFile;
+import org.apache.nifi.util.MockProcessSession;
+import org.apache.nifi.util.SharedSessionState;
+import org.junit.Assert;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class OldestFirstPrioritizerTest {
+
+    @Test
+    public void testPrioritizer() throws InstantiationException, IllegalAccessException {
+        final Processor processor = new SimpleProcessor();
+        final AtomicLong idGenerator = new AtomicLong(0L);
+        final MockProcessSession session = new MockProcessSession(new SharedSessionState(processor, idGenerator), Mockito.mock(Processor.class));
+
+        final MockFlowFile flowFile1 = session.create();
+        try {
+            Thread.sleep(2); // guarantee the FlowFile entryDate for flowFile2 is different than flowFile1
+        } catch (final InterruptedException e) {
+        }
+        final MockFlowFile flowFile2 = session.create();
+
+        final OldestFlowFileFirstPrioritizer prioritizer = new OldestFlowFileFirstPrioritizer();
+        Assert.assertEquals(0, prioritizer.compare(null, null));
+        Assert.assertEquals(-1, prioritizer.compare(flowFile1, null));
+        Assert.assertEquals(1, prioritizer.compare(null, flowFile1));
+        Assert.assertEquals(0, prioritizer.compare(flowFile1, flowFile1));
+        Assert.assertEquals(0, prioritizer.compare(flowFile2, flowFile2));
+        Assert.assertEquals(-1, prioritizer.compare(flowFile1, flowFile2));
+        Assert.assertEquals(1, prioritizer.compare(flowFile2, flowFile1));
+    }
+
+    public class SimpleProcessor extends AbstractProcessor {
+
+        @Override
+        public void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException {
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/PriorityAttributePrioritizerTest.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/PriorityAttributePrioritizerTest.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/PriorityAttributePrioritizerTest.java
new file mode 100644
index 0000000..7098551
--- /dev/null
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-standard-prioritizers/src/test/java/org/apache/nifi/prioritizer/PriorityAttributePrioritizerTest.java
@@ -0,0 +1,117 @@
+/*
+ * 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.prioritizer;
+
+import static org.junit.Assert.assertEquals;
+
+import java.util.HashMap;
+import java.util.Map;
+import java.util.concurrent.atomic.AtomicLong;
+
+import org.apache.nifi.flowfile.attributes.CoreAttributes;
+import org.apache.nifi.processor.AbstractProcessor;
+import org.apache.nifi.processor.ProcessContext;
+import org.apache.nifi.processor.ProcessSession;
+import org.apache.nifi.processor.Processor;
+import org.apache.nifi.processor.exception.ProcessException;
+import org.apache.nifi.util.MockFlowFile;
+import org.apache.nifi.util.MockProcessSession;
+import org.apache.nifi.util.SharedSessionState;
+import org.junit.BeforeClass;
+import org.junit.Test;
+import org.mockito.Mockito;
+
+public class PriorityAttributePrioritizerTest {
+
+    static Map<String, String> attrsPri1 = new HashMap<String, String>();
+    static Map<String, String> attrsPri2 = new HashMap<String, String>();
+    static Map<String, String> attrsPrin1 = new HashMap<String, String>();
+    static Map<String, String> attrsPriA = new HashMap<String, String>();
+    static Map<String, String> attrsPriB = new HashMap<String, String>();
+    static Map<String, String> attrsPriLP = new HashMap<String, String>();
+    static Map<String, String> attrsPriLN = new HashMap<String, String>();
+
+    @BeforeClass
+    public static void init() {
+        attrsPri1.put(CoreAttributes.PRIORITY.key(), "1");
+        attrsPri2.put(CoreAttributes.PRIORITY.key(), "2");
+        attrsPrin1.put(CoreAttributes.PRIORITY.key(), "-1");
+        attrsPriA.put(CoreAttributes.PRIORITY.key(), "A");
+        attrsPriB.put(CoreAttributes.PRIORITY.key(), "B");
+        attrsPriLP.put(CoreAttributes.PRIORITY.key(), "5432123456789");
+        attrsPriLN.put(CoreAttributes.PRIORITY.key(), "-5432123456789");
+    }
+
+    @Test
+    public void testPrioritizer() throws InstantiationException, IllegalAccessException {
+        final Processor processor = new SimpleProcessor();
+        final AtomicLong idGenerator = new AtomicLong(0L);
+        final MockProcessSession session = new MockProcessSession(new SharedSessionState(processor, idGenerator), Mockito.mock(Processor.class));
+
+        final MockFlowFile ffNoPriority = session.create();
+        final MockFlowFile ffPri1 = session.create();
+        ffPri1.putAttributes(attrsPri1);
+        final MockFlowFile ffPri2 = session.create();
+        ffPri2.putAttributes(attrsPri2);
+        final MockFlowFile ffPrin1 = session.create();
+        ffPrin1.putAttributes(attrsPrin1);
+        final MockFlowFile ffPriA = session.create();
+        ffPriA.putAttributes(attrsPriA);
+        final MockFlowFile ffPriB = session.create();
+        ffPriB.putAttributes(attrsPriB);
+        final MockFlowFile ffPriLP = session.create();
+        ffPriLP.putAttributes(attrsPriLP);
+        final MockFlowFile ffPriLN = session.create();
+        ffPriLN.putAttributes(attrsPriLN);
+
+        final PriorityAttributePrioritizer prioritizer = new PriorityAttributePrioritizer();
+        assertEquals(0, prioritizer.compare(null, null));
+        assertEquals(-1, prioritizer.compare(ffNoPriority, null));
+        assertEquals(1, prioritizer.compare(null, ffNoPriority));
+
+        assertEquals(-1, prioritizer.compare(ffNoPriority, ffNoPriority));
+        assertEquals(-1, prioritizer.compare(ffPri1, ffNoPriority));
+        assertEquals(1, prioritizer.compare(ffNoPriority, ffPri1));
+
+        assertEquals(0, prioritizer.compare(ffPri1, ffPri1));
+        assertEquals(-1, prioritizer.compare(ffPri1, ffPri2));
+        assertEquals(1, prioritizer.compare(ffPri2, ffPri1));
+        assertEquals(-1, prioritizer.compare(ffPrin1, ffPri1));
+        assertEquals(1, prioritizer.compare(ffPri1, ffPrin1));
+
+        assertEquals(-1, prioritizer.compare(ffPri1, ffPriA));
+        assertEquals(1, prioritizer.compare(ffPriA, ffPri1));
+
+        assertEquals(0, prioritizer.compare(ffPriA, ffPriA));
+        assertEquals(-1, prioritizer.compare(ffPriA, ffPriB));
+        assertEquals(1, prioritizer.compare(ffPriB, ffPriA));
+
+        assertEquals(1, prioritizer.compare(ffPriLP, ffPri1));
+        assertEquals(-1, prioritizer.compare(ffPri1, ffPriLP));
+        assertEquals(-1, prioritizer.compare(ffPriLN, ffPri1));
+        assertEquals(1, prioritizer.compare(ffPri1, ffPriLN));
+    }
+
+    public class SimpleProcessor extends AbstractProcessor {
+
+        @Override
+        public void onTrigger(ProcessContext context, ProcessSession session) throws ProcessException {
+        }
+
+    }
+
+}

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
index d2def9f..84c9671 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-jetty/src/main/java/org/apache/nifi/web/server/JettyServer.java
@@ -19,15 +19,15 @@ package org.apache.nifi.web.server;
 import com.google.common.base.Strings;
 import com.google.common.collect.Lists;
 import org.apache.commons.collections4.CollectionUtils;
-import org.apache.commons.io.IOUtils;
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.NiFiServer;
+import org.apache.nifi.bundle.Bundle;
+import org.apache.nifi.bundle.BundleDetails;
 import org.apache.nifi.controller.UninheritableFlowException;
 import org.apache.nifi.controller.serialization.FlowSerializationException;
 import org.apache.nifi.controller.serialization.FlowSynchronizationException;
 import org.apache.nifi.lifecycle.LifeCycleStartException;
 import org.apache.nifi.nar.ExtensionMapping;
-import org.apache.nifi.nar.NarClassLoaders;
 import org.apache.nifi.security.util.KeyStoreUtils;
 import org.apache.nifi.services.FlowService;
 import org.apache.nifi.ui.extension.UiExtension;
@@ -125,12 +125,7 @@ public class JettyServer implements NiFiServer {
     private UiExtensionMapping componentUiExtensions;
     private Collection<WebAppContext> componentUiExtensionWebContexts;
 
-    /**
-     * Creates and configures a new Jetty instance.
-     *
-     * @param props the configuration
-     */
-    public JettyServer(final NiFiProperties props) {
+    public JettyServer(final NiFiProperties props, final Set<Bundle> bundles) {
         final QueuedThreadPool threadPool = new QueuedThreadPool(props.getWebThreads());
         threadPool.setName("NiFi Web Server");
 
@@ -145,41 +140,14 @@ public class JettyServer implements NiFiServer {
         // configure server
         configureConnectors(server);
 
-        // load wars from the nar working directories
-        loadWars(locateNarWorkingDirectories());
-    }
-
-    private Set<File> locateNarWorkingDirectories() {
-        final File frameworkWorkingDir = props.getFrameworkWorkingDirectory();
-        final File extensionsWorkingDir = props.getExtensionsWorkingDirectory();
-
-        final File[] frameworkDir = frameworkWorkingDir.listFiles();
-        if (frameworkDir == null) {
-            throw new IllegalStateException(String.format("Unable to access framework working directory: %s", frameworkWorkingDir.getAbsolutePath()));
-        }
-
-        final File[] extensionDirs = extensionsWorkingDir.listFiles();
-        if (extensionDirs == null) {
-            throw new IllegalStateException(String.format("Unable to access extensions working directory: %s", extensionsWorkingDir.getAbsolutePath()));
-        }
-
-        // we want to consider the framework and all extension NARs
-        final Set<File> narWorkingDirectories = new HashSet<>(Arrays.asList(frameworkDir));
-        narWorkingDirectories.addAll(Arrays.asList(extensionDirs));
-
-        return narWorkingDirectories;
+        // load wars from the bundle
+        loadWars(bundles);
     }
 
-    /**
-     * Loads the WARs in the specified NAR working directories. A WAR file must
-     * have a ".war" extension.
-     *
-     * @param narWorkingDirectories dirs
-     */
-    private void loadWars(final Set<File> narWorkingDirectories) {
+    private void loadWars(final Set<Bundle> bundles) {
 
         // load WARs
-        Map<File, File> warToNarWorkingDirectoryLookup = findWars(narWorkingDirectories);
+        final Map<File, Bundle> warToBundleLookup = findWars(bundles);
 
         // locate each war being deployed
         File webUiWar = null;
@@ -188,7 +156,7 @@ public class JettyServer implements NiFiServer {
         File webDocsWar = null;
         File webContentViewerWar = null;
         List<File> otherWars = new ArrayList<>();
-        for (File war : warToNarWorkingDirectoryLookup.keySet()) {
+        for (File war : warToBundleLookup.keySet()) {
             if (war.getName().toLowerCase().startsWith("nifi-web-api")) {
                 webApiWar = war;
             } else if (war.getName().toLowerCase().startsWith("nifi-web-error")) {
@@ -242,8 +210,8 @@ public class JettyServer implements NiFiServer {
                     String warName = StringUtils.substringBeforeLast(war.getName(), ".");
                     String warContextPath = String.format("/%s", warName);
 
-                    // attempt to locate the nar class loader for this war
-                    ClassLoader narClassLoaderForWar = NarClassLoaders.getInstance().getExtensionClassLoader(warToNarWorkingDirectoryLookup.get(war));
+                    // get the classloader for this war
+                    ClassLoader narClassLoaderForWar = warToBundleLookup.get(war).getClassLoader();
 
                     // this should never be null
                     if (narClassLoaderForWar == null) {
@@ -269,17 +237,22 @@ public class JettyServer implements NiFiServer {
                             contentViewerWebContexts.add(extensionUiContext);
                         } else {
                             // consider each component type identified
-                            for (final String componentType : types) {
-                                logger.info(String.format("Loading UI extension [%s, %s] for %s", extensionType, warContextPath, types));
+                            for (final String componentTypeCoordinates : types) {
+                                logger.info(String.format("Loading UI extension [%s, %s] for %s", extensionType, warContextPath, componentTypeCoordinates));
 
                                 // record the extension definition
                                 final UiExtension uiExtension = new UiExtension(extensionType, warContextPath);
 
                                 // create if this is the first extension for this component type
-                                List<UiExtension> componentUiExtensionsForType = componentUiExtensionsByType.get(componentType);
+                                List<UiExtension> componentUiExtensionsForType = componentUiExtensionsByType.get(componentTypeCoordinates);
                                 if (componentUiExtensionsForType == null) {
                                     componentUiExtensionsForType = new ArrayList<>();
-                                    componentUiExtensionsByType.put(componentType, componentUiExtensionsForType);
+                                    componentUiExtensionsByType.put(componentTypeCoordinates, componentUiExtensionsForType);
+                                }
+
+                                // see if there is already a ui extension of this same time
+                                if (containsUiExtensionType(componentUiExtensionsForType, extensionType)) {
+                                    throw new IllegalStateException(String.format("Encountered duplicate UI for %s", componentTypeCoordinates));
                                 }
 
                                 // record this extension
@@ -335,6 +308,23 @@ public class JettyServer implements NiFiServer {
     }
 
     /**
+     * Returns whether or not the specified ui extensions already contains an extension of the specified type.
+     *
+     * @param componentUiExtensionsForType  ui extensions for the type
+     * @param extensionType type of ui extension
+     * @return whether or not the specified ui extensions already contains an extension of the specified type
+     */
+    private boolean containsUiExtensionType(final List<UiExtension> componentUiExtensionsForType, final UiExtensionType extensionType) {
+        for (final UiExtension uiExtension : componentUiExtensionsForType) {
+            if (extensionType.equals(uiExtension.getExtensionType())) {
+                return true;
+            }
+        }
+
+        return false;
+    }
+
+    /**
      * Enables compression for the specified handler.
      *
      * @param handler handler to enable compression for
@@ -347,12 +337,13 @@ public class JettyServer implements NiFiServer {
         return gzip;
     }
 
-    private Map<File, File> findWars(final Set<File> narWorkingDirectories) {
-        final Map<File, File> wars = new HashMap<>();
+    private Map<File, Bundle> findWars(final Set<Bundle> bundles) {
+        final Map<File, Bundle> wars = new HashMap<>();
 
         // consider each nar working directory
-        for (final File narWorkingDirectory : narWorkingDirectories) {
-            final File narDependencies = new File(narWorkingDirectory, "META-INF/bundled-dependencies");
+        bundles.forEach(bundle -> {
+            final BundleDetails details = bundle.getBundleDetails();
+            final File narDependencies = new File(details.getWorkingDirectory(), "META-INF/bundled-dependencies");
             if (narDependencies.isDirectory()) {
                 // list the wars from this nar
                 final File[] narDependencyDirs = narDependencies.listFiles(WAR_FILTER);
@@ -362,10 +353,10 @@ public class JettyServer implements NiFiServer {
 
                 // add each war
                 for (final File war : narDependencyDirs) {
-                    wars.put(war, narWorkingDirectory);
+                    wars.put(war, bundle);
                 }
             }
-        }
+        });
 
         return wars;
     }
@@ -433,48 +424,6 @@ public class JettyServer implements NiFiServer {
         return null;
     }
 
-    /**
-     * Returns the extension in the specified WAR using the specified path.
-     *
-     * @param war war
-     * @param path path
-     * @return extensions
-     */
-    private List<String> getWarExtensions(final File war, final String path) {
-        List<String> processorTypes = new ArrayList<>();
-
-        // load the jar file and attempt to find the nifi-processor entry
-        JarFile jarFile = null;
-        try {
-            jarFile = new JarFile(war);
-            JarEntry jarEntry = jarFile.getJarEntry(path);
-
-            // ensure the nifi-processor entry was found
-            if (jarEntry != null) {
-                // get an input stream for the nifi-processor configuration file
-                try (final BufferedReader in = new BufferedReader(
-                        new InputStreamReader(jarFile.getInputStream(jarEntry)))) {
-
-                    // read in each configured type
-                    String rawProcessorType;
-                    while ((rawProcessorType = in.readLine()) != null) {
-                        // extract the processor type
-                        final String processorType = extractComponentType(rawProcessorType);
-                        if (processorType != null) {
-                            processorTypes.add(processorType);
-                        }
-                    }
-                }
-            }
-        } catch (IOException ioe) {
-            logger.warn("Unable to inspect {} for a custom processor UI.", new Object[]{war, ioe});
-        } finally {
-            IOUtils.closeQuietly(jarFile);
-        }
-
-        return processorTypes;
-    }
-
     private WebAppContext loadWar(final File warFile, final String contextPath, final ClassLoader parentClassLoader) {
         final WebAppContext webappContext = new WebAppContext(warFile.getPath(), contextPath);
         webappContext.setContextPath(contextPath);
@@ -530,8 +479,8 @@ public class JettyServer implements NiFiServer {
             final Resource docsResource = Resource.newResource(docsDir);
 
             // load the component documentation working directory
-            final String componentDocsDirPath = props.getProperty(NiFiProperties.COMPONENT_DOCS_DIRECTORY, "work/docs/components");
-            final File workingDocsDirectory = Paths.get(componentDocsDirPath).toRealPath().getParent().toFile();
+            final File componentDocsDirPath = props.getComponentDocumentationWorkingDirectory();
+            final File workingDocsDirectory = componentDocsDirPath.toPath().toRealPath().getParent().toFile();
             final Resource workingDocsResource = Resource.newResource(workingDocsDirectory);
 
             // load the rest documentation
@@ -917,4 +866,5 @@ public class JettyServer implements NiFiServer {
             logger.warn("Failed to stop web server", ex);
         }
     }
+
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-ui-extension/pom.xml
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-ui-extension/pom.xml b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-ui-extension/pom.xml
index 3fcbfe9..a79ec78 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-ui-extension/pom.xml
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-ui-extension/pom.xml
@@ -31,9 +31,5 @@
             <groupId>org.apache.nifi</groupId>
             <artifactId>nifi-framework-api</artifactId>
         </dependency>
-        <dependency>
-            <groupId>org.apache.nifi</groupId>
-            <artifactId>nifi-user-actions</artifactId>
-        </dependency>
     </dependencies>
 </project>

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-ui-extension/src/main/java/org/apache/nifi/ui/extension/UiExtensionMapping.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-ui-extension/src/main/java/org/apache/nifi/ui/extension/UiExtensionMapping.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-ui-extension/src/main/java/org/apache/nifi/ui/extension/UiExtensionMapping.java
index 73e39f8..4202830 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-ui-extension/src/main/java/org/apache/nifi/ui/extension/UiExtensionMapping.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-ui-extension/src/main/java/org/apache/nifi/ui/extension/UiExtensionMapping.java
@@ -30,21 +30,45 @@ public class UiExtensionMapping {
         this.uiExtensions = uiExtensions;
     }
 
+    private String getBundleSpecificKey(final String type, final String bundleGroup, final String bundleArtifact, final String bundleVersion) {
+        return type + ":" + bundleGroup + ":" + bundleArtifact + ":" + bundleVersion;
+    }
+
     /**
      * @param type type
+     * @param bundleGroup bundle group
+     * @param bundleArtifact bundle artifact
+     * @param bundleVersion bundle version
      * @return whether there are any UI extensions for the specified component
      * type
      */
-    public boolean hasUiExtension(final String type) {
+    public boolean hasUiExtension(final String type, final String bundleGroup, final String bundleArtifact, final String bundleVersion) {
+        // if there is an extension registered with these bundle coordinates use it
+        final String bundleSpecificKey = getBundleSpecificKey(type, bundleGroup, bundleArtifact, bundleVersion);
+        if (uiExtensions.containsKey(bundleSpecificKey)) {
+            return true;
+        }
+
+        // otherwise fall back to the component type
         return uiExtensions.containsKey(type);
     }
 
     /**
      * @param type type
+     * @param bundleGroup bundle group
+     * @param bundleArtifact bundle artifact
+     * @param bundleVersion bundle version
      * @return the listing of all discovered UI extensions for the specified
      * component type
      */
-    public List<UiExtension> getUiExtension(final String type) {
+    public List<UiExtension> getUiExtension(final String type, final String bundleGroup, final String bundleArtifact, final String bundleVersion) {
+        // if there is an extension registered with these bundle coordinates use it
+        final String bundleSpecificKey = getBundleSpecificKey(type, bundleGroup, bundleArtifact, bundleVersion);
+        if (uiExtensions.containsKey(bundleSpecificKey)) {
+            return uiExtensions.get(bundleSpecificKey);
+        }
+
+        // otherwise fall back to the component type
         return uiExtensions.get(type);
     }
 

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
index b4af48f..efb11a0 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ControllerServiceAuditor.java
@@ -25,6 +25,7 @@ import org.apache.nifi.action.details.ActionDetails;
 import org.apache.nifi.action.details.FlowChangeConfigureDetails;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
+import org.apache.nifi.bundle.BundleCoordinate;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.controller.ConfiguredComponent;
 import org.apache.nifi.controller.ProcessorNode;
@@ -60,6 +61,7 @@ public class ControllerServiceAuditor extends NiFiAuditor {
     private static final String COMMENTS = "Comments";
     private static final String NAME = "Name";
     private static final String ANNOTATION_DATA = "Annotation Data";
+    private static final String EXTENSION_VERSION = "Extension Version";
 
     /**
      * Audits the creation of controller service via createControllerService().
@@ -414,6 +416,10 @@ public class ControllerServiceAuditor extends NiFiAuditor {
         if (controllerServiceDTO.getAnnotationData() != null) {
             values.put(ANNOTATION_DATA, controllerService.getAnnotationData());
         }
+        if (controllerServiceDTO.getBundle() != null) {
+            final BundleCoordinate bundle = controllerService.getBundleCoordinate();
+            values.put(EXTENSION_VERSION, formatExtensionVersion(controllerService.getComponentType(), bundle));
+        }
         if (controllerServiceDTO.getProperties() != null) {
             // for each property specified, extract its configured value
             Map<String, String> properties = controllerServiceDTO.getProperties();

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/NiFiAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/NiFiAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/NiFiAuditor.java
index 14c4b64..8dd7c85 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/NiFiAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/NiFiAuditor.java
@@ -16,19 +16,20 @@
  */
 package org.apache.nifi.audit;
 
-import java.util.ArrayList;
-import java.util.Collection;
-
 import org.apache.commons.lang3.StringUtils;
 import org.apache.nifi.action.Action;
 import org.apache.nifi.action.details.FlowChangeMoveDetails;
 import org.apache.nifi.action.details.MoveDetails;
 import org.apache.nifi.admin.service.AuditService;
+import org.apache.nifi.bundle.BundleCoordinate;
 import org.apache.nifi.groups.ProcessGroup;
 import org.apache.nifi.web.NiFiServiceFacade;
 import org.apache.nifi.web.dao.ProcessGroupDAO;
 import org.slf4j.Logger;
 
+import java.util.ArrayList;
+import java.util.Collection;
+
 /**
  * A NiFi audit service.
  */
@@ -91,6 +92,24 @@ public abstract class NiFiAuditor {
         return moveDetails;
     }
 
+    protected String formatExtensionVersion(final String type, final BundleCoordinate bundle) {
+        final String formattedType;
+        if (BundleCoordinate.DEFAULT_VERSION.equals(bundle.getVersion())) {
+            formattedType = type;
+        } else {
+            formattedType = type + " " + bundle.getVersion();
+        }
+
+        final String formattedBundle;
+        if (BundleCoordinate.DEFAULT_GROUP.equals(bundle.getGroup())) {
+            formattedBundle = bundle.getId();
+        } else {
+            formattedBundle = bundle.getGroup() + " - " + bundle.getId();
+        }
+
+        return String.format("%s from %s", formattedType, formattedBundle);
+    }
+
     /* setters / getters */
     public void setAuditService(AuditService auditService) {
         this.auditService = auditService;

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java
index 915ee79..c40c087 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ProcessorAuditor.java
@@ -26,6 +26,7 @@ import org.apache.nifi.action.details.ActionDetails;
 import org.apache.nifi.action.details.FlowChangeConfigureDetails;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
+import org.apache.nifi.bundle.BundleCoordinate;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.controller.ProcessorNode;
 import org.apache.nifi.controller.ScheduledState;
@@ -69,6 +70,7 @@ public class ProcessorAuditor extends NiFiAuditor {
     private static final String SCHEDULING_PERIOD = "Run Schedule";
     private static final String SCHEDULING_STRATEGY = "Scheduling Strategy";
     private static final String EXECUTION_NODE = "Execution Node";
+    private static final String EXTENSION_VERSION = "Extension Version";
 
     /**
      * Audits the creation of processors via createProcessor().
@@ -315,6 +317,10 @@ public class ProcessorAuditor extends NiFiAuditor {
         if (processorDTO.getName() != null) {
             values.put(NAME, processor.getName());
         }
+        if (processorDTO.getBundle() != null) {
+            final BundleCoordinate bundle = processor.getBundleCoordinate();
+            values.put(EXTENSION_VERSION, formatExtensionVersion(processor.getComponentType(), bundle));
+        }
         if (processorDTO.getConfig() != null) {
             ProcessorConfigDTO newConfig = processorDTO.getConfig();
             if (newConfig.getConcurrentlySchedulableTaskCount() != null) {

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java
index e198d5e..c8e2682 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/ReportingTaskAuditor.java
@@ -25,6 +25,7 @@ import org.apache.nifi.action.details.ActionDetails;
 import org.apache.nifi.action.details.FlowChangeConfigureDetails;
 import org.apache.nifi.authorization.user.NiFiUser;
 import org.apache.nifi.authorization.user.NiFiUserUtils;
+import org.apache.nifi.bundle.BundleCoordinate;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.controller.ReportingTaskNode;
 import org.apache.nifi.controller.ScheduledState;
@@ -53,6 +54,7 @@ public class ReportingTaskAuditor extends NiFiAuditor {
 
     private static final String NAME = "Name";
     private static final String ANNOTATION_DATA = "Annotation Data";
+    private static final String EXTENSION_VERSION = "Extension Version";
 
     /**
      * Audits the creation of reporting task via createReportingTask().
@@ -306,6 +308,10 @@ public class ReportingTaskAuditor extends NiFiAuditor {
         if (reportingTaskDTO.getAnnotationData() != null) {
             values.put(ANNOTATION_DATA, reportingTask.getAnnotationData());
         }
+        if (reportingTaskDTO.getBundle() != null) {
+            final BundleCoordinate bundle = reportingTask.getBundleCoordinate();
+            values.put(EXTENSION_VERSION, formatExtensionVersion(reportingTask.getComponentType(), bundle));
+        }
         if (reportingTaskDTO.getProperties() != null) {
             // for each property specified, extract its configured value
             Map<String, String> properties = reportingTaskDTO.getProperties();

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java
index ce7313e..af3d19b 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/audit/SnippetAuditor.java
@@ -94,7 +94,7 @@ public class SnippetAuditor extends NiFiAuditor {
      * @throws Throwable ex
      */
     @Around("within(org.apache.nifi.web.dao.SnippetDAO+) && "
-            + "execution(org.apache.nifi.web.api.dto.FlowSnippetDTO copySnippet(java.lang.String, java.lang.String, java.lang.Double, java.lang.Double))")
+            + "execution(org.apache.nifi.web.api.dto.FlowSnippetDTO copySnippet(java.lang.String, java.lang.String, java.lang.Double, java.lang.Double, java.lang.String))")
     public FlowSnippetDTO copySnippetAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
         // perform the underlying operation
         FlowSnippetDTO snippet = (FlowSnippetDTO) proceedingJoinPoint.proceed();
@@ -110,7 +110,8 @@ public class SnippetAuditor extends NiFiAuditor {
      * @throws Throwable ex
      */
     @Around("within(org.apache.nifi.web.dao.TemplateDAO+) && "
-            + "execution(org.apache.nifi.web.api.dto.FlowSnippetDTO instantiateTemplate(java.lang.String, java.lang.Double, java.lang.Double, java.lang.String))")
+            + "execution(org.apache.nifi.web.api.dto.FlowSnippetDTO instantiateTemplate("
+            + "java.lang.String, java.lang.Double, java.lang.Double, java.lang.String, org.apache.nifi.web.api.dto.FlowSnippetDTO, java.lang.String))")
     public FlowSnippetDTO instantiateTemplateAdvice(ProceedingJoinPoint proceedingJoinPoint) throws Throwable {
         // perform the underlying operation
         FlowSnippetDTO snippet = (FlowSnippetDTO) proceedingJoinPoint.proceed();

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
index b1d0844..db5bd17 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/AuthorizableLookup.java
@@ -17,6 +17,8 @@
 package org.apache.nifi.authorization;
 
 import org.apache.nifi.authorization.resource.Authorizable;
+import org.apache.nifi.web.api.dto.BundleDTO;
+import org.apache.nifi.web.api.dto.FlowSnippetDTO;
 
 public interface AuthorizableLookup {
 
@@ -43,7 +45,7 @@ public interface AuthorizableLookup {
      * @param type processor type
      * @return authorizable
      */
-    ConfigurableComponentAuthorizable getProcessorByType(String type);
+    ConfigurableComponentAuthorizable getProcessorByType(String type, BundleDTO bundle);
 
     /**
      * Get the authorizable for querying Provenance.
@@ -144,10 +146,11 @@ public interface AuthorizableLookup {
      * controller service. The intent of this method is to provide access to the PropertyDescriptors
      * prior to the component being created.
      *
-     * @param type processor type
+     * @param type controller service type
+     * @param bundle bundle
      * @return authorizable
      */
-    ConfigurableComponentAuthorizable getControllerServiceByType(String type);
+    ConfigurableComponentAuthorizable getControllerServiceByType(String type, BundleDTO bundle);
 
     /**
      * Get the authorizable referencing component.
@@ -171,10 +174,11 @@ public interface AuthorizableLookup {
      * reporting task. The intent of this method is to provide access to the PropertyDescriptors
      * prior to the component being created.
      *
-     * @param type processor type
+     * @param type reporting task type
+     * @param bundle bundle
      * @return authorizable
      */
-    ConfigurableComponentAuthorizable getReportingTaskByType(String type);
+    ConfigurableComponentAuthorizable getReportingTaskByType(String type, BundleDTO bundle);
 
     /**
      * Get the authorizable Template.
@@ -182,7 +186,15 @@ public interface AuthorizableLookup {
      * @param id template id
      * @return authorizable
      */
-    TemplateAuthorizable getTemplate(String id);
+    Authorizable getTemplate(String id);
+
+    /**
+     * Get the authorizable Template contents.
+     *
+     * @param snippet the template contents
+     * @return authorizable
+     */
+    TemplateContentsAuthorizable getTemplateContents(FlowSnippetDTO snippet);
 
     /**
      * Get the authorizable connectable. Note this does not include RemoteGroupPorts.

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConfigurableComponentAuthorizable.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConfigurableComponentAuthorizable.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConfigurableComponentAuthorizable.java
index f352211..aaf1d3d 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConfigurableComponentAuthorizable.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/ConfigurableComponentAuthorizable.java
@@ -61,4 +61,9 @@ public interface ConfigurableComponentAuthorizable {
      * @return value
      */
     String getValue(PropertyDescriptor propertyDescriptor);
+
+    /**
+     * Cleans up any resources resulting from the creation of these temporary components.
+     */
+    void cleanUpResources();
 }

http://git-wip-us.apache.org/repos/asf/nifi/blob/d90cf846/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
----------------------------------------------------------------------
diff --git a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
index 28092cd..ebc98de 100644
--- a/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
+++ b/nifi-nar-bundles/nifi-framework-bundle/nifi-framework/nifi-web/nifi-web-api/src/main/java/org/apache/nifi/authorization/StandardAuthorizableLookup.java
@@ -26,6 +26,7 @@ import org.apache.nifi.authorization.resource.ResourceType;
 import org.apache.nifi.authorization.resource.RestrictedComponentsAuthorizable;
 import org.apache.nifi.authorization.resource.TenantAuthorizable;
 import org.apache.nifi.authorization.user.NiFiUser;
+import org.apache.nifi.bundle.BundleCoordinate;
 import org.apache.nifi.components.PropertyDescriptor;
 import org.apache.nifi.connectable.Connectable;
 import org.apache.nifi.connectable.Connection;
@@ -34,15 +35,16 @@ import org.apache.nifi.controller.ConfiguredComponent;
 import org.apache.nifi.controller.ProcessorNode;
 import org.apache.nifi.controller.ReportingTaskNode;
 import org.apache.nifi.controller.Snippet;
-import org.apache.nifi.controller.Template;
 import org.apache.nifi.controller.service.ControllerServiceNode;
 import org.apache.nifi.controller.service.ControllerServiceReference;
 import org.apache.nifi.groups.ProcessGroup;
+import org.apache.nifi.nar.ExtensionManager;
 import org.apache.nifi.remote.PortAuthorizationResult;
 import org.apache.nifi.remote.RootGroupPort;
+import org.apache.nifi.util.BundleUtils;
 import org.apache.nifi.web.ResourceNotFoundException;
+import org.apache.nifi.web.api.dto.BundleDTO;
 import org.apache.nifi.web.api.dto.FlowSnippetDTO;
-import org.apache.nifi.web.api.dto.TemplateDTO;
 import org.apache.nifi.web.controller.ControllerFacade;
 import org.apache.nifi.web.dao.AccessPolicyDAO;
 import org.apache.nifi.web.dao.ConnectionDAO;
@@ -146,9 +148,9 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public ConfigurableComponentAuthorizable getProcessorByType(String type) {
+    public ConfigurableComponentAuthorizable getProcessorByType(String type, BundleDTO bundle) {
         try {
-            final ProcessorNode processorNode = controllerFacade.createTemporaryProcessor(type);
+            final ProcessorNode processorNode = controllerFacade.createTemporaryProcessor(type, bundle);
             return new ProcessorConfigurableComponentAuthorizable(processorNode);
         } catch (final Exception e) {
             throw new AccessDeniedException("Unable to create processor to verify if it references any Controller Services.");
@@ -255,9 +257,9 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public ConfigurableComponentAuthorizable getControllerServiceByType(String type) {
+    public ConfigurableComponentAuthorizable getControllerServiceByType(String type, BundleDTO bundle) {
         try {
-            final ControllerServiceNode controllerService = controllerFacade.createTemporaryControllerService(type);
+            final ControllerServiceNode controllerService = controllerFacade.createTemporaryControllerService(type, bundle);
             return new ControllerServiceConfigurableComponentAuthorizable(controllerService);
         } catch (final Exception e) {
             throw new AccessDeniedException("Unable to create controller service to verify if it references any Controller Services.");
@@ -314,9 +316,9 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public ConfigurableComponentAuthorizable getReportingTaskByType(String type) {
+    public ConfigurableComponentAuthorizable getReportingTaskByType(String type, BundleDTO bundle) {
         try {
-            final ReportingTaskNode reportingTask = controllerFacade.createTemporaryReportingTask(type);
+            final ReportingTaskNode reportingTask = controllerFacade.createTemporaryReportingTask(type, bundle);
             return new ReportingTaskConfigurableComponentAuthorizable(reportingTask);
         } catch (final Exception e) {
             throw new AccessDeniedException("Unable to create reporting to verify if it references any Controller Services.");
@@ -510,7 +512,7 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
                 authorizable = getReportingTask(componentId).getAuthorizable();
                 break;
             case Template:
-                authorizable = getTemplate(componentId).getAuthorizable();
+                authorizable = getTemplate(componentId);
                 break;
         }
 
@@ -622,11 +624,25 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
         }
 
         if (snippet.getProcessors() != null) {
-            processors.addAll(snippet.getProcessors().stream().map(processor -> getProcessorByType(processor.getType())).collect(Collectors.toSet()));
+            snippet.getProcessors().forEach(processor -> {
+                try {
+                    final BundleCoordinate bundle = BundleUtils.getCompatibleBundle(processor.getType(), processor.getBundle());
+                    processors.add(getProcessorByType(processor.getType(), new BundleDTO(bundle.getGroup(), bundle.getId(), bundle.getVersion())));
+                } catch (final IllegalStateException e) {
+                    // no compatible bundles... no additional auth checks necessary... if created, will be ghosted
+                }
+            });
         }
 
         if (snippet.getControllerServices() != null) {
-            controllerServices.addAll(snippet.getControllerServices().stream().map(controllerService -> getControllerServiceByType(controllerService.getType())).collect(Collectors.toSet()));
+            snippet.getControllerServices().forEach(controllerService -> {
+                try {
+                    final BundleCoordinate bundle = BundleUtils.getCompatibleBundle(controllerService.getType(), controllerService.getBundle());
+                    controllerServices.add(getControllerServiceByType(controllerService.getType(), new BundleDTO(bundle.getGroup(), bundle.getId(), bundle.getVersion())));
+                } catch (final IllegalStateException e) {
+                    // no compatible bundles... no additional auth checks necessary... if created, will be ghosted
+                }
+            });
         }
 
         if (snippet.getProcessGroups() != null) {
@@ -635,23 +651,20 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
     }
 
     @Override
-    public TemplateAuthorizable getTemplate(final String id) {
-        final Template template = templateDAO.getTemplate(id);
-        final TemplateDTO contents = template.getDetails();
+    public Authorizable getTemplate(String id) {
+        return templateDAO.getTemplate(id);
+    }
 
+    @Override
+    public TemplateContentsAuthorizable getTemplateContents(final FlowSnippetDTO snippet) {
         // templates are immutable so we can pre-compute all encapsulated processors and controller services
         final Set<ConfigurableComponentAuthorizable> processors = new HashSet<>();
         final Set<ConfigurableComponentAuthorizable> controllerServices = new HashSet<>();
 
         // find all processors and controller services
-        createTemporaryProcessorsAndControllerServices(contents.getSnippet(), processors, controllerServices);
-
-        return new TemplateAuthorizable() {
-            @Override
-            public Authorizable getAuthorizable() {
-                return template;
-            }
+        createTemporaryProcessorsAndControllerServices(snippet, processors, controllerServices);
 
+        return new TemplateContentsAuthorizable() {
             @Override
             public Set<ConfigurableComponentAuthorizable> getEncapsulatedProcessors() {
                 return processors;
@@ -720,6 +733,11 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
         public List<PropertyDescriptor> getPropertyDescriptors() {
             return processorNode.getPropertyDescriptors();
         }
+
+        @Override
+        public void cleanUpResources() {
+            ExtensionManager.removeInstanceClassLoaderIfExists(processorNode.getIdentifier());
+        }
     }
 
     /**
@@ -756,6 +774,11 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
         public List<PropertyDescriptor> getPropertyDescriptors() {
             return controllerServiceNode.getControllerServiceImplementation().getPropertyDescriptors();
         }
+
+        @Override
+        public void cleanUpResources() {
+            ExtensionManager.removeInstanceClassLoaderIfExists(controllerServiceNode.getIdentifier());
+        }
     }
 
     /**
@@ -792,6 +815,11 @@ class StandardAuthorizableLookup implements AuthorizableLookup {
         public List<PropertyDescriptor> getPropertyDescriptors() {
             return reportingTaskNode.getReportingTask().getPropertyDescriptors();
         }
+
+        @Override
+        public void cleanUpResources() {
+            ExtensionManager.removeInstanceClassLoaderIfExists(reportingTaskNode.getIdentifier());
+        }
     }
 
     private static class StandardProcessGroupAuthorizable implements ProcessGroupAuthorizable {